diff options
| -rw-r--r-- | nova/tests/test_xenapi.py | 6 | ||||
| -rw-r--r-- | nova/tests/xenapi/stubs.py | 7 | ||||
| -rw-r--r-- | nova/virt/xenapi/driver.py | 6 | ||||
| -rw-r--r-- | nova/virt/xenapi/fake.py | 9 | ||||
| -rw-r--r-- | nova/virt/xenapi/vm_utils.py | 33 | ||||
| -rw-r--r-- | nova/virt/xenapi/vmops.py | 13 | ||||
| -rwxr-xr-x | plugins/xenserver/xenapi/etc/xapi.d/plugins/glance | 45 | ||||
| -rwxr-xr-x | plugins/xenserver/xenapi/etc/xapi.d/plugins/migration | 37 | ||||
| -rw-r--r-- | plugins/xenserver/xenapi/etc/xapi.d/plugins/utils.py | 20 | ||||
| -rwxr-xr-x | plugins/xenserver/xenapi/etc/xapi.d/plugins/workarounds | 24 |
10 files changed, 68 insertions, 132 deletions
diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index ea6ed857c..2bf7429bd 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -2105,6 +2105,10 @@ class VmUtilsTestCase(test.TestCase): def call_plugin(session_self, service, command, kwargs): self.kwargs = kwargs + def call_plugin_serialized(session_self, service, command, *args, + **kwargs): + self.kwargs = kwargs + def fake_dumps(thing): return thing @@ -2119,7 +2123,7 @@ class VmUtilsTestCase(test.TestCase): session = FakeSession() vm_utils.upload_image(ctx, session, instance, "vmi uuids", "image id") - actual = self.kwargs['params']['properties'] + actual = self.kwargs['properties'] expected = dict(a=1, b=2, c='c', d='d', auto_disk_config='auto disk config', os_type='os type') diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index bb31a5327..3bfdd3dbe 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -16,6 +16,7 @@ """Stubouts, mocks and fixtures for the test suite""" import contextlib +import pickle import random import sys @@ -169,7 +170,7 @@ class FakeSessionForVMTests(fake.SessionBase): def host_call_plugin(self, _1, _2, plugin, method, _5): if (plugin, method) == ('glance', 'download_vhd'): root_uuid = _make_fake_vdi() - return jsonutils.dumps(dict(root=dict(uuid=root_uuid))) + return pickle.dumps(dict(root=dict(uuid=root_uuid))) elif (plugin, method) == ("xenhost", "iptables_config"): return fake.as_json(out=self._fake_iptables_save_output, err='') @@ -181,8 +182,8 @@ class FakeSessionForVMTests(fake.SessionBase): if (plugin, method) == ('glance', 'download_vhd'): root_uuid = _make_fake_vdi() swap_uuid = _make_fake_vdi() - return jsonutils.dumps(dict(root=dict(uuid=root_uuid), - swap=dict(uuid=swap_uuid))) + return pickle.dumps(dict(root=dict(uuid=root_uuid), + swap=dict(uuid=swap_uuid))) else: return (super(FakeSessionForVMTests, self). host_call_plugin(_1, _2, plugin, method, _5)) diff --git a/nova/virt/xenapi/driver.py b/nova/virt/xenapi/driver.py index 644f598ca..09eba2489 100644 --- a/nova/virt/xenapi/driver.py +++ b/nova/virt/xenapi/driver.py @@ -38,6 +38,7 @@ A driver for XenServer or Xen Cloud Platform. """ import contextlib +import cPickle as pickle import time import urlparse import xmlrpclib @@ -710,6 +711,11 @@ class XenAPISession(object): session.xenapi.host.call_plugin, host, plugin, fn, args) + def call_plugin_serialized(self, plugin, fn, *args, **kwargs): + params = {'params': pickle.dumps(dict(args=args, kwargs=kwargs))} + rv = self.call_plugin(plugin, fn, params) + return pickle.loads(rv) + def _create_session(self, url): """Stubout point. This can be replaced with a mock session.""" return self.XenAPI.Session(url) diff --git a/nova/virt/xenapi/fake.py b/nova/virt/xenapi/fake.py index 3b3100f21..27feb3a05 100644 --- a/nova/virt/xenapi/fake.py +++ b/nova/virt/xenapi/fake.py @@ -50,7 +50,7 @@ A fake XenAPI SDK. """ - +import pickle import random import uuid from xml.sax import saxutils @@ -561,12 +561,15 @@ class SessionBase(object): def _plugin_noop(self, method, args): return '' - _plugin_glance_upload_vhd = _plugin_noop + def _plugin_pickle_noop(self, method, args): + return pickle.dumps(None) + + _plugin_glance_upload_vhd = _plugin_pickle_noop _plugin_kernel_copy_vdi = _plugin_noop _plugin_kernel_create_kernel_ramdisk = _plugin_noop _plugin_kernel_remove_kernel_ramdisk = _plugin_noop _plugin_migration_move_vhds_into_sr = _plugin_noop - _plugin_migration_transfer_vhd = _plugin_noop + _plugin_migration_transfer_vhd = _plugin_pickle_noop def _plugin_xenhost_host_data(self, method, args): return jsonutils.dumps({'host_memory': {'total': 10, diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index 97650b248..458b0dcad 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -22,7 +22,6 @@ their attributes like VDIs, VIFs, as well as their lookup functions. """ import contextlib -import cPickle as pickle import decimal import os import re @@ -44,7 +43,6 @@ from nova import flags from nova.image import glance from nova.openstack.common import cfg from nova.openstack.common import excutils -from nova.openstack.common import jsonutils from nova.openstack.common import log as logging from nova import utils from nova.virt.disk import api as disk @@ -467,17 +465,11 @@ def _safe_copy_vdi(session, sr_ref, instance, vdi_to_copy_ref): """ with _dummy_vm(session, instance, vdi_to_copy_ref) as vm_ref: label = "snapshot" - with snapshot_attached_here( session, instance, vm_ref, label) as vdi_uuids: - params = {'sr_path': get_sr_path(session), - 'vdi_uuids': vdi_uuids, - 'uuid_stack': _make_uuid_stack()} - - kwargs = {'params': pickle.dumps(params)} - result = session.call_plugin( - 'workarounds', 'safe_copy_vdis', kwargs) - imported_vhds = jsonutils.loads(result) + imported_vhds = session.call_plugin_serialized( + 'workarounds', 'safe_copy_vdis', sr_path=get_sr_path(session), + vdi_uuids=vdi_uuids, uuid_stack=_make_uuid_stack()) root_uuid = imported_vhds['root']['uuid'] @@ -674,8 +666,7 @@ def upload_image(context, session, instance, vdi_uuids, image_id): 'auth_token': getattr(context, 'auth_token', None), 'properties': properties} - kwargs = {'params': pickle.dumps(params)} - session.call_plugin('glance', 'upload_vhd', kwargs) + session.call_plugin_serialized('glance', 'upload_vhd', **params) def resize_disk(session, instance, vdi_ref, instance_type): @@ -971,9 +962,9 @@ def _fetch_using_dom0_plugin_with_retry(context, session, image_id, try: if callback: callback(params) - kwargs = {'params': pickle.dumps(params)} - result = session.call_plugin(plugin_name, 'download_vhd', kwargs) - return jsonutils.loads(result) + + return session.call_plugin_serialized( + plugin_name, 'download_vhd', **params) except session.XenAPI.Failure as exc: _type, _method, error = exc.details[:3] if error == 'RetryableError': @@ -2163,13 +2154,9 @@ def ensure_correct_host(session): def move_disks(session, instance, disk_info): """Move and possibly link VHDs via the XAPI plugin.""" - params = {'instance_uuid': instance['uuid'], - 'sr_path': get_sr_path(session), - 'uuid_stack': _make_uuid_stack()} - - result = session.call_plugin( - 'migration', 'move_vhds_into_sr', {'params': pickle.dumps(params)}) - imported_vhds = jsonutils.loads(result) + imported_vhds = session.call_plugin_serialized( + 'migration', 'move_vhds_into_sr', instance_uuid=instance['uuid'], + sr_path=get_sr_path(session), uuid_stack=_make_uuid_stack()) # Now we rescan the SR so we find the VHDs scan_default_sr(session) diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 090a16d46..813158246 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -19,7 +19,6 @@ Management class for VM-related functions (spawn, reboot, etc). """ -import cPickle as pickle import functools import itertools import time @@ -610,16 +609,10 @@ class VMOps(object): LOG.debug(_("Migrating VHD '%(vdi_uuid)s' with seq_num %(seq_num)d"), locals(), instance=instance) instance_uuid = instance['uuid'] - params = {'host': dest, - 'vdi_uuid': vdi_uuid, - 'instance_uuid': instance_uuid, - 'sr_path': sr_path, - 'seq_num': seq_num} - try: - _params = {'params': pickle.dumps(params)} - self._session.call_plugin('migration', 'transfer_vhd', - _params) + self._session.call_plugin_serialized('migration', 'transfer_vhd', + instance_uuid=instance_uuid, host=dest, vdi_uuid=vdi_uuid, + sr_path=sr_path, seq_num=seq_num) except self._session.XenAPI.Failure: msg = _("Failed to transfer vhd to new host") raise exception.MigrationError(reason=msg) diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance b/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance index a574bb406..924bf10d7 100755 --- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance +++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance @@ -20,18 +20,9 @@ """Handle the uploading and downloading of images via Glance.""" -import cPickle as pickle import httplib -try: - import json -except ImportError: - import simplejson as json import md5 -import os -import shutil - import urllib2 -import XenAPIPlugin import utils @@ -202,19 +193,11 @@ def _upload_tarball(staging_path, image_id, glance_host, glance_port, conn.close() -def download_vhd(session, args): +def download_vhd(session, image_id, glance_host, glance_port, glance_use_ssl, + uuid_stack, sr_path, auth_token): """Download an image from Glance, unbundle it, and then deposit the VHDs into the storage repository """ - params = pickle.loads(exists(args, 'params')) - image_id = params["image_id"] - glance_host = params["glance_host"] - glance_port = params["glance_port"] - glance_use_ssl = params["glance_use_ssl"] - uuid_stack = params["uuid_stack"] - sr_path = params["sr_path"] - auth_token = params["auth_token"] - staging_path = utils.make_staging_area(sr_path) try: # Download tarball into staging area and extract it @@ -223,28 +206,15 @@ def download_vhd(session, args): glance_use_ssl, auth_token) # Move the VHDs from the staging area into the storage repository - imported_vhds = utils.import_vhds(sr_path, staging_path, uuid_stack) + return utils.import_vhds(sr_path, staging_path, uuid_stack) finally: utils.cleanup_staging_area(staging_path) - # Right now, it's easier to return a single string via XenAPI, - # so we'll json encode the list of VHDs. - return json.dumps(imported_vhds) - -def upload_vhd(session, args): +def upload_vhd(session, vdi_uuids, image_id, glance_host, glance_port, + glance_use_ssl, sr_path, auth_token, properties): """Bundle the VHDs comprising an image and then stream them into Glance. """ - params = pickle.loads(exists(args, 'params')) - vdi_uuids = params["vdi_uuids"] - image_id = params["image_id"] - glance_host = params["glance_host"] - glance_port = params["glance_port"] - glance_use_ssl = params["glance_use_ssl"] - sr_path = params["sr_path"] - auth_token = params["auth_token"] - properties = params["properties"] - staging_path = utils.make_staging_area(sr_path) try: utils.prepare_staging_area(sr_path, staging_path, vdi_uuids) @@ -253,9 +223,6 @@ def upload_vhd(session, args): finally: utils.cleanup_staging_area(staging_path) - return "" # Nothing useful to return on an upload - if __name__ == '__main__': - XenAPIPlugin.dispatch({'upload_vhd': upload_vhd, - 'download_vhd': download_vhd}) + utils.register_plugin_calls(download_vhd, upload_vhd) diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/migration b/plugins/xenserver/xenapi/etc/xapi.d/plugins/migration index 85ad0bdbc..35316a9b8 100755 --- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/migration +++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/migration @@ -18,37 +18,18 @@ """ XenAPI Plugin for transfering data between host nodes """ - -import cPickle as pickle -try: - import json -except ImportError: - import simplejson as json -import os -import os.path -import shlex -import shutil -import subprocess - -import XenAPIPlugin - import utils from pluginlib_nova import * configure_logging('migration') -def move_vhds_into_sr(session, args): +def move_vhds_into_sr(session, instance_uuid, sr_path, uuid_stack): """Moves the VHDs from their copied location to the SR""" - params = pickle.loads(exists(args, 'params')) - instance_uuid = params['instance_uuid'] - sr_path = params['sr_path'] - uuid_stack = params['uuid_stack'] - staging_path = "/images/instance%s" % instance_uuid imported_vhds = utils.import_vhds(sr_path, staging_path, uuid_stack) utils.cleanup_staging_area(staging_path) - return json.dumps(imported_vhds) + return imported_vhds def _rsync_vhds(instance_uuid, host, staging_path, user="root"): @@ -65,15 +46,8 @@ def _rsync_vhds(instance_uuid, host, staging_path, user="root"): utils.finish_subprocess(rsync_proc, rsync_cmd) -def transfer_vhd(session, args): +def transfer_vhd(session, instance_uuid, host, vdi_uuid, sr_path, seq_num): """Rsyncs a VHD to an adjacent host""" - params = pickle.loads(exists(args, 'params')) - instance_uuid = params['instance_uuid'] - host = params['host'] - vdi_uuid = params['vdi_uuid'] - sr_path = params['sr_path'] - seq_num = params['seq_num'] - staging_path = utils.make_staging_area(sr_path) try: utils.prepare_staging_area( @@ -82,9 +56,6 @@ def transfer_vhd(session, args): finally: utils.cleanup_staging_area(staging_path) - return "" - if __name__ == '__main__': - XenAPIPlugin.dispatch({'transfer_vhd': transfer_vhd, - 'move_vhds_into_sr': move_vhds_into_sr}) + utils.register_plugin_calls(move_vhds_into_sr, transfer_vhd) diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/utils.py b/plugins/xenserver/xenapi/etc/xapi.d/plugins/utils.py index 9eba58936..027d26a67 100644 --- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/utils.py +++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/utils.py @@ -14,6 +14,7 @@ """Various utilities used by XenServer plugins.""" +import cPickle as pickle import logging import os import shlex @@ -21,6 +22,7 @@ import shutil import subprocess import tempfile +import XenAPIPlugin CHUNK_SIZE = 8192 @@ -362,3 +364,21 @@ def extract_tarball(fileobj, path, callback=None): tar_proc.stdin.write(chunk) finish_subprocess(tar_proc, tar_cmd) + + +def _handle_serialization(func): + def wrapped(session, params): + params = pickle.loads(params['params']) + rv = func(session, *params['args'], **params['kwargs']) + return pickle.dumps(rv) + return wrapped + + +def register_plugin_calls(*funcs): + """Wrapper around XenAPIPlugin.dispatch which handles pickle + serialization. + """ + wrapped_dict = {} + for func in funcs: + wrapped_dict[func.__name__] = _handle_serialization(func) + XenAPIPlugin.dispatch(wrapped_dict) diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/workarounds b/plugins/xenserver/xenapi/etc/xapi.d/plugins/workarounds index 771c27a0d..244939f00 100755 --- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/workarounds +++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/workarounds @@ -17,21 +17,14 @@ """Handle the uploading and downloading of images via Glance.""" -import cPickle as pickle -try: - import json -except ImportError: - import simplejson as json import os import shutil -import XenAPIPlugin - import utils #FIXME(sirp): should this use pluginlib from 5.6? from pluginlib_nova import * -configure_logging('hacks') +configure_logging('workarounds') def _copy_vdis(sr_path, staging_path, vdi_uuids): @@ -43,23 +36,14 @@ def _copy_vdis(sr_path, staging_path, vdi_uuids): seq_num += 1 -def safe_copy_vdis(session, args): - params = pickle.loads(exists(args, 'params')) - sr_path = params["sr_path"] - vdi_uuids = params["vdi_uuids"] - uuid_stack = params["uuid_stack"] - +def safe_copy_vdis(session, sr_path, vdi_uuids, uuid_stack): staging_path = utils.make_staging_area(sr_path) try: _copy_vdis(sr_path, staging_path, vdi_uuids) - imported_vhds = utils.import_vhds(sr_path, staging_path, uuid_stack) + return utils.import_vhds(sr_path, staging_path, uuid_stack) finally: utils.cleanup_staging_area(staging_path) - # Right now, it's easier to return a single string via XenAPI, - # so we'll json encode the list of VHDs. - return json.dumps(imported_vhds) - if __name__ == '__main__': - XenAPIPlugin.dispatch({'safe_copy_vdis': safe_copy_vdis}) + utils.register_plugin_calls(safe_copy_vdis) |
