Adding NVMEoF for libvirt driver
Adding NVMEoF libvirt driver for supporting NVMEoF initiator CLI. Libvirt NVMe volume driver is added to handle required calls for attaching and detaching volume from instaces through calling os-brick's NVMe Connector. Implements: blueprint nvme-over-fabirc-nova Co-Authored-By: Ivan Kolodyazhny <e0ne@e0ne.info> Change-Id: I67a72c4226e54c18b3a6e4a13b5055fa6e85af09
This commit is contained in:
parent
5bf9aa7fd4
commit
a833bcd05f
@ -66,7 +66,7 @@ netifaces==0.10.4
|
||||
networkx==1.11
|
||||
numpy==1.14.2
|
||||
openstacksdk==0.12.0
|
||||
os-brick==2.4.0
|
||||
os-brick==2.5.0
|
||||
os-client-config==1.29.0
|
||||
os-service-types==1.2.0
|
||||
os-traits==0.4.0
|
||||
|
@ -1190,6 +1190,18 @@ v2.10."""),
|
||||
]
|
||||
|
||||
|
||||
libvirt_volume_nvmeof_opts = [
|
||||
cfg.IntOpt('num_nvme_discover_tries',
|
||||
default=3,
|
||||
help="""
|
||||
Number of times to rediscover NVMe target to find volume
|
||||
|
||||
Nova provides support for block storage attaching to hosts via NVMe
|
||||
(Non-Volatile Memory Express). This option allows the user to specify the
|
||||
maximum number of retry attempts that can be made to discover the NVMe device.
|
||||
"""),
|
||||
]
|
||||
|
||||
ALL_OPTS = list(itertools.chain(
|
||||
libvirt_general_opts,
|
||||
libvirt_imagebackend_opts,
|
||||
@ -1208,6 +1220,7 @@ ALL_OPTS = list(itertools.chain(
|
||||
libvirt_remotefs_opts,
|
||||
libvirt_volume_vzstorage_opts,
|
||||
libvirt_virtio_queue_sizes,
|
||||
libvirt_volume_nvmeof_opts,
|
||||
))
|
||||
|
||||
|
||||
|
66
nova/tests/unit/virt/libvirt/volume/test_nvme.py
Normal file
66
nova/tests/unit/virt/libvirt/volume/test_nvme.py
Normal file
@ -0,0 +1,66 @@
|
||||
# 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 nvme
|
||||
|
||||
from os_brick.initiator import connector
|
||||
|
||||
|
||||
class LibvirtNVMEVolumeDriverTestCase(test_volume.LibvirtVolumeBaseTestCase):
|
||||
|
||||
@mock.patch('os.path.exists', return_value=True)
|
||||
def test_libvirt_nvme_driver(self, exists):
|
||||
libvirt_driver = nvme.LibvirtNVMEVolumeDriver(self.fake_host)
|
||||
self.assertIsInstance(libvirt_driver.connector,
|
||||
connector.NVMeConnector)
|
||||
|
||||
def test_libvirt_nvme_driver_connect(self):
|
||||
nvme_driver = nvme.LibvirtNVMEVolumeDriver(self.fake_host)
|
||||
config = {'server_ip': '127.0.0.1', 'server_port': 9898}
|
||||
disk_info = {
|
||||
'id': '1234567',
|
||||
'name': 'aNVMEVolume',
|
||||
'conf': config}
|
||||
connection_info = {'data': disk_info}
|
||||
with mock.patch.object(nvme_driver.connector,
|
||||
'connect_volume',
|
||||
return_value={'path': '/dev/dms1234567'}):
|
||||
nvme_driver.connect_volume(connection_info, None)
|
||||
self.assertEqual('/dev/dms1234567',
|
||||
connection_info['data']['device_path'])
|
||||
|
||||
def test_libvirt_nvme_driver_disconnect(self):
|
||||
nvme_con = nvme.LibvirtNVMEVolumeDriver(self.connr)
|
||||
nvme_con.connector.disconnect_volume = mock.MagicMock()
|
||||
disk_info = {
|
||||
'path': '/dev/dms1234567', 'name': 'aNVMEVolume',
|
||||
'type': 'raw', 'dev': 'vda1', 'bus': 'pci0',
|
||||
'device_path': '/dev/dms123456'}
|
||||
connection_info = {'data': disk_info}
|
||||
nvme_con.disconnect_volume(connection_info, None)
|
||||
nvme_con.connector.disconnect_volume.assert_called_once_with(
|
||||
disk_info, None)
|
||||
|
||||
def test_libvirt_nvme_driver_get_config(self):
|
||||
nvme_driver = nvme.LibvirtNVMEVolumeDriver(self.fake_host)
|
||||
device_path = '/dev/fake-dev'
|
||||
connection_info = {'data': {'device_path': device_path}}
|
||||
|
||||
conf = nvme_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'))
|
@ -187,6 +187,7 @@ libvirt_volume_drivers = [
|
||||
'nova.virt.libvirt.volume.vrtshyperscale.'
|
||||
'LibvirtHyperScaleVolumeDriver',
|
||||
'storpool=nova.virt.libvirt.volume.storpool.LibvirtStorPoolVolumeDriver',
|
||||
'nvmeof=nova.virt.libvirt.volume.nvme.LibvirtNVMEVolumeDriver',
|
||||
]
|
||||
|
||||
|
||||
|
63
nova/virt/libvirt/volume/nvme.py
Normal file
63
nova/virt/libvirt/volume/nvme.py
Normal file
@ -0,0 +1,63 @@
|
||||
# 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 LibvirtNVMEVolumeDriver(libvirt_volume.LibvirtVolumeDriver):
|
||||
"""Driver to attach NVMe volumes to libvirt."""
|
||||
|
||||
def __init__(self, connection):
|
||||
super(LibvirtNVMEVolumeDriver,
|
||||
self).__init__(connection)
|
||||
|
||||
self.connector = connector.InitiatorConnector.factory(
|
||||
initiator.NVME, 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")
|
||||
self.connector.disconnect_volume(
|
||||
connection_info['data'], None)
|
||||
super(LibvirtNVMEVolumeDriver,
|
||||
self).disconnect_volume(connection_info, instance)
|
||||
|
||||
def extend_volume(self, connection_info, instance):
|
||||
"""Extend the volume."""
|
||||
LOG.debug("calling os-brick to extend NVMe Volume", instance=instance)
|
||||
new_size = self.connector.extend_volume(connection_info['data'])
|
||||
LOG.debug("Extend NVMe Volume %s; new_size=%s",
|
||||
connection_info['data']['device_path'],
|
||||
new_size, instance=instance)
|
||||
return new_size
|
@ -0,0 +1,4 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Added support for ``nvmeof`` type volumes to the libvirt driver.
|
@ -52,7 +52,7 @@ rfc3986>=0.3.1 # Apache-2.0
|
||||
oslo.middleware>=3.31.0 # Apache-2.0
|
||||
psutil>=3.2.2 # BSD
|
||||
oslo.versionedobjects>=1.31.2 # Apache-2.0
|
||||
os-brick>=2.4.0 # Apache-2.0
|
||||
os-brick>=2.5.0 # Apache-2.0
|
||||
os-traits>=0.4.0 # Apache-2.0
|
||||
os-vif!=1.8.0,>=1.7.0 # Apache-2.0
|
||||
os-win>=3.0.0 # Apache-2.0
|
||||
|
Loading…
x
Reference in New Issue
Block a user