# Copyright 2015 The Chromium OS Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import string import common from chromite.lib import gce from autotest_lib.client.common_lib import error from autotest_lib.client.common_lib import lsbrelease_utils from autotest_lib.client.cros import constants as client_constants from autotest_lib.server.hosts import abstract_ssh SSH_KEYS_METADATA_KEY = "sshKeys" def extract_arguments(args_dict): """Extract GCE-specific arguments from arguments dictionary. @param args_dict: dictionary of all arguments supplied to the test. """ return {k: v for k, v in args_dict.items() if k in ('gce_project', 'gce_instance', 'gce_zone', 'gce_key_file')} class GceHost(abstract_ssh.AbstractSSHHost): """GCE-specific subclass of Host.""" def _initialize(self, hostname, gce_args=None, *args, **dargs): """Initializes this instance of GceHost. @param hostname: the hostnname to be passed down to AbstractSSHHost. @param gce_args: GCE-specific arguments extracted using extract_arguments(). """ super(GceHost, self)._initialize(hostname=hostname, *args, **dargs) if gce_args: self._gce_project = gce_args['gce_project'] self._gce_zone = gce_args['gce_zone'] self._gce_instance = gce_args['gce_instance'] self._gce_key_file = gce_args['gce_key_file'] else: # TODO(andreyu): determine project, zone and instance names by # querying metadata from the DUT instance raise error.AutoservError('No GCE flags provided.') self.gce = gce.GceContext.ForServiceAccountThreadSafe( self._gce_project, self._gce_zone, self._gce_key_file) def _modify_ssh_keys(self, to_add, to_remove): """Modifies the list of ssh keys. @param username: user name to add. @param to_add: a list of new enties. @param to_remove: a list of enties to be removed. """ keys = self.gce.GetCommonInstanceMetadata( SSH_KEYS_METADATA_KEY) or '' key_set = set(string.split(keys, '\n')) new_key_set = (key_set | set(to_add)) - set(to_remove) if key_set != new_key_set: self.gce.SetCommonInstanceMetadata( SSH_KEYS_METADATA_KEY, string.join(list(new_key_set), '\n')) def add_ssh_key(self, username, ssh_key): """Adds a new SSH key in GCE metadata. @param username: user name to add. @param ssh_key: the key to add. """ self._modify_ssh_keys(['%s:%s' % (username, ssh_key)], []) def del_ssh_key(self, username, ssh_key): """Deletes the given SSH key from GCE metadata @param username: user name to delete. @param ssh_key: the key to delete. """ self._modify_ssh_keys([], ['%s:%s' % (username, ssh_key)]) def get_release_version(self): """Get the value of attribute CHROMEOS_RELEASE_VERSION from lsb-release. @returns The version string in lsb-release, under attribute CHROMEOS_RELEASE_VERSION. """ lsb_release_content = self.run( 'cat "%s"' % client_constants.LSB_RELEASE).stdout.strip() return lsbrelease_utils.get_chromeos_release_version( lsb_release_content=lsb_release_content) def set_instance_metadata(self, key, value): """Sets a single metadata value on the DUT instance. @param key: Metadata key to be set. @param value: New value, or None if the given key should be removed. """ self.gce.SetInstanceMetadata(self._gce_instance, key, value) def stop(self): """Stops the DUT instance """ self.gce.StopInstance(self._gce_instance) def start(self): """Starts the DUT instance """ self.gce.StartInstance(self._gce_instance)