def tag_image(self, image_name): """Associate image tags with image""" LOGGER.info('Set image labels.') # Get current labels fingerprint. To avoid/detect conflicts, you must # provide the current label fingerprint (reference) when you request to # set image labels. This fingerprint value is updated whenever labels # are updated and the set labels request will fail if the labels were # updated out of band. try: # pylint: disable=no-member request = self.gce_service.images().get( project=self.gce_project_id, image=image_name) result = request.execute() label_fingerprint = result['labelFingerprint'] except HttpError as exp: LOGGER.error("Exception setting image labels:") LOGGER.exception(exp) return False if not result: return False if label_fingerprint is None or label_fingerprint == '': LOGGER.info('Label fingerprint was empty.') return False cloud_image_tags = CloudImageTags(self.metadata) cloud_image_tags.transform_values(to_lower=True, disallowed_regex='[^a-z0-9-]') image_labels = cloud_image_tags.get() set_labels_body = { "labels": image_labels, "labelFingerprint": label_fingerprint } try: # pylint: disable=no-member request = self.gce_service.images().setLabels( project=self.gce_project_id, resource=image_name, body=set_labels_body) result = request.execute() except HttpError as exp: LOGGER.error("Exception setting image labels:") LOGGER.exception(exp) return False if not result: return False LOGGER.debug("Image set labels response: %s", result) return True
def get_image_tag_metadata(self): """Returns associated image metadata tags through the member variable metadata.""" metadata_tags = CloudImageTags(self.metadata) return metadata_tags.get()
def _get_tags(self): tags = CloudImageTags(self.metadata) tags.title_case_keys() return tags.get()
def create_image(self, image_name): """ Create image implementation for Alibaba """ images_json = self.client.describe_images(None, image_name) if int(images_json['TotalCount']) == 0: LOGGER.debug('No old images named \'%s\' were found', image_name) else: # image names are unique, delete only one image image_id = images_json['Images']['Image'][0]['ImageId'] LOGGER.info('Image \'%s\' already exists, its id is \'%s\', deleting it', image_name, image_id) self.client.delete_image(image_id) # start image creation LOGGER.info('Started creation of image \'%s\' at %s', image_name, datetime.datetime.now().strftime('%H:%M:%S')) start_time = time() imported_image = self.client.import_image(get_config_value('ALIBABA_BUCKET'), self.disk.uploaded_disk_name, image_name) if 'Code' in imported_image.keys(): if imported_image['Code'] == 'InvalidOSSObject.NotFound': raise RuntimeError('ImportImageRequest could not find uloaded disk \'' + image_name + '\'') if imported_image['Code'] == 'InvalidImageName.Duplicated': raise RuntimeError('Image \'' + image_name + '\' still exists, ' + 'should have been removed by this point') if imported_image['Code'] == 'ImageIsImporting': raise RuntimeError('Another image named \'' + image_name + '\' is in the ' + 'process of importing, probably from the previous run. ' + 'Delete it first.') if 'ImageId' not in imported_image.keys() or 'TaskId' not in imported_image.keys(): LOGGER.info('Alibaba response to ImportImageRequest:') LOGGER.info(json.dumps(imported_image, sort_keys=True, indent=4, separators=(',', ': '))) raise RuntimeError('ImageId and/or TaskId were not found in the response ' + 'cannot initiate image import') self.image_id = imported_image['ImageId'] task_id = imported_image['TaskId'] LOGGER.info('Started image import with image id \'%s\' and task id \'%s\'', self.image_id, task_id) task_status_count = int(get_config_value('ALIBABA_IMAGE_IMPORT_MONITOR_RETRY_COUNT')) task_status_delay = int(get_config_value('ALIBABA_IMAGE_IMPORT_MONITOR_RETRY_DELAY')) if self.monitor_task(task_id, task_status_count, task_status_delay): LOGGER.info('Image \'%s\' imported after %d seconds', self.image_id, time() - start_time) else: canceled_task_msg = 'Image import failed or took too long, ' + \ 'canceling task \'{}\' and '.format(task_id) + \ 'deleting image \'{}\''.format(self.image_id) LOGGER.info(canceled_task_msg) self.client.cancel_task(task_id) self.client.delete_image(self.image_id) raise RuntimeError('Failed to import image \'{}\' after monitoring it for {} retries'. format(self.image_id, task_status_count)) # Add image_id and location (region) to the metadata used for image registration metadata = CloudImageMetadata() metadata.set(self.__class__.__name__, 'image_id', self.image_id) metadata.set(self.__class__.__name__, 'location', get_config_value('ALIBABA_REGION')) # Add tags to image LOGGER.info('Add tags to image \'%s\'', self.image_id) self.client.add_tags(self.image_id, 'image', CloudImageTags(metadata).get()) # Add tags to associated snapshot images_json = self.client.describe_images(self.image_id, None) if not 'Images' in images_json.keys(): LOGGER.error('No image data found for image \'%s\'', self.image_id) LOGGER.error('Unable to tag snapshot.') else: snapshot_id = images_json['Images']['Image'][0] \ ['DiskDeviceMappings']['DiskDeviceMapping'][0]['SnapshotId'] LOGGER.info('Add tags to snapshot \'%s\'', snapshot_id) self.client.add_tags(snapshot_id, 'snapshot', CloudImageTags(metadata).get())
def get_snapshot_tag_metadata(self): """Returns associated snapshot metadata tags.""" metadata_tags = CloudImageTags(self.metadata) return metadata_tags.get()