def __init__(self, apiv='v1'): self.apiv = apiv # GCE also has a deprecated API "0.1" but we always want to use # the "computeMetadata" API self.api = 'computeMetadata' self.data_categories = ['project/', 'instance/'] self.default_disk_id = '0' self.default_license_id = '0' self.default_net_dev_id = '0' self.default_subnet_id = '0' self.disk_data_shown = [] self.disk_dev_id = -1 self.header = {'Metadata-Flavor': 'Google'} self.identity_arg = None self.identity_format = 'standard' self.license_data_shown = [] self.license_id = -1 self.net_data_shown = [] self.net_dev_id = -1 self.options = {} self.query_disk_data = False self.query_license_data = False self.query_net_data = False self.server = 'metadata.google.internal' self.subnet_id = -1 if not self._test_connectivity(self.server, 80): msg = 'Could not connect to: %s' % self.server raise GCEMetadataException(msg) if apiv not in self.get_available_api_versions(): msg = 'Given API version "%s" not available' % apiv raise GCEMetadataException(msg) self._create_options_map()
def set_subnet(self, subnet_id): """Set the subnet ID for this query""" if self.net_dev_id == -1: msg = 'When specifying the subnet the network device to query ' msg += 'must also be specified with "--netid"' raise GCEMetadataException(msg) self.subnet_id = subnet_id self.query_net_data = True self.net_data_shown = []
def _open_file(path): """Open a file for the given path""" fout = None try: fout = open(path, 'w') except: msg = 'Unable to open file "%s" for writing' % path raise GCEMetadataException(msg) return fout
def set_api_version(self, apiv): """Set the API Version to use for the query""" known_api_versions = self.get_available_api_versions() if apiv not in known_api_versions: msg = 'Specififed api version "%s" not available ' % apiv msg += 'must be one of %s' % known_api_versions raise GCEMetadataException(msg) self.apiv = apiv
def set_net_device(self, net_dev_id): """Set the network device ID to query""" known_ids = self._get_item_id_list('network-interfaces') if net_dev_id not in known_ids: msg = 'Requested device "%s" not available for ' % net_dev_id msg += 'query. Available network interfaces: %s' % known_ids raise GCEMetadataException(msg) self.net_dev_id = net_dev_id self.query_net_data = True self.net_data_shown = []
def set_disk_device(self, disk_id): """Set the disk device ID to query""" known_disk_ids = self._get_item_id_list('disks') if disk_id not in known_disk_ids: msg = 'Requested device "%s" not available for query. ' % disk_id msg += 'Available disks: %s' % known_disk_ids raise GCEMetadataException(msg) self.disk_dev_id = disk_id self.query_disk_data = True self.disk_data_shown = []
def set_license_id(self, license_id): """Set the id for the license to query""" known_ids = self._get_item_id_list('licenses') if license_id not in known_ids: msg = 'Requested license "%s" ' % license_id msg += 'not available for query. ' msg += 'Available license: %s' % known_ids raise GCEMetadataException(msg) self.license_id = license_id self.query_license_data = True self.license_data_shown = []
def set_data_category(self, category): """Set the data category for this query""" if category[-1] != '/': category = category + '/' if category not in self.data_categories: msg = 'Query option "%s" invalid, must be ' % category msg += 'one of %s' % self.data_categories raise GCEMetadataException(msg) self.query_category = category return 1
def get(self, option): """Get the data for the specified option""" option_map = self._gen_flat_option_list() if option not in option_map: return None if (option == 'disks' or option == 'network-interfaces' or option == 'licenses'): return self._get_item_id_list(option) path = None # Top level accessors and lower level accessors are not necessarily # unique, for example "id" is used for license and for instance id. # Thus we need to differentiate what the user is looking for. When # querying for a path that has suboptions such as disks, licenses, # and network interfaces we give preference to the sub options if # --diskid --licenseid or --netid where specifid. However we also # need to account for the usecase where the user may want both, # thus we need to keep track of the options already shown. if ((self.query_disk_data or self.query_license_data or self.query_net_data) and (option not in self.disk_data_shown and option not in self.license_data_shown and option not in self.net_data_shown)): path = self._get_path_from_suboption(option) if isinstance(path, dict): values = '' for key, uri in path.items(): values += self._get(self._build_full_url(uri + key)) return values if not path: path = self.options[self.query_category].get(option, None) # Try the sub options again as the user may have specified a unique # suboption identifier such as --disk-name that we can find without # special handling if not path: path = self._get_path_from_suboption(option) if not path: msg = 'No query path for option "%s", please file a bug' % option raise GCEMetadataException(msg) path += option + self._add_arguments(option) return self._get(self._build_full_url(path))
def _write(file_path, data): """Write the data to the given file""" fout = None close_file = False if type(file_path) is str: fout = _open_file(file_path) close_file = True elif isinstance(file_path, IOBase): if file_path.closed: fout = _open_file(file_path.name) close_file = True else: fout = file_path try: fout.write(data) except: if close_file: fout.close() msg = 'Unable to write to file "%s"' % fout.name raise GCEMetadataException(msg) if close_file: fout.close()