summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoryuval brave <yuval@lightbitslabs.com>2021-12-13 18:13:19 +0200
committerElod Illes <elod.illes@est.tech>2022-02-22 16:17:29 +0100
commitb5e2128f3847d444a808a2b0f89e6f1e4ffb77fc (patch)
treec1d17b5d7425a941c91e42096f9c776e3e9abe8a
parent0c31561792e0e13a9f8267e71fa484ab79957f04 (diff)
downloadnova-b5e2128f3847d444a808a2b0f89e6f1e4ffb77fc.tar.gz
Lightbits LightOS driver
This commit introduces the LightOS driver for nova. LightOS is a software-defined disaggregated clustered storage solution running on commodity servers with commodity SSDs. It it developed by Lightbits Labs (https://www.lightbitslabs.com) and is actively developed and maintained. LightOS is proprietary but the openstack drivers are licensed under Apache v2.0. The Cinder driver for LightOS currently supports the following functionality: Create volume Delete volume Attach volume Detach volume Create image from volume create volume from image Live migration Volume replication Thin provisioning Multi-attach Extend volume Create snapshot Delete snapshot Create volume from snapshot Create volume from volume (clone) This driver has been developed and has been in use for a couple of years by Lightbits and our clients. We have tested it extensively internally with multiple openstack versions, including Queens, Rocky, Stein, and Train. We have also tested it with master (19.1 xena) and we are working to extend testing to cover additional openstack releases. We are glad to join the openstack community and hope to get your feedback and comments on this driver, and if it is acceptable, to see it merged into the tree. Note: the patch depends on os-brick 5.2.0. That version also increased the lower constraints of several dependencies, thus needs nova to increase those as well in requirements.txt, lower-constraints.txt and setup.cfg. Depends-On: I2e86fa84049053b7c75421d33ad1a1af459ef4e0 Signed-off-by: Yuval Brave yuval@lightbitslabs.com Change-Id: Ic314b26695d9681d31a18adcec0794c2ff41fe71
-rw-r--r--lower-constraints.txt22
-rw-r--r--nova/tests/unit/virt/libvirt/volume/test_lightos.py81
-rw-r--r--nova/virt/libvirt/driver.py1
-rw-r--r--nova/virt/libvirt/volume/lightos.py63
-rw-r--r--requirements.txt20
-rw-r--r--setup.cfg2
6 files changed, 167 insertions, 22 deletions
diff --git a/lower-constraints.txt b/lower-constraints.txt
index fc397161cb..41afef13c7 100644
--- a/lower-constraints.txt
+++ b/lower-constraints.txt
@@ -58,31 +58,31 @@ netifaces==0.10.4
networkx==2.1.0
numpy==1.19.0
openstacksdk==0.35.0
-os-brick==4.3.1
+os-brick==5.2
os-client-config==1.29.0
os-resource-classes==1.1.0
os-service-types==1.7.0
os-traits==2.7.0
os-vif==1.15.2
-os-win==5.4.0
+os-win==5.5.0
osc-lib==1.10.0
oslo.cache==1.26.0
-oslo.concurrency==4.4.0
+oslo.concurrency==4.5.0
oslo.config==8.6.0
-oslo.context==3.1.1
+oslo.context==3.4.0
oslo.db==10.0.0
-oslo.i18n==5.0.1
-oslo.log==4.4.0
+oslo.i18n==5.1.0
+oslo.log==4.6.1
oslo.messaging==10.3.0
oslo.middleware==3.31.0
oslo.policy==3.7.0
-oslo.privsep==2.4.0
+oslo.privsep==2.6.2
oslo.reports==1.18.0
oslo.rootwrap==5.8.0
-oslo.serialization==4.1.0
-oslo.service==2.5.0
+oslo.serialization==4.2.0
+oslo.service==2.8.0
oslo.upgradecheck==1.3.0
-oslo.utils==4.8.0
+oslo.utils==4.12.1
oslo.versionedobjects==1.35.0
oslo.vmware==3.6.0
oslotest==3.8.0
@@ -93,7 +93,7 @@ packaging==20.4
paramiko==2.7.1
Paste==2.0.2
PasteDeploy==1.5.0
-pbr==5.5.1
+pbr==5.8.0
pluggy==0.6.0
ply==3.11
prettytable==0.7.1
diff --git a/nova/tests/unit/virt/libvirt/volume/test_lightos.py b/nova/tests/unit/virt/libvirt/volume/test_lightos.py
new file mode 100644
index 0000000000..0be0f5aefe
--- /dev/null
+++ b/nova/tests/unit/virt/libvirt/volume/test_lightos.py
@@ -0,0 +1,81 @@
+# 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 nova.tests.unit.virt.libvirt.volume import test_volume
+from nova.virt.libvirt.volume import lightos
+
+from os_brick import initiator
+
+
+class LibvirtLightVolumeDriverTestCase(test_volume.LibvirtVolumeBaseTestCase):
+
+ @mock.patch('queue.Queue', return_value='queue')
+ @mock.patch('nova.utils.get_root_helper')
+ @mock.patch('os_brick.initiator.connector.InitiatorConnector.factory')
+ def test_libvirt_lightos_driver(self, mock_factory, mock_helper,
+ queue):
+ self.flags(group='libvirt')
+ mock_helper.return_value = 'sudo'
+ lightos.LibvirtLightOSVolumeDriver(self.fake_host)
+ mock_factory.assert_called_once_with(
+ initiator.LIGHTOS, root_helper='sudo',
+ device_scan_attempts=5)
+
+ @mock.patch('os_brick.initiator.connector.InitiatorConnector.factory',
+ new=mock.Mock(return_value=mock.Mock()))
+ def test_libvirt_lightos_driver_connect(self):
+ lightos_driver = lightos.LibvirtLightOSVolumeDriver(
+ self.fake_host)
+ config = {'server_ip': '127.0.0.1', 'server_port': 9898}
+ disk_info = {
+ 'id': '1234567',
+ 'name': 'aLightVolume',
+ 'conf': config}
+ connection_info = {'data': disk_info}
+ with mock.patch.object(lightos_driver.connector,
+ 'connect_volume',
+ return_value={'path': '/dev/dms1234567'}):
+ lightos_driver.connect_volume(connection_info, None)
+ (lightos_driver.connector.connect_volume.
+ assert_called_once_with(
+ connection_info['data']))
+ self.assertEqual('/dev/dms1234567',
+ connection_info['data']['device_path'])
+
+ @mock.patch('os_brick.initiator.connector.InitiatorConnector.factory',
+ new=mock.Mock(return_value=mock.Mock()))
+ def test_libvirt_lightos_driver_disconnect(self):
+ lightos_driver = lightos.LibvirtLightOSVolumeDriver(self.connr)
+ disk_info = {
+ 'path': '/dev/dms1234567', 'name': 'aLightosVolume',
+ 'type': 'raw', 'dev': 'vda1', 'bus': 'pci0',
+ 'device_path': '/dev/dms123456'}
+ connection_info = {'data': disk_info}
+ lightos_driver.disconnect_volume(connection_info, None)
+ lightos_driver.connector.disconnect_volume.assert_called_once_with(
+ disk_info, None)
+
+ @mock.patch('os_brick.initiator.connector.InitiatorConnector.factory',
+ new=mock.Mock(return_value=mock.Mock()))
+ def test_libvirt_lightos_driver_get_config(self):
+ lightos_driver = lightos.LibvirtLightOSVolumeDriver(self.fake_host)
+ device_path = '/dev/fake-dev'
+ connection_info = {'data': {'device_path': device_path}}
+
+ conf = lightos_driver.get_config(connection_info, self.disk_info)
+ tree = conf.format_dom()
+
+ self.assertEqual('block', tree.get('type'))
+ self.assertEqual(device_path, tree.find('./source').get('dev'))
+ self.assertEqual('raw', tree.find('./driver').get('type'))
diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py
index dc51541975..5dd5bbb9d6 100644
--- a/nova/virt/libvirt/driver.py
+++ b/nova/virt/libvirt/driver.py
@@ -188,6 +188,7 @@ VOLUME_DRIVERS = {
'vzstorage': 'nova.virt.libvirt.volume.vzstorage.LibvirtVZStorageVolumeDriver', # noqa:E501
'storpool': 'nova.virt.libvirt.volume.storpool.LibvirtStorPoolVolumeDriver', # noqa:E501
'nvmeof': 'nova.virt.libvirt.volume.nvme.LibvirtNVMEVolumeDriver',
+ 'lightos': 'nova.virt.libvirt.volume.lightos.LibvirtLightOSVolumeDriver',
}
diff --git a/nova/virt/libvirt/volume/lightos.py b/nova/virt/libvirt/volume/lightos.py
new file mode 100644
index 0000000000..d6d393994e
--- /dev/null
+++ b/nova/virt/libvirt/volume/lightos.py
@@ -0,0 +1,63 @@
+# Copyright (C) 2016-2020 Lightbits Labs Ltd.
+# Copyright (C) 2020 Intel 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 nova.conf
+from nova import utils
+from nova.virt.libvirt.volume import volume as libvirt_volume
+from os_brick import initiator
+from os_brick.initiator import connector
+from oslo_log import log as logging
+
+
+LOG = logging.getLogger(__name__)
+CONF = nova.conf.CONF
+
+
+class LibvirtLightOSVolumeDriver(libvirt_volume.LibvirtVolumeDriver):
+ """Driver to attach NVMe volumes to libvirt."""
+ VERSION = '2.3.12'
+
+ def __init__(self, connection):
+ super(LibvirtLightOSVolumeDriver, self).__init__(connection)
+ self.connector = connector.InitiatorConnector.factory(
+ initiator.LIGHTOS,
+ root_helper=utils.get_root_helper(),
+ device_scan_attempts=CONF.libvirt.num_nvme_discover_tries)
+
+ def connect_volume(self, connection_info, instance):
+ device_info = self.connector.connect_volume(connection_info['data'])
+ LOG.debug("Connecting NVMe volume with device_info %s", device_info)
+ connection_info['data']['device_path'] = device_info['path']
+
+ def disconnect_volume(self, connection_info, instance):
+ """Detach the volume from the instance."""
+ LOG.debug("Disconnecting NVMe disk. instance:%s, volume_id:%s",
+ connection_info.get("instance", ""),
+ connection_info.get("volume_id", ""))
+ self.connector.disconnect_volume(connection_info['data'], None)
+ super(LibvirtLightOSVolumeDriver, self).disconnect_volume(
+ connection_info, instance)
+
+ def extend_volume(self, connection_info, instance, requested_size=None):
+ """Extend the volume."""
+ LOG.debug("calling os-brick to extend LightOS Volume."
+ "instance:%s, volume_id:%s",
+ connection_info.get("instance", ""),
+ connection_info.get("volume_id", ""))
+ new_size = self.connector.extend_volume(connection_info['data'])
+ LOG.debug("Extend LightOS Volume %s; new_size=%s",
+ connection_info['data']['device_path'], new_size)
+ return new_size
diff --git a/requirements.txt b/requirements.txt
index c83d6e38fa..dc5860d6e6 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,4 @@
-pbr>=5.5.1 # Apache-2.0
+pbr>=5.8.0 # Apache-2.0
SQLAlchemy>=1.4.13 # MIT
decorator>=4.1.0 # BSD
eventlet>=0.30.1 # MIT
@@ -27,26 +27,26 @@ requests>=2.25.1 # Apache-2.0
stevedore>=1.20.0 # Apache-2.0
websockify>=0.9.0 # LGPLv3
oslo.cache>=1.26.0 # Apache-2.0
-oslo.concurrency>=4.4.0 # Apache-2.0
+oslo.concurrency>=4.5.0 # Apache-2.0
oslo.config>=8.6.0 # Apache-2.0
-oslo.context>=3.1.1 # Apache-2.0
-oslo.log>=4.4.0 # Apache-2.0
+oslo.context>=3.4.0 # Apache-2.0
+oslo.log>=4.6.1 # Apache-2.0
oslo.reports>=1.18.0 # Apache-2.0
-oslo.serialization>=4.1.0 # Apache-2.0
+oslo.serialization>=4.2.0 # Apache-2.0
oslo.upgradecheck>=1.3.0
-oslo.utils>=4.8.0 # Apache-2.0
+oslo.utils>=4.12.1 # Apache-2.0
oslo.db>=10.0.0 # Apache-2.0
oslo.rootwrap>=5.8.0 # Apache-2.0
oslo.messaging>=10.3.0 # Apache-2.0
oslo.policy>=3.7.0 # Apache-2.0
-oslo.privsep>=2.4.0 # Apache-2.0
-oslo.i18n>=5.0.1 # Apache-2.0
-oslo.service>=2.5.0 # Apache-2.0
+oslo.privsep>=2.6.2 # Apache-2.0
+oslo.i18n>=5.1.0 # Apache-2.0
+oslo.service>=2.8.0 # Apache-2.0
rfc3986>=1.2.0 # Apache-2.0
oslo.middleware>=3.31.0 # Apache-2.0
psutil>=3.2.2 # BSD
oslo.versionedobjects>=1.35.0 # Apache-2.0
-os-brick>=4.3.1 # Apache-2.0
+os-brick>=5.2 # Apache-2.0
os-resource-classes>=1.1.0 # Apache-2.0
os-traits>=2.7.0 # Apache-2.0
os-vif>=1.15.2 # Apache-2.0
diff --git a/setup.cfg b/setup.cfg
index 99d7cdaf10..f433c2f6e7 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -35,7 +35,7 @@ powervm =
zvm =
zVMCloudConnector>=1.3.0;sys_platform!='win32' # Apache 2.0 License
hyperv =
- os-win>=5.4.0 # Apache-2.0
+ os-win>=5.5.0 # Apache-2.0
vmware =
oslo.vmware>=3.6.0 # Apache-2.0