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
This commit is contained in:
parent
c9dca64fa6
commit
eab58069ea
@ -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',
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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')
|
||||
|
@ -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'])
|
||||
|
@ -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'])
|
||||
|
@ -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)
|
||||
|
@ -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))
|
||||
|
@ -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)
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
"""
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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'])
|
||||
|
@ -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'])
|
||||
|
@ -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
|
||||
|
@ -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'])
|
||||
|
@ -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'])
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
||||
|
||||
|
@ -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
|
||||
"""
|
||||
|
||||
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Adds support for extending RBD attached volumes using the libvirt network
|
||||
volume driver.
|
Loading…
Reference in New Issue
Block a user