Connecting Nova to DRBD storage nodes directly
Our DRBD block storage driver for Cinder can be used to make Nova directly connect to the DRBD 9 storage servers, instead of needing an iSCSI hop. Co-Authored-By: Matt Riedemann <mriedem.os@gmail.com> Change-Id: I60477778a73701794db0c0860183ea9ab144040b Implements: blueprint drbd-driver
This commit is contained in:
parent
a1eca94d89
commit
562a04091f
63
nova/tests/unit/virt/libvirt/volume/test_drbd.py
Normal file
63
nova/tests/unit/virt/libvirt/volume/test_drbd.py
Normal file
@ -0,0 +1,63 @@
|
||||
# Copyright (c) 2015 LINBIT HA-Solutions GmbH.
|
||||
# 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.
|
||||
"""Unit tests for the DRDB volume driver module."""
|
||||
|
||||
import mock
|
||||
from os_brick.initiator import connector
|
||||
|
||||
from nova import context as nova_context
|
||||
from nova.tests.unit import fake_instance
|
||||
from nova.tests.unit.virt.libvirt.volume import test_volume
|
||||
from nova.virt.libvirt.volume import drbd
|
||||
|
||||
|
||||
class LibvirtDRBDVolumeDriverTestCase(
|
||||
test_volume.LibvirtVolumeBaseTestCase):
|
||||
"""Tests the LibvirtDRBDVolumeDriver class."""
|
||||
|
||||
def test_libvirt_drbd_driver(self):
|
||||
drbd_driver = drbd.LibvirtDRBDVolumeDriver(self.fake_host)
|
||||
self.assertIsInstance(drbd_driver.connector, connector.DRBDConnector)
|
||||
# connect a fake volume
|
||||
connection_info = {
|
||||
'data': {
|
||||
'device': '/path/to/fake-device'
|
||||
}
|
||||
}
|
||||
ctxt = nova_context.RequestContext('fake-user', 'fake-project')
|
||||
instance = fake_instance.fake_instance_obj(ctxt)
|
||||
device_info = {
|
||||
'type': 'block',
|
||||
'path': connection_info['data']['device'],
|
||||
}
|
||||
with mock.patch.object(connector.DRBDConnector, 'connect_volume',
|
||||
return_value=device_info):
|
||||
drbd_driver.connect_volume(
|
||||
connection_info, self.disk_info, instance)
|
||||
# assert that the device_path was set
|
||||
self.assertIn('device_path', connection_info['data'])
|
||||
self.assertEqual('/path/to/fake-device',
|
||||
connection_info['data']['device_path'])
|
||||
# now get the config using the updated connection_info
|
||||
conf = drbd_driver.get_config(connection_info, self.disk_info)
|
||||
# assert things were passed through to the parent class
|
||||
self.assertEqual('block', conf.source_type)
|
||||
self.assertEqual('/path/to/fake-device', conf.source_path)
|
||||
# now disconnect the volume
|
||||
with mock.patch.object(connector.DRBDConnector,
|
||||
'disconnect_volume') as mock_disconnect:
|
||||
drbd_driver.disconnect_volume(connection_info, 'vda', instance)
|
||||
# disconnect is all passthrough so just assert the call
|
||||
mock_disconnect.assert_called_once_with(connection_info['data'], None)
|
@ -150,6 +150,7 @@ libvirt_volume_drivers = [
|
||||
'iscsi=nova.virt.libvirt.volume.iscsi.LibvirtISCSIVolumeDriver',
|
||||
'iser=nova.virt.libvirt.volume.iser.LibvirtISERVolumeDriver',
|
||||
'local=nova.virt.libvirt.volume.volume.LibvirtVolumeDriver',
|
||||
'drbd=nova.virt.libvirt.volume.drbd.LibvirtDRBDVolumeDriver',
|
||||
'fake=nova.virt.libvirt.volume.volume.LibvirtFakeVolumeDriver',
|
||||
'rbd=nova.virt.libvirt.volume.net.LibvirtNetVolumeDriver',
|
||||
'sheepdog=nova.virt.libvirt.volume.net.LibvirtNetVolumeDriver',
|
||||
|
61
nova/virt/libvirt/volume/drbd.py
Normal file
61
nova/virt/libvirt/volume/drbd.py
Normal file
@ -0,0 +1,61 @@
|
||||
# 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.
|
||||
|
||||
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 LibvirtDRBDVolumeDriver(libvirt_volume.LibvirtVolumeDriver):
|
||||
"""Driver to attach DRBD volumes to libvirt."""
|
||||
|
||||
def __init__(self, host):
|
||||
super(LibvirtDRBDVolumeDriver, self).__init__(host)
|
||||
self.connector = connector.InitiatorConnector.factory(
|
||||
connector.DRBD, utils.get_root_helper())
|
||||
|
||||
def connect_volume(self, connection_info, disk_info, instance):
|
||||
"""Connect the volume.
|
||||
|
||||
Sets the connection_info['data']['device_path'] value upon successful
|
||||
connection.
|
||||
|
||||
:param connection_info: dict of connection information for the backend
|
||||
storage when a connection was initiated with Cinder. Expects
|
||||
connection_info['data']['device'] to be set.
|
||||
:param disk_info: dict of block device information (not used).
|
||||
:param instance: The nova.objects.Instance that is having a volume
|
||||
connected to it.
|
||||
"""
|
||||
LOG.debug("Calling os-brick to attach DRBD Volume.", instance=instance)
|
||||
device_info = self.connector.connect_volume(connection_info['data'])
|
||||
LOG.debug("Attached DRBD volume %s", device_info, instance=instance)
|
||||
connection_info['data']['device_path'] = device_info['path']
|
||||
|
||||
def disconnect_volume(self, connection_info, disk_dev, instance):
|
||||
"""Disconnect the volume.
|
||||
|
||||
:param connection_info: dict of connection information for the backend
|
||||
storage when a connection was initiated with Cinder.
|
||||
:param disk_dev: The block device mountpoint device name (not path).
|
||||
This is currently not used by this method.
|
||||
:param instance: The nova.objects.Instance that is having a volume
|
||||
disconnected from it.
|
||||
"""
|
||||
LOG.debug("Calling os-brick to detach DRBD Volume.", instance=instance)
|
||||
self.connector.disconnect_volume(connection_info['data'], None)
|
||||
LOG.debug("Disconnected DRBD Volume %s", disk_dev, instance=instance)
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
The libvirt compute driver now supports attaching volumes of type "drbd".
|
||||
See the `DRBD documentation`_ for more information.
|
||||
|
||||
.. _DRBD documentation: http://docs.linbit.com/docs/users-guide-9.0/p-apps/#s-openstack-transport-protocol
|
Loading…
Reference in New Issue
Block a user