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
This commit is contained in:
Rick Harris 2012-06-29 21:26:42 +00:00
parent 019d953ef5
commit 1dea34fa1a
6 changed files with 146 additions and 104 deletions

View File

@ -498,13 +498,13 @@ class SessionBase(object):
return as_json(returncode='0', message='success') return as_json(returncode='0', message='success')
elif (plugin, method) == ('agent', 'resetnetwork'): elif (plugin, method) == ('agent', 'resetnetwork'):
return as_json(returncode='0', message='success') return as_json(returncode='0', message='success')
elif (plugin, method) == ('glance', 'copy_kernel_vdi'):
return ''
elif (plugin, method) == ('glance', 'upload_vhd'): elif (plugin, method) == ('glance', 'upload_vhd'):
return '' return ''
elif (plugin, method) == ('glance', 'create_kernel_ramdisk'): elif (plugin, method) == ('kernel', 'copy_vdi'):
return '' return ''
elif (plugin, method) == ('glance', 'remove_kernel_ramdisk'): elif (plugin, method) == ('kernel', 'create_kernel_ramdisk'):
return ''
elif (plugin, method) == ('kernel', 'remove_kernel_ramdisk'):
return '' return ''
elif (plugin, method) == ('migration', 'move_vhds_into_sr'): elif (plugin, method) == ('migration', 'move_vhds_into_sr'):
return '' return ''

View File

@ -600,8 +600,8 @@ def create_kernel_image(context, session, instance, image_id, user_id,
args = {} args = {}
args['cached-image'] = image_id args['cached-image'] = image_id
args['new-image-uuid'] = str(uuid.uuid4()) args['new-image-uuid'] = str(uuid.uuid4())
filename = session.call_plugin('glance', 'create_kernel_ramdisk', filename = session.call_plugin(
args) 'kernel', 'create_kernel_ramdisk', args)
if filename == "": if filename == "":
return _fetch_image(context, session, instance, image_id, image_type) 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)} 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): def _create_cached_image(context, session, instance, image_id, image_type):
sr_ref = safe_find_sr(session) sr_ref = safe_find_sr(session)
sr_type = session.call_xenapi('SR.get_record', sr_ref)["type"] 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. # content of the VDI into the proper path.
LOG.debug(_("Copying VDI %s to /boot/guest on dom0"), LOG.debug(_("Copying VDI %s to /boot/guest on dom0"),
vdi_ref, instance=instance) vdi_ref, instance=instance)
fn = "copy_kernel_vdi"
args = {} args = {}
args['vdi-ref'] = vdi_ref 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) args['image-size'] = str(vdi_size)
if FLAGS.cache_images: if FLAGS.cache_images:
args['cached-image'] = image_id 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. # Remove the VDI as it is not needed anymore.
destroy_vdi(session, vdi_ref) destroy_vdi(session, vdi_ref)

View File

@ -292,8 +292,9 @@ class VMOps(object):
if kernel_file or ramdisk_file: if kernel_file or ramdisk_file:
LOG.debug(_("Removing kernel/ramdisk files from dom0"), LOG.debug(_("Removing kernel/ramdisk files from dom0"),
instance=instance) instance=instance)
self._destroy_kernel_ramdisk_plugin_call(kernel_file, vm_utils.destroy_kernel_ramdisk(
ramdisk_file) self._session, kernel_file, ramdisk_file)
undo_mgr.undo_with(undo_create_kernel_ramdisk) undo_mgr.undo_with(undo_create_kernel_ramdisk)
return kernel_file, ramdisk_file return kernel_file, ramdisk_file
@ -1001,14 +1002,6 @@ class VMOps(object):
except volume_utils.StorageError as exc: except volume_utils.StorageError as exc:
LOG.error(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): def _destroy_kernel_ramdisk(self, instance, vm_ref):
"""Three situations can occur: """Three situations can occur:
@ -1038,7 +1031,7 @@ class VMOps(object):
(kernel, ramdisk) = vm_utils.lookup_kernel_ramdisk(self._session, (kernel, ramdisk) = vm_utils.lookup_kernel_ramdisk(self._session,
vm_ref) 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) LOG.debug(_("kernel/ramdisk files removed"), instance=instance)
def _destroy_vm(self, instance, vm_ref): def _destroy_vm(self, instance, vm_ref):

View File

@ -30,6 +30,7 @@ rm -rf $RPM_BUILD_ROOT
%defattr(-,root,root,-) %defattr(-,root,root,-)
/etc/xapi.d/plugins/agent /etc/xapi.d/plugins/agent
/etc/xapi.d/plugins/glance /etc/xapi.d/plugins/glance
/etc/xapi.d/plugins/kernel
/etc/xapi.d/plugins/migration /etc/xapi.d/plugins/migration
/etc/xapi.d/plugins/pluginlib_nova.py /etc/xapi.d/plugins/pluginlib_nova.py
/etc/xapi.d/plugins/xenhost /etc/xapi.d/plugins/xenhost

View File

@ -28,7 +28,6 @@ except ImportError:
import simplejson as json import simplejson as json
import md5 import md5
import os import os
import os.path
import shutil import shutil
import urllib2 import urllib2
@ -40,47 +39,11 @@ import utils
from pluginlib_nova import * from pluginlib_nova import *
configure_logging('glance') configure_logging('glance')
KERNEL_DIR = '/boot/guest'
class RetryableError(Exception): class RetryableError(Exception):
pass 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): def _download_tarball_and_verify(request, staging_path):
try: try:
response = urllib2.urlopen(request) response = urllib2.urlopen(request)
@ -225,24 +188,6 @@ def _upload_tarball(staging_path, image_id, glance_host, glance_port,
conn.close() 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): def download_vhd(session, args):
"""Download an image from Glance, unbundle it, and then deposit the VHDs """Download an image from Glance, unbundle it, and then deposit the VHDs
into the storage repository into the storage repository
@ -295,35 +240,6 @@ def upload_vhd(session, args):
return "" # Nothing useful to return on an upload 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__': if __name__ == '__main__':
XenAPIPlugin.dispatch({'upload_vhd': upload_vhd, XenAPIPlugin.dispatch({'upload_vhd': upload_vhd,
'download_vhd': download_vhd, 'download_vhd': download_vhd})
'copy_kernel_vdi': copy_kernel_vdi,
'create_kernel_ramdisk': create_kernel_ramdisk,
'remove_kernel_ramdisk': remove_kernel_ramdisk})

View File

@ -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})