XenAPI: Add versioning for plugins
Because the plugins live on a host seperate to Nova we need an interface to test whether they are the expected version. We can't use pip or other requirement systems as they are cross-machine. Closes bug 1226622 Change-Id: I58ab669061f51bd87071e2cf0d93d33021001309
This commit is contained in:
parent
026edcd686
commit
24fd331b8c
@ -239,7 +239,10 @@ class FakeSessionForFirewallTests(FakeSessionForVMTests):
|
||||
if '*filter' in lines:
|
||||
output = '\n'.join(lines)
|
||||
ret_str = fake.as_json(out=output, err='')
|
||||
return ret_str
|
||||
return ret_str
|
||||
else:
|
||||
return (super(FakeSessionForVMTests, self).
|
||||
host_call_plugin(_1, _2, plugin, method, args))
|
||||
|
||||
|
||||
def stub_out_vm_methods(stubs):
|
||||
|
@ -3957,6 +3957,78 @@ class XenAPISessionTestCase(test.NoDBTestCase):
|
||||
session._get_product_version_and_brand()
|
||||
)
|
||||
|
||||
def test_verify_plugin_version_same(self):
|
||||
session = self._get_mock_xapisession({})
|
||||
|
||||
session.PLUGIN_REQUIRED_VERSION = '2.4'
|
||||
|
||||
self.mox.StubOutWithMock(session, 'call_plugin_serialized')
|
||||
session.call_plugin_serialized('nova_plugin_version', 'get_version',
|
||||
).AndReturn("2.4")
|
||||
|
||||
self.mox.ReplayAll()
|
||||
session._verify_plugin_version()
|
||||
|
||||
def test_verify_plugin_version_compatible(self):
|
||||
session = self._get_mock_xapisession({})
|
||||
session.XenAPI = xenapi_fake.FakeXenAPI()
|
||||
|
||||
session.PLUGIN_REQUIRED_VERSION = '2.4'
|
||||
|
||||
self.mox.StubOutWithMock(session, 'call_plugin_serialized')
|
||||
session.call_plugin_serialized('nova_plugin_version', 'get_version',
|
||||
).AndReturn("2.5")
|
||||
|
||||
self.mox.ReplayAll()
|
||||
session._verify_plugin_version()
|
||||
|
||||
def test_verify_plugin_version_bad_maj(self):
|
||||
session = self._get_mock_xapisession({})
|
||||
session.XenAPI = xenapi_fake.FakeXenAPI()
|
||||
|
||||
session.PLUGIN_REQUIRED_VERSION = '2.4'
|
||||
|
||||
self.mox.StubOutWithMock(session, 'call_plugin_serialized')
|
||||
session.call_plugin_serialized('nova_plugin_version', 'get_version',
|
||||
).AndReturn("3.0")
|
||||
|
||||
self.mox.ReplayAll()
|
||||
self.assertRaises(xenapi_fake.Failure, session._verify_plugin_version)
|
||||
|
||||
def test_verify_plugin_version_bad_min(self):
|
||||
session = self._get_mock_xapisession({})
|
||||
session.XenAPI = xenapi_fake.FakeXenAPI()
|
||||
|
||||
session.PLUGIN_REQUIRED_VERSION = '2.4'
|
||||
|
||||
self.mox.StubOutWithMock(session, 'call_plugin_serialized')
|
||||
session.call_plugin_serialized('nova_plugin_version', 'get_version',
|
||||
).AndReturn("2.3")
|
||||
|
||||
self.mox.ReplayAll()
|
||||
self.assertRaises(xenapi_fake.Failure, session._verify_plugin_version)
|
||||
|
||||
def test_verify_current_version_matches(self):
|
||||
session = self._get_mock_xapisession({})
|
||||
|
||||
# Import the plugin to extract its version
|
||||
path = os.path.dirname(__file__)
|
||||
rel_path_elem = "../../../../plugins/xenserver/xenapi/etc/xapi.d/" \
|
||||
"plugins/nova_plugin_version"
|
||||
for elem in rel_path_elem.split('/'):
|
||||
path = os.path.join(path, elem)
|
||||
path = os.path.realpath(path)
|
||||
|
||||
plugin_version = None
|
||||
with open(path) as plugin_file:
|
||||
for line in plugin_file:
|
||||
if "PLUGIN_VERSION = " in line:
|
||||
print line
|
||||
plugin_version = line.strip()[17:].strip('"')
|
||||
|
||||
self.assertEquals(session.PLUGIN_REQUIRED_VERSION,
|
||||
plugin_version)
|
||||
|
||||
|
||||
class XenAPIFakeTestCase(test.NoDBTestCase):
|
||||
def test_query_matches(self):
|
||||
|
@ -654,6 +654,12 @@ class XenAPIDriver(driver.ComputeDriver):
|
||||
class XenAPISession(object):
|
||||
"""The session to invoke XenAPI SDK calls."""
|
||||
|
||||
# This is not a config option as it should only ever be
|
||||
# changed in development environments.
|
||||
# MAJOR VERSION: Incompatible changes with the plugins
|
||||
# MINOR VERSION: Compatible changes, new plguins, etc
|
||||
PLUGIN_REQUIRED_VERSION = '1.0'
|
||||
|
||||
def __init__(self, url, user, pw, virtapi):
|
||||
import XenAPI
|
||||
self.XenAPI = XenAPI
|
||||
@ -668,6 +674,22 @@ class XenAPISession(object):
|
||||
self._get_product_version_and_brand()
|
||||
self._virtapi = virtapi
|
||||
|
||||
self._verify_plugin_version()
|
||||
|
||||
def _verify_plugin_version(self):
|
||||
# Verify that we're using the right version of the plugins
|
||||
returned_version = self.call_plugin_serialized(
|
||||
'nova_plugin_version', 'get_version')
|
||||
|
||||
# Can't use vmops.cmp_version because that tolerates differences in
|
||||
# major version
|
||||
req_maj, req_min = self.PLUGIN_REQUIRED_VERSION.split('.')
|
||||
got_maj, got_min = returned_version.split('.')
|
||||
if req_maj != got_maj or req_min > got_min:
|
||||
raise self.XenAPI.Failure(
|
||||
_("Plugin version mismatch (Expected %(exp)s, got %(got)s)") %
|
||||
{'exp': self.PLUGIN_REQUIRED_VERSION, 'got': returned_version})
|
||||
|
||||
def _create_first_session(self, url, user, pw, exception):
|
||||
try:
|
||||
session = self._create_session(url)
|
||||
|
@ -673,6 +673,9 @@ class SessionBase(object):
|
||||
raise Failure('Guest does not have a console')
|
||||
return base64.b64encode(zlib.compress("dom_id: %s" % dom_id))
|
||||
|
||||
def _plugin_nova_plugin_version_get_version(self, method, args):
|
||||
return pickle.dumps("1.0")
|
||||
|
||||
def host_call_plugin(self, _1, _2, plugin, method, args):
|
||||
func = getattr(self, '_plugin_%s_%s' % (plugin, method), None)
|
||||
if not func:
|
||||
|
@ -42,3 +42,4 @@ rm -rf $RPM_BUILD_ROOT
|
||||
/etc/xapi.d/plugins/xenhost
|
||||
/etc/xapi.d/plugins/xenstore.py
|
||||
/etc/xapi.d/plugins/utils.py
|
||||
/etc/xapi.d/plugins/nova_plugin_version
|
||||
|
33
plugins/xenserver/xenapi/etc/xapi.d/plugins/nova_plugin_version
Executable file
33
plugins/xenserver/xenapi/etc/xapi.d/plugins/nova_plugin_version
Executable file
@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright (c) 2013 OpenStack Foundation
|
||||
# Copyright (c) 2013 Citrix Systems, Inc.
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""Returns the version of the nova plugins"""
|
||||
|
||||
import utils
|
||||
|
||||
# MAJOR VERSION: Incompatible changes
|
||||
# MINOR VERSION: Compatible changes, new plugins, etc
|
||||
|
||||
# 1.0 - Initial version.
|
||||
PLUGIN_VERSION = "1.0"
|
||||
|
||||
def get_version(session):
|
||||
return PLUGIN_VERSION
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
utils.register_plugin_calls(get_version)
|
Loading…
Reference in New Issue
Block a user