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:
Rawan Herzallah 2017-07-11 20:18:07 +03:00 committed by Hamdy Khader
parent 5bf9aa7fd4
commit a833bcd05f
7 changed files with 149 additions and 2 deletions

@ -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,
))

@ -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',
]

@ -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