diff --git a/nova/tests/unit/virt/libvirt/volume/test_vrtshyperscale.py b/nova/tests/unit/virt/libvirt/volume/test_vrtshyperscale.py new file mode 100644 index 000000000000..4bd155b71d72 --- /dev/null +++ b/nova/tests/unit/virt/libvirt/volume/test_vrtshyperscale.py @@ -0,0 +1,83 @@ +# Copyright (c) 2017 Veritas Technologies LLC +# 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 vrtshyperscale + +DEVICE_NAME = '{8ee71c33-dcd0-4267-8f2b-e0742ecabe9f}' +DEVICE_PATH = '/dev/8ee71c33-dcd0-4267-8f2b-e0742ec' + + +class LibvirtHyperScaleVolumeDriverTestCase( + test_volume.LibvirtVolumeBaseTestCase): + + def test_driver_init(self): + hs = vrtshyperscale.LibvirtHyperScaleVolumeDriver(self.fake_host) + self.assertIsInstance(hs.connector, connector.HyperScaleConnector) + + def test_get_config(self): + hs = vrtshyperscale.LibvirtHyperScaleVolumeDriver(self.fake_host) + + # expect valid conf is returned if called with proper arguments + disk_info = {'name': DEVICE_NAME, + 'type': None, + 'dev': None, + 'bus': None, + 'device_path': DEVICE_PATH, + } + conn = {'data': disk_info} + + conf = hs.get_config(conn, disk_info) + + self.assertEqual("block", conf.source_type) + self.assertEqual(DEVICE_PATH, conf.source_path) + + @mock.patch('os_brick.initiator.connectors.vrtshyperscale' + '.HyperScaleConnector.connect_volume') + def test_connect_volume(self, mock_brick_connect_volume): + mock_brick_connect_volume.return_value = {'path': DEVICE_PATH} + + hs = vrtshyperscale.LibvirtHyperScaleVolumeDriver(self.fake_host) + + # dummy arguments are just passed through to mock connector + disk_info = {'name': DEVICE_NAME} + connection_info = {'data': disk_info} + + hs.connect_volume( + connection_info, disk_info, mock.sentinel.instance) + + # expect connect_volume to add device_path to connection_info: + self.assertEqual(connection_info['data']['device_path'], DEVICE_PATH) + + @mock.patch('os_brick.initiator.connectors.vrtshyperscale' + '.HyperScaleConnector.disconnect_volume') + def test_disconnect_volume(self, mock_brick_disconnect_volume): + mock_brick_disconnect_volume.return_value = None + + hs = vrtshyperscale.LibvirtHyperScaleVolumeDriver(self.fake_host) + + # dummy arguments are just passed through to mock connector + disk_info = {'name': DEVICE_NAME} + connection_info = {'data': disk_info} + + hs.disconnect_volume( + connection_info, disk_info, mock.sentinel.instance) + + hs.connector.disconnect_volume.assert_called_once_with( + connection_info['data'], None) diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 38c7dc942b89..508104add4e3 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -166,6 +166,9 @@ libvirt_volume_drivers = [ 'disco=nova.virt.libvirt.volume.disco.LibvirtDISCOVolumeDriver', 'vzstorage=' 'nova.virt.libvirt.volume.vzstorage.LibvirtVZStorageVolumeDriver', + 'veritas_hyperscale=' + 'nova.virt.libvirt.volume.vrtshyperscale.' + 'LibvirtHyperScaleVolumeDriver', ] diff --git a/nova/virt/libvirt/volume/vrtshyperscale.py b/nova/virt/libvirt/volume/vrtshyperscale.py new file mode 100644 index 000000000000..2a438787eb9c --- /dev/null +++ b/nova/virt/libvirt/volume/vrtshyperscale.py @@ -0,0 +1,56 @@ +# Copyright (c) 2017 Veritas Technologies LLC. +# 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 HyperScale.""" + +from os_brick.initiator import connector +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__) + + +class LibvirtHyperScaleVolumeDriver(libvirt_volume.LibvirtVolumeDriver): + """Class HyperScale libvirt volume driver + + This class implements a Libvirt volume driver for Veritas + HyperScale storage. The class uses its parent class get_config method, + and calls the Veritas HyperScale os-brick connector to handle the work + of the connect_volume and disconnect volume methods. + """ + + def __init__(self, connection): + super(LibvirtHyperScaleVolumeDriver, self).__init__(connection) + self.connector = connector.InitiatorConnector.factory( + 'VERITAS_HYPERSCALE', utils.get_root_helper()) + + def connect_volume(self, connection_info, disk_info, instance): + # The os-brick connector may raise BrickException. + # The convention in nova is to just propagate it up. + # Note that the device path is returned from the os-brick connector + # using the "path" key, LibvirtVolumeDriver.get_config gets the + # device path from the "device_path" key in connection_info. + + device_info = self.connector.connect_volume(connection_info['data']) + connection_info['data']['device_path'] = device_info.get('path') + LOG.info("connect_volume: device path %(device_path)s", + {'device_path': connection_info['data']['device_path']}) + + def disconnect_volume(self, connection_info, disk_dev, instance): + self.connector.disconnect_volume(connection_info['data'], None) + LOG.info("Disconnected volume %(vol_id)s", + {'vol_id': connection_info['data']['name']}) diff --git a/releasenotes/notes/veritas_hyperscale_libvirt_driver-ba02bea54a9a99db.yaml b/releasenotes/notes/veritas_hyperscale_libvirt_driver-ba02bea54a9a99db.yaml new file mode 100644 index 000000000000..2446474178d0 --- /dev/null +++ b/releasenotes/notes/veritas_hyperscale_libvirt_driver-ba02bea54a9a99db.yaml @@ -0,0 +1,3 @@ +--- +features: + - The libvirt compute driver now supports connecting to Veritas HyperScale volume backends.