Add upload/download vhd2 interfaces

This adds interfaces to the glance plugin for uploading / downloading
vhd files by glance url instead of with a host / port / use_ssl
tuple. This makes it possible to have glance hosted on a non root url
and still work with xenserver.

This bumps the plugin version to 1.3 as these are new functions exposed.

Convert xenapi driver to using up/down vhd2

All unit test converted to use this new functionality.

Change-Id: I73f60de0b1644827238961e1659b0119b80bf82f
This commit is contained in:
Sean Dague 2015-12-08 09:17:06 -05:00
parent 6ebd61b28b
commit 89de4ed5e9
9 changed files with 72 additions and 33 deletions

View File

@ -61,9 +61,7 @@ class TestGlanceStore(stubs.XenAPITestBaseNoDB):
def _get_params(self):
return {'image_id': 'fake_image_uuid',
'glance_host': '1.1.1.1',
'glance_port': 123,
'glance_use_ssl': False,
'endpoint': 'http://1.1.1.1:123',
'sr_path': '/fake/sr/path',
'extra_headers': {'X-Auth-Token': 'foobar',
'X-Roles': '',
@ -83,7 +81,8 @@ class TestGlanceStore(stubs.XenAPITestBaseNoDB):
lambda *a, **kw: ['uuid1'])
self.mox.StubOutWithMock(self.session, 'call_plugin_serialized')
self.session.call_plugin_serialized('glance', 'download_vhd', **params)
self.session.call_plugin_serialized('glance', 'download_vhd2',
**params)
self.mox.ReplayAll()
self.store.download_image(self.context, self.session,
@ -102,19 +101,20 @@ class TestGlanceStore(stubs.XenAPITestBaseNoDB):
params = self._get_download_params()
self.flags(num_retries=2, group='glance')
params.pop("glance_port")
params.pop("glance_host")
calls = [mock.call('glance', 'download_vhd', glance_port=9292,
glance_host='10.0.1.1', **params),
mock.call('glance', 'download_vhd', glance_port=9293,
glance_host='10.0.0.1', **params)]
params.pop("endpoint")
calls = [mock.call('glance', 'download_vhd2',
endpoint='http://10.0.1.1:9292',
**params),
mock.call('glance', 'download_vhd2',
endpoint='http://10.0.0.1:9293',
**params)]
log_calls = [mock.call(mock.ANY, {'callback_result': '10.0.1.1',
'attempts': 3, 'attempt': 1,
'fn': 'download_vhd',
'fn': 'download_vhd2',
'plugin': 'glance'}),
mock.call(mock.ANY, {'callback_result': '10.0.0.1',
'attempts': 3, 'attempt': 2,
'fn': 'download_vhd',
'fn': 'download_vhd2',
'plugin': 'glance'})]
glance_api_servers = ['10.0.1.1:9292',
@ -147,7 +147,7 @@ class TestGlanceStore(stubs.XenAPITestBaseNoDB):
params = self._get_upload_params(auto_disk_config, expected_os_type)
self.mox.StubOutWithMock(self.session, 'call_plugin_serialized')
self.session.call_plugin_serialized('glance', 'upload_vhd', **params)
self.session.call_plugin_serialized('glance', 'upload_vhd2', **params)
self.mox.ReplayAll()
self.store.upload_image(self.context, self.session, self.instance,
@ -174,7 +174,7 @@ class TestGlanceStore(stubs.XenAPITestBaseNoDB):
params = self._get_upload_params()
self.mox.StubOutWithMock(self.session, 'call_plugin_serialized')
self.session.call_plugin_serialized('glance', 'upload_vhd',
self.session.call_plugin_serialized('glance', 'upload_vhd2',
**params).AndRaise(RuntimeError)
self.mox.ReplayAll()
@ -192,21 +192,21 @@ class TestGlanceStore(stubs.XenAPITestBaseNoDB):
self.mox.StubOutWithMock(compute_utils, 'add_instance_fault_from_exc')
error_details = ["", "", "RetryableError", ""]
error = self.session.XenAPI.Failure(details=error_details)
self.session.call_plugin_serialized('glance', 'upload_vhd',
self.session.call_plugin_serialized('glance', 'upload_vhd2',
**params).AndRaise(error)
compute_utils.add_instance_fault_from_exc(self.context, self.instance,
error, (fake.Failure,
error,
mox.IgnoreArg()))
time.sleep(0.5)
self.session.call_plugin_serialized('glance', 'upload_vhd',
self.session.call_plugin_serialized('glance', 'upload_vhd2',
**params).AndRaise(error)
compute_utils.add_instance_fault_from_exc(self.context, self.instance,
error, (fake.Failure,
error,
mox.IgnoreArg()))
time.sleep(1)
self.session.call_plugin_serialized('glance', 'upload_vhd',
self.session.call_plugin_serialized('glance', 'upload_vhd2',
**params).AndRaise(error)
compute_utils.add_instance_fault_from_exc(self.context, self.instance,
error, (fake.Failure,
@ -229,7 +229,7 @@ class TestGlanceStore(stubs.XenAPITestBaseNoDB):
self.mox.StubOutWithMock(compute_utils, 'add_instance_fault_from_exc')
error_details = ["", "task signaled", "", ""]
error = self.session.XenAPI.Failure(details=error_details)
self.session.call_plugin_serialized('glance', 'upload_vhd',
self.session.call_plugin_serialized('glance', 'upload_vhd2',
**params).AndRaise(error)
compute_utils.add_instance_fault_from_exc(self.context, self.instance,
error, (fake.Failure,
@ -239,14 +239,14 @@ class TestGlanceStore(stubs.XenAPITestBaseNoDB):
# Note(johngarbutt) XenServer 6.1 and later has this error
error_details = ["", "signal: SIGTERM", "", ""]
error = self.session.XenAPI.Failure(details=error_details)
self.session.call_plugin_serialized('glance', 'upload_vhd',
self.session.call_plugin_serialized('glance', 'upload_vhd2',
**params).AndRaise(error)
compute_utils.add_instance_fault_from_exc(self.context, self.instance,
error, (fake.Failure,
error,
mox.IgnoreArg()))
time.sleep(1)
self.session.call_plugin_serialized('glance', 'upload_vhd',
self.session.call_plugin_serialized('glance', 'upload_vhd2',
**params)
self.mox.ReplayAll()

View File

@ -168,7 +168,7 @@ class FakeSessionForVMTests(fake.SessionBase):
"# Completed on Sun Nov 6 22:49:02 2011\n")
def host_call_plugin(self, _1, _2, plugin, method, _5):
if (plugin, method) == ('glance', 'download_vhd'):
if plugin == 'glance' and method in ('download_vhd', 'download_vhd2'):
root_uuid = _make_fake_vdi()
return pickle.dumps(dict(root=dict(uuid=root_uuid)))
elif (plugin, method) == ("xenhost", "iptables_config"):

View File

@ -283,7 +283,7 @@ class FetchVhdImageTestCase(VMUtilsTestBase):
self.mox.StubOutWithMock(
self.session, 'call_plugin_serialized_with_retry')
func = self.session.call_plugin_serialized_with_retry(
'glance', 'download_vhd', 0, mox.IgnoreArg(), mox.IgnoreArg(),
'glance', 'download_vhd2', 0, mox.IgnoreArg(), mox.IgnoreArg(),
extra_headers={'X-Auth-Token': 'auth_token',
'X-Roles': '',
'X-Tenant-Id': None,

View File

@ -81,7 +81,7 @@ class XenAPISession(object):
# changed in development environments.
# MAJOR VERSION: Incompatible changes with the plugins
# MINOR VERSION: Compatible changes, new plguins, etc
PLUGIN_REQUIRED_VERSION = '1.2'
PLUGIN_REQUIRED_VERSION = '1.3'
def __init__(self, url, user, pw):
version_string = version.version_string_with_package()

View File

@ -665,6 +665,7 @@ class SessionBase(object):
return pickle.dumps(None)
_plugin_glance_upload_vhd = _plugin_pickle_noop
_plugin_glance_upload_vhd2 = _plugin_pickle_noop
_plugin_kernel_copy_vdi = _plugin_noop
_plugin_kernel_create_kernel_ramdisk = _plugin_noop
_plugin_kernel_remove_kernel_ramdisk = _plugin_noop
@ -761,7 +762,7 @@ class SessionBase(object):
return base64.b64encode(zlib.compress("dom_id: %s" % dom_id))
def _plugin_nova_plugin_version_get_version(self, method, args):
return pickle.dumps("1.2")
return pickle.dumps("1.3")
def _plugin_xenhost_query_gc(self, method, args):
return pickle.dumps("False")

View File

@ -36,11 +36,10 @@ class GlanceStore(object):
glance_api_servers = glance.get_api_servers()
def pick_glance(kwargs):
g_host, g_port, g_use_ssl = next(glance_api_servers).as_tuple()
kwargs['glance_host'] = g_host
kwargs['glance_port'] = g_port
kwargs['glance_use_ssl'] = g_use_ssl
return g_host
server = next(glance_api_servers)
kwargs['endpoint'] = server.url
# NOTE(sdague): is the return significant here at all?
return server.host
def retry_cb(context, instance, exc=None):
if exc:
@ -65,7 +64,7 @@ class GlanceStore(object):
try:
vdis = self._call_glance_plugin(context, instance, session,
'download_vhd', params)
'download_vhd2', params)
except exception.PluginRetriesExceeded:
raise exception.CouldNotFetchImage(image_id=image_id)
@ -90,6 +89,6 @@ class GlanceStore(object):
try:
self._call_glance_plugin(context, instance, session,
'upload_vhd', params)
'upload_vhd2', params)
except exception.PluginRetriesExceeded:
raise exception.CouldNotUploadImage(image_id=image_id)

View File

@ -375,6 +375,24 @@ def validate_image_status_before_upload(conn, url, extra_headers):
'image_status': image_status})
def download_vhd2(session, image_id, endpoint,
uuid_stack, sr_path, extra_headers):
"""Download an image from Glance, unbundle it, and then deposit the VHDs
into the storage repository
"""
staging_path = utils.make_staging_area(sr_path)
try:
# Download tarball into staging area and extract it
_download_tarball_by_url(
sr_path, staging_path, image_id,
endpoint, extra_headers)
# Move the VHDs from the staging area into the storage repository
return utils.import_vhds(sr_path, staging_path, uuid_stack)
finally:
utils.cleanup_staging_area(staging_path)
def download_vhd(session, image_id, glance_host, glance_port, glance_use_ssl,
uuid_stack, sr_path, extra_headers):
"""Download an image from Glance, unbundle it, and then deposit the VHDs
@ -393,6 +411,19 @@ def download_vhd(session, image_id, glance_host, glance_port, glance_use_ssl,
utils.cleanup_staging_area(staging_path)
def upload_vhd2(session, vdi_uuids, image_id,
endpoint, sr_path, extra_headers, properties):
"""Bundle the VHDs comprising an image and then stream them into Glance.
"""
staging_path = utils.make_staging_area(sr_path)
try:
utils.prepare_staging_area(sr_path, staging_path, vdi_uuids)
_upload_tarball_by_url(staging_path, image_id,
endpoint, extra_headers, properties)
finally:
utils.cleanup_staging_area(staging_path)
def upload_vhd(session, vdi_uuids, image_id, glance_host, glance_port,
glance_use_ssl, sr_path, extra_headers, properties):
"""Bundle the VHDs comprising an image and then stream them into Glance.
@ -407,4 +438,5 @@ def upload_vhd(session, vdi_uuids, image_id, glance_host, glance_port,
if __name__ == '__main__':
utils.register_plugin_calls(download_vhd, upload_vhd)
utils.register_plugin_calls(download_vhd, upload_vhd,
download_vhd2, upload_vhd2)

View File

@ -28,7 +28,8 @@ import utils
# 1.0 - Initial version.
# 1.1 - New call to check GC status
# 1.2 - Added support for pci passthrough devices
PLUGIN_VERSION = "1.2"
# 1.3 - Add vhd2 functions for doing glance operations by url
PLUGIN_VERSION = "1.3"
def get_version(session):
return PLUGIN_VERSION

View File

@ -0,0 +1,6 @@
---
upgrade:
- The glance xenserver plugin has been bumped to version 1.3 which
includes new interfaces for referencing glance servers by url. All
dom0 will need to be upgraded with this plugin before upgrading
the nova code.