factory.py revision 724b8a50f34b85dda9f1990e3e8c5b68edbdb37b
1d1c2b73b7a1cbc74701ddc2b6bbbb3a162ace047Fang Deng"""Provides a factory method to create a host object.""" 2d1c2b73b7a1cbc74701ddc2b6bbbb3a162ace047Fang Deng 3d1c2b73b7a1cbc74701ddc2b6bbbb3a162ace047Fang Deng 4c5947faa755945f81537c6c33c322dccacac0adeAviv Keshetfrom autotest_lib.client.common_lib import error, global_config 5c6136e92bb5aef1acda979fd303fc855cf704434jadmanskifrom autotest_lib.server import autotest, utils as server_utils 60ca40e28b664c76d62909b1a344738dfb6f7e936Fang Dengfrom autotest_lib.server.hosts import site_factory, cros_host, ssh_host, serial 7431010f31bceddcf92f36e1b82397b9a56ffee54Simran Basifrom autotest_lib.server.hosts import adb_host, logfile_monitor 8431010f31bceddcf92f36e1b82397b9a56ffee54Simran Basi 9e48bcfb879c943df72a866e3db8b2df8e930b2c1mbligh 10d1c2b73b7a1cbc74701ddc2b6bbbb3a162ace047Fang Deng 11e48bcfb879c943df72a866e3db8b2df8e930b2c1mblighDEFAULT_FOLLOW_PATH = '/var/log/kern.log' 12e48bcfb879c943df72a866e3db8b2df8e930b2c1mblighDEFAULT_PATTERNS_PATH = 'console_patterns' 1355552bf4a54d847f2cc30b307b3636c2be2ad5a2mblighSSH_ENGINE = global_config.global_config.get_config_value('AUTOSERV', 1455552bf4a54d847f2cc30b307b3636c2be2ad5a2mbligh 'ssh_engine', 1555552bf4a54d847f2cc30b307b3636c2be2ad5a2mbligh type=str) 16d0672689266d3d63901f3a35fb7e0a2d96d6e39abeeps 17d0672689266d3d63901f3a35fb7e0a2d96d6e39abeeps# Default ssh options used in creating a host. 18d0672689266d3d63901f3a35fb7e0a2d96d6e39abeepsDEFAULT_SSH_USER = 'root' 19d0672689266d3d63901f3a35fb7e0a2d96d6e39abeepsDEFAULT_SSH_PASS = '' 20d0672689266d3d63901f3a35fb7e0a2d96d6e39abeepsDEFAULT_SSH_PORT = 22 21d0672689266d3d63901f3a35fb7e0a2d96d6e39abeepsDEFAULT_SSH_VERBOSITY = '' 22d0672689266d3d63901f3a35fb7e0a2d96d6e39abeepsDEFAULT_SSH_OPTIONS = '' 23d0672689266d3d63901f3a35fb7e0a2d96d6e39abeeps 24d60321a8b012aa6101bcb237341fab5bd2d25a04jadmanski# for tracking which hostnames have already had job_start called 25d60321a8b012aa6101bcb237341fab5bd2d25a04jadmanski_started_hostnames = set() 26d60321a8b012aa6101bcb237341fab5bd2d25a04jadmanski 27d1c2b73b7a1cbc74701ddc2b6bbbb3a162ace047Fang Deng 28d0672689266d3d63901f3a35fb7e0a2d96d6e39abeepsdef _get_host_arguments(): 29d0672689266d3d63901f3a35fb7e0a2d96d6e39abeeps """Returns parameters needed to ssh into a host. 30d0672689266d3d63901f3a35fb7e0a2d96d6e39abeeps 31d0672689266d3d63901f3a35fb7e0a2d96d6e39abeeps There are currently 2 use cases for creating a host. 32d0672689266d3d63901f3a35fb7e0a2d96d6e39abeeps 1. Through the server_job, in which case the server_job injects 33d0672689266d3d63901f3a35fb7e0a2d96d6e39abeeps the appropriate ssh parameters into our name space and they 34d0672689266d3d63901f3a35fb7e0a2d96d6e39abeeps are available as the variables ssh_user, ssh_pass etc. 35d0672689266d3d63901f3a35fb7e0a2d96d6e39abeeps 2. Directly through factory.create_host, in which case we use 36d0672689266d3d63901f3a35fb7e0a2d96d6e39abeeps the same defaults as used in the server job to create a host. 37d0672689266d3d63901f3a35fb7e0a2d96d6e39abeeps 38d0672689266d3d63901f3a35fb7e0a2d96d6e39abeeps @returns: A tuple of parameters needed to create an ssh connection, ordered 39d0672689266d3d63901f3a35fb7e0a2d96d6e39abeeps as: ssh_user, ssh_pass, ssh_port, ssh_verbosity, ssh_options. 40d0672689266d3d63901f3a35fb7e0a2d96d6e39abeeps """ 41d0672689266d3d63901f3a35fb7e0a2d96d6e39abeeps g = globals() 42d0672689266d3d63901f3a35fb7e0a2d96d6e39abeeps return (g.get('ssh_user', DEFAULT_SSH_USER), 43d0672689266d3d63901f3a35fb7e0a2d96d6e39abeeps g.get('ssh_pass', DEFAULT_SSH_PASS), 44d0672689266d3d63901f3a35fb7e0a2d96d6e39abeeps g.get('ssh_port', DEFAULT_SSH_PORT), 45d0672689266d3d63901f3a35fb7e0a2d96d6e39abeeps g.get('ssh_verbosity_flag', DEFAULT_SSH_VERBOSITY), 46d0672689266d3d63901f3a35fb7e0a2d96d6e39abeeps g.get('ssh_options', DEFAULT_SSH_OPTIONS)) 47d0672689266d3d63901f3a35fb7e0a2d96d6e39abeeps 48d0672689266d3d63901f3a35fb7e0a2d96d6e39abeeps 49724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basidef _detect_host(connectivity_class, hostname, **args): 50724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi """Detect host type. 51724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi 52724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi Currently checks if adb is on the host and if so returns ADBHost if not or 53724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi if the check fails, it will return CrosHost. 54724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi 55724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi @param connectivity_class: connectivity class to use to talk to the host 56724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi (ParamikoHost or SSHHost) 57724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi @param hostname: A string representing the host name of the device. 58724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi @param args: Args that will be passed to the constructor of 59724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi the host class. 60724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi 61724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi @returns Class type to use for this host. 62724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi """ 63724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi # Detect if adb is on the host. If so we are using an ADBHost. If not use, 64724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi # CrosHost. 65724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi try: 66724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi # Attempt to find adb on the system. If that succeeds use ADBHost. 67724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi host = connectivity_class(hostname, **args) 68724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi result = host.run('which adb', timeout=10) 69724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi return adb_host.ADBHost 70724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi except (error.AutoservRunError, error.AutoservSSHTimeout): 71724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi # If any errors occur use CrosHost. 72724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi # TODO(fdeng): this method should should dynamically discover 73724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi # and allocate host types, crbug.com/273843 74724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi # TODO crbug.com/302026 (sbasi) - adjust this pathway for ADBHost in 75724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi # the future should a host require verify/repair. 76724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi return cros_host.CrosHost 77724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi 78724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi 79e48bcfb879c943df72a866e3db8b2df8e930b2c1mblighdef create_host( 803693fc8d1136f17c47bac3e4a2faeb525301e05aDale Curtis hostname, auto_monitor=False, follow_paths=None, pattern_paths=None, 81724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi netconsole=False, **args): 82d1c2b73b7a1cbc74701ddc2b6bbbb3a162ace047Fang Deng """Create a host object. 83d1c2b73b7a1cbc74701ddc2b6bbbb3a162ace047Fang Deng 84d1c2b73b7a1cbc74701ddc2b6bbbb3a162ace047Fang Deng This method mixes host classes that are needed into a new subclass 85d1c2b73b7a1cbc74701ddc2b6bbbb3a162ace047Fang Deng and creates a instance of the new class. 86d1c2b73b7a1cbc74701ddc2b6bbbb3a162ace047Fang Deng 87d1c2b73b7a1cbc74701ddc2b6bbbb3a162ace047Fang Deng @param hostname: A string representing the host name of the device. 88d1c2b73b7a1cbc74701ddc2b6bbbb3a162ace047Fang Deng @param auto_monitor: A boolean value, if True, will try to mix 89d1c2b73b7a1cbc74701ddc2b6bbbb3a162ace047Fang Deng SerialHost in. If the host supports use as SerialHost, 90d1c2b73b7a1cbc74701ddc2b6bbbb3a162ace047Fang Deng will not mix in LogfileMonitorMixin anymore. 91d1c2b73b7a1cbc74701ddc2b6bbbb3a162ace047Fang Deng If the host doesn't support it, will 92d1c2b73b7a1cbc74701ddc2b6bbbb3a162ace047Fang Deng fall back to direct demesg logging and mix 93d1c2b73b7a1cbc74701ddc2b6bbbb3a162ace047Fang Deng LogfileMonitorMixin in. 94d1c2b73b7a1cbc74701ddc2b6bbbb3a162ace047Fang Deng @param follow_paths: A list, passed to LogfileMonitorMixin, 95d1c2b73b7a1cbc74701ddc2b6bbbb3a162ace047Fang Deng remote paths to monitor. 96d1c2b73b7a1cbc74701ddc2b6bbbb3a162ace047Fang Deng @param pattern_paths: A list, passed to LogfileMonitorMixin, 97d1c2b73b7a1cbc74701ddc2b6bbbb3a162ace047Fang Deng local paths to alert pattern definition files. 98d1c2b73b7a1cbc74701ddc2b6bbbb3a162ace047Fang Deng @param netconsole: A boolean value, if True, will mix NetconsoleHost in. 99d1c2b73b7a1cbc74701ddc2b6bbbb3a162ace047Fang Deng @param args: Args that will be passed to the constructor of 100d1c2b73b7a1cbc74701ddc2b6bbbb3a162ace047Fang Deng the new host class. 101431010f31bceddcf92f36e1b82397b9a56ffee54Simran Basi @param adb: If True creates an instance of adb_host not cros_host. 102d1c2b73b7a1cbc74701ddc2b6bbbb3a162ace047Fang Deng 103d1c2b73b7a1cbc74701ddc2b6bbbb3a162ace047Fang Deng @returns: A host object which is an instance of the newly created 104d1c2b73b7a1cbc74701ddc2b6bbbb3a162ace047Fang Deng host class. 105d1c2b73b7a1cbc74701ddc2b6bbbb3a162ace047Fang Deng """ 10696667caad23538696f737100803e68a1c1ecf357Fang Deng 107724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi ssh_user, ssh_pass, ssh_port, ssh_verbosity_flag, ssh_options = \ 108724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi _get_host_arguments() 109724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi 110724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi hostname, args['user'], args['password'], args['port'] = \ 111724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi server_utils.parse_machine(hostname, ssh_user, ssh_pass, ssh_port) 112724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi args['ssh_verbosity_flag'] = ssh_verbosity_flag 113724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi args['ssh_options'] = ssh_options 114431010f31bceddcf92f36e1b82397b9a56ffee54Simran Basi 115635b06f6c016fd5e4e14e98c471e92b1f435ac46jadmanski # by default assume we're using SSH support 11655552bf4a54d847f2cc30b307b3636c2be2ad5a2mbligh if SSH_ENGINE == 'paramiko': 11755552bf4a54d847f2cc30b307b3636c2be2ad5a2mbligh from autotest_lib.server.hosts import paramiko_host 118724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi connectivity_class = paramiko_host.ParamikoHost 11955552bf4a54d847f2cc30b307b3636c2be2ad5a2mbligh elif SSH_ENGINE == 'raw_ssh': 120724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi connectivity_class = ssh_host.SSHHost 12155552bf4a54d847f2cc30b307b3636c2be2ad5a2mbligh else: 12255552bf4a54d847f2cc30b307b3636c2be2ad5a2mbligh raise error.AutoServError("Unknown SSH engine %s. Please verify the " 12355552bf4a54d847f2cc30b307b3636c2be2ad5a2mbligh "value of the configuration key 'ssh_engine' " 12455552bf4a54d847f2cc30b307b3636c2be2ad5a2mbligh "on autotest's global_config.ini file." % 12555552bf4a54d847f2cc30b307b3636c2be2ad5a2mbligh SSH_ENGINE) 126635b06f6c016fd5e4e14e98c471e92b1f435ac46jadmanski 127724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi classes = [_detect_host(connectivity_class, hostname, **args), 128724b8a50f34b85dda9f1990e3e8c5b68edbdb37bSimran Basi connectivity_class] 129c6136e92bb5aef1acda979fd303fc855cf704434jadmanski # by default mix in run_test support 130c6136e92bb5aef1acda979fd303fc855cf704434jadmanski classes.append(autotest.AutotestHostMixin) 131c6136e92bb5aef1acda979fd303fc855cf704434jadmanski 132cb4aac7441db2fa1880d06ba57b1ab354fdbc18ajadmanski # if the user really wants to use netconsole, let them 133cb4aac7441db2fa1880d06ba57b1ab354fdbc18ajadmanski if netconsole: 134cb4aac7441db2fa1880d06ba57b1ab354fdbc18ajadmanski classes.append(netconsole.NetconsoleHost) 135cb4aac7441db2fa1880d06ba57b1ab354fdbc18ajadmanski 13654f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski if auto_monitor: 13754f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski # use serial console support if it's available 13854f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski conmux_args = {} 13954f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski for key in ("conmux_server", "conmux_attach"): 14054f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski if key in args: 14154f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski conmux_args[key] = args[key] 14254f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski if serial.SerialHost.host_is_supported(hostname, **conmux_args): 14354f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski classes.append(serial.SerialHost) 144635b06f6c016fd5e4e14e98c471e92b1f435ac46jadmanski else: 145af959a4e2909cd0013cc58d22ca4527570995319jadmanski # no serial available, fall back to direct dmesg logging 146af959a4e2909cd0013cc58d22ca4527570995319jadmanski if follow_paths is None: 147af959a4e2909cd0013cc58d22ca4527570995319jadmanski follow_paths = [DEFAULT_FOLLOW_PATH] 14854f90af69daac8a781678f0ccd42d6728d5d81d1jadmanski else: 149af959a4e2909cd0013cc58d22ca4527570995319jadmanski follow_paths = list(follow_paths) + [DEFAULT_FOLLOW_PATH] 150e48bcfb879c943df72a866e3db8b2df8e930b2c1mbligh 151af959a4e2909cd0013cc58d22ca4527570995319jadmanski if pattern_paths is None: 152af959a4e2909cd0013cc58d22ca4527570995319jadmanski pattern_paths = [DEFAULT_PATTERNS_PATH] 153af959a4e2909cd0013cc58d22ca4527570995319jadmanski else: 154af959a4e2909cd0013cc58d22ca4527570995319jadmanski pattern_paths = ( 155af959a4e2909cd0013cc58d22ca4527570995319jadmanski list(pattern_paths) + [DEFAULT_PATTERNS_PATH]) 156e48bcfb879c943df72a866e3db8b2df8e930b2c1mbligh 157af959a4e2909cd0013cc58d22ca4527570995319jadmanski logfile_monitor_class = logfile_monitor.NewLogfileMonitorMixin( 158af959a4e2909cd0013cc58d22ca4527570995319jadmanski follow_paths, pattern_paths) 159af959a4e2909cd0013cc58d22ca4527570995319jadmanski classes.append(logfile_monitor_class) 160e48bcfb879c943df72a866e3db8b2df8e930b2c1mbligh 161e48bcfb879c943df72a866e3db8b2df8e930b2c1mbligh elif follow_paths: 162e48bcfb879c943df72a866e3db8b2df8e930b2c1mbligh logfile_monitor_class = logfile_monitor.NewLogfileMonitorMixin( 163e48bcfb879c943df72a866e3db8b2df8e930b2c1mbligh follow_paths, pattern_paths) 164e48bcfb879c943df72a866e3db8b2df8e930b2c1mbligh classes.append(logfile_monitor_class) 165635b06f6c016fd5e4e14e98c471e92b1f435ac46jadmanski 166635b06f6c016fd5e4e14e98c471e92b1f435ac46jadmanski # do any site-specific processing of the classes list 167d60321a8b012aa6101bcb237341fab5bd2d25a04jadmanski site_factory.postprocess_classes(classes, hostname, 168ea90226c42c24de00839d2c68a04909b233e9a4fjadmanski auto_monitor=auto_monitor, **args) 169635b06f6c016fd5e4e14e98c471e92b1f435ac46jadmanski 170635b06f6c016fd5e4e14e98c471e92b1f435ac46jadmanski # create a custom host class for this machine and return an instance of it 171635b06f6c016fd5e4e14e98c471e92b1f435ac46jadmanski host_class = type("%s_host" % hostname, tuple(classes), {}) 172d60321a8b012aa6101bcb237341fab5bd2d25a04jadmanski host_instance = host_class(hostname, **args) 173d60321a8b012aa6101bcb237341fab5bd2d25a04jadmanski 174d60321a8b012aa6101bcb237341fab5bd2d25a04jadmanski # call job_start if this is the first time this host is being used 175d60321a8b012aa6101bcb237341fab5bd2d25a04jadmanski if hostname not in _started_hostnames: 176d60321a8b012aa6101bcb237341fab5bd2d25a04jadmanski host_instance.job_start() 177d60321a8b012aa6101bcb237341fab5bd2d25a04jadmanski _started_hostnames.add(hostname) 178d60321a8b012aa6101bcb237341fab5bd2d25a04jadmanski 179d60321a8b012aa6101bcb237341fab5bd2d25a04jadmanski return host_instance 180