OLD | NEW |
---|---|
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 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. |
(...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
495 | 495 |
496 self.host_proc = subprocess.Popen(args, env=self.child_env, | 496 self.host_proc = subprocess.Popen(args, env=self.child_env, |
497 stdin=subprocess.PIPE) | 497 stdin=subprocess.PIPE) |
498 logging.info(args) | 498 logging.info(args) |
499 if not self.host_proc.pid: | 499 if not self.host_proc.pid: |
500 raise Exception("Could not start Chrome Remote Desktop host") | 500 raise Exception("Could not start Chrome Remote Desktop host") |
501 self.host_proc.stdin.write(json.dumps(host_config.data)) | 501 self.host_proc.stdin.write(json.dumps(host_config.data)) |
502 self.host_proc.stdin.close() | 502 self.host_proc.stdin.close() |
503 | 503 |
504 | 504 |
505 def get_daemon_pid(): | 505 def get_daemon_proc(): |
506 """Checks if there is already an instance of this script running, and returns | 506 """Checks if there is already an instance of this script running, and returns |
507 its PID. | 507 a psutil.Process instance for it. |
508 | 508 |
509 Returns: | 509 Returns: |
510 The process ID of the existing daemon process, or 0 if the daemon is not | 510 A Process instance for the existing daemon process, or None if the daemon |
511 running. | 511 is not running. |
512 """ | 512 """ |
513 | |
513 uid = os.getuid() | 514 uid = os.getuid() |
514 this_pid = os.getpid() | 515 this_pid = os.getpid() |
515 | 516 |
516 # Support new & old psutil API. This is the right way to check, according to | 517 # Support new & old psutil API. This is the right way to check, according to |
517 # http://grodola.blogspot.com/2014/01/psutil-20-porting.html | 518 # http://grodola.blogspot.com/2014/01/psutil-20-porting.html |
518 if psutil.version_info >= (2, 0): | 519 if psutil.version_info >= (2, 0): |
519 psget = lambda x: x() | 520 psget = lambda x: x() |
520 else: | 521 else: |
521 psget = lambda x: x | 522 psget = lambda x: x |
522 | 523 |
523 for process in psutil.process_iter(): | 524 for process in psutil.process_iter(): |
524 # Skip any processes that raise an exception, as processes may terminate | 525 # Skip any processes that raise an exception, as processes may terminate |
525 # during iteration over the list. | 526 # during iteration over the list. |
526 try: | 527 try: |
527 # Skip other users' processes. | 528 # Skip other users' processes. |
528 if psget(process.uids).real != uid: | 529 if psget(process.uids).real != uid: |
529 continue | 530 continue |
530 | 531 |
531 # Skip the process for this instance. | 532 # Skip the process for this instance. |
532 if process.pid == this_pid: | 533 if process.pid == this_pid: |
533 continue | 534 continue |
534 | 535 |
535 # |cmdline| will be [python-interpreter, script-file, other arguments...] | 536 # |cmdline| will be [python-interpreter, script-file, other arguments...] |
536 cmdline = psget(process.cmdline) | 537 cmdline = psget(process.cmdline) |
537 if len(cmdline) < 2: | 538 if len(cmdline) < 2: |
538 continue | 539 continue |
539 if cmdline[0] == sys.executable and cmdline[1] == sys.argv[0]: | 540 if cmdline[0] == sys.executable and cmdline[1] == sys.argv[0]: |
540 return process.pid | 541 return process |
541 except (psutil.NoSuchProcess, psutil.AccessDenied): | 542 except (psutil.NoSuchProcess, psutil.AccessDenied): |
542 continue | 543 continue |
543 | 544 |
544 return 0 | 545 return None |
545 | 546 |
546 | 547 |
547 def choose_x_session(): | 548 def choose_x_session(): |
548 """Chooses the most appropriate X session command for this system. | 549 """Chooses the most appropriate X session command for this system. |
549 | 550 |
550 Returns: | 551 Returns: |
551 A string containing the command to run, or a list of strings containing | 552 A string containing the command to run, or a list of strings containing |
552 the executable program and its arguments, which is suitable for passing as | 553 the executable program and its arguments, which is suitable for passing as |
553 the first parameter of subprocess.Popen(). If a suitable session cannot | 554 the first parameter of subprocess.Popen(). If a suitable session cannot |
554 be found, returns None. | 555 be found, returns None. |
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
972 help="Prints version of the host.") | 973 help="Prints version of the host.") |
973 (options, args) = parser.parse_args() | 974 (options, args) = parser.parse_args() |
974 | 975 |
975 # Determine the filename of the host configuration and PID files. | 976 # Determine the filename of the host configuration and PID files. |
976 if not options.config: | 977 if not options.config: |
977 options.config = os.path.join(CONFIG_DIR, "host#%s.json" % g_host_hash) | 978 options.config = os.path.join(CONFIG_DIR, "host#%s.json" % g_host_hash) |
978 | 979 |
979 # Check for a modal command-line option (start, stop, etc.) | 980 # Check for a modal command-line option (start, stop, etc.) |
980 | 981 |
981 if options.get_status: | 982 if options.get_status: |
982 pid = get_daemon_pid() | 983 proc = get_daemon_proc() |
983 if pid != 0: | 984 if proc is not None: |
Sergey Ulanov
2014/06/18 00:23:58
nit: why not 'proc != None'?
Or I would prefer 'if
Lambros
2014/06/18 00:44:57
I'm following the advice from the Google Python st
Sergey Ulanov
2014/06/18 08:01:27
I didn't know about this. Still, the guide says th
| |
984 print "STARTED" | 985 print "STARTED" |
985 elif is_supported_platform(): | 986 elif is_supported_platform(): |
986 print "STOPPED" | 987 print "STOPPED" |
987 else: | 988 else: |
988 print "NOT_IMPLEMENTED" | 989 print "NOT_IMPLEMENTED" |
989 return 0 | 990 return 0 |
990 | 991 |
991 # TODO(sergeyu): Remove --check-running once NPAPI plugin and NM host are | 992 # TODO(sergeyu): Remove --check-running once NPAPI plugin and NM host are |
992 # updated to always use get-status flag instead. | 993 # updated to always use get-status flag instead. |
993 if options.check_running: | 994 if options.check_running: |
994 pid = get_daemon_pid() | 995 proc = get_daemon_proc() |
995 return 0 if pid != 0 else 1 | 996 return 1 if proc is None else 0 |
996 | 997 |
997 if options.stop: | 998 if options.stop: |
998 pid = get_daemon_pid() | 999 proc = get_daemon_proc() |
999 if pid == 0: | 1000 if proc is None: |
1000 print "The daemon is not currently running" | 1001 print "The daemon is not currently running" |
1001 else: | 1002 else: |
1002 print "Killing process %s" % pid | 1003 print "Killing process %s" % proc.pid |
1003 os.kill(pid, signal.SIGTERM) | 1004 proc.terminate() |
1005 try: | |
1006 proc.wait(timeout=30) | |
1007 except psutil.TimeoutExpired: | |
1008 print "Timed out trying to kill daemon process" | |
1009 return 1 | |
1004 return 0 | 1010 return 0 |
1005 | 1011 |
1006 if options.reload: | 1012 if options.reload: |
1007 pid = get_daemon_pid() | 1013 proc = get_daemon_proc() |
1008 if pid == 0: | 1014 if proc is None: |
1009 return 1 | 1015 return 1 |
1010 os.kill(pid, signal.SIGHUP) | 1016 proc.send_signal(signal.SIGHUP) |
1011 return 0 | 1017 return 0 |
1012 | 1018 |
1013 if options.add_user: | 1019 if options.add_user: |
1014 user = getpass.getuser() | 1020 user = getpass.getuser() |
1015 try: | 1021 try: |
1016 if user in grp.getgrnam(CHROME_REMOTING_GROUP_NAME).gr_mem: | 1022 if user in grp.getgrnam(CHROME_REMOTING_GROUP_NAME).gr_mem: |
1017 logging.info("User '%s' is already a member of '%s'." % | 1023 logging.info("User '%s' is already a member of '%s'." % |
1018 (user, CHROME_REMOTING_GROUP_NAME)) | 1024 (user, CHROME_REMOTING_GROUP_NAME)) |
1019 return 0 | 1025 return 0 |
1020 except KeyError: | 1026 except KeyError: |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1092 auth = Authentication() | 1098 auth = Authentication() |
1093 auth_config_valid = auth.copy_from(host_config) | 1099 auth_config_valid = auth.copy_from(host_config) |
1094 host = Host() | 1100 host = Host() |
1095 host_config_valid = host.copy_from(host_config) | 1101 host_config_valid = host.copy_from(host_config) |
1096 if not host_config_valid or not auth_config_valid: | 1102 if not host_config_valid or not auth_config_valid: |
1097 logging.error("Failed to load host configuration.") | 1103 logging.error("Failed to load host configuration.") |
1098 return 1 | 1104 return 1 |
1099 | 1105 |
1100 # Determine whether a desktop is already active for the specified host | 1106 # Determine whether a desktop is already active for the specified host |
1101 # host configuration. | 1107 # host configuration. |
1102 pid = get_daemon_pid() | 1108 proc = get_daemon_proc() |
1103 if pid != 0: | 1109 if proc is not None: |
1104 # Debian policy requires that services should "start" cleanly and return 0 | 1110 # Debian policy requires that services should "start" cleanly and return 0 |
1105 # if they are already running. | 1111 # if they are already running. |
1106 print "Service already running." | 1112 print "Service already running." |
1107 return 0 | 1113 return 0 |
1108 | 1114 |
1109 # Detach a separate "daemon" process to run the session, unless specifically | 1115 # Detach a separate "daemon" process to run the session, unless specifically |
1110 # requested to run in the foreground. | 1116 # requested to run in the foreground. |
1111 if not options.foreground: | 1117 if not options.foreground: |
1112 daemonize() | 1118 daemonize() |
1113 | 1119 |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1234 else: | 1240 else: |
1235 logging.info("Host exited with status %s." % os.WEXITSTATUS(status)) | 1241 logging.info("Host exited with status %s." % os.WEXITSTATUS(status)) |
1236 elif os.WIFSIGNALED(status): | 1242 elif os.WIFSIGNALED(status): |
1237 logging.info("Host terminated by signal %s." % os.WTERMSIG(status)) | 1243 logging.info("Host terminated by signal %s." % os.WTERMSIG(status)) |
1238 | 1244 |
1239 | 1245 |
1240 if __name__ == "__main__": | 1246 if __name__ == "__main__": |
1241 logging.basicConfig(level=logging.DEBUG, | 1247 logging.basicConfig(level=logging.DEBUG, |
1242 format="%(asctime)s:%(levelname)s:%(message)s") | 1248 format="%(asctime)s:%(levelname)s:%(message)s") |
1243 sys.exit(main()) | 1249 sys.exit(main()) |
OLD | NEW |