Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1255)

Side by Side Diff: remoting/tools/me2me_virtual_host.py

Issue 8885030: Add command-line option for Virtual Me2Me to set the desktop size. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix nits Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 # Virtual Me2Me implementation. This script runs and manages the processes 6 # Virtual Me2Me implementation. This script runs and manages the processes
7 # required for a Virtual Me2Me desktop, which are: X server, X desktop 7 # required for a Virtual Me2Me desktop, which are: X server, X desktop
8 # session, and Host process. 8 # session, and Host process.
9 # This script is intended to run continuously as a background daemon 9 # This script is intended to run continuously as a background daemon
10 # process, running under an ordinary (non-root) user account. 10 # process, running under an ordinary (non-root) user account.
11 11
12 import atexit 12 import atexit
13 import getpass 13 import getpass
14 import hashlib 14 import hashlib
15 import json 15 import json
16 import logging 16 import logging
17 import optparse
17 import os 18 import os
18 import random 19 import random
19 import signal 20 import signal
20 import socket 21 import socket
21 import subprocess 22 import subprocess
22 import sys 23 import sys
23 import time 24 import time
24 import urllib2 25 import urllib2
25 import uuid 26 import uuid
26 27
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 logging.info("Terminating Xvfb") 195 logging.info("Terminating Xvfb")
195 desktop.x_proc.terminate() 196 desktop.x_proc.terminate()
196 197
197 def signal_handler(signum, stackframe): 198 def signal_handler(signum, stackframe):
198 # Exit cleanly so the atexit handler, cleanup(), gets called. 199 # Exit cleanly so the atexit handler, cleanup(), gets called.
199 raise SystemExit 200 raise SystemExit
200 201
201 202
202 class Desktop: 203 class Desktop:
203 """Manage a single virtual desktop""" 204 """Manage a single virtual desktop"""
204 def __init__(self): 205 def __init__(self, width, height):
205 self.x_proc = None 206 self.x_proc = None
207 self.width = width
208 self.height = height
206 g_desktops.append(self) 209 g_desktops.append(self)
207 210
208 @staticmethod 211 @staticmethod
209 def get_unused_display_number(): 212 def get_unused_display_number():
210 """Return a candidate display number for which there is currently no 213 """Return a candidate display number for which there is currently no
211 X Server lock file""" 214 X Server lock file"""
212 display = FIRST_X_DISPLAY_NUMBER 215 display = FIRST_X_DISPLAY_NUMBER
213 while os.path.exists(X_LOCK_FILE_TEMPLATE % display): 216 while os.path.exists(X_LOCK_FILE_TEMPLATE % display):
214 display += 1 217 display += 1
215 return display 218 return display
216 219
217 def launch_x_server(self): 220 def launch_x_server(self):
218 display = self.get_unused_display_number() 221 display = self.get_unused_display_number()
219 ret_code = subprocess.call("xauth add :%d . `mcookie`" % display, 222 ret_code = subprocess.call("xauth add :%d . `mcookie`" % display,
220 shell=True) 223 shell=True)
221 if ret_code != 0: 224 if ret_code != 0:
222 raise Exception("xauth failed with code %d" % ret_code) 225 raise Exception("xauth failed with code %d" % ret_code)
223 226
224 logging.info("Starting Xvfb on display :%d" % display); 227 logging.info("Starting Xvfb on display :%d" % display);
228 screen_option = "%dx%dx24" % (self.width, self.height)
225 self.x_proc = subprocess.Popen(["Xvfb", ":%d" % display, 229 self.x_proc = subprocess.Popen(["Xvfb", ":%d" % display,
226 "-auth", X_AUTH_FILE, 230 "-auth", X_AUTH_FILE,
227 "-nolisten", "tcp", 231 "-nolisten", "tcp",
228 "-screen", "0", "1024x768x24", 232 "-screen", "0", screen_option
229 ]) 233 ])
230 if not self.x_proc.pid: 234 if not self.x_proc.pid:
231 raise Exception("Could not start Xvfb.") 235 raise Exception("Could not start Xvfb.")
232 236
233 # Create clean environment for new session, so it is cleanly separated from 237 # Create clean environment for new session, so it is cleanly separated from
234 # the user's console X session. 238 # the user's console X session.
235 self.child_env = {"DISPLAY": ":%d" % display} 239 self.child_env = {"DISPLAY": ":%d" % display}
236 for key in [ 240 for key in [
237 "HOME", 241 "HOME",
238 "LOGNAME", 242 "LOGNAME",
(...skipping 28 matching lines...) Expand all
267 def launch_host(self, host): 271 def launch_host(self, host):
268 # Start remoting host 272 # Start remoting host
269 args = [locate_executable(REMOTING_COMMAND), 273 args = [locate_executable(REMOTING_COMMAND),
270 "--%s=%s" % (HOST_CONFIG_SWITCH_NAME, host.config_file)] 274 "--%s=%s" % (HOST_CONFIG_SWITCH_NAME, host.config_file)]
271 self.host_proc = subprocess.Popen(args, env=self.child_env) 275 self.host_proc = subprocess.Popen(args, env=self.child_env)
272 if not self.host_proc.pid: 276 if not self.host_proc.pid:
273 raise Exception("Could not start remoting host") 277 raise Exception("Could not start remoting host")
274 278
275 279
276 def main(): 280 def main():
281 parser = optparse.OptionParser()
282 parser.add_option("-s", "--size", dest="size", default="1280x1024",
283 help="dimensions of virtual desktop (default: %default)")
284 (options, args) = parser.parse_args()
285
286 size_components = options.size.split("x")
287 if len(size_components) != 2:
288 parser.error("Incorrect size format, should be WIDTHxHEIGHT");
289
290 try:
291 width = int(size_components[0])
292 height = int(size_components[1])
293
294 # Enforce minimum desktop size, as a sanity-check. The limit of 100 will
295 # detect typos of 2 instead of 3 digits.
296 if width < 100 or height < 100:
297 raise ValueError
298 except ValueError:
299 parser.error("Dimensions should be 100 pixels or greater")
Wez 2011/12/13 01:43:52 nit: I'd actually use "Width and height" rather th
300
277 atexit.register(cleanup) 301 atexit.register(cleanup)
278 302
279 for s in [signal.SIGHUP, signal.SIGINT, signal.SIGTERM]: 303 for s in [signal.SIGHUP, signal.SIGINT, signal.SIGTERM]:
280 signal.signal(s, signal_handler) 304 signal.signal(s, signal_handler)
281 305
282 # Ensure full path to config directory exists. 306 # Ensure full path to config directory exists.
283 if not os.path.exists(CONFIG_DIR): 307 if not os.path.exists(CONFIG_DIR):
284 os.makedirs(CONFIG_DIR, mode=0700) 308 os.makedirs(CONFIG_DIR, mode=0700)
285 309
286 auth = Authentication(os.path.join(CONFIG_DIR, "auth.json")) 310 auth = Authentication(os.path.join(CONFIG_DIR, "auth.json"))
287 if not auth.load_config(): 311 if not auth.load_config():
288 try: 312 try:
289 auth.refresh_tokens() 313 auth.refresh_tokens()
290 except: 314 except:
291 logging.error("Authentication failed.") 315 logging.error("Authentication failed.")
292 return 1 316 return 1
293 auth.save_config() 317 auth.save_config()
294 318
295 host_hash = hashlib.md5(socket.gethostname()).hexdigest() 319 host_hash = hashlib.md5(socket.gethostname()).hexdigest()
296 host = Host(os.path.join(CONFIG_DIR, "host#%s.json" % host_hash)) 320 host = Host(os.path.join(CONFIG_DIR, "host#%s.json" % host_hash))
297 321
298 if not host.load_config(): 322 if not host.load_config():
299 host.create_config(auth) 323 host.create_config(auth)
300 host.save_config() 324 host.save_config()
301 325
302 logging.info("Using host_id: " + host.host_id) 326 logging.info("Using host_id: " + host.host_id)
303 327
304 desktop = Desktop() 328 desktop = Desktop(width, height)
305 desktop.launch_x_server() 329 desktop.launch_x_server()
306 desktop.launch_x_session() 330 desktop.launch_x_session()
307 desktop.launch_host(host) 331 desktop.launch_host(host)
308 332
309 while True: 333 while True:
310 pid, status = os.wait() 334 pid, status = os.wait()
311 logging.info("wait() returned (%s,%s)" % (pid, status)) 335 logging.info("wait() returned (%s,%s)" % (pid, status))
312 336
313 if pid == desktop.x_proc.pid: 337 if pid == desktop.x_proc.pid:
314 logging.info("X server process terminated with code %d", status) 338 logging.info("X server process terminated with code %d", status)
315 break 339 break
316 340
317 if pid == desktop.host_proc.pid: 341 if pid == desktop.host_proc.pid:
318 logging.info("Host process terminated, relaunching") 342 logging.info("Host process terminated, relaunching")
319 desktop.launch_host(host) 343 desktop.launch_host(host)
320 344
321 if __name__ == "__main__": 345 if __name__ == "__main__":
322 logging.basicConfig(level=logging.DEBUG) 346 logging.basicConfig(level=logging.DEBUG)
323 sys.exit(main()) 347 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698