From 48046310bb7afd35770a831f6b6099958736b9da Mon Sep 17 00:00:00 2001 From: jianghua wang Date: Fri, 18 Aug 2017 06:02:12 +0000 Subject: [PATCH] WIP: using stevedore to load image handler automatically. --- nova/conf/xenserver.py | 17 ++----- nova/virt/xenapi/image/glanceStore.py | 33 ++++++++++++++ nova/virt/xenapi/image/vdiStream.py | 66 +++++++++++++++++++++++++++ nova/virt/xenapi/vm_utils.py | 7 ++- nova/virt/xenapi/vmops.py | 18 +++++++- setup.cfg | 3 ++ 6 files changed, 128 insertions(+), 16 deletions(-) create mode 100644 nova/virt/xenapi/image/glanceStore.py create mode 100644 nova/virt/xenapi/image/vdiStream.py diff --git a/nova/conf/xenserver.py b/nova/conf/xenserver.py index d68c28baa5e..00657da8c0f 100644 --- a/nova/conf/xenserver.py +++ b/nova/conf/xenserver.py @@ -471,6 +471,11 @@ * ``vlan_interface`` * ``ovs_integration_bridge`` """), + cfg.StrOpt('image_glance_store', + default='', + help=""" +"""), + # TODO(dharinic): Make this, a stevedore plugin cfg.StrOpt('image_upload_handler', default='nova.virt.xenapi.image.glance.GlanceStore', @@ -484,18 +489,6 @@ store for use. image_upload_handler takes in a value for the Dom0 plugin driver. This driver is then called to uplaod images to the GlanceStore. -"""), - cfg.StrOpt('image_download_handler', - default='nova.virt.xenapi.image.glance.GlanceStore', - help=""" -The plugin driver used to handle image downloads. - -Provide a string value representing a plugin driver required to -handle the image downloading from Glance. - -Images from Glance need to be downloaded to XenServer and create -disk from the image. This driver is called to download images and -create disk. """), ] diff --git a/nova/virt/xenapi/image/glanceStore.py b/nova/virt/xenapi/image/glanceStore.py new file mode 100644 index 00000000000..988a4c33a9e --- /dev/null +++ b/nova/virt/xenapi/image/glanceStore.py @@ -0,0 +1,33 @@ +# Copyright 2017 Citrix Systems +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import abc + +import six + + +@six.add_metaclass(abc.ABCMeta) +class glanceStore(object): + """Base class for glance store used to upload/download images. + """ + + @abc.abstractmethod + def download_image(self, context, session, instance, image_id): + """Download image from glance and create disk from image. + """ + + @abc.abstractmethod + def upload_image(self, context, session, instance, image_id, vdi_uuids): + """create image from disk and upload to glance. + """ diff --git a/nova/virt/xenapi/image/vdiStream.py b/nova/virt/xenapi/image/vdiStream.py new file mode 100644 index 00000000000..d88d8474789 --- /dev/null +++ b/nova/virt/xenapi/image/vdiStream.py @@ -0,0 +1,66 @@ +# Copyright 2016 Citrix Systems +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +""" This class will handle image data in a streaming way. +""" + + +from os_xenapi.client import exception as xenapi_exception +from os_xenapi.client.image import vdi_handler +from oslo_log import log as logging + +import nova.conf +from nova import exception +from nova import image +from nova.virt.xenapi.image.glanceStore import glanceStore +from nova.virt.xenapi.image import utils + +CONF = nova.conf.CONF +LOG = logging.getLogger(__name__) + +IMAGE_API = image.API() + + +class vdiStream(glanceStore): + def download_image(self, context, session, instance, image_id): + LOG.debug("in vdiStream.download_image") + try: + host_url = CONF.xenserver.connection_url + image_data = IMAGE_API.download(context, image_id) + image_stream = utils.IterableToFileAdapter(image_data) + vdis = vdi_handler.stream_to_vdis(context, session, + instance, host_url, + data=image_stream) + except xenapi_exception.OsXenApiException: + raise exception.CouldNotFetchImage(image_id=image_id) + return vdis + + def upload_image(self, context, session, instance, image_id, vdi_uuids): + try: + host_url = CONF.xenserver.connection_url + metadata = IMAGE_API.get(context, image_id) + metadata['disk_format'] = 'vhd' + metadata['container_format'] = "ovf" + # set size as zero, so that it will update the size in end basing + # on the uploaded data. + metadata['size'] = 0 + image_trunks = vdi_handler.vdis_to_stream(context, session, + instance, host_url, + vdi_uuids) + image_stream = utils.IterableToFileAdapter(image_trunks) + IMAGE_API.update(context, image_id, metadata, + data=image_stream) + except xenapi_exception.OsXenApiException: + raise exception.CouldNotUploadImage(image_id=image_id) diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index 08a0a9ab040..84b4bea2c7e 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -22,6 +22,7 @@ import contextlib import math import os +import stevedore import time import urllib from xml.dom import minidom @@ -1357,8 +1358,10 @@ def _fetch_vhd_image(context, session, instance, image_id): LOG.debug("Asking xapi to fetch vhd image %s", image_id, instance=instance) - handler = importutils.import_object( - CONF.xenserver.image_download_handler) + handler = stevedore.driver.DriverManager( + "xenapi.image.glance_store", + CONF.xenserver.image_glance_store, + invoke_on_load=True).driver try: vdis = handler.download_image(context, session, instance, image_id) diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index e1247bf3099..2aeee7a9d98 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -19,6 +19,7 @@ import base64 import functools +import stevedore import time import zlib @@ -38,6 +39,7 @@ from oslo_utils import units import six +from nova.i18n import _LW from nova import block_device from nova import compute from nova.compute import power_state @@ -152,8 +154,20 @@ def __init__(self, session, virtapi): LOG.debug("Importing image upload handler: %s", CONF.xenserver.image_upload_handler) - self.image_upload_handler = importutils.import_object( - CONF.xenserver.image_upload_handler) + + handler = CONF.xenserver.image_upload_handler + try: + self.image_upload_handler = stevedore.driver.DriverManager( + "xenapi.image.glance_store", handler, + invoke_on_load=True).driver + except stevedore.exception.NoMatches: + self.image_upload_handler = importutils.import_object( + handler) + LOG.warning(_LW("DEPRECATED: image_upload_handler uses " + "importutils to load %(path)s. This " + "legacy loading style will be removed " + "in the next release."), + {'path': handler}) def agent_enabled(self, instance): if CONF.xenserver.disable_agent: diff --git a/setup.cfg b/setup.cfg index b02cec4f376..e839f96e530 100644 --- a/setup.cfg +++ b/setup.cfg @@ -27,6 +27,9 @@ packages = nova [entry_points] +xenapi.image.glance_store = + vdi_stream = nova.virt.xenapi.image.vdiStream:vdiStream + oslo.config.opts = nova.conf = nova.conf.opts:list_opts