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

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: Allow arbitrary X options to be passed. 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, extra_x_args):
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 ] + extra_x_args)
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",
239 "PATH", 243 "PATH",
(...skipping 27 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 "Usage: %prog [options] [ -- [ X server options ] ]")
283 parser.add_option("-s", "--size", dest="size", default="1280x1024",
284 help="dimensions of virtual desktop (default: %default)")
285 (options, args) = parser.parse_args()
286
287 size_components = options.size.split("x")
288 if len(size_components) != 2:
289 parser.error("Incorrect size format, should be WIDTHxHEIGHT");
290
291 try:
292 width = int(size_components[0])
293 height = int(size_components[1])
294
295 # Enforce minimum desktop size, as a sanity-check. The limit of 100 will
296 # detect typos of 2 instead of 3 digits.
297 if width < 100 or height < 100:
298 raise ValueError
299 except ValueError:
300 parser.error("Width and height should be 100 pixels or greater")
301
277 atexit.register(cleanup) 302 atexit.register(cleanup)
278 303
279 for s in [signal.SIGHUP, signal.SIGINT, signal.SIGTERM]: 304 for s in [signal.SIGHUP, signal.SIGINT, signal.SIGTERM]:
280 signal.signal(s, signal_handler) 305 signal.signal(s, signal_handler)
281 306
282 # Ensure full path to config directory exists. 307 # Ensure full path to config directory exists.
283 if not os.path.exists(CONFIG_DIR): 308 if not os.path.exists(CONFIG_DIR):
284 os.makedirs(CONFIG_DIR, mode=0700) 309 os.makedirs(CONFIG_DIR, mode=0700)
285 310
286 auth = Authentication(os.path.join(CONFIG_DIR, "auth.json")) 311 auth = Authentication(os.path.join(CONFIG_DIR, "auth.json"))
287 if not auth.load_config(): 312 if not auth.load_config():
288 try: 313 try:
289 auth.refresh_tokens() 314 auth.refresh_tokens()
290 except: 315 except:
291 logging.error("Authentication failed.") 316 logging.error("Authentication failed.")
292 return 1 317 return 1
293 auth.save_config() 318 auth.save_config()
294 319
295 host_hash = hashlib.md5(socket.gethostname()).hexdigest() 320 host_hash = hashlib.md5(socket.gethostname()).hexdigest()
296 host = Host(os.path.join(CONFIG_DIR, "host#%s.json" % host_hash)) 321 host = Host(os.path.join(CONFIG_DIR, "host#%s.json" % host_hash))
297 322
298 if not host.load_config(): 323 if not host.load_config():
299 host.create_config(auth) 324 host.create_config(auth)
300 host.save_config() 325 host.save_config()
301 326
302 logging.info("Using host_id: " + host.host_id) 327 logging.info("Using host_id: " + host.host_id)
303 328
304 desktop = Desktop() 329 desktop = Desktop(width, height)
305 desktop.launch_x_server() 330 desktop.launch_x_server(args)
306 desktop.launch_x_session() 331 desktop.launch_x_session()
307 desktop.launch_host(host) 332 desktop.launch_host(host)
308 333
309 while True: 334 while True:
310 pid, status = os.wait() 335 pid, status = os.wait()
311 logging.info("wait() returned (%s,%s)" % (pid, status)) 336 logging.info("wait() returned (%s,%s)" % (pid, status))
312 337
313 if pid == desktop.x_proc.pid: 338 if pid == desktop.x_proc.pid:
314 logging.info("X server process terminated with code %d", status) 339 logging.info("X server process terminated with code %d", status)
315 break 340 break
316 341
317 if pid == desktop.host_proc.pid: 342 if pid == desktop.host_proc.pid:
318 logging.info("Host process terminated, relaunching") 343 logging.info("Host process terminated, relaunching")
319 desktop.launch_host(host) 344 desktop.launch_host(host)
320 345
321 if __name__ == "__main__": 346 if __name__ == "__main__":
322 logging.basicConfig(level=logging.DEBUG) 347 logging.basicConfig(level=logging.DEBUG)
323 sys.exit(main()) 348 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