From 96bb7f9a20ed6decd75f72d065652de396b36b6f Mon Sep 17 00:00:00 2001 From: Xing Yang Date: Mon, 22 Jun 2015 18:42:40 -0400 Subject: [PATCH] Add os-brick based LibvirtVolumeDriver for ScaleIO This patch adds a shim LibvirtScaleIOVolumeDriver calling the os-brick library. Both ScaleIO Cinder driver and ScaleIO connector driver in os-brick were merged. The connector driver is available in os-brick 0.3.0 and later. implements blueprint emc-sdc-libvirt-volume-driver Change-Id: If2bba1f9d4c2ddfad7a26ca74bb61fe9ed6684ba --- etc/nova/rootwrap.d/compute.filters | 2 + .../unit/virt/libvirt/volume/test_scaleio.py | 62 ++++++++++++++++++ nova/virt/libvirt/driver.py | 1 + nova/virt/libvirt/volume/scaleio.py | 63 +++++++++++++++++++ 4 files changed, 128 insertions(+) create mode 100644 nova/tests/unit/virt/libvirt/volume/test_scaleio.py create mode 100644 nova/virt/libvirt/volume/scaleio.py diff --git a/etc/nova/rootwrap.d/compute.filters b/etc/nova/rootwrap.d/compute.filters index a1d3a1d1bb53..ad3e80e99270 100644 --- a/etc/nova/rootwrap.d/compute.filters +++ b/etc/nova/rootwrap.d/compute.filters @@ -208,6 +208,8 @@ multipathd: CommandFilter, multipathd, root systool: CommandFilter, systool, root sginfo: CommandFilter, sginfo, root vgc-cluster: CommandFilter, vgc-cluster, root +# os_brick/initiator/connector.py +drv_cfg: CommandFilter, /opt/emc/scaleio/sdc/bin/drv_cfg, --query_guid, root # nova/storage/linuxscsi.py: sg_scan device sg_scan: CommandFilter, sg_scan, root diff --git a/nova/tests/unit/virt/libvirt/volume/test_scaleio.py b/nova/tests/unit/virt/libvirt/volume/test_scaleio.py new file mode 100644 index 000000000000..b2ef496a7509 --- /dev/null +++ b/nova/tests/unit/virt/libvirt/volume/test_scaleio.py @@ -0,0 +1,62 @@ +# Copyright (c) 2015 EMC Corporation +# 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 mock + +from os_brick.initiator import connector + +from nova.tests.unit.virt.libvirt.volume import test_volume +from nova.virt.libvirt.volume import scaleio + + +class LibvirtScaleIOVolumeDriverTestCase( + test_volume.LibvirtVolumeBaseTestCase): + + def test_libvirt_scaleio_driver(self): + libvirt_driver = scaleio.LibvirtScaleIOVolumeDriver( + self.fake_conn) + self.assertIsInstance(libvirt_driver.connector, + connector.ScaleIOConnector) + + def test_libvirt_scaleio_driver_connect(self): + def brick_conn_vol(data): + return {'path': '/dev/vol01'} + + sio = scaleio.LibvirtScaleIOVolumeDriver(self.fake_conn) + sio.connector.connect_volume = brick_conn_vol + disk_info = {'path': '/dev/vol01', 'name': 'vol01'} + conn = {'data': disk_info} + sio.connect_volume(conn, None) + self.assertEqual('/dev/vol01', + conn['data']['device_path']) + + def test_libvirt_scaleio_driver_get_config(self): + sio = scaleio.LibvirtScaleIOVolumeDriver(self.fake_conn) + disk_info = {'path': '/dev/vol01', 'name': 'vol01', 'type': 'raw', + 'dev': 'vda1', 'bus': 'pci0', 'device_path': '/dev/vol01'} + conn = {'data': disk_info} + conf = sio.get_config(conn, disk_info) + self.assertEqual('block', conf.source_type) + self.assertEqual('/dev/vol01', conf.source_path) + + def test_libvirt_scaleio_driver_disconnect(self): + sio = scaleio.LibvirtScaleIOVolumeDriver(self.fake_conn) + sio.connector.disconnect_volume = mock.MagicMock() + disk_info = {'path': '/dev/vol01', 'name': 'vol01', 'type': 'raw', + 'dev': 'vda1', 'bus': 'pci0', 'device_path': '/dev/vol01'} + conn = {'data': disk_info} + sio.disconnect_volume(conn, disk_info) + sio.connector.disconnect_volume.assert_called_once_with( + disk_info, None) diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index cb915c2e2638..4dcf384ca07b 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -292,6 +292,7 @@ libvirt_volume_drivers = [ 'gpfs=nova.virt.libvirt.volume.gpfs.LibvirtGPFSVolumeDriver', 'quobyte=nova.virt.libvirt.volume.quobyte.LibvirtQuobyteVolumeDriver', 'hgst=nova.virt.libvirt.volume.hgst.LibvirtHGSTVolumeDriver', + 'scaleio=nova.virt.libvirt.volume.scaleio.LibvirtScaleIOVolumeDriver', ] diff --git a/nova/virt/libvirt/volume/scaleio.py b/nova/virt/libvirt/volume/scaleio.py new file mode 100644 index 000000000000..76b1b3daa7dc --- /dev/null +++ b/nova/virt/libvirt/volume/scaleio.py @@ -0,0 +1,63 @@ +# Copyright (c) 2015 EMC Corporation +# 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. + +"""Libvirt volume driver for ScaleIO.""" + +from os_brick.initiator import connector +from oslo_config import cfg +from oslo_log import log as logging + +from nova import utils +from nova.virt.libvirt.volume import volume as libvirt_volume + +LOG = logging.getLogger(__name__) + +CONF = cfg.CONF +CONF.import_opt('num_iscsi_scan_tries', 'nova.virt.libvirt.volume.iscsi', + group='libvirt') + + +class LibvirtScaleIOVolumeDriver(libvirt_volume.LibvirtBaseVolumeDriver): + """Class ScaleIO Libvirt volume Driver + + Implements Libvirt part of volume driver for ScaleIO cinder driver. + Uses the ScaleIO connector from the os-brick projects + """ + def __init__(self, connection): + super(LibvirtScaleIOVolumeDriver, self).__init__(connection, + is_block_dev=False) + self.connector = connector.InitiatorConnector.factory( + 'SCALEIO', utils._get_root_helper(), + device_scan_attempts=CONF.libvirt.num_iscsi_scan_tries) + + def get_config(self, connection_info, disk_info): + conf = super(LibvirtScaleIOVolumeDriver, self).get_config( + connection_info, disk_info) + + conf.source_type = 'block' + conf.source_path = connection_info['data']['device_path'] + return conf + + def connect_volume(self, connection_info, disk_info): + device_info = self.connector.connect_volume(connection_info['data']) + LOG.debug("Attached ScaleIO volume %s.", device_info) + connection_info['data']['device_path'] = device_info['path'] + + def disconnect_volume(self, connection_info, disk_dev): + self.connector.disconnect_volume(connection_info['data'], None) + LOG.debug("Disconnected volume %s.", disk_dev) + + super(LibvirtScaleIOVolumeDriver, self).disconnect_volume( + connection_info, disk_dev)