From cd0def136c73f3fc2059ce22f4d4a68b053e47d4 Mon Sep 17 00:00:00 2001 From: Bob Ball Date: Mon, 22 Sep 2014 16:29:00 +0100 Subject: [PATCH] Remove XenAPI driver The XenAPI driver does not have known users and does not meet the minimum requirements for Cinder drivers. This patch removes the driver from the tree. Closes-bug: 1372836 Change-Id: I2123b2d52180bbdffe90c458f115c67f50dfd5e9 --- cinder/tests/test_xenapi_sm.py | 507 --------------------- cinder/volume/drivers/xenapi/__init__.py | 0 cinder/volume/drivers/xenapi/lib.py | 542 ----------------------- cinder/volume/drivers/xenapi/sm.py | 270 ----------- cinder/volume/drivers/xenapi/tools.py | 7 - etc/cinder/cinder.conf.sample | 23 - 6 files changed, 1349 deletions(-) delete mode 100644 cinder/tests/test_xenapi_sm.py delete mode 100644 cinder/volume/drivers/xenapi/__init__.py delete mode 100644 cinder/volume/drivers/xenapi/lib.py delete mode 100644 cinder/volume/drivers/xenapi/sm.py delete mode 100644 cinder/volume/drivers/xenapi/tools.py diff --git a/cinder/tests/test_xenapi_sm.py b/cinder/tests/test_xenapi_sm.py deleted file mode 100644 index 8b6d00c6c..000000000 --- a/cinder/tests/test_xenapi_sm.py +++ /dev/null @@ -1,507 +0,0 @@ -# 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. - - -import contextlib - -import mock -import mox -import six - -from cinder.db import api as db_api -from cinder import exception -from cinder import test -from cinder.volume import configuration as conf -from cinder.volume.drivers.xenapi import lib -from cinder.volume.drivers.xenapi import sm as driver -from cinder.volume.drivers.xenapi import tools - - -class MockContext(object): - def __init__(ctxt, auth_token): - ctxt.auth_token = auth_token - - -@contextlib.contextmanager -def simple_context(value): - yield value - - -def get_configured_driver(server='ignore_server', path='ignore_path'): - configuration = mox.MockObject(conf.Configuration) - configuration.xenapi_nfs_server = server - configuration.xenapi_nfs_serverpath = path - configuration.append_config_values(mox.IgnoreArg()) - configuration.volume_dd_blocksize = '1M' - return driver.XenAPINFSDriver(configuration=configuration) - - -class DriverTestCase(test.TestCase): - - def assert_flag(self, flagname): - self.assertTrue(hasattr(driver.CONF, flagname)) - - def test_config_options(self): - self.assert_flag('xenapi_connection_url') - self.assert_flag('xenapi_connection_username') - self.assert_flag('xenapi_connection_password') - self.assert_flag('xenapi_nfs_server') - self.assert_flag('xenapi_nfs_serverpath') - self.assert_flag('xenapi_sr_base_path') - - def test_do_setup(self): - mock = mox.Mox() - mock.StubOutWithMock(driver, 'xenapi_lib') - mock.StubOutWithMock(driver, 'xenapi_opts') - - configuration = mox.MockObject(conf.Configuration) - configuration.xenapi_connection_url = 'url' - configuration.xenapi_connection_username = 'user' - configuration.xenapi_connection_password = 'pass' - configuration.append_config_values(mox.IgnoreArg()) - - session_factory = object() - nfsops = object() - - driver.xenapi_lib.SessionFactory('url', 'user', 'pass').AndReturn( - session_factory) - - driver.xenapi_lib.NFSBasedVolumeOperations( - session_factory).AndReturn(nfsops) - - drv = driver.XenAPINFSDriver(configuration=configuration) - - mock.ReplayAll() - drv.do_setup('context') - mock.VerifyAll() - - self.assertEqual(nfsops, drv.nfs_ops) - - def test_create_volume(self): - mock = mox.Mox() - - ops = mock.CreateMock(lib.NFSBasedVolumeOperations) - drv = get_configured_driver('server', 'path') - drv.nfs_ops = ops - - volume_details = dict( - sr_uuid='sr_uuid', - vdi_uuid='vdi_uuid' - ) - ops.create_volume( - 'server', 'path', 1, 'name', 'desc').AndReturn(volume_details) - - mock.ReplayAll() - result = drv.create_volume(dict( - size=1, display_name='name', display_description='desc')) - mock.VerifyAll() - - self.assertEqual(dict(provider_location='sr_uuid/vdi_uuid'), result) - - def test_delete_volume(self): - mock = mox.Mox() - - ops = mock.CreateMock(lib.NFSBasedVolumeOperations) - drv = get_configured_driver('server', 'path') - drv.nfs_ops = ops - - ops.delete_volume('server', 'path', 'sr_uuid', 'vdi_uuid') - - mock.ReplayAll() - drv.delete_volume(dict(provider_location='sr_uuid/vdi_uuid')) - mock.VerifyAll() - - def test_create_export_does_not_raise_exception(self): - configuration = conf.Configuration([]) - drv = driver.XenAPINFSDriver(configuration=configuration) - drv.create_export('context', 'volume') - - def test_remove_export_does_not_raise_exception(self): - configuration = conf.Configuration([]) - drv = driver.XenAPINFSDriver(configuration=configuration) - drv.remove_export('context', 'volume') - - def test_initialize_connection(self): - mock = mox.Mox() - - drv = get_configured_driver('server', 'path') - - mock.ReplayAll() - result = drv.initialize_connection( - dict( - display_name='name', - display_description='desc', - provider_location='sr_uuid/vdi_uuid'), - 'connector' - ) - mock.VerifyAll() - - self.assertEqual( - dict( - driver_volume_type='xensm', - data=dict( - name_label='name', - name_description='desc', - sr_uuid='sr_uuid', - vdi_uuid='vdi_uuid', - sr_type='nfs', - server='server', - serverpath='path', - introduce_sr_keys=['sr_type', 'server', 'serverpath'] - ) - ), - result - ) - - def test_initialize_connection_null_values(self): - mock = mox.Mox() - - drv = get_configured_driver('server', 'path') - - mock.ReplayAll() - result = drv.initialize_connection( - dict( - display_name=None, - display_description=None, - provider_location='sr_uuid/vdi_uuid'), - 'connector' - ) - mock.VerifyAll() - - self.assertEqual( - dict( - driver_volume_type='xensm', - data=dict( - name_label='', - name_description='', - sr_uuid='sr_uuid', - vdi_uuid='vdi_uuid', - sr_type='nfs', - server='server', - serverpath='path', - introduce_sr_keys=['sr_type', 'server', 'serverpath'] - ) - ), - result - ) - - def _setup_mock_driver(self, server, serverpath, sr_base_path="_srbp"): - mock = mox.Mox() - - drv = get_configured_driver(server, serverpath) - ops = mock.CreateMock(lib.NFSBasedVolumeOperations) - db = mock.CreateMock(db_api) - drv.nfs_ops = ops - drv.db = db - - mock.StubOutWithMock(driver, 'CONF') - driver.CONF.xenapi_nfs_server = server - driver.CONF.xenapi_nfs_serverpath = serverpath - driver.CONF.xenapi_sr_base_path = sr_base_path - - return mock, drv - - def test_create_snapshot(self): - mock, drv = self._setup_mock_driver('server', 'serverpath') - - snapshot = dict( - volume_id="volume-id", - display_name="snapshot-name", - display_description="snapshot-desc", - volume=dict(provider_location="sr-uuid/vdi-uuid")) - - drv.nfs_ops.copy_volume( - "server", "serverpath", "sr-uuid", "vdi-uuid", - "snapshot-name", "snapshot-desc" - ).AndReturn(dict(sr_uuid="copied-sr", vdi_uuid="copied-vdi")) - - mock.ReplayAll() - result = drv.create_snapshot(snapshot) - mock.VerifyAll() - self.assertEqual( - dict(provider_location="copied-sr/copied-vdi"), - result) - - def test_create_volume_from_snapshot(self): - mock, drv = self._setup_mock_driver('server', 'serverpath') - - snapshot = dict( - provider_location='src-sr-uuid/src-vdi-uuid') - volume = dict( - display_name='tgt-name', name_description='tgt-desc') - - drv.nfs_ops.copy_volume( - "server", "serverpath", "src-sr-uuid", "src-vdi-uuid", - "tgt-name", "tgt-desc" - ).AndReturn(dict(sr_uuid="copied-sr", vdi_uuid="copied-vdi")) - - mock.ReplayAll() - result = drv.create_volume_from_snapshot(volume, snapshot) - mock.VerifyAll() - - self.assertEqual( - dict(provider_location='copied-sr/copied-vdi'), result) - - def test_delete_snapshot(self): - mock, drv = self._setup_mock_driver('server', 'serverpath') - - snapshot = dict( - provider_location='src-sr-uuid/src-vdi-uuid') - - drv.nfs_ops.delete_volume( - "server", "serverpath", "src-sr-uuid", "src-vdi-uuid") - - mock.ReplayAll() - drv.delete_snapshot(snapshot) - mock.VerifyAll() - - def test_copy_volume_to_image_xenserver_case(self): - mock, drv = self._setup_mock_driver( - 'server', 'serverpath', '/var/run/sr-mount') - - mock.StubOutWithMock(drv, '_use_glance_plugin_to_upload_volume') - mock.StubOutWithMock(driver.image_utils, 'is_xenserver_format') - context = MockContext('token') - - driver.image_utils.is_xenserver_format('image_meta').AndReturn(True) - - drv._use_glance_plugin_to_upload_volume( - context, 'volume', 'image_service', 'image_meta').AndReturn( - 'result') - mock.ReplayAll() - - result = drv.copy_volume_to_image( - context, "volume", "image_service", "image_meta") - self.assertEqual('result', result) - - mock.VerifyAll() - - def test_copy_volume_to_image_non_xenserver_case(self): - mock, drv = self._setup_mock_driver( - 'server', 'serverpath', '/var/run/sr-mount') - - mock.StubOutWithMock(drv, '_use_image_utils_to_upload_volume') - mock.StubOutWithMock(driver.image_utils, 'is_xenserver_format') - context = MockContext('token') - - driver.image_utils.is_xenserver_format('image_meta').AndReturn(False) - - drv._use_image_utils_to_upload_volume( - context, 'volume', 'image_service', 'image_meta').AndReturn( - 'result') - mock.ReplayAll() - - result = drv.copy_volume_to_image( - context, "volume", "image_service", "image_meta") - self.assertEqual('result', result) - - mock.VerifyAll() - - def test_use_image_utils_to_upload_volume(self): - mock, drv = self._setup_mock_driver( - 'server', 'serverpath', '/var/run/sr-mount') - - volume = dict(provider_location='sr-uuid/vdi-uuid') - context = MockContext('token') - - mock.StubOutWithMock(driver.image_utils, 'upload_volume') - - drv.nfs_ops.volume_attached_here( - 'server', 'serverpath', 'sr-uuid', 'vdi-uuid', True).AndReturn( - simple_context('device')) - - driver.image_utils.upload_volume( - context, 'image_service', 'image_meta', 'device') - - mock.ReplayAll() - drv._use_image_utils_to_upload_volume( - context, volume, "image_service", "image_meta") - mock.VerifyAll() - - def test_use_glance_plugin_to_upload_volume(self): - mock, drv = self._setup_mock_driver( - 'server', 'serverpath', '/var/run/sr-mount') - - volume = dict(provider_location='sr-uuid/vdi-uuid') - context = MockContext('token') - - mock.StubOutWithMock(driver.glance, 'get_api_servers') - - driver.glance.get_api_servers().AndReturn((x for x in ['glancesrv'])) - - drv.nfs_ops.use_glance_plugin_to_upload_volume( - 'server', 'serverpath', 'sr-uuid', 'vdi-uuid', 'glancesrv', - 'image-id', 'token', '/var/run/sr-mount') - - mock.ReplayAll() - drv._use_glance_plugin_to_upload_volume( - context, volume, "image_service", {"id": "image-id"}) - mock.VerifyAll() - - def test_copy_image_to_volume_xenserver_case(self): - mock, drv = self._setup_mock_driver( - 'server', 'serverpath', '/var/run/sr-mount') - - mock.StubOutWithMock(drv, '_use_glance_plugin_to_copy_image_to_volume') - mock.StubOutWithMock(driver.image_utils, 'is_xenserver_image') - context = MockContext('token') - - driver.image_utils.is_xenserver_image( - context, 'image_service', 'image_id').AndReturn(True) - drv._use_glance_plugin_to_copy_image_to_volume( - context, 'volume', 'image_service', 'image_id').AndReturn('result') - mock.ReplayAll() - result = drv.copy_image_to_volume( - context, "volume", "image_service", "image_id") - self.assertEqual('result', result) - mock.VerifyAll() - - def test_copy_image_to_volume_non_xenserver_case(self): - mock, drv = self._setup_mock_driver( - 'server', 'serverpath', '/var/run/sr-mount') - - mock.StubOutWithMock(drv, '_use_image_utils_to_pipe_bytes_to_volume') - mock.StubOutWithMock(driver.image_utils, 'is_xenserver_image') - context = MockContext('token') - - driver.image_utils.is_xenserver_image( - context, 'image_service', 'image_id').AndReturn(False) - drv._use_image_utils_to_pipe_bytes_to_volume( - context, 'volume', 'image_service', 'image_id').AndReturn(True) - mock.ReplayAll() - drv.copy_image_to_volume( - context, "volume", "image_service", "image_id") - mock.VerifyAll() - - def test_use_image_utils_to_pipe_bytes_to_volume(self): - mock, drv = self._setup_mock_driver( - 'server', 'serverpath', '/var/run/sr-mount') - - volume = dict(provider_location='sr-uuid/vdi-uuid', size=1) - context = MockContext('token') - - mock.StubOutWithMock(driver.image_utils, 'fetch_to_raw') - - drv.nfs_ops.volume_attached_here( - 'server', 'serverpath', 'sr-uuid', 'vdi-uuid', False).AndReturn( - simple_context('device')) - - driver.image_utils.fetch_to_raw( - context, 'image_service', 'image_id', 'device', mox.IgnoreArg(), - size=1) - - mock.ReplayAll() - drv._use_image_utils_to_pipe_bytes_to_volume( - context, volume, "image_service", "image_id") - mock.VerifyAll() - - def test_use_glance_plugin_to_copy_image_to_volume_success(self): - mock, drv = self._setup_mock_driver( - 'server', 'serverpath', '/var/run/sr-mount') - - volume = dict( - provider_location='sr-uuid/vdi-uuid', - size=2) - - mock.StubOutWithMock(driver.glance, 'get_api_servers') - - driver.glance.get_api_servers().AndReturn((x for x in ['glancesrv'])) - - drv.nfs_ops.use_glance_plugin_to_overwrite_volume( - 'server', 'serverpath', 'sr-uuid', 'vdi-uuid', 'glancesrv', - 'image_id', 'token', '/var/run/sr-mount').AndReturn(True) - - drv.nfs_ops.resize_volume( - 'server', 'serverpath', 'sr-uuid', 'vdi-uuid', 2) - - mock.ReplayAll() - drv._use_glance_plugin_to_copy_image_to_volume( - MockContext('token'), volume, "ignore", "image_id") - mock.VerifyAll() - - def test_use_glance_plugin_to_copy_image_to_volume_fail(self): - mock, drv = self._setup_mock_driver( - 'server', 'serverpath', '/var/run/sr-mount') - - volume = dict( - provider_location='sr-uuid/vdi-uuid', - size=2) - - mock.StubOutWithMock(driver.glance, 'get_api_servers') - - driver.glance.get_api_servers().AndReturn((x for x in ['glancesrv'])) - - drv.nfs_ops.use_glance_plugin_to_overwrite_volume( - 'server', 'serverpath', 'sr-uuid', 'vdi-uuid', 'glancesrv', - 'image_id', 'token', '/var/run/sr-mount').AndReturn(False) - - mock.ReplayAll() - - self.assertRaises( - exception.ImageCopyFailure, - lambda: drv._use_glance_plugin_to_copy_image_to_volume( - MockContext('token'), volume, "ignore", "image_id")) - - mock.VerifyAll() - - def test_get_volume_stats_reports_required_keys(self): - drv = get_configured_driver() - - stats = drv.get_volume_stats() - - required_metrics = [ - 'volume_backend_name', 'vendor_name', 'driver_version', - 'storage_protocol', 'total_capacity_gb', 'free_capacity_gb', - 'reserved_percentage' - ] - - for metric in required_metrics: - self.assertIn(metric, stats) - - def test_get_volume_stats_reports_unknown_cap(self): - drv = get_configured_driver() - - stats = drv.get_volume_stats() - - self.assertEqual('unknown', stats['free_capacity_gb']) - - def test_reported_driver_type(self): - drv = get_configured_driver() - - stats = drv.get_volume_stats() - - self.assertEqual('xensm', stats['storage_protocol']) - - -class ToolsTest(test.TestCase): - @mock.patch('cinder.volume.drivers.xenapi.tools._stripped_first_line_of') - def test_get_this_vm_uuid(self, mock_read_first_line): - mock_read_first_line.return_value = 'someuuid' - self.assertEqual('someuuid', tools.get_this_vm_uuid()) - mock_read_first_line.assert_called_once_with('/sys/hypervisor/uuid') - - def test_stripped_first_line_of(self): - mock_context_manager = mock.Mock() - mock_context_manager.__enter__ = mock.Mock( - return_value=six.StringIO(' blah \n second line \n')) - mock_context_manager.__exit__ = mock.Mock(return_value=False) - mock_open = mock.Mock(return_value=mock_context_manager) - - with mock.patch('__builtin__.open', mock_open): - self.assertEqual( - 'blah', tools._stripped_first_line_of('/somefile')) - - mock_open.assert_called_once_with('/somefile', 'rb') diff --git a/cinder/volume/drivers/xenapi/__init__.py b/cinder/volume/drivers/xenapi/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/cinder/volume/drivers/xenapi/lib.py b/cinder/volume/drivers/xenapi/lib.py deleted file mode 100644 index a827d5d84..000000000 --- a/cinder/volume/drivers/xenapi/lib.py +++ /dev/null @@ -1,542 +0,0 @@ -# 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. - -import contextlib -import os -import pickle - -from cinder.openstack.common import units -from cinder.volume.drivers.xenapi import tools - - -class XenAPIException(Exception): - def __init__(self, original_exception): - super(XenAPIException, self).__init__(original_exception) - self.original_exception = original_exception - - -class OperationsBase(object): - def __init__(self, xenapi_session): - self.session = xenapi_session - - def call_xenapi(self, method, *args): - return self.session.call_xenapi(method, *args) - - -class VMOperations(OperationsBase): - def get_by_uuid(self, vm_uuid): - return self.call_xenapi('VM.get_by_uuid', vm_uuid) - - def get_vbds(self, vm_uuid): - return self.call_xenapi('VM.get_VBDs', vm_uuid) - - -class VBDOperations(OperationsBase): - def create(self, vm_ref, vdi_ref, userdevice, bootable, mode, type, - empty, other_config): - vbd_rec = dict( - VM=vm_ref, - VDI=vdi_ref, - userdevice=str(userdevice), - bootable=bootable, - mode=mode, - type=type, - empty=empty, - other_config=other_config, - qos_algorithm_type='', - qos_algorithm_params=dict() - ) - return self.call_xenapi('VBD.create', vbd_rec) - - def destroy(self, vbd_ref): - self.call_xenapi('VBD.destroy', vbd_ref) - - def get_device(self, vbd_ref): - return self.call_xenapi('VBD.get_device', vbd_ref) - - def plug(self, vbd_ref): - return self.call_xenapi('VBD.plug', vbd_ref) - - def unplug(self, vbd_ref): - return self.call_xenapi('VBD.unplug', vbd_ref) - - def get_vdi(self, vbd_ref): - return self.call_xenapi('VBD.get_VDI', vbd_ref) - - -class PoolOperations(OperationsBase): - def get_all(self): - return self.call_xenapi('pool.get_all') - - def get_default_SR(self, pool_ref): - return self.call_xenapi('pool.get_default_SR', pool_ref) - - -class PbdOperations(OperationsBase): - def get_all(self): - return self.call_xenapi('PBD.get_all') - - def unplug(self, pbd_ref): - self.call_xenapi('PBD.unplug', pbd_ref) - - def create(self, host_ref, sr_ref, device_config): - return self.call_xenapi( - 'PBD.create', - dict( - host=host_ref, - SR=sr_ref, - device_config=device_config - ) - ) - - def plug(self, pbd_ref): - self.call_xenapi('PBD.plug', pbd_ref) - - -class SrOperations(OperationsBase): - def get_all(self): - return self.call_xenapi('SR.get_all') - - def get_record(self, sr_ref): - return self.call_xenapi('SR.get_record', sr_ref) - - def forget(self, sr_ref): - self.call_xenapi('SR.forget', sr_ref) - - def scan(self, sr_ref): - self.call_xenapi('SR.scan', sr_ref) - - def create(self, host_ref, device_config, name_label, name_description, - sr_type, physical_size=None, content_type=None, - shared=False, sm_config=None): - return self.call_xenapi( - 'SR.create', - host_ref, - device_config, - physical_size or '0', - name_label or '', - name_description or '', - sr_type, - content_type or '', - shared, - sm_config or dict() - ) - - def introduce(self, sr_uuid, name_label, name_description, sr_type, - content_type=None, shared=False, sm_config=None): - return self.call_xenapi( - 'SR.introduce', - sr_uuid, - name_label or '', - name_description or '', - sr_type, - content_type or '', - shared, - sm_config or dict() - ) - - def get_uuid(self, sr_ref): - return self.get_record(sr_ref)['uuid'] - - def get_name_label(self, sr_ref): - return self.get_record(sr_ref)['name_label'] - - def get_name_description(self, sr_ref): - return self.get_record(sr_ref)['name_description'] - - def destroy(self, sr_ref): - self.call_xenapi('SR.destroy', sr_ref) - - -class VdiOperations(OperationsBase): - def get_all(self): - return self.call_xenapi('VDI.get_all') - - def get_record(self, vdi_ref): - return self.call_xenapi('VDI.get_record', vdi_ref) - - def get_by_uuid(self, vdi_uuid): - return self.call_xenapi('VDI.get_by_uuid', vdi_uuid) - - def get_uuid(self, vdi_ref): - return self.get_record(vdi_ref)['uuid'] - - def create(self, sr_ref, size, vdi_type, - sharable=False, read_only=False, other_config=None): - return self.call_xenapi('VDI.create', - dict(SR=sr_ref, - virtual_size=str(size), - type=vdi_type, - sharable=sharable, - read_only=read_only, - other_config=other_config or dict())) - - def destroy(self, vdi_ref): - self.call_xenapi('VDI.destroy', vdi_ref) - - def copy(self, vdi_ref, sr_ref): - return self.call_xenapi('VDI.copy', vdi_ref, sr_ref) - - def resize(self, vdi_ref, size): - return self.call_xenapi('VDI.resize', vdi_ref, str(size)) - - -class HostOperations(OperationsBase): - def get_record(self, host_ref): - return self.call_xenapi('host.get_record', host_ref) - - def get_uuid(self, host_ref): - return self.get_record(host_ref)['uuid'] - - -class XenAPISession(object): - def __init__(self, session, exception_to_convert): - self._session = session - self._exception_to_convert = exception_to_convert - self.handle = self._session.handle - self.PBD = PbdOperations(self) - self.SR = SrOperations(self) - self.VDI = VdiOperations(self) - self.host = HostOperations(self) - self.pool = PoolOperations(self) - self.VBD = VBDOperations(self) - self.VM = VMOperations(self) - - def close(self): - return self.call_xenapi('logout') - - @contextlib.contextmanager - def exception_converter(self): - try: - yield None - except self._exception_to_convert as e: - raise XenAPIException(e) - - def call_xenapi(self, method, *args): - with self.exception_converter(): - return self._session.xenapi_request(method, args) - - def call_plugin(self, host_ref, plugin, function, args): - with self.exception_converter(): - return self._session.xenapi.host.call_plugin( - host_ref, plugin, function, args) - - def get_pool(self): - return self.call_xenapi('session.get_pool', self.handle) - - def get_this_host(self): - return self.call_xenapi('session.get_this_host', self.handle) - - -class CompoundOperations(object): - def unplug_pbds_from_sr(self, sr_ref): - sr_rec = self.SR.get_record(sr_ref) - for pbd_ref in sr_rec.get('PBDs', []): - self.PBD.unplug(pbd_ref) - - def unplug_pbds_and_forget_sr(self, sr_ref): - self.unplug_pbds_from_sr(sr_ref) - self.SR.forget(sr_ref) - - def create_new_vdi(self, sr_ref, size_in_gigabytes): - return self.VDI.create(sr_ref, - to_bytes(size_in_gigabytes), - 'User', ) - - -def to_bytes(size_in_gigs): - return size_in_gigs * units.Gi - - -class NFSOperationsMixIn(CompoundOperations): - def is_nfs_sr(self, sr_ref): - return self.SR.get_record(sr_ref).get('type') == 'nfs' - - @contextlib.contextmanager - def new_sr_on_nfs(self, host_ref, server, serverpath, - name_label=None, name_description=None): - - device_config = dict( - server=server, - serverpath=serverpath - ) - name_label = name_label or '' - name_description = name_description or '' - sr_type = 'nfs' - - sr_ref = self.SR.create( - host_ref, - device_config, - name_label, - name_description, - sr_type, - ) - yield sr_ref - - self.unplug_pbds_and_forget_sr(sr_ref) - - def plug_nfs_sr(self, host_ref, server, serverpath, sr_uuid, - name_label=None, name_description=None): - - device_config = dict( - server=server, - serverpath=serverpath - ) - sr_type = 'nfs' - - sr_ref = self.SR.introduce( - sr_uuid, - name_label, - name_description, - sr_type, - ) - - pbd_ref = self.PBD.create( - host_ref, - sr_ref, - device_config - ) - - self.PBD.plug(pbd_ref) - - return sr_ref - - def connect_volume(self, server, serverpath, sr_uuid, vdi_uuid): - host_ref = self.get_this_host() - sr_ref = self.plug_nfs_sr( - host_ref, - server, - serverpath, - sr_uuid - ) - self.SR.scan(sr_ref) - vdi_ref = self.VDI.get_by_uuid(vdi_uuid) - return dict(sr_ref=sr_ref, vdi_ref=vdi_ref) - - def copy_vdi_to_sr(self, vdi_ref, sr_ref): - return self.VDI.copy(vdi_ref, sr_ref) - - -class ContextAwareSession(XenAPISession): - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, traceback): - self.close() - - -class OpenStackXenAPISession(ContextAwareSession, - NFSOperationsMixIn): - pass - - -def connect(url, user, password): - import XenAPI - session = XenAPI.Session(url) - session.login_with_password(user, password) - return OpenStackXenAPISession(session, XenAPI.Failure) - - -class SessionFactory(object): - def __init__(self, url, user, password): - self.url = url - self.user = user - self.password = password - - def get_session(self): - return connect(self.url, self.user, self.password) - - -class XapiPluginProxy(object): - def __init__(self, session_factory, plugin_name): - self._session_factory = session_factory - self._plugin_name = plugin_name - - def call(self, function, *plugin_args, **plugin_kwargs): - plugin_params = dict(args=plugin_args, kwargs=plugin_kwargs) - args = dict(params=pickle.dumps(plugin_params)) - - with self._session_factory.get_session() as session: - host_ref = session.get_this_host() - result = session.call_plugin( - host_ref, self._plugin_name, function, args) - - return pickle.loads(result) - - -class GlancePluginProxy(XapiPluginProxy): - def __init__(self, session_factory): - super(GlancePluginProxy, self).__init__(session_factory, 'glance') - - def download_vhd(self, image_id, glance_host, glance_port, glance_use_ssl, - uuid_stack, sr_path, auth_token): - return self.call( - 'download_vhd', - image_id=image_id, - glance_host=glance_host, - glance_port=glance_port, - glance_use_ssl=glance_use_ssl, - uuid_stack=uuid_stack, - sr_path=sr_path, - auth_token=auth_token) - - def upload_vhd(self, vdi_uuids, image_id, glance_host, glance_port, - glance_use_ssl, sr_path, auth_token, properties): - return self.call( - 'upload_vhd', - vdi_uuids=vdi_uuids, - image_id=image_id, - glance_host=glance_host, - glance_port=glance_port, - glance_use_ssl=glance_use_ssl, - sr_path=sr_path, - auth_token=auth_token, - properties=properties) - - -class NFSBasedVolumeOperations(object): - def __init__(self, session_factory): - self._session_factory = session_factory - self.glance_plugin = GlancePluginProxy(session_factory) - - def create_volume(self, server, serverpath, size, - name=None, description=None): - with self._session_factory.get_session() as session: - host_ref = session.get_this_host() - with session.new_sr_on_nfs(host_ref, server, serverpath, - name, description) as sr_ref: - vdi_ref = session.create_new_vdi(sr_ref, size) - - return dict( - sr_uuid=session.SR.get_uuid(sr_ref), - vdi_uuid=session.VDI.get_uuid(vdi_ref) - ) - - def delete_volume(self, server, serverpath, sr_uuid, vdi_uuid): - with self._session_factory.get_session() as session: - refs = session.connect_volume( - server, serverpath, sr_uuid, vdi_uuid) - - session.VDI.destroy(refs['vdi_ref']) - sr_ref = refs['sr_ref'] - session.unplug_pbds_from_sr(sr_ref) - session.SR.destroy(sr_ref) - - def connect_volume(self, server, serverpath, sr_uuid, vdi_uuid): - with self._session_factory.get_session() as session: - refs = session.connect_volume( - server, serverpath, sr_uuid, vdi_uuid) - - return session.VDI.get_uuid(refs['vdi_ref']) - - def disconnect_volume(self, vdi_uuid): - with self._session_factory.get_session() as session: - vdi_ref = session.VDI.get_by_uuid(vdi_uuid) - vdi_rec = session.VDI.get_record(vdi_ref) - sr_ref = vdi_rec['SR'] - session.unplug_pbds_and_forget_sr(sr_ref) - - def copy_volume(self, server, serverpath, sr_uuid, vdi_uuid, - name=None, description=None): - with self._session_factory.get_session() as session: - src_refs = session.connect_volume( - server, serverpath, sr_uuid, vdi_uuid) - try: - host_ref = session.get_this_host() - - with session.new_sr_on_nfs(host_ref, server, serverpath, - name, description) as target_sr_ref: - target_vdi_ref = session.copy_vdi_to_sr( - src_refs['vdi_ref'], target_sr_ref) - - dst_refs = dict( - sr_uuid=session.SR.get_uuid(target_sr_ref), - vdi_uuid=session.VDI.get_uuid(target_vdi_ref) - ) - - finally: - session.unplug_pbds_and_forget_sr(src_refs['sr_ref']) - - return dst_refs - - def resize_volume(self, server, serverpath, sr_uuid, vdi_uuid, - size_in_gigabytes): - self.connect_volume(server, serverpath, sr_uuid, vdi_uuid) - - try: - with self._session_factory.get_session() as session: - vdi_ref = session.VDI.get_by_uuid(vdi_uuid) - session.VDI.resize(vdi_ref, to_bytes(size_in_gigabytes)) - finally: - self.disconnect_volume(vdi_uuid) - - def use_glance_plugin_to_overwrite_volume(self, server, serverpath, - sr_uuid, vdi_uuid, glance_server, - image_id, auth_token, - sr_base_path): - self.connect_volume(server, serverpath, sr_uuid, vdi_uuid) - - uuid_stack = [vdi_uuid] - glance_host, glance_port, glance_use_ssl = glance_server - - try: - result = self.glance_plugin.download_vhd( - image_id, glance_host, glance_port, glance_use_ssl, uuid_stack, - os.path.join(sr_base_path, sr_uuid), auth_token) - finally: - self.disconnect_volume(vdi_uuid) - - if len(result) != 1 or result['root']['uuid'] != vdi_uuid: - return False - - return True - - def use_glance_plugin_to_upload_volume(self, server, serverpath, - sr_uuid, vdi_uuid, glance_server, - image_id, auth_token, sr_base_path): - self.connect_volume(server, serverpath, sr_uuid, vdi_uuid) - - vdi_uuids = [vdi_uuid] - glance_host, glance_port, glance_use_ssl = glance_server - - try: - self.glance_plugin.upload_vhd( - vdi_uuids, image_id, glance_host, glance_port, glance_use_ssl, - os.path.join(sr_base_path, sr_uuid), auth_token, dict()) - finally: - self.disconnect_volume(vdi_uuid) - - @contextlib.contextmanager - def volume_attached_here(self, server, serverpath, sr_uuid, vdi_uuid, - readonly=True): - self.connect_volume(server, serverpath, sr_uuid, vdi_uuid) - - with self._session_factory.get_session() as session: - vm_uuid = tools.get_this_vm_uuid() - vm_ref = session.VM.get_by_uuid(vm_uuid) - vdi_ref = session.VDI.get_by_uuid(vdi_uuid) - vbd_ref = session.VBD.create( - vm_ref, vdi_ref, userdevice='autodetect', bootable=False, - mode='RO' if readonly else 'RW', type='disk', empty=False, - other_config=dict()) - session.VBD.plug(vbd_ref) - device = session.VBD.get_device(vbd_ref) - try: - yield "/dev/" + device - finally: - session.VBD.unplug(vbd_ref) - session.VBD.destroy(vbd_ref) - self.disconnect_volume(vdi_uuid) diff --git a/cinder/volume/drivers/xenapi/sm.py b/cinder/volume/drivers/xenapi/sm.py deleted file mode 100644 index 2152b4ae7..000000000 --- a/cinder/volume/drivers/xenapi/sm.py +++ /dev/null @@ -1,270 +0,0 @@ -# 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. - -from oslo.config import cfg - -from cinder import exception -from cinder.image import glance -from cinder.image import image_utils -from cinder.openstack.common import log as logging -from cinder.volume import driver -from cinder.volume.drivers.xenapi import lib as xenapi_lib - -LOG = logging.getLogger(__name__) - -xenapi_opts = [ - cfg.StrOpt('xenapi_connection_url', - default=None, - help='URL for XenAPI connection'), - cfg.StrOpt('xenapi_connection_username', - default='root', - help='Username for XenAPI connection'), - cfg.StrOpt('xenapi_connection_password', - default=None, - help='Password for XenAPI connection', - secret=True), - cfg.StrOpt('xenapi_sr_base_path', - default='/var/run/sr-mount', - help='Base path to the storage repository'), -] - -xenapi_nfs_opts = [ - cfg.StrOpt('xenapi_nfs_server', - default=None, - help='NFS server to be used by XenAPINFSDriver'), - cfg.StrOpt('xenapi_nfs_serverpath', - default=None, - help='Path of exported NFS, used by XenAPINFSDriver'), -] - -CONF = cfg.CONF -CONF.register_opts(xenapi_opts) -CONF.register_opts(xenapi_nfs_opts) - - -class XenAPINFSDriver(driver.VolumeDriver): - - VERSION = "1.0.0" - - def __init__(self, *args, **kwargs): - super(XenAPINFSDriver, self).__init__(*args, **kwargs) - self.configuration.append_config_values(xenapi_opts) - self.configuration.append_config_values(xenapi_nfs_opts) - - def do_setup(self, context): - session_factory = xenapi_lib.SessionFactory( - self.configuration.xenapi_connection_url, - self.configuration.xenapi_connection_username, - self.configuration.xenapi_connection_password - ) - self.nfs_ops = xenapi_lib.NFSBasedVolumeOperations(session_factory) - - def create_cloned_volume(self, volume, src_vref): - raise NotImplementedError() - - def create_volume(self, volume): - volume_details = self.nfs_ops.create_volume( - self.configuration.xenapi_nfs_server, - self.configuration.xenapi_nfs_serverpath, - volume['size'], - volume['display_name'], - volume['display_description'] - ) - location = "%(sr_uuid)s/%(vdi_uuid)s" % volume_details - return dict(provider_location=location) - - def create_export(self, context, volume): - pass - - def delete_volume(self, volume): - sr_uuid, vdi_uuid = volume['provider_location'].split('/') - - self.nfs_ops.delete_volume( - self.configuration.xenapi_nfs_server, - self.configuration.xenapi_nfs_serverpath, - sr_uuid, - vdi_uuid - ) - - def remove_export(self, context, volume): - pass - - def initialize_connection(self, volume, connector): - sr_uuid, vdi_uuid = volume['provider_location'].split('/') - - return dict( - driver_volume_type='xensm', - data=dict( - name_label=volume['display_name'] or '', - name_description=volume['display_description'] or '', - sr_uuid=sr_uuid, - vdi_uuid=vdi_uuid, - sr_type='nfs', - server=self.configuration.xenapi_nfs_server, - serverpath=self.configuration.xenapi_nfs_serverpath, - introduce_sr_keys=['sr_type', 'server', 'serverpath'] - ) - ) - - def terminate_connection(self, volume, connector, **kwargs): - pass - - def check_for_setup_error(self): - """To override superclass' method.""" - - def create_volume_from_snapshot(self, volume, snapshot): - return self._copy_volume( - snapshot, volume['display_name'], volume['name_description']) - - def create_snapshot(self, snapshot): - volume = snapshot['volume'] - return self._copy_volume( - volume, snapshot['display_name'], snapshot['display_description']) - - def _copy_volume(self, volume, target_name, target_desc): - sr_uuid, vdi_uuid = volume['provider_location'].split('/') - - volume_details = self.nfs_ops.copy_volume( - self.configuration.xenapi_nfs_server, - self.configuration.xenapi_nfs_serverpath, - sr_uuid, - vdi_uuid, - target_name, - target_desc - ) - location = "%(sr_uuid)s/%(vdi_uuid)s" % volume_details - return dict(provider_location=location) - - def delete_snapshot(self, snapshot): - self.delete_volume(snapshot) - - def ensure_export(self, context, volume): - pass - - def copy_image_to_volume(self, context, volume, image_service, image_id): - if image_utils.is_xenserver_image(context, image_service, image_id): - return self._use_glance_plugin_to_copy_image_to_volume( - context, volume, image_service, image_id) - - return self._use_image_utils_to_pipe_bytes_to_volume( - context, volume, image_service, image_id) - - def _use_image_utils_to_pipe_bytes_to_volume(self, context, volume, - image_service, image_id): - sr_uuid, vdi_uuid = volume['provider_location'].split('/') - with self.nfs_ops.volume_attached_here(CONF.xenapi_nfs_server, - CONF.xenapi_nfs_serverpath, - sr_uuid, vdi_uuid, - False) as device: - image_utils.fetch_to_raw(context, - image_service, - image_id, - device, - self.configuration.volume_dd_blocksize, - size=volume['size']) - - def _use_glance_plugin_to_copy_image_to_volume(self, context, volume, - image_service, image_id): - sr_uuid, vdi_uuid = volume['provider_location'].split('/') - - api_servers = glance.get_api_servers() - glance_server = api_servers.next() - auth_token = context.auth_token - - overwrite_result = self.nfs_ops.use_glance_plugin_to_overwrite_volume( - CONF.xenapi_nfs_server, - CONF.xenapi_nfs_serverpath, - sr_uuid, - vdi_uuid, - glance_server, - image_id, - auth_token, - CONF.xenapi_sr_base_path) - - if overwrite_result is False: - raise exception.ImageCopyFailure(reason='Overwriting volume ' - 'failed.') - - self.nfs_ops.resize_volume( - CONF.xenapi_nfs_server, - CONF.xenapi_nfs_serverpath, - sr_uuid, - vdi_uuid, - volume['size']) - - def copy_volume_to_image(self, context, volume, image_service, image_meta): - if image_utils.is_xenserver_format(image_meta): - return self._use_glance_plugin_to_upload_volume( - context, volume, image_service, image_meta) - - return self._use_image_utils_to_upload_volume( - context, volume, image_service, image_meta) - - def _use_image_utils_to_upload_volume(self, context, volume, image_service, - image_meta): - sr_uuid, vdi_uuid = volume['provider_location'].split('/') - with self.nfs_ops.volume_attached_here(CONF.xenapi_nfs_server, - CONF.xenapi_nfs_serverpath, - sr_uuid, vdi_uuid, - True) as device: - image_utils.upload_volume(context, - image_service, - image_meta, - device) - - def _use_glance_plugin_to_upload_volume(self, context, volume, - image_service, image_meta): - image_id = image_meta['id'] - - sr_uuid, vdi_uuid = volume['provider_location'].split('/') - - api_servers = glance.get_api_servers() - glance_server = api_servers.next() - auth_token = context.auth_token - - self.nfs_ops.use_glance_plugin_to_upload_volume( - CONF.xenapi_nfs_server, - CONF.xenapi_nfs_serverpath, - sr_uuid, - vdi_uuid, - glance_server, - image_id, - auth_token, - CONF.xenapi_sr_base_path) - - def get_volume_stats(self, refresh=False): - if refresh or not self._stats: - data = {} - - backend_name = self.configuration.safe_get('volume_backend_name') - data["volume_backend_name"] = backend_name or 'XenAPINFS', - data['vendor_name'] = 'Open Source', - data['driver_version'] = self.VERSION - data['storage_protocol'] = 'xensm' - data['total_capacity_gb'] = 'unknown' - data['free_capacity_gb'] = 'unknown' - data['reserved_percentage'] = 0 - self._stats = data - - return self._stats - - def backup_volume(self, context, backup, backup_service): - """Create a new backup from an existing volume.""" - raise NotImplementedError() - - def restore_backup(self, context, backup, volume, backup_service): - """Restore an existing backup to a new or existing volume.""" - raise NotImplementedError() diff --git a/cinder/volume/drivers/xenapi/tools.py b/cinder/volume/drivers/xenapi/tools.py deleted file mode 100644 index d452fbfa7..000000000 --- a/cinder/volume/drivers/xenapi/tools.py +++ /dev/null @@ -1,7 +0,0 @@ -def _stripped_first_line_of(filename): - with open(filename, 'rb') as f: - return f.readline().strip() - - -def get_this_vm_uuid(): - return _stripped_first_line_of('/sys/hypervisor/uuid') diff --git a/etc/cinder/cinder.conf.sample b/etc/cinder/cinder.conf.sample index 4ba44f58e..380b22df8 100644 --- a/etc/cinder/cinder.conf.sample +++ b/etc/cinder/cinder.conf.sample @@ -2152,29 +2152,6 @@ #windows_iscsi_lun_path=C:\iSCSIVirtualDisks -# -# Options defined in cinder.volume.drivers.xenapi.sm -# - -# NFS server to be used by XenAPINFSDriver (string value) -#xenapi_nfs_server= - -# Path of exported NFS, used by XenAPINFSDriver (string value) -#xenapi_nfs_serverpath= - -# URL for XenAPI connection (string value) -#xenapi_connection_url= - -# Username for XenAPI connection (string value) -#xenapi_connection_username=root - -# Password for XenAPI connection (string value) -#xenapi_connection_password= - -# Base path to the storage repository (string value) -#xenapi_sr_base_path=/var/run/sr-mount - - # # Options defined in cinder.volume.drivers.zadara # -- 2.45.2