Pass bdm info to _get_instance_disk_info method
If bdm info is not passed to the '_get_instance_disk_info' method, then in case of processing qcow2 backing file, it raises permission denied error provided the backing is belonging to an attached and NFS-hosted Cinder volume. Passed bdm info to the '_get_instance_disk_info' method if any volumes are attached to the instance. Co-Authored-By: Ankit Agrawal <ankit11.agrawal@nttdata.com> Closes-Bug: #1416132 Change-Id: I5d5c64ea4d304022282ec9ab121e295f3c9e0d03
This commit is contained in:
parent
b57fbc725f
commit
1345d0fe1c
|
@ -10552,11 +10552,15 @@ class LibvirtConnTestCase(test.NoDBTestCase):
|
|||
drvr._undefine_domain(instance)
|
||||
|
||||
@mock.patch.object(host.Host, "list_instance_domains")
|
||||
def test_disk_over_committed_size_total(self, mock_list):
|
||||
@mock.patch.object(objects.BlockDeviceMappingList, "bdms_by_instance_uuid")
|
||||
@mock.patch.object(objects.InstanceList, "get_by_filters")
|
||||
def test_disk_over_committed_size_total(self, mock_get, mock_bdms,
|
||||
mock_list):
|
||||
# Ensure destroy calls managedSaveRemove for saved instance.
|
||||
class DiagFakeDomain(object):
|
||||
def __init__(self, name):
|
||||
self._name = name
|
||||
self._uuid = str(uuid.uuid4())
|
||||
|
||||
def ID(self):
|
||||
return 1
|
||||
|
@ -10565,14 +10569,15 @@ class LibvirtConnTestCase(test.NoDBTestCase):
|
|||
return self._name
|
||||
|
||||
def UUIDString(self):
|
||||
return "19479fee-07a5-49bb-9138-d3738280d63c"
|
||||
return self._uuid
|
||||
|
||||
def XMLDesc(self, flags):
|
||||
return "<domain/>"
|
||||
|
||||
mock_list.return_value = [
|
||||
instance_domains = [
|
||||
DiagFakeDomain("instance0000001"),
|
||||
DiagFakeDomain("instance0000002")]
|
||||
mock_list.return_value = instance_domains
|
||||
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
|
||||
|
||||
|
@ -10592,21 +10597,39 @@ class LibvirtConnTestCase(test.NoDBTestCase):
|
|||
def get_info(instance_name, xml, **kwargs):
|
||||
return fake_disks.get(instance_name)
|
||||
|
||||
instance_uuids = [dom.UUIDString() for dom in instance_domains]
|
||||
instances = [objects.Instance(
|
||||
uuid=instance_uuids[0],
|
||||
root_device_name='/dev/vda'),
|
||||
objects.Instance(
|
||||
uuid=instance_uuids[1],
|
||||
root_device_name='/dev/vdb')
|
||||
]
|
||||
mock_get.return_value = instances
|
||||
|
||||
with mock.patch.object(drvr,
|
||||
"_get_instance_disk_info") as mock_info:
|
||||
mock_info.side_effect = get_info
|
||||
|
||||
result = drvr._get_disk_over_committed_size_total()
|
||||
self.assertEqual(result, 10653532160)
|
||||
mock_list.assert_called_with(only_guests=True, only_running=True)
|
||||
self.assertTrue(mock_info.called)
|
||||
mock_list.assert_called_once_with()
|
||||
self.assertEqual(2, mock_info.call_count)
|
||||
|
||||
filters = {'uuid': instance_uuids}
|
||||
mock_get.assert_called_once_with(mock.ANY, filters, use_slave=True)
|
||||
mock_bdms.assert_called_with(mock.ANY, instance_uuids)
|
||||
|
||||
@mock.patch.object(host.Host, "list_instance_domains")
|
||||
def test_disk_over_committed_size_total_eperm(self, mock_list):
|
||||
@mock.patch.object(objects.BlockDeviceMappingList, "bdms_by_instance_uuid")
|
||||
@mock.patch.object(objects.InstanceList, "get_by_filters")
|
||||
def test_disk_over_committed_size_total_eperm(self, mock_get, mock_bdms,
|
||||
mock_list):
|
||||
# Ensure destroy calls managedSaveRemove for saved instance.
|
||||
class DiagFakeDomain(object):
|
||||
def __init__(self, name):
|
||||
self._name = name
|
||||
self._uuid = str(uuid.uuid4())
|
||||
|
||||
def ID(self):
|
||||
return 1
|
||||
|
@ -10615,14 +10638,15 @@ class LibvirtConnTestCase(test.NoDBTestCase):
|
|||
return self._name
|
||||
|
||||
def UUIDString(self):
|
||||
return "19479fee-07a5-49bb-9138-d3738280d63c"
|
||||
return self._uuid
|
||||
|
||||
def XMLDesc(self, flags):
|
||||
return "<domain/>"
|
||||
|
||||
mock_list.return_value = [
|
||||
instance_domains = [
|
||||
DiagFakeDomain("instance0000001"),
|
||||
DiagFakeDomain("instance0000002")]
|
||||
mock_list.return_value = instance_domains
|
||||
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
|
||||
|
||||
|
@ -10639,24 +10663,46 @@ class LibvirtConnTestCase(test.NoDBTestCase):
|
|||
'disk_size': '10737418240',
|
||||
'over_committed_disk_size': '21474836480'}]}
|
||||
|
||||
def side_effect(name, dom):
|
||||
def side_effect(name, dom, block_device_info):
|
||||
if name == 'instance0000001':
|
||||
self.assertEqual('/dev/vda',
|
||||
block_device_info['root_device_name'])
|
||||
raise OSError(errno.EACCES, 'Permission denied')
|
||||
if name == 'instance0000002':
|
||||
self.assertEqual('/dev/vdb',
|
||||
block_device_info['root_device_name'])
|
||||
return fake_disks.get(name)
|
||||
get_disk_info = mock.Mock()
|
||||
get_disk_info.side_effect = side_effect
|
||||
drvr._get_instance_disk_info = get_disk_info
|
||||
|
||||
instance_uuids = [dom.UUIDString() for dom in instance_domains]
|
||||
instances = [objects.Instance(
|
||||
uuid=instance_uuids[0],
|
||||
root_device_name='/dev/vda'),
|
||||
objects.Instance(
|
||||
uuid=instance_uuids[1],
|
||||
root_device_name='/dev/vdb')
|
||||
]
|
||||
mock_get.return_value = instances
|
||||
|
||||
result = drvr._get_disk_over_committed_size_total()
|
||||
self.assertEqual(21474836480, result)
|
||||
mock_list.assert_called_with(only_guests=True, only_running=True)
|
||||
mock_list.assert_called_once_with()
|
||||
self.assertEqual(2, get_disk_info.call_count)
|
||||
filters = {'uuid': instance_uuids}
|
||||
mock_get.assert_called_once_with(mock.ANY, filters, use_slave=True)
|
||||
mock_bdms.assert_called_with(mock.ANY, instance_uuids)
|
||||
|
||||
@mock.patch.object(host.Host, "list_instance_domains",
|
||||
return_value=[mock.MagicMock(name='foo')])
|
||||
@mock.patch.object(libvirt_driver.LibvirtDriver, "_get_instance_disk_info",
|
||||
side_effect=exception.VolumeBDMPathNotFound(path='bar'))
|
||||
@mock.patch.object(objects.BlockDeviceMappingList, "bdms_by_instance_uuid")
|
||||
@mock.patch.object(objects.InstanceList, "get_by_filters")
|
||||
def test_disk_over_committed_size_total_bdm_not_found(self,
|
||||
mock_get,
|
||||
mock_bdms,
|
||||
mock_get_disk_info,
|
||||
mock_list_domains):
|
||||
# Tests that we handle VolumeBDMPathNotFound gracefully.
|
||||
|
|
|
@ -6923,11 +6923,46 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||
"""Return total over committed disk size for all instances."""
|
||||
# Disk size that all instance uses : virtual_size - disk_size
|
||||
disk_over_committed_size = 0
|
||||
for guest in self._host.list_guests():
|
||||
instance_domains = self._host.list_instance_domains()
|
||||
if not instance_domains:
|
||||
return disk_over_committed_size
|
||||
|
||||
# Get all instance uuids
|
||||
instance_uuids = [dom.UUIDString() for dom in instance_domains]
|
||||
ctx = nova_context.get_admin_context()
|
||||
# Get instance object list by uuid filter
|
||||
filters = {'uuid': instance_uuids}
|
||||
# NOTE(ankit): objects.InstanceList.get_by_filters method is
|
||||
# getting called twice one is here and another in the
|
||||
# _update_available_resource method of resource_tracker. Since
|
||||
# _update_available_resource method is synchronized, there is a
|
||||
# possibility the instances list retrieved here to calculate
|
||||
# disk_over_committed_size would differ to the list you would get
|
||||
# in _update_available_resource method for calculating usages based
|
||||
# on instance utilization.
|
||||
local_instance_list = objects.InstanceList.get_by_filters(
|
||||
ctx, filters, use_slave=True)
|
||||
# Convert instance list to dictionary with instace uuid as key.
|
||||
local_instances = {inst.uuid: inst for inst in local_instance_list}
|
||||
|
||||
# Get bdms by instance uuids
|
||||
bdms = objects.BlockDeviceMappingList.bdms_by_instance_uuid(
|
||||
ctx, instance_uuids)
|
||||
|
||||
for dom in instance_domains:
|
||||
try:
|
||||
guest = libvirt_guest.Guest(dom)
|
||||
xml = guest.get_xml_desc()
|
||||
|
||||
disk_infos = self._get_instance_disk_info(guest.name, xml)
|
||||
block_device_info = None
|
||||
if guest.uuid in local_instances:
|
||||
# Get block device info for instance
|
||||
block_device_info = driver.get_block_device_info(
|
||||
local_instances[guest.uuid], bdms[guest.uuid])
|
||||
|
||||
disk_infos = self._get_instance_disk_info(guest.name, xml,
|
||||
block_device_info=block_device_info)
|
||||
|
||||
for info in disk_infos:
|
||||
disk_over_committed_size += int(
|
||||
info['over_committed_disk_size'])
|
||||
|
|
Loading…
Reference in New Issue