From ef594ebf68b460745fb3152fdc733ac9335d2e33 Mon Sep 17 00:00:00 2001 From: Jerome Pansanel Date: Tue, 13 Jun 2017 21:51:48 +0200 Subject: [PATCH 1/2] Enhancement of the retrieve_image function. This enhancement permits to: * Add additional debug messages * Return true if the download is successful --- cloudkeeper_os/utils.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/cloudkeeper_os/utils.py b/cloudkeeper_os/utils.py index 3200c1a..448dc0e 100644 --- a/cloudkeeper_os/utils.py +++ b/cloudkeeper_os/utils.py @@ -22,17 +22,25 @@ import requests from requests.auth import HTTPBasicAuth -def retrieve_image(uri, filename, username=None, password=None, capath=None): +from oslo_log import log + +LOG = log.getLogger(__name__) + +def retrieve_image(uri, filename, username='', password='', capath=None): """Retrieve an image """ # TODO manage SSL case - if username and password: - auth = HTTPBasicAuth(username, password) - response = requests.get(uri, auth=auth, stream=True) - else: - response = requests.get(uri, stream=True) + LOG.info("Download image from %s" % uri) + auth = HTTPBasicAuth(username, password) + response = requests.get(uri, auth=auth, stream=True) + LOG.debug("Response: %s when accessing the image." % str(response.status_code)) if response.status_code == 200: output = open(filename, 'wb') - # response.raw.decode_content = True shutil.copyfileobj(response.raw, output) output.close() + LOG.debug("Image data successfully saved to %s" % filename) + return True + else: + # TODO raise an exception + LOG.error("Failed to download image data due to HTTP error") + return False From 696c445c1613cdf069a065a6a59204603044e04b Mon Sep 17 00:00:00 2001 From: Jerome Pansanel Date: Tue, 13 Jun 2017 22:24:26 +0200 Subject: [PATCH 2/2] Bug fix of the imagemanager module. This bug fix permits to: * have the image downloaded from nginx endpoint working * have additional debug string * deal with the case when the cloudkeeper user is not member of the project * deal with all non-string type of the appliance The code has also been verified with pylint. --- cloudkeeper_os/imagemanager.py | 65 ++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/cloudkeeper_os/imagemanager.py b/cloudkeeper_os/imagemanager.py index 739ad5d..a6dd8f2 100644 --- a/cloudkeeper_os/imagemanager.py +++ b/cloudkeeper_os/imagemanager.py @@ -31,6 +31,8 @@ CONF = cfg.CONF LOG = log.getLogger(__name__) + +APPLIANCE_INT_VALUES = ['ram', 'core', 'expiration_date'] IMAGE_ID_TAG = 'APPLIANCE_ID' IMAGE_LIST_ID_TAG = 'APPLIANCE_IMAGE_LIST_ID' @@ -52,19 +54,22 @@ def add_appliance(self, appliance): sess = keystone_client.get_session(project_name=project_name) glance = glanceclient.Client(session=sess) LOG.info('Adding appliance: ' + appliance.title) - image = appliance.image - appliance.ClearField('image') - if image.mode == 'REMOTE': + LOG.debug("Image access mode: " + "%s" % appliance.image.Mode.Name(appliance.image.mode)) + if appliance.image.Mode.Name(appliance.image.mode) == 'REMOTE': + LOG.debug("Downloading image from Cloudkeeper") filename = CONF.tempdir + '/' + str(uuid.uuid4()) kwargs = {} - kwargs['uri'] = image.location + kwargs['uri'] = appliance.image.location kwargs['filename'] = filename - if image.HasField('username') and image.HasField('password'): - kwargs['username'] = image.username - kwargs['password'] = image.password - utils.retrieve_image(**kwargs) + kwargs['username'] = appliance.image.username + kwargs['password'] = appliance.image.password + if not utils.retrieve_image(**kwargs): + return None else: - filename = image.location + filename = appliance.image.location + image_format = appliance.image.Format.Name(appliance.image.format) + appliance.ClearField('image') image_data = open(filename, 'rb') properties = {} for (descriptor, value) in appliance.ListFields(): @@ -79,13 +84,15 @@ def add_appliance(self, appliance): LOG.debug("attribute value: %s" % value) key = 'APPLIANCE_' + str.upper(descriptor.name) properties[key] = str(value) - image_format = str.lower(image.Format.Name(image.format)) + # Add property for cloud-info-provider compatibility + properties['vmcatcher_event_ad_mpuri'] = appliance.mpuri LOG.debug("Create image %s (format: %s, " - "properties %s)" % (appliance.title, image_format, + "properties %s)" % (appliance.title, + str.lower(image_format), properties) ) glance_image = glance.images.create(name=appliance.title, - disk_format=image_format, + disk_format=str.lower(image_format), container_format="bare" ) glance.images.upload(glance_image.id, image_data) @@ -132,9 +139,11 @@ def update_appliance(self, appliance): data = dict(value) value = json.dumps(data) key = 'APPLIANCE_' + str.upper(descriptor.name) - properties[key] = str(value) - LOG.debug("The appliance properties are updated with" - "these values: %s" % (properties)) + properties[key] = str(value) + # Add property for cloud-info-provider compatibility + properties['vmcatcher_event_ad_mpuri'] = appliance.mpuri + LOG.debug("Appliance properties updated with new " + "values: %s" % (properties)) glance.images.update(image_list[0]['id'], **properties) def remove_appliance(self, appliance): @@ -183,16 +192,20 @@ def update_image_list_identifiers(self, project_name=None): else: project_list = self.mapping.get_projects() for project in project_list: - sess = keystone_client.get_session(project) - glance = glanceclient.Client(session=sess) - img_generator = glance.images.list() - image_list = list(img_generator) - for image in image_list: - if IMAGE_LIST_ID_TAG in image: - if image[IMAGE_LIST_ID_TAG] not in appliances: - appliances[image[IMAGE_LIST_ID_TAG]] = [] - appliances[image[IMAGE_LIST_ID_TAG]].append(image) - self.appliances = appliances + try: + sess = keystone_client.get_session(project) + glance = glanceclient.Client(session=sess) + img_generator = glance.images.list() + image_list = list(img_generator) + for image in image_list: + if IMAGE_LIST_ID_TAG in image: + if image[IMAGE_LIST_ID_TAG] not in appliances: + appliances[image[IMAGE_LIST_ID_TAG]] = [] + appliances[image[IMAGE_LIST_ID_TAG]].append(image) + except Exception: + LOG.error("Not authorized to manage images from the " + "project: %s" % project) + self.appliances = appliances def get_appliances(self, image_list_identifier): """Return all appliances with a given image_list_identifier @@ -209,7 +222,7 @@ def get_appliances(self, image_list_identifier): else: key = 'APPLIANCE_'+str.upper(field) if key in image: - if field == 'expiration_date': + if field in APPLIANCE_INT_VALUES: properties[field] = long(image[key]) elif field == 'attributes': properties[field] = json.loads(image[key])