nfv/nfv/nfv-plugins/nfv_plugins/nfvi_plugins/nfvi_image_api.py

602 lines
21 KiB
Python
Executable File

#
# Copyright (c) 2015-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
import httplib
from nfv_common import debug
from nfv_vim import nfvi
from nfv_vim.nfvi.objects import v1 as nfvi_objs
from nfv_plugins.nfvi_plugins import config
from nfv_plugins.nfvi_plugins.openstack import exceptions
from nfv_plugins.nfvi_plugins.openstack import openstack
from nfv_plugins.nfvi_plugins.openstack import glance
from nfv_plugins.nfvi_plugins.openstack.objects import OPENSTACK_SERVICE
DLOG = debug.debug_get_logger('nfv_plugins.nfvi_plugins.image_api')
def image_get_avail_status(status):
"""
Convert the nfvi image status to an image availability status
"""
avail_status = list()
if glance.IMAGE_STATUS.DELETED == status:
avail_status.append(nfvi_objs.IMAGE_AVAIL_STATUS.DELETED)
elif glance.IMAGE_STATUS.ACTIVE == status:
avail_status.append(nfvi_objs.IMAGE_AVAIL_STATUS.AVAILABLE)
return avail_status
def image_get_action(status):
"""
Convert the nfvi image status to an image action
"""
if glance.IMAGE_STATUS.PENDING_DELETE == status:
return nfvi_objs.IMAGE_ACTION.DELETING
elif glance.IMAGE_STATUS.SAVING == status:
return nfvi_objs.IMAGE_ACTION.SAVING
else:
return nfvi_objs.IMAGE_ACTION.NONE
class NFVIImageAPI(nfvi.api.v1.NFVIImageAPI):
"""
NFVI Image API Class Definition
"""
_name = 'Image-API'
_version = '1.0.0'
_provider = 'Wind River'
_signature = '22b3dbf6-e4ba-441b-8797-fb8a51210a43'
def __init__(self):
super(NFVIImageAPI, self).__init__()
self._token = None
self._directory = None
@property
def name(self):
return self._name
@property
def version(self):
return self._version
@property
def provider(self):
return self._provider
@property
def signature(self):
return self._signature
def get_images(self, future, paging, callback):
"""
Get a list of images
"""
response = dict()
response['completed'] = False
response['reason'] = ''
response['page-request-id'] = paging.page_request_id
try:
future.set_timeouts(config.CONF.get('nfvi-timeouts', None))
if self._directory.get_service_info(OPENSTACK_SERVICE.GLANCE) \
is None:
DLOG.info("Glance service get-images not available.")
response['result-data'] = list()
response['completed'] = True
paging.next_page = None
return
if self._token is None or self._token.is_expired():
future.work(openstack.get_token, self._directory)
future.result = (yield)
if not future.result.is_complete():
return
self._token = future.result.data
DLOG.verbose("Image paging (before): %s" % paging)
future.work(glance.get_images, self._token, paging.page_limit,
paging.next_page)
future.result = (yield)
if not future.result.is_complete():
return
image_data_list = future.result.data
image_objs = list()
for image_data in image_data_list['images']:
description = image_data.get('description', "")
avail_status = image_get_avail_status(image_data['status'])
action = image_get_action(image_data['status'])
if description is None:
description = ""
if image_data['protected']:
protected = 'yes'
else:
protected = 'no'
properties = dict()
sw_wrs_auto_recovery = image_data.get(
nfvi_objs.IMAGE_PROPERTY.INSTANCE_AUTO_RECOVERY, None)
if sw_wrs_auto_recovery is not None:
if 'false' == sw_wrs_auto_recovery.lower():
properties[
nfvi_objs.IMAGE_PROPERTY.INSTANCE_AUTO_RECOVERY] \
= False
elif 'true' == sw_wrs_auto_recovery.lower():
properties[
nfvi_objs.IMAGE_PROPERTY.INSTANCE_AUTO_RECOVERY] \
= True
else:
raise AttributeError("sw_wrs_auto_recovery is %s, "
"expecting 'true' or 'false'"
% sw_wrs_auto_recovery)
properties[nfvi_objs.IMAGE_PROPERTY.LIVE_MIGRATION_TIMEOUT] \
= image_data.get(
nfvi_objs.IMAGE_PROPERTY.LIVE_MIGRATION_TIMEOUT, None)
properties[
nfvi_objs.IMAGE_PROPERTY.LIVE_MIGRATION_MAX_DOWNTIME] \
= image_data.get(
nfvi_objs.IMAGE_PROPERTY.LIVE_MIGRATION_MAX_DOWNTIME, None)
image_obj = nfvi_objs.Image(
image_data['id'], image_data['name'], description,
avail_status, action, image_data['container_format'],
image_data['disk_format'], image_data['min_disk'],
image_data['min_ram'], image_data['visibility'], protected,
properties)
image_objs.append(image_obj)
paging.next_page = image_data_list.get('next', None)
DLOG.verbose("Image paging (after): %s" % paging)
response['result-data'] = image_objs
response['completed'] = True
except exceptions.OpenStackRestAPIException as e:
if httplib.UNAUTHORIZED == e.http_status_code:
response['error-code'] = nfvi.NFVI_ERROR_CODE.TOKEN_EXPIRED
if self._token is not None:
self._token.set_expired()
else:
DLOG.exception("Caught exception while trying to get image "
"list, error=%s." % e)
except Exception as e:
DLOG.exception("Caught exception while trying to get image list, "
"error=%s." % e)
finally:
callback.send(response)
callback.close()
def create_image(self, future, image_name, image_description,
image_attributes, image_data_url, callback):
"""
Create an image
"""
response = dict()
response['completed'] = False
response['reason'] = ''
try:
future.set_timeouts(config.CONF.get('nfvi-timeouts', None))
if self._token is None or self._token.is_expired():
future.work(openstack.get_token, self._directory)
future.result = (yield)
if not future.result.is_complete():
return
self._token = future.result.data
future.work(glance.create_image, self._token, image_name,
image_description, image_attributes.container_format,
image_attributes.disk_format,
image_attributes.min_disk_size_gb,
image_attributes.min_memory_size_mb,
image_attributes.visibility,
image_attributes.protected,
image_attributes.properties)
future.result = (yield)
if not future.result.is_complete():
return
image_data = future.result.data
if image_data_url.startswith('file://'):
image_file = image_data_url[6:]
future.work(glance.upload_image_data_by_file, self._token,
image_data['id'], image_file)
else:
future.work(glance.upload_image_data_by_url, self._token,
image_data['id'], image_data_url)
future.result = (yield)
if not future.result.is_complete():
return
future.work(glance.get_image, self._token, image_data['id'])
future.result = (yield)
if not future.result.is_complete():
return
image_data = future.result.data
description = image_data.get('description', "")
avail_status = image_get_avail_status(image_data['status'])
action = image_get_action(image_data['status'])
if description is None:
description = ""
if image_data['protected']:
protected = 'yes'
else:
protected = 'no'
properties = dict()
sw_wrs_auto_recovery = image_data.get(
nfvi_objs.IMAGE_PROPERTY.INSTANCE_AUTO_RECOVERY, None)
if sw_wrs_auto_recovery is not None:
if 'false' == sw_wrs_auto_recovery.lower():
properties[
nfvi_objs.IMAGE_PROPERTY.INSTANCE_AUTO_RECOVERY] \
= False
elif 'true' == sw_wrs_auto_recovery.lower():
properties[
nfvi_objs.IMAGE_PROPERTY.INSTANCE_AUTO_RECOVERY] \
= True
else:
raise AttributeError("sw_wrs_auto_recovery is %s, "
"expecting 'True' or 'False'"
% sw_wrs_auto_recovery)
properties[nfvi_objs.IMAGE_PROPERTY.INSTANCE_AUTO_RECOVERY] \
= image_data.get(
nfvi_objs.IMAGE_PROPERTY.INSTANCE_AUTO_RECOVERY, None)
properties[nfvi_objs.IMAGE_PROPERTY.LIVE_MIGRATION_TIMEOUT] \
= image_data.get(
nfvi_objs.IMAGE_PROPERTY.LIVE_MIGRATION_TIMEOUT, None)
properties[nfvi_objs.IMAGE_PROPERTY.LIVE_MIGRATION_MAX_DOWNTIME] \
= image_data.get(
nfvi_objs.IMAGE_PROPERTY.LIVE_MIGRATION_MAX_DOWNTIME, None)
image_obj = nfvi_objs.Image(
image_data['id'], image_data['name'], description,
avail_status, action, image_data['container_format'],
image_data['disk_format'], image_data['min_disk'],
image_data['min_ram'], image_data['visibility'], protected,
properties)
response['result-data'] = image_obj
response['completed'] = True
except exceptions.OpenStackRestAPIException as e:
if httplib.UNAUTHORIZED == e.http_status_code:
response['error-code'] = nfvi.NFVI_ERROR_CODE.TOKEN_EXPIRED
if self._token is not None:
self._token.set_expired()
else:
DLOG.exception("Caught exception while trying to create an "
"image, error=%s." % e)
except Exception as e:
DLOG.exception("Caught exception while trying to create an image, "
"error=%s." % e)
finally:
callback.send(response)
callback.close()
def delete_image(self, future, image_uuid, callback):
"""
Delete an image
"""
response = dict()
response['completed'] = False
response['reason'] = ''
try:
future.set_timeouts(config.CONF.get('nfvi-timeouts', None))
if self._token is None or self._token.is_expired():
future.work(openstack.get_token, self._directory)
future.result = (yield)
if not future.result.is_complete():
return
self._token = future.result.data
future.work(glance.delete_image, self._token, image_uuid)
future.result = (yield)
if not future.result.is_complete():
return
response['completed'] = True
except exceptions.OpenStackRestAPIException as e:
if httplib.UNAUTHORIZED == e.http_status_code:
response['error-code'] = nfvi.NFVI_ERROR_CODE.TOKEN_EXPIRED
if self._token is not None:
self._token.set_expired()
elif httplib.NOT_FOUND == e.http_status_code:
response['completed'] = True
else:
DLOG.exception("Caught exception while trying to delete an "
"image, error=%s." % e)
except Exception as e:
DLOG.exception("Caught exception while trying to delete an image, "
"error=%s." % e)
finally:
callback.send(response)
callback.close()
def update_image(self, future, image_uuid, image_description,
image_attributes, callback):
"""
Update an image
"""
response = dict()
response['completed'] = False
response['reason'] = ''
try:
future.set_timeouts(config.CONF.get('nfvi-timeouts', None))
if self._token is None or self._token.is_expired():
future.work(openstack.get_token, self._directory)
future.result = (yield)
if not future.result.is_complete():
return
self._token = future.result.data
future.work(glance.update_image, self._token, image_uuid,
image_description,
image_attributes.min_disk_size_gb,
image_attributes.min_memory_size_mb,
image_attributes.visibility,
image_attributes.protected,
image_attributes.properties)
future.result = (yield)
if not future.result.is_complete():
return
future.work(glance.get_image, self._token, image_uuid)
future.result = (yield)
if not future.result.is_complete():
return
image_data = future.result.data
description = image_data.get('description', "")
avail_status = image_get_avail_status(image_data['status'])
action = image_get_action(image_data['status'])
if description is None:
description = ""
if image_data['protected']:
protected = 'yes'
else:
protected = 'no'
properties = dict()
sw_wrs_auto_recovery = image_data.get(
nfvi_objs.IMAGE_PROPERTY.INSTANCE_AUTO_RECOVERY, None)
if sw_wrs_auto_recovery is not None:
if 'false' == sw_wrs_auto_recovery.lower():
properties[
nfvi_objs.IMAGE_PROPERTY.INSTANCE_AUTO_RECOVERY] \
= False
elif 'true' == sw_wrs_auto_recovery.lower():
properties[
nfvi_objs.IMAGE_PROPERTY.INSTANCE_AUTO_RECOVERY] \
= True
else:
raise AttributeError("sw_wrs_auto_recovery is %s, "
"expecting 'True' or 'False'"
% sw_wrs_auto_recovery)
properties[nfvi_objs.IMAGE_PROPERTY.INSTANCE_AUTO_RECOVERY] \
= image_data.get(
nfvi_objs.IMAGE_PROPERTY.INSTANCE_AUTO_RECOVERY, None)
properties[nfvi_objs.IMAGE_PROPERTY.LIVE_MIGRATION_TIMEOUT] \
= image_data.get(
nfvi_objs.IMAGE_PROPERTY.LIVE_MIGRATION_TIMEOUT, None)
properties[nfvi_objs.IMAGE_PROPERTY.LIVE_MIGRATION_MAX_DOWNTIME] \
= image_data.get(
nfvi_objs.IMAGE_PROPERTY.LIVE_MIGRATION_MAX_DOWNTIME, None)
image_obj = nfvi_objs.Image(
image_data['id'], image_data['name'], description,
avail_status, action, image_data['container_format'],
image_data['disk_format'], image_data['min_disk'],
image_data['min_ram'], image_data['visibility'], protected,
properties)
response['result-data'] = image_obj
response['completed'] = True
except exceptions.OpenStackRestAPIException as e:
if httplib.UNAUTHORIZED == e.http_status_code:
response['error-code'] = nfvi.NFVI_ERROR_CODE.TOKEN_EXPIRED
if self._token is not None:
self._token.set_expired()
else:
DLOG.exception("Caught exception while trying to update image "
"data, error=%s." % e)
except Exception as e:
DLOG.exception("Caught exception while trying to update image "
"data, error=%s." % e)
finally:
callback.send(response)
callback.close()
def get_image(self, future, image_uuid, callback):
"""
Get an image
"""
response = dict()
response['completed'] = False
response['reason'] = ''
try:
future.set_timeouts(config.CONF.get('nfvi-timeouts', None))
if self._token is None or self._token.is_expired():
future.work(openstack.get_token, self._directory)
future.result = (yield)
if not future.result.is_complete():
return
self._token = future.result.data
future.work(glance.get_image, self._token, image_uuid)
future.result = (yield)
if not future.result.is_complete():
return
image_data = future.result.data
description = image_data.get('description', "")
avail_status = image_get_avail_status(image_data['status'])
action = image_get_action(image_data['status'])
properties = dict()
sw_wrs_auto_recovery = image_data.get(
nfvi_objs.IMAGE_PROPERTY.INSTANCE_AUTO_RECOVERY, None)
if sw_wrs_auto_recovery is not None:
if 'false' == sw_wrs_auto_recovery.lower():
properties[
nfvi_objs.IMAGE_PROPERTY.INSTANCE_AUTO_RECOVERY] \
= False
elif 'true' == sw_wrs_auto_recovery.lower():
properties[
nfvi_objs.IMAGE_PROPERTY.INSTANCE_AUTO_RECOVERY] \
= True
else:
raise AttributeError("sw_wrs_auto_recovery is %s, "
"expecting 'True' or 'False'"
% sw_wrs_auto_recovery)
properties[nfvi_objs.IMAGE_PROPERTY.LIVE_MIGRATION_TIMEOUT] \
= image_data.get(
nfvi_objs.IMAGE_PROPERTY.LIVE_MIGRATION_TIMEOUT, None)
properties[nfvi_objs.IMAGE_PROPERTY.LIVE_MIGRATION_MAX_DOWNTIME] \
= image_data.get(
nfvi_objs.IMAGE_PROPERTY.LIVE_MIGRATION_MAX_DOWNTIME, None)
if description is None:
description = ""
if image_data['protected']:
protected = 'yes'
else:
protected = 'no'
image_obj = nfvi_objs.Image(
image_data['id'], image_data['name'], description,
avail_status, action, image_data['container_format'],
image_data['disk_format'], image_data['min_disk'],
image_data['min_ram'], image_data['visibility'], protected,
properties)
response['result-data'] = image_obj
response['completed'] = True
except exceptions.OpenStackRestAPIException as e:
if httplib.UNAUTHORIZED == e.http_status_code:
response['error-code'] = nfvi.NFVI_ERROR_CODE.TOKEN_EXPIRED
if self._token is not None:
self._token.set_expired()
elif httplib.NOT_FOUND == e.http_status_code:
response['error-code'] = nfvi.NFVI_ERROR_CODE.NOT_FOUND
else:
DLOG.exception("Caught exception while trying to get an "
"image, error=%s." % e)
except Exception as e:
DLOG.exception("Caught exception while trying to get an image, "
"error=%s." % e)
finally:
callback.send(response)
callback.close()
def initialize(self, config_file):
"""
Initialize the plugin
"""
config.load(config_file)
self._directory = openstack.get_directory(
config, openstack.SERVICE_CATEGORY.OPENSTACK)
def finalize(self):
"""
Finalize the plugin
"""
return