From: Bob Ball Date: Mon, 22 Sep 2014 15:29:00 +0000 (+0100) Subject: Remove XenAPI driver X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=cd0def136c73f3fc2059ce22f4d4a68b053e47d4;p=openstack-build%2Fcinder-build.git 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 --- 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 #