From 1dea34fa1ab15ef2bef9811ef585c8b3bf5c0d22 Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Fri, 29 Jun 2012 21:26:42 +0000 Subject: [PATCH] Refactoring code to kernel Dom0 plugin. The kernel and ramdisk VDI manipulation code really has nothing to do with Glance so it doesn't make a lot of sense for it to exist in the Glance Dom0 plugin. This patch refactors the code out to its own plugin and then applies a few misc cleanups. Change-Id: I363d54ea3c2d51aa6a6c1635b4fb59ebb9ce1fc0 --- nova/virt/xenapi/fake.py | 8 +- nova/virt/xenapi/vm_utils.py | 17 ++- nova/virt/xenapi/vmops.py | 15 +-- .../rpmbuild/SPECS/openstack-xen-plugins.spec | 1 + .../xenapi/etc/xapi.d/plugins/glance | 86 +----------- .../xenapi/etc/xapi.d/plugins/kernel | 123 ++++++++++++++++++ 6 files changed, 146 insertions(+), 104 deletions(-) create mode 100755 plugins/xenserver/xenapi/etc/xapi.d/plugins/kernel diff --git a/nova/virt/xenapi/fake.py b/nova/virt/xenapi/fake.py index 081d3c89ed25..5df0c2aead5b 100644 --- a/nova/virt/xenapi/fake.py +++ b/nova/virt/xenapi/fake.py @@ -498,13 +498,13 @@ class SessionBase(object): return as_json(returncode='0', message='success') elif (plugin, method) == ('agent', 'resetnetwork'): return as_json(returncode='0', message='success') - elif (plugin, method) == ('glance', 'copy_kernel_vdi'): - return '' elif (plugin, method) == ('glance', 'upload_vhd'): return '' - elif (plugin, method) == ('glance', 'create_kernel_ramdisk'): + elif (plugin, method) == ('kernel', 'copy_vdi'): return '' - elif (plugin, method) == ('glance', 'remove_kernel_ramdisk'): + elif (plugin, method) == ('kernel', 'create_kernel_ramdisk'): + return '' + elif (plugin, method) == ('kernel', 'remove_kernel_ramdisk'): return '' elif (plugin, method) == ('migration', 'move_vhds_into_sr'): return '' diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index cbc7a70ce5c1..9c7399606935 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -600,8 +600,8 @@ def create_kernel_image(context, session, instance, image_id, user_id, args = {} args['cached-image'] = image_id args['new-image-uuid'] = str(uuid.uuid4()) - filename = session.call_plugin('glance', 'create_kernel_ramdisk', - args) + filename = session.call_plugin( + 'kernel', 'create_kernel_ramdisk', args) if filename == "": return _fetch_image(context, session, instance, image_id, image_type) @@ -610,6 +610,15 @@ def create_kernel_image(context, session, instance, image_id, user_id, return {vdi_type: dict(uuid=None, file=filename)} +def destroy_kernel_ramdisk(session, kernel, ramdisk): + args = {} + if kernel: + args['kernel-file'] = kernel + if ramdisk: + args['ramdisk-file'] = ramdisk + session.call_plugin('kernel', 'remove_kernel_ramdisk', args) + + def _create_cached_image(context, session, instance, image_id, image_type): sr_ref = safe_find_sr(session) sr_type = session.call_xenapi('SR.get_record', sr_ref)["type"] @@ -904,7 +913,7 @@ def _fetch_disk_image(context, session, instance, image_id, image_type): # content of the VDI into the proper path. LOG.debug(_("Copying VDI %s to /boot/guest on dom0"), vdi_ref, instance=instance) - fn = "copy_kernel_vdi" + args = {} args['vdi-ref'] = vdi_ref @@ -912,7 +921,7 @@ def _fetch_disk_image(context, session, instance, image_id, image_type): args['image-size'] = str(vdi_size) if FLAGS.cache_images: args['cached-image'] = image_id - filename = session.call_plugin('glance', fn, args) + filename = session.call_plugin('kernel', 'copy_vdi', args) # Remove the VDI as it is not needed anymore. destroy_vdi(session, vdi_ref) diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 475e8264f98a..5797557fe1da 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -292,8 +292,9 @@ class VMOps(object): if kernel_file or ramdisk_file: LOG.debug(_("Removing kernel/ramdisk files from dom0"), instance=instance) - self._destroy_kernel_ramdisk_plugin_call(kernel_file, - ramdisk_file) + vm_utils.destroy_kernel_ramdisk( + self._session, kernel_file, ramdisk_file) + undo_mgr.undo_with(undo_create_kernel_ramdisk) return kernel_file, ramdisk_file @@ -1001,14 +1002,6 @@ class VMOps(object): except volume_utils.StorageError as exc: LOG.error(exc) - def _destroy_kernel_ramdisk_plugin_call(self, kernel, ramdisk): - args = {} - if kernel: - args['kernel-file'] = kernel - if ramdisk: - args['ramdisk-file'] = ramdisk - self._session.call_plugin('glance', 'remove_kernel_ramdisk', args) - def _destroy_kernel_ramdisk(self, instance, vm_ref): """Three situations can occur: @@ -1038,7 +1031,7 @@ class VMOps(object): (kernel, ramdisk) = vm_utils.lookup_kernel_ramdisk(self._session, vm_ref) - self._destroy_kernel_ramdisk_plugin_call(kernel, ramdisk) + vm_utils.destroy_kernel_ramdisk(self._session, kernel, ramdisk) LOG.debug(_("kernel/ramdisk files removed"), instance=instance) def _destroy_vm(self, instance, vm_ref): diff --git a/plugins/xenserver/xenapi/contrib/rpmbuild/SPECS/openstack-xen-plugins.spec b/plugins/xenserver/xenapi/contrib/rpmbuild/SPECS/openstack-xen-plugins.spec index 505d42fe2654..8f44153115c5 100644 --- a/plugins/xenserver/xenapi/contrib/rpmbuild/SPECS/openstack-xen-plugins.spec +++ b/plugins/xenserver/xenapi/contrib/rpmbuild/SPECS/openstack-xen-plugins.spec @@ -30,6 +30,7 @@ rm -rf $RPM_BUILD_ROOT %defattr(-,root,root,-) /etc/xapi.d/plugins/agent /etc/xapi.d/plugins/glance +/etc/xapi.d/plugins/kernel /etc/xapi.d/plugins/migration /etc/xapi.d/plugins/pluginlib_nova.py /etc/xapi.d/plugins/xenhost diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance b/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance index 58de40a01e83..6fbd14714995 100755 --- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance +++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance @@ -28,7 +28,6 @@ except ImportError: import simplejson as json import md5 import os -import os.path import shutil import urllib2 @@ -40,47 +39,11 @@ import utils from pluginlib_nova import * configure_logging('glance') -KERNEL_DIR = '/boot/guest' - class RetryableError(Exception): pass -def _copy_kernel_vdi(dest, copy_args): - vdi_uuid = copy_args['vdi_uuid'] - vdi_size = copy_args['vdi_size'] - cached_image = copy_args['cached-image'] - logging.debug("copying kernel/ramdisk file from %s to /boot/guest/%s", - dest, vdi_uuid) - filename = KERNEL_DIR + '/' + vdi_uuid - #make sure KERNEL_DIR exists, otherwise create it - if not os.path.isdir(KERNEL_DIR): - logging.debug("Creating directory %s", KERNEL_DIR) - os.makedirs(KERNEL_DIR) - #read data from /dev/ and write into a file on /boot/guest - of = open(filename, 'wb') - f = open(dest, 'rb') - #copy only vdi_size bytes - data = f.read(vdi_size) - of.write(data) - if cached_image: - #create a cache file. If caching is enabled, kernel images do not have - #to be fetched from glance. - cached_image = KERNEL_DIR + '/' + cached_image - logging.debug("copying kernel/ramdisk file from %s to /boot/guest/%s", - dest, cached_image) - cache_file = open(cached_image, 'wb') - cache_file.write(data) - cache_file.close() - logging.debug("Done. Filename: %s", cached_image) - - f.close() - of.close() - logging.debug("Done. Filename: %s", filename) - return filename - - def _download_tarball_and_verify(request, staging_path): try: response = urllib2.urlopen(request) @@ -225,24 +188,6 @@ def _upload_tarball(staging_path, image_id, glance_host, glance_port, conn.close() -def create_kernel_ramdisk(session, args): - """Creates a copy of the kernel/ramdisk image if it is present in the - cache. If the image is not present in the cache, it does nothing. - """ - cached_image = exists(args, 'cached-image') - image_uuid = exists(args, 'new-image-uuid') - cached_image_filename = KERNEL_DIR + '/' + cached_image - filename = KERNEL_DIR + '/' + image_uuid - - if os.path.isfile(cached_image_filename): - shutil.copyfile(cached_image_filename, filename) - logging.debug("Done. Filename: %s", filename) - else: - filename = "" - logging.debug("Cached kernel/ramdisk image not found") - return filename - - def download_vhd(session, args): """Download an image from Glance, unbundle it, and then deposit the VHDs into the storage repository @@ -295,35 +240,6 @@ def upload_vhd(session, args): return "" # Nothing useful to return on an upload -def copy_kernel_vdi(session, args): - vdi = exists(args, 'vdi-ref') - size = exists(args, 'image-size') - cached_image = optional(args, 'cached-image') - #Use the uuid as a filename - vdi_uuid = session.xenapi.VDI.get_uuid(vdi) - copy_args = {'vdi_uuid': vdi_uuid, - 'vdi_size': int(size), - 'cached-image': cached_image} - filename = with_vdi_in_dom0(session, vdi, False, - lambda dev: - _copy_kernel_vdi('/dev/%s' % dev, copy_args)) - return filename - - -def remove_kernel_ramdisk(session, args): - """Removes kernel and/or ramdisk from dom0's file system""" - kernel_file = optional(args, 'kernel-file') - ramdisk_file = optional(args, 'ramdisk-file') - if kernel_file: - os.remove(kernel_file) - if ramdisk_file: - os.remove(ramdisk_file) - return "ok" - - if __name__ == '__main__': XenAPIPlugin.dispatch({'upload_vhd': upload_vhd, - 'download_vhd': download_vhd, - 'copy_kernel_vdi': copy_kernel_vdi, - 'create_kernel_ramdisk': create_kernel_ramdisk, - 'remove_kernel_ramdisk': remove_kernel_ramdisk}) + 'download_vhd': download_vhd}) diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/kernel b/plugins/xenserver/xenapi/etc/xapi.d/plugins/kernel new file mode 100755 index 000000000000..a0ca7badceb8 --- /dev/null +++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/kernel @@ -0,0 +1,123 @@ +#!/usr/bin/env python + +# Copyright (c) 2012 Openstack, LLC +# Copyright (c) 2010 Citrix Systems, Inc. +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# 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. + +"""Handle the manipulation of kernel images.""" + +import os +import shutil + +import XenAPIPlugin + +#FIXME(sirp): should this use pluginlib from 5.6? +from pluginlib_nova import * +configure_logging('kernel') + +KERNEL_DIR = '/boot/guest' + + +def _copy_vdi(dest, copy_args): + vdi_uuid = copy_args['vdi_uuid'] + vdi_size = copy_args['vdi_size'] + cached_image = copy_args['cached-image'] + + logging.debug("copying kernel/ramdisk file from %s to /boot/guest/%s", + dest, vdi_uuid) + filename = KERNEL_DIR + '/' + vdi_uuid + + # Make sure KERNEL_DIR exists, otherwise create it + if not os.path.isdir(KERNEL_DIR): + logging.debug("Creating directory %s", KERNEL_DIR) + os.makedirs(KERNEL_DIR) + + # Read data from /dev/ and write into a file on /boot/guest + of = open(filename, 'wb') + f = open(dest, 'rb') + + # Copy only vdi_size bytes + data = f.read(vdi_size) + of.write(data) + + if cached_image: + # Create a cache file. If caching is enabled, kernel images do not have + # to be fetched from glance. + cached_image = KERNEL_DIR + '/' + cached_image + logging.debug("copying kernel/ramdisk file from %s to /boot/guest/%s", + dest, cached_image) + cache_file = open(cached_image, 'wb') + cache_file.write(data) + cache_file.close() + logging.debug("Done. Filename: %s", cached_image) + + f.close() + of.close() + logging.debug("Done. Filename: %s", filename) + return filename + + +def copy_vdi(session, args): + vdi = exists(args, 'vdi-ref') + size = exists(args, 'image-size') + cached_image = optional(args, 'cached-image') + + # Use the uuid as a filename + vdi_uuid = session.xenapi.VDI.get_uuid(vdi) + copy_args = {'vdi_uuid': vdi_uuid, + 'vdi_size': int(size), + 'cached-image': cached_image} + + filename = with_vdi_in_dom0(session, vdi, False, + lambda dev: + _copy_vdi('/dev/%s' % dev, copy_args)) + return filename + + +def create_kernel_ramdisk(session, args): + """Creates a copy of the kernel/ramdisk image if it is present in the + cache. If the image is not present in the cache, it does nothing. + """ + cached_image = exists(args, 'cached-image') + image_uuid = exists(args, 'new-image-uuid') + cached_image_filename = KERNEL_DIR + '/' + cached_image + filename = KERNEL_DIR + '/' + image_uuid + + if os.path.isfile(cached_image_filename): + shutil.copyfile(cached_image_filename, filename) + logging.debug("Done. Filename: %s", filename) + else: + filename = "" + logging.debug("Cached kernel/ramdisk image not found") + return filename + + +def remove_kernel_ramdisk(session, args): + """Removes kernel and/or ramdisk from dom0's file system""" + kernel_file = optional(args, 'kernel-file') + ramdisk_file = optional(args, 'ramdisk-file') + if kernel_file: + os.remove(kernel_file) + if ramdisk_file: + os.remove(ramdisk_file) + return "ok" + + +if __name__ == '__main__': + XenAPIPlugin.dispatch({'copy_vdi': copy_vdi, + 'create_kernel_ramdisk': create_kernel_ramdisk, + 'remove_kernel_ramdisk': remove_kernel_ramdisk})