Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env 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 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 376 self.session_proc = subprocess.Popen(XSESSION_COMMAND, | 376 self.session_proc = subprocess.Popen(XSESSION_COMMAND, |
| 377 stdin=open(os.devnull, "r"), | 377 stdin=open(os.devnull, "r"), |
| 378 cwd=HOME_DIR, | 378 cwd=HOME_DIR, |
| 379 env=self.child_env) | 379 env=self.child_env) |
| 380 if not self.session_proc.pid: | 380 if not self.session_proc.pid: |
| 381 raise Exception("Could not start X session") | 381 raise Exception("Could not start X session") |
| 382 | 382 |
| 383 def launch_host(self, host): | 383 def launch_host(self, host): |
| 384 # Start remoting host | 384 # Start remoting host |
| 385 args = [locate_executable(REMOTING_COMMAND), | 385 args = [locate_executable(REMOTING_COMMAND), |
| 386 "--host_config=%s" % (host.config_file), | 386 "--host_config=%s" % (host.config_file)] |
| 387 "--auth_config=%s" % (host.auth.config_file)] | 387 if host.auth.config_file != host.config_file: |
| 388 args.append("--auth_config=%s" % (host.auth.config_file)) | |
| 388 self.host_proc = subprocess.Popen(args, env=self.child_env) | 389 self.host_proc = subprocess.Popen(args, env=self.child_env) |
| 390 logging.info(args) | |
| 389 if not self.host_proc.pid: | 391 if not self.host_proc.pid: |
| 390 raise Exception("Could not start remoting host") | 392 raise Exception("Could not start remoting host") |
| 391 | 393 |
| 392 | 394 |
| 393 class PidFile: | 395 class PidFile: |
| 394 """Class to allow creating and deleting a file which holds the PID of the | 396 """Class to allow creating and deleting a file which holds the PID of the |
| 395 running process. This is used to detect if a process is already running, and | 397 running process. This is used to detect if a process is already running, and |
| 396 inform the user of the PID. On process termination, the PID file is | 398 inform the user of the PID. On process termination, the PID file is |
| 397 deleted. | 399 deleted. |
| 398 | 400 |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 616 help="don't run as a background daemon") | 618 help="don't run as a background daemon") |
| 617 parser.add_option("-k", "--stop", dest="stop", default=False, | 619 parser.add_option("-k", "--stop", dest="stop", default=False, |
| 618 action="store_true", | 620 action="store_true", |
| 619 help="stop the daemon currently running") | 621 help="stop the daemon currently running") |
| 620 parser.add_option("-p", "--new-pin", dest="new_pin", default=False, | 622 parser.add_option("-p", "--new-pin", dest="new_pin", default=False, |
| 621 action="store_true", | 623 action="store_true", |
| 622 help="set new PIN before starting the host") | 624 help="set new PIN before starting the host") |
| 623 parser.add_option("", "--check-running", dest="check_running", default=False, | 625 parser.add_option("", "--check-running", dest="check_running", default=False, |
| 624 action="store_true", | 626 action="store_true", |
| 625 help="return 0 if the daemon is running, or 1 otherwise") | 627 help="return 0 if the daemon is running, or 1 otherwise") |
| 626 parser.add_option("", "--explicit-config", dest="explicit_config", | 628 parser.add_option("", "--silent", dest="silent", default=False, |
| 627 help="explicitly specify content of the config") | 629 action="store_true", |
| 630 help="Start the host without trying to configure it.") | |
| 628 (options, args) = parser.parse_args() | 631 (options, args) = parser.parse_args() |
| 629 | 632 |
| 630 host_hash = hashlib.md5(socket.gethostname()).hexdigest() | 633 host_hash = hashlib.md5(socket.gethostname()).hexdigest() |
| 631 pid_filename = os.path.join(CONFIG_DIR, "host#%s.pid" % host_hash) | 634 pid_filename = os.path.join(CONFIG_DIR, "host#%s.pid" % host_hash) |
| 632 | 635 |
| 633 if options.check_running: | 636 if options.check_running: |
| 634 running, pid = PidFile(pid_filename).check() | 637 running, pid = PidFile(pid_filename).check() |
| 635 return 0 if (running and pid != 0) else 1 | 638 return 0 if (running and pid != 0) else 1 |
| 636 | 639 |
| 637 if options.stop: | 640 if options.stop: |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 679 | 682 |
| 680 atexit.register(cleanup) | 683 atexit.register(cleanup) |
| 681 | 684 |
| 682 for s in [signal.SIGHUP, signal.SIGINT, signal.SIGTERM, signal.SIGUSR1]: | 685 for s in [signal.SIGHUP, signal.SIGINT, signal.SIGTERM, signal.SIGUSR1]: |
| 683 signal.signal(s, signal_handler) | 686 signal.signal(s, signal_handler) |
| 684 | 687 |
| 685 # Ensure full path to config directory exists. | 688 # Ensure full path to config directory exists. |
| 686 if not os.path.exists(CONFIG_DIR): | 689 if not os.path.exists(CONFIG_DIR): |
| 687 os.makedirs(CONFIG_DIR, mode=0700) | 690 os.makedirs(CONFIG_DIR, mode=0700) |
| 688 | 691 |
| 689 if options.explicit_config: | 692 host_config_file = os.path.join(CONFIG_DIR, "host#%s.json" % host_hash) |
| 690 for file_name in ["auth.json", "host#%s.json" % host_hash]: | |
| 691 settings_file = open(os.path.join(CONFIG_DIR, file_name), 'w') | |
| 692 settings_file.write(options.explicit_config) | |
| 693 settings_file.close() | |
| 694 | 693 |
| 695 # TODO(sergeyu): Move auth parameters to the host config. | 694 # --silent option is specified when we are started from WebApp UI. Don't use |
| 696 auth = Authentication(os.path.join(CONFIG_DIR, "auth.json")) | 695 # separate auth file in that case. |
| 697 need_auth_tokens = not auth.load_config() | 696 # TODO(sergeyu): Always use host config for auth parameters. |
| 697 if options.silent: | |
| 698 auth_config_file = host_config_file | |
| 699 else: | |
| 700 auth_config_file = os.path.join(CONFIG_DIR, "auth.json") | |
| 698 | 701 |
|
Lambros
2012/08/01 18:30:57
Good TODO. As it is now, the script will use a di
Sergey Ulanov
2012/08/01 20:20:54
I'll do it in my next CL for this code. Problem is
| |
| 699 host = Host(os.path.join(CONFIG_DIR, "host#%s.json" % host_hash), auth) | 702 auth = Authentication(auth_config_file) |
| 700 register_host = not host.load_config() | 703 auth_config_loaded = auth.load_config() |
| 701 | 704 |
| 702 # Outside the loop so user doesn't get asked twice. | 705 host = Host(host_config_file, auth) |
| 703 if register_host: | 706 host_config_loaded = host.load_config() |
| 704 host.ask_pin() | |
| 705 elif options.new_pin or not host.is_pin_set(): | |
| 706 host.ask_pin() | |
| 707 host.save_config() | |
| 708 running, pid = PidFile(pid_filename).check() | |
| 709 if running and pid != 0: | |
| 710 os.kill(pid, signal.SIGUSR1) | |
| 711 print "The running instance has been updated with the new PIN." | |
| 712 return 0 | |
| 713 | 707 |
| 714 if not options.explicit_config: | 708 if options.silent: |
| 709 if not host_config_loaded or not auth_config_loaded: | |
| 710 logging.error("Failed to load host configuration.") | |
| 711 return 1 | |
| 712 else: | |
| 713 need_auth_tokens = not auth_config_loaded | |
| 714 need_register_host = not host_config_loaded | |
| 715 # Outside the loop so user doesn't get asked twice. | |
| 716 if need_register_host: | |
| 717 host.ask_pin() | |
| 718 elif options.new_pin or not host.is_pin_set(): | |
| 719 host.ask_pin() | |
| 720 host.save_config() | |
| 721 running, pid = PidFile(pid_filename).check() | |
| 722 if running and pid != 0: | |
| 723 os.kill(pid, signal.SIGUSR1) | |
| 724 print "The running instance has been updated with the new PIN." | |
| 725 return 0 | |
| 726 | |
| 715 # The loop is to deal with the case of registering a new Host with | 727 # The loop is to deal with the case of registering a new Host with |
| 716 # previously-saved auth tokens (from a previous run of this script), which | 728 # previously-saved auth tokens (from a previous run of this script), which |
| 717 # may require re-prompting for username & password. | 729 # may require re-prompting for username & password. |
| 718 while True: | 730 while True: |
| 719 try: | 731 try: |
| 720 if need_auth_tokens: | 732 if need_auth_tokens: |
| 721 auth.generate_tokens() | 733 auth.generate_tokens() |
| 722 auth.save_config() | 734 auth.save_config() |
| 723 need_auth_tokens = False | 735 need_auth_tokens = False |
| 724 except Exception: | 736 except Exception: |
| 725 logging.error("Authentication failed") | 737 logging.error("Authentication failed") |
| 726 return 1 | 738 return 1 |
| 727 | 739 |
| 728 try: | 740 try: |
| 729 if register_host: | 741 if need_register_host: |
| 730 host.register() | 742 host.register() |
| 731 host.save_config() | 743 host.save_config() |
| 732 except urllib2.HTTPError, err: | 744 except urllib2.HTTPError, err: |
| 733 if err.getcode() == 401: | 745 if err.getcode() == 401: |
| 734 # Authentication failed - re-prompt for username & password. | 746 # Authentication failed - re-prompt for username & password. |
| 735 need_auth_tokens = True | 747 need_auth_tokens = True |
| 736 continue | 748 continue |
| 737 else: | 749 else: |
| 738 # Not an authentication error. | 750 # Not an authentication error. |
| 739 logging.error("Directory returned error: " + str(err)) | 751 logging.error("Directory returned error: " + str(err)) |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 834 logging.info("Host process terminated") | 846 logging.info("Host process terminated") |
| 835 desktop.host_proc = None | 847 desktop.host_proc = None |
| 836 | 848 |
| 837 # These exit-codes must match the ones used by the host. | 849 # These exit-codes must match the ones used by the host. |
| 838 # See remoting/host/constants.h. | 850 # See remoting/host/constants.h. |
| 839 # Delete the host or auth configuration depending on the returned error | 851 # Delete the host or auth configuration depending on the returned error |
| 840 # code, so the next time this script is run, a new configuration | 852 # code, so the next time this script is run, a new configuration |
| 841 # will be created and registered. | 853 # will be created and registered. |
| 842 if os.WEXITSTATUS(status) == 2: | 854 if os.WEXITSTATUS(status) == 2: |
| 843 logging.info("Host configuration is invalid - exiting.") | 855 logging.info("Host configuration is invalid - exiting.") |
| 844 os.remove(auth.config_file) | 856 try: |
| 845 os.remove(host.config_file) | 857 os.remove(host.config_file) |
| 858 os.remove(auth.config_file) | |
| 859 except: | |
| 860 pass | |
| 846 return 0 | 861 return 0 |
| 847 elif os.WEXITSTATUS(status) == 3: | 862 elif os.WEXITSTATUS(status) == 3: |
| 848 logging.info("Host ID has been deleted - exiting.") | 863 logging.info("Host ID has been deleted - exiting.") |
| 849 os.remove(host.config_file) | 864 try: |
| 865 os.remove(host.config_file) | |
| 866 except: | |
| 867 pass | |
| 850 return 0 | 868 return 0 |
| 851 elif os.WEXITSTATUS(status) == 4: | 869 elif os.WEXITSTATUS(status) == 4: |
| 852 logging.info("OAuth credentials are invalid - exiting.") | 870 logging.info("OAuth credentials are invalid - exiting.") |
| 853 os.remove(auth.config_file) | 871 try: |
| 872 os.remove(auth.config_file) | |
| 873 except: | |
| 874 pass | |
| 854 return 0 | 875 return 0 |
| 855 | 876 |
| 856 if __name__ == "__main__": | 877 if __name__ == "__main__": |
| 857 logging.basicConfig(level=logging.DEBUG) | 878 logging.basicConfig(level=logging.DEBUG) |
| 858 sys.exit(main()) | 879 sys.exit(main()) |
| OLD | NEW |