summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGaudenz Steinlin <gaudenz.steinlin@cloudscale.ch>2018-09-11 16:09:27 +0200
committerJose Castro Leon <jose.castro.leon@cern.ch>2019-03-06 16:37:57 +0100
commiteab58069ea6afba875fb0a7d7ac68c7e83ebf14a (patch)
tree34eedbe34e46d2462f628a1a9b8b32e68a27c470
parentc9dca64fa64005e5bea327f06a7a3f4821ab72b1 (diff)
downloadnova-eab58069ea6afba875fb0a7d7ac68c7e83ebf14a.tar.gz
Extend volume for libvirt network volumes (RBD)
Implement support for extending RBD attached volumes using the libvirt network volume driver. This adds a new parameter "requested_size" to the extend_volume method. This is necessary because the new volume size can not be detected by libvirt for network volumes. All other volume types currently implementing the extend_volume call have a block device on the hypervisor which needs to be updated and can be polled for it's new size. For network volumes no such block device exists. Alternatively this could be implemented without a new parameter by calling into Ceph using os_brick to get the new size of the volume. This would make the LibvirtNetVolumeDriver Ceph specific. This also extends the logic to get the device_path for extending volumes in the libvirt driver. This is necessary as network volumes don't have the device path in the connection_info. The device_path is retrieved by matching the connection_info serial (= volume UUID) against all guest disks. Co-Authored-By: Jose Castro Leon <jose.castro.leon@cern.ch> Blueprint: extend-in-use-rbd-volumes Change-Id: I5698e451861828a8b1240d046d1610d8d37ca5a2
-rw-r--r--nova/compute/manager.py4
-rw-r--r--nova/tests/unit/compute/test_compute_mgr.py5
-rw-r--r--nova/tests/unit/virt/libvirt/test_driver.py87
-rw-r--r--nova/tests/unit/virt/libvirt/volume/test_fibrechannel.py9
-rw-r--r--nova/tests/unit/virt/libvirt/volume/test_iscsi.py9
-rw-r--r--nova/tests/unit/virt/libvirt/volume/test_net.py13
-rw-r--r--nova/tests/unit/virt/libvirt/volume/test_scaleio.py3
-rw-r--r--nova/tests/unit/virt/libvirt/volume/test_storpool.py16
-rw-r--r--nova/tests/unit/virt/powervm/test_driver.py2
-rw-r--r--nova/virt/driver.py4
-rw-r--r--nova/virt/fake.py2
-rw-r--r--nova/virt/libvirt/driver.py27
-rw-r--r--nova/virt/libvirt/volume/fibrechannel.py2
-rw-r--r--nova/virt/libvirt/volume/iscsi.py2
-rw-r--r--nova/virt/libvirt/volume/net.py6
-rw-r--r--nova/virt/libvirt/volume/nvme.py2
-rw-r--r--nova/virt/libvirt/volume/scaleio.py2
-rw-r--r--nova/virt/libvirt/volume/storpool.py2
-rw-r--r--nova/virt/libvirt/volume/volume.py15
-rw-r--r--nova/virt/powervm/driver.py3
-rw-r--r--releasenotes/notes/bp-extend-in-use-rbd-volumes-8f334ce2a06ee247.yaml5
21 files changed, 181 insertions, 39 deletions
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 10a38511da..8bb5e22855 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -52,6 +52,7 @@ from oslo_service import periodic_task
from oslo_utils import excutils
from oslo_utils import strutils
from oslo_utils import timeutils
+from oslo_utils import units
import six
from six.moves import range
@@ -8048,7 +8049,8 @@ class ComputeManager(manager.Manager):
try:
self.driver.extend_volume(connection_info,
- instance)
+ instance,
+ bdm.volume_size * units.Gi)
except Exception as ex:
LOG.warning('Extend volume failed, '
'volume_id=%(volume_id)s, reason: %(msg)s',
diff --git a/nova/tests/unit/compute/test_compute_mgr.py b/nova/tests/unit/compute/test_compute_mgr.py
index ca0b9ca4c7..8544b9d666 100644
--- a/nova/tests/unit/compute/test_compute_mgr.py
+++ b/nova/tests/unit/compute/test_compute_mgr.py
@@ -2965,6 +2965,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase):
def test_extend_volume(self):
inst_obj = objects.Instance(id=3, uuid=uuids.instance)
connection_info = {'foo': 'bar'}
+ new_size = 20
bdm = objects.BlockDeviceMapping(
source_type='volume',
destination_type='volume',
@@ -2982,13 +2983,13 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase):
def do_test(bdm_save, bdm_get_by_vol_and_inst, extend_volume,
volume_api):
bdm_get_by_vol_and_inst.return_value = bdm
- volume_api.get.return_value = {'size': 20}
+ volume_api.get.return_value = {'size': new_size}
self.compute.extend_volume(
self.context, inst_obj, uuids.volume_id)
bdm_save.assert_called_once_with()
extend_volume.assert_called_once_with(
- connection_info, inst_obj)
+ connection_info, inst_obj, new_size * pow(1024, 3))
do_test()
diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py
index f9a1ac3173..85292a1b50 100644
--- a/nova/tests/unit/virt/libvirt/test_driver.py
+++ b/nova/tests/unit/virt/libvirt/test_driver.py
@@ -7997,9 +7997,11 @@ class LibvirtConnTestCase(test.NoDBTestCase,
for state in (power_state.RUNNING, power_state.PAUSED):
guest.get_power_state = mock.Mock(return_value=state)
- drvr.extend_volume(connection_info, instance)
+ drvr.extend_volume(connection_info,
+ instance, new_size_in_kb * 1024)
drvr._extend_volume.assert_called_with(connection_info,
- instance)
+ instance,
+ new_size_in_kb * 1024)
guest.get_block_device.assert_called_with('/fake')
block_device.resize.assert_called_with(20480)
@@ -8012,7 +8014,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
connection_info = {'driver_volume_type': 'fake'}
self.assertRaises(exception.ExtendVolumeNotSupported,
drvr.extend_volume,
- connection_info, instance)
+ connection_info, instance, 0)
def test_extend_volume_disk_not_found(self):
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
@@ -8031,7 +8033,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
drvr._host.get_guest = mock.Mock(return_value=guest)
drvr._extend_volume = mock.Mock(return_value=new_size_in_kb)
- drvr.extend_volume(connection_info, instance)
+ drvr.extend_volume(connection_info, instance, new_size_in_kb * 1024)
def test_extend_volume_with_instance_not_found(self):
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
@@ -8046,7 +8048,7 @@ class LibvirtConnTestCase(test.NoDBTestCase,
connection_info = {'driver_volume_type': 'fake'}
self.assertRaises(exception.InstanceNotFound,
drvr.extend_volume,
- connection_info, instance)
+ connection_info, instance, 0)
def test_extend_volume_with_libvirt_error(self):
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
@@ -8071,7 +8073,80 @@ class LibvirtConnTestCase(test.NoDBTestCase,
self.assertRaises(fakelibvirt.libvirtError,
drvr.extend_volume,
- connection_info, instance)
+ connection_info, instance, new_size_in_kb * 1024)
+
+ def test_extend_volume_with_no_device_path_attribute(self):
+ drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
+ instance = objects.Instance(**self.test_instance)
+ connection_info = {
+ 'serial': '58a84f6d-3f0c-4e19-a0af-eb657b790657',
+ 'driver_volume_type': 'fake',
+ 'data': {'cluster_name': 'fake',
+ 'auth_enabled': False,
+ 'volume_id': '58a84f6d-3f0c-4e19-a0af-eb657b790657',
+ 'access_mode': 'rw'}
+ }
+ new_size_in_kb = 20 * 1024 * 1024
+
+ guest = mock.Mock(spec='nova.virt.libvirt.guest.Guest')
+ # block_device
+ block_device = mock.Mock(
+ spec='nova.virt.libvirt.guest.BlockDevice')
+ block_device.resize = mock.Mock()
+ disk = mock.Mock(
+ spec='nova.virt.libvirt.config.LibvirtConfigGuestDisk',
+ serial='58a84f6d-3f0c-4e19-a0af-eb657b790657',
+ target_dev='vdb')
+ guest.get_block_device = mock.Mock(return_value=block_device)
+ guest.get_all_disks = mock.Mock(return_value=[disk])
+ drvr._host.get_guest = mock.Mock(return_value=guest)
+ drvr._extend_volume = mock.Mock(return_value=new_size_in_kb)
+
+ for state in (power_state.RUNNING, power_state.PAUSED):
+ guest.get_power_state = mock.Mock(return_value=state)
+ drvr.extend_volume(connection_info, instance,
+ new_size_in_kb * 1024)
+ drvr._extend_volume.assert_called_with(connection_info,
+ instance,
+ new_size_in_kb * 1024)
+ guest.get_block_device.assert_called_with('vdb')
+ block_device.resize.assert_called_with(20480)
+
+ def test_extend_volume_no_disk_found_by_serial(self):
+ drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
+ instance = objects.Instance(**self.test_instance)
+ connection_info = {
+ 'serial': '58a84f6d-3f0c-4e19-a0af-eb657b790657',
+ 'driver_volume_type': 'fake',
+ 'data': {'cluster_name': 'fake',
+ 'auth_enabled': False,
+ 'volume_id': '58a84f6d-3f0c-4e19-a0af-eb657b790657',
+ 'access_mode': 'rw'}
+ }
+ new_size_in_kb = 20 * 1024 * 1024
+
+ guest = mock.Mock(spec='nova.virt.libvirt.guest.Guest')
+ # block_device
+ block_device = mock.Mock(
+ spec='nova.virt.libvirt.guest.BlockDevice')
+ block_device.resize = mock.Mock()
+ disk = mock.Mock(
+ spec='nova.virt.libvirt.config.LibvirtConfigGuestDisk',
+ serial='12345678-abcd-abcd-abcd-0123456789012',
+ target_dev='vdb')
+ guest.get_block_device = mock.Mock(return_value=block_device)
+ guest.get_all_disks = mock.Mock(return_value=[disk])
+ drvr._host.get_guest = mock.Mock(return_value=guest)
+ drvr._extend_volume = mock.Mock(return_value=new_size_in_kb)
+ guest.get_power_state = mock.Mock(return_value=power_state.RUNNING)
+
+ self.assertRaises(
+ exception.VolumeNotFound,
+ drvr.extend_volume,
+ connection_info,
+ instance,
+ new_size_in_kb * 1024
+ )
@mock.patch('os_brick.encryptors.get_encryption_metadata')
@mock.patch('nova.virt.libvirt.driver.LibvirtDriver._get_volume_encryptor')
diff --git a/nova/tests/unit/virt/libvirt/volume/test_fibrechannel.py b/nova/tests/unit/virt/libvirt/volume/test_fibrechannel.py
index 4289ac5aef..89a59f2f1a 100644
--- a/nova/tests/unit/virt/libvirt/volume/test_fibrechannel.py
+++ b/nova/tests/unit/virt/libvirt/volume/test_fibrechannel.py
@@ -68,13 +68,16 @@ class LibvirtFibreChannelVolumeDriverTestCase(
def test_extend_volume(self):
device_path = '/dev/fake-dev'
connection_info = {'data': {'device_path': device_path}}
+ requested_size = 1
libvirt_driver = fibrechannel.LibvirtFibreChannelVolumeDriver(
self.fake_host)
- libvirt_driver.connector.extend_volume = mock.MagicMock(return_value=1)
+ libvirt_driver.connector.extend_volume = mock.MagicMock(
+ return_value=requested_size)
new_size = libvirt_driver.extend_volume(connection_info,
- mock.sentinel.instance)
+ mock.sentinel.instance,
+ requested_size)
- self.assertEqual(1, new_size)
+ self.assertEqual(requested_size, new_size)
libvirt_driver.connector.extend_volume.assert_called_once_with(
connection_info['data'])
diff --git a/nova/tests/unit/virt/libvirt/volume/test_iscsi.py b/nova/tests/unit/virt/libvirt/volume/test_iscsi.py
index 2991ef1ac9..f8a64abea5 100644
--- a/nova/tests/unit/virt/libvirt/volume/test_iscsi.py
+++ b/nova/tests/unit/virt/libvirt/volume/test_iscsi.py
@@ -64,12 +64,15 @@ class LibvirtISCSIVolumeDriverTestCase(
def test_extend_volume(self):
device_path = '/dev/fake-dev'
connection_info = {'data': {'device_path': device_path}}
+ requested_size = 1
libvirt_driver = iscsi.LibvirtISCSIVolumeDriver(self.fake_host)
- libvirt_driver.connector.extend_volume = mock.MagicMock(return_value=1)
+ libvirt_driver.connector.extend_volume = mock.MagicMock(
+ return_value=requested_size)
new_size = libvirt_driver.extend_volume(connection_info,
- mock.sentinel.instance)
+ mock.sentinel.instance,
+ requested_size)
- self.assertEqual(1, new_size)
+ self.assertEqual(requested_size, new_size)
libvirt_driver.connector.extend_volume.assert_called_once_with(
connection_info['data'])
diff --git a/nova/tests/unit/virt/libvirt/volume/test_net.py b/nova/tests/unit/virt/libvirt/volume/test_net.py
index 640c1709de..bea90a24dc 100644
--- a/nova/tests/unit/virt/libvirt/volume/test_net.py
+++ b/nova/tests/unit/virt/libvirt/volume/test_net.py
@@ -240,3 +240,16 @@ class LibvirtNetVolumeDriverTestCase(
tree.find('./auth/secret').get('uuid'))
libvirt_driver.disconnect_volume(connection_info,
mock.sentinel.instance)
+
+ def test_extend_volume(self):
+ device_path = '/dev/fake-dev'
+ connection_info = {'data': {'device_path': device_path}}
+
+ requested_size = 20 * pow(1024, 3) # 20GiB
+
+ libvirt_driver = net.LibvirtNetVolumeDriver(self.fake_host)
+ new_size = libvirt_driver.extend_volume(connection_info,
+ mock.sentinel.instance,
+ requested_size)
+
+ self.assertEqual(requested_size, new_size)
diff --git a/nova/tests/unit/virt/libvirt/volume/test_scaleio.py b/nova/tests/unit/virt/libvirt/volume/test_scaleio.py
index 1c3aa23cdc..bf42779b18 100644
--- a/nova/tests/unit/virt/libvirt/volume/test_scaleio.py
+++ b/nova/tests/unit/virt/libvirt/volume/test_scaleio.py
@@ -71,4 +71,5 @@ class LibvirtScaleIOVolumeDriverTestCase(
'extend_volume',
side_effect=brick_extend_vol):
self.assertEqual(extended_vol_size,
- sio.extend_volume(conn, mock.sentinel.instance))
+ sio.extend_volume(conn, mock.sentinel.instance,
+ extended_vol_size))
diff --git a/nova/tests/unit/virt/libvirt/volume/test_storpool.py b/nova/tests/unit/virt/libvirt/volume/test_storpool.py
index 96dd4894e3..d9df648f52 100644
--- a/nova/tests/unit/virt/libvirt/volume/test_storpool.py
+++ b/nova/tests/unit/virt/libvirt/volume/test_storpool.py
@@ -127,32 +127,34 @@ class LibvirtStorPoolVolumeDriverTestCase(
ci_1 = self.conn_info('1')
ci_2 = self.conn_info('2')
+ rs_1 = ci_1['data']['real_size']
+ rs_2 = ci_2['data']['real_size']
self.assertRaises(MockStorPoolExc,
libvirt_driver.extend_volume,
- ci_1, mock.sentinel.instance)
+ ci_1, mock.sentinel.instance, rs_1)
self.assertRaises(MockStorPoolExc,
libvirt_driver.extend_volume,
- ci_2, mock.sentinel.instance)
+ ci_2, mock.sentinel.instance, rs_2)
libvirt_driver.connect_volume(ci_1, mock.sentinel.instance)
self.assertStorpoolAttached(('1',))
- ns_1 = libvirt_driver.extend_volume(ci_1, mock.sentinel.instance)
+ ns_1 = libvirt_driver.extend_volume(ci_1, mock.sentinel.instance, rs_1)
self.assertEqual(ci_1['data']['real_size'], ns_1)
self.assertRaises(MockStorPoolExc,
libvirt_driver.extend_volume,
- ci_2, mock.sentinel.instance)
+ ci_2, mock.sentinel.instance, rs_2)
libvirt_driver.connect_volume(ci_2, mock.sentinel.instance)
self.assertStorpoolAttached(('1', '2'))
- ns_1 = libvirt_driver.extend_volume(ci_1, mock.sentinel.instance)
+ ns_1 = libvirt_driver.extend_volume(ci_1, mock.sentinel.instance, rs_1)
self.assertEqual(ci_1['data']['real_size'], ns_1)
- ns_2 = libvirt_driver.extend_volume(ci_2, mock.sentinel.instance)
+ ns_2 = libvirt_driver.extend_volume(ci_2, mock.sentinel.instance, rs_2)
self.assertEqual(ci_2['data']['real_size'], ns_2)
self.assertRaises(MockStorPoolExc,
@@ -168,7 +170,7 @@ class LibvirtStorPoolVolumeDriverTestCase(
self.assertRaises(MockStorPoolExc,
libvirt_driver.extend_volume,
- ci_1, mock.sentinel.instance)
+ ci_1, mock.sentinel.instance, rs_1)
libvirt_driver.disconnect_volume(ci_2, mock.sentinel.instance)
self.assertDictEqual({}, test_attached)
diff --git a/nova/tests/unit/virt/powervm/test_driver.py b/nova/tests/unit/virt/powervm/test_driver.py
index 9f3cd9d8c7..b307c3b767 100644
--- a/nova/tests/unit/virt/powervm/test_driver.py
+++ b/nova/tests/unit/virt/powervm/test_driver.py
@@ -587,7 +587,7 @@ class TestPowerVMDriver(test.NoDBTestCase):
@mock.patch('nova.virt.powervm.volume.fcvscsi.FCVscsiVolumeAdapter')
def test_extend_volume(self, mock_vscsi_adpt):
mock_bdm = self._fake_bdms()['block_device_mapping'][0]
- self.drv.extend_volume(mock_bdm.get('connection_info'), self.inst)
+ self.drv.extend_volume(mock_bdm.get('connection_info'), self.inst, 0)
mock_vscsi_adpt.return_value.extend_volume.assert_called_once_with()
def test_vol_drv_iter(self):
diff --git a/nova/virt/driver.py b/nova/virt/driver.py
index ff4748cc72..819d7dfde8 100644
--- a/nova/virt/driver.py
+++ b/nova/virt/driver.py
@@ -522,13 +522,15 @@ class ComputeDriver(object):
"""
raise NotImplementedError()
- def extend_volume(self, connection_info, instance):
+ def extend_volume(self, connection_info, instance, requested_size):
"""Extend the disk attached to the instance.
:param dict connection_info:
The connection for the extended volume.
:param nova.objects.instance.Instance instance:
The instance whose volume gets extended.
+ :param int requested_size
+ The requested new size of the volume in bytes
:return: None
"""
diff --git a/nova/virt/fake.py b/nova/virt/fake.py
index 26a06eabdb..488817edcc 100644
--- a/nova/virt/fake.py
+++ b/nova/virt/fake.py
@@ -326,7 +326,7 @@ class FakeDriver(driver.ComputeDriver):
self._mounts[instance_name] = {}
self._mounts[instance_name][mountpoint] = new_connection_info
- def extend_volume(self, connection_info, instance):
+ def extend_volume(self, connection_info, instance, requested_size):
"""Extend the disk attached to the instance."""
pass
diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py
index 8668087b65..158b647510 100644
--- a/nova/virt/libvirt/driver.py
+++ b/nova/virt/libvirt/driver.py
@@ -1266,9 +1266,10 @@ class LibvirtDriver(driver.ComputeDriver):
driver_block_device.get_volume_id(connection_info),
instance=instance)
- def _extend_volume(self, connection_info, instance):
+ def _extend_volume(self, connection_info, instance, requested_size):
vol_driver = self._get_volume_driver(connection_info)
- return vol_driver.extend_volume(connection_info, instance)
+ return vol_driver.extend_volume(connection_info, instance,
+ requested_size)
def _use_native_luks(self, encryption=None):
"""Is LUKS the required provider and native QEMU LUKS available
@@ -1618,9 +1619,10 @@ class LibvirtDriver(driver.ComputeDriver):
self._disconnect_volume(context, connection_info, instance,
encryption=encryption)
- def extend_volume(self, connection_info, instance):
+ def extend_volume(self, connection_info, instance, requested_size):
try:
- new_size = self._extend_volume(connection_info, instance)
+ new_size = self._extend_volume(connection_info, instance,
+ requested_size)
except NotImplementedError:
raise exception.ExtendVolumeNotSupported()
@@ -1631,7 +1633,22 @@ class LibvirtDriver(driver.ComputeDriver):
state = guest.get_power_state(self._host)
active_state = state in (power_state.RUNNING, power_state.PAUSED)
if active_state:
- disk_path = connection_info['data']['device_path']
+ if 'device_path' in connection_info['data']:
+ disk_path = connection_info['data']['device_path']
+ else:
+ # Some drivers (eg. net) don't put the device_path
+ # into the connection_info. Match disks by their serial
+ # number instead
+ volume_id = driver_block_device.get_volume_id(
+ connection_info)
+ disk = next(iter([
+ d for d in guest.get_all_disks()
+ if d.serial == volume_id
+ ]), None)
+ if not disk:
+ raise exception.VolumeNotFound(volume_id=volume_id)
+ disk_path = disk.target_dev
+
LOG.debug('resizing block device %(dev)s to %(size)u kb',
{'dev': disk_path, 'size': new_size})
dev = guest.get_block_device(disk_path)
diff --git a/nova/virt/libvirt/volume/fibrechannel.py b/nova/virt/libvirt/volume/fibrechannel.py
index 8a304cd79d..7a0cf5e843 100644
--- a/nova/virt/libvirt/volume/fibrechannel.py
+++ b/nova/virt/libvirt/volume/fibrechannel.py
@@ -75,7 +75,7 @@ class LibvirtFibreChannelVolumeDriver(libvirt_volume.LibvirtBaseVolumeDriver):
super(LibvirtFibreChannelVolumeDriver,
self).disconnect_volume(connection_info, instance)
- def extend_volume(self, connection_info, instance):
+ def extend_volume(self, connection_info, instance, requested_size):
"""Extend the volume."""
LOG.debug("calling os-brick to extend FC Volume", instance=instance)
new_size = self.connector.extend_volume(connection_info['data'])
diff --git a/nova/virt/libvirt/volume/iscsi.py b/nova/virt/libvirt/volume/iscsi.py
index 6a6d6f1006..9eb08b0a90 100644
--- a/nova/virt/libvirt/volume/iscsi.py
+++ b/nova/virt/libvirt/volume/iscsi.py
@@ -80,7 +80,7 @@ class LibvirtISCSIVolumeDriver(libvirt_volume.LibvirtBaseVolumeDriver):
super(LibvirtISCSIVolumeDriver,
self).disconnect_volume(connection_info, instance)
- def extend_volume(self, connection_info, instance):
+ def extend_volume(self, connection_info, instance, requested_size):
"""Extend the volume."""
LOG.debug("calling os-brick to extend iSCSI Volume", instance=instance)
new_size = self.connector.extend_volume(connection_info['data'])
diff --git a/nova/virt/libvirt/volume/net.py b/nova/virt/libvirt/volume/net.py
index 3b432dea54..8faa61a678 100644
--- a/nova/virt/libvirt/volume/net.py
+++ b/nova/virt/libvirt/volume/net.py
@@ -132,3 +132,9 @@ class LibvirtNetVolumeDriver(libvirt_volume.LibvirtBaseVolumeDriver):
super(LibvirtNetVolumeDriver,
self).disconnect_volume(connection_info, instance)
self._delete_secret_by_name(connection_info)
+
+ def extend_volume(self, connection_info, instance, requested_size):
+ # There is nothing to do for network volumes. Cinder already extended
+ # the volume and there is no local block device which needs to be
+ # refreshed.
+ return requested_size
diff --git a/nova/virt/libvirt/volume/nvme.py b/nova/virt/libvirt/volume/nvme.py
index 8d20ab10d5..4b4e701ed9 100644
--- a/nova/virt/libvirt/volume/nvme.py
+++ b/nova/virt/libvirt/volume/nvme.py
@@ -53,7 +53,7 @@ class LibvirtNVMEVolumeDriver(libvirt_volume.LibvirtVolumeDriver):
super(LibvirtNVMEVolumeDriver,
self).disconnect_volume(connection_info, instance)
- def extend_volume(self, connection_info, instance):
+ def extend_volume(self, connection_info, instance, requested_size):
"""Extend the volume."""
LOG.debug("calling os-brick to extend NVMe Volume", instance=instance)
new_size = self.connector.extend_volume(connection_info['data'])
diff --git a/nova/virt/libvirt/volume/scaleio.py b/nova/virt/libvirt/volume/scaleio.py
index 4195bc1096..2fa2ea3fcc 100644
--- a/nova/virt/libvirt/volume/scaleio.py
+++ b/nova/virt/libvirt/volume/scaleio.py
@@ -62,7 +62,7 @@ class LibvirtScaleIOVolumeDriver(libvirt_volume.LibvirtBaseVolumeDriver):
super(LibvirtScaleIOVolumeDriver, self).disconnect_volume(
connection_info, instance)
- def extend_volume(self, connection_info, instance):
+ def extend_volume(self, connection_info, instance, requested_size):
LOG.debug("calling os-brick to extend ScaleIO Volume",
instance=instance)
new_size = self.connector.extend_volume(connection_info['data'])
diff --git a/nova/virt/libvirt/volume/storpool.py b/nova/virt/libvirt/volume/storpool.py
index a99589a6ca..cc950186ca 100644
--- a/nova/virt/libvirt/volume/storpool.py
+++ b/nova/virt/libvirt/volume/storpool.py
@@ -46,7 +46,7 @@ class LibvirtStorPoolVolumeDriver(libvirt_volume.LibvirtVolumeDriver):
self.connector.disconnect_volume(connection_info['data'], None)
LOG.debug("Detached StorPool volume", instance=instance)
- def extend_volume(self, connection_info, instance):
+ def extend_volume(self, connection_info, instance, requested_size):
"""Extend the volume."""
LOG.debug("Extending StorPool volume %s",
connection_info['data']['volume'], instance=instance)
diff --git a/nova/virt/libvirt/volume/volume.py b/nova/virt/libvirt/volume/volume.py
index aaffaa074c..114887445e 100644
--- a/nova/virt/libvirt/volume/volume.py
+++ b/nova/virt/libvirt/volume/volume.py
@@ -132,8 +132,19 @@ class LibvirtBaseVolumeDriver(object):
"""Disconnect the volume."""
pass
- def extend_volume(self, connection_info, instance):
- """Extend the volume."""
+ def extend_volume(self, connection_info, instance, requested_size):
+ """Extend the volume.
+
+ :param: connection_info: connection information about the volume
+ that has been extended.
+ :param: instance: instance connected to the newly extended volume.
+ :param: requested_size: new extended size (in bytes) for the volume to
+ be extended.
+
+ :returns: the new size to use when resizing the disk in QEMU.
+
+ Note: the requested_size parameter is not used by all volume drivers
+ """
raise NotImplementedError()
diff --git a/nova/virt/powervm/driver.py b/nova/virt/powervm/driver.py
index a153257ee7..d8f62954ea 100644
--- a/nova/virt/powervm/driver.py
+++ b/nova/virt/powervm/driver.py
@@ -634,12 +634,13 @@ class PowerVMDriver(driver.ComputeDriver):
# Run the flow
tf_base.run(flow, instance=instance)
- def extend_volume(self, connection_info, instance):
+ def extend_volume(self, connection_info, instance, requested_size):
"""Extend the disk attached to the instance.
:param dict connection_info: The connection for the extended volume.
:param nova.objects.instance.Instance instance:
The instance whose volume gets extended.
+ :param int requested_size: The requested new volume size in bytes.
:return: None
"""
diff --git a/releasenotes/notes/bp-extend-in-use-rbd-volumes-8f334ce2a06ee247.yaml b/releasenotes/notes/bp-extend-in-use-rbd-volumes-8f334ce2a06ee247.yaml
new file mode 100644
index 0000000000..4e81eb6665
--- /dev/null
+++ b/releasenotes/notes/bp-extend-in-use-rbd-volumes-8f334ce2a06ee247.yaml
@@ -0,0 +1,5 @@
+---
+features:
+ - |
+ Adds support for extending RBD attached volumes using the libvirt network
+ volume driver.