Skip to content

Commit 2ce5a44

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "libvirt: manage COMPUTE_STATUS_DISABLED for hypervisor connection"
2 parents 8652477 + 9b99be4 commit 2ce5a44

File tree

2 files changed

+80
-4
lines changed

2 files changed

+80
-4
lines changed

nova/tests/unit/virt/libvirt/test_driver.py

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1583,7 +1583,11 @@ def test_set_host_enabled_with_disable(self, mock_svc, mock_save):
15831583
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
15841584
svc = self._create_service(host='fake-mini')
15851585
mock_svc.return_value = svc
1586-
drvr._set_host_enabled(False)
1586+
with mock.patch.object(
1587+
drvr, '_update_compute_provider_status') as ucps:
1588+
drvr._set_host_enabled(False)
1589+
ucps.assert_called_once_with(
1590+
test.MatchType(context.RequestContext), svc)
15871591
self.assertTrue(svc.disabled)
15881592
mock_save.assert_called_once_with()
15891593

@@ -1594,7 +1598,10 @@ def test_set_host_enabled_with_enable(self, mock_svc, mock_save):
15941598
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
15951599
svc = self._create_service(disabled=True, host='fake-mini')
15961600
mock_svc.return_value = svc
1597-
drvr._set_host_enabled(True)
1601+
with mock.patch.object(
1602+
drvr, '_update_compute_provider_status') as ucps:
1603+
drvr._set_host_enabled(True)
1604+
ucps.assert_not_called()
15981605
# since disabled_reason is not set and not prefixed with "AUTO:",
15991606
# service should not be enabled.
16001607
mock_save.assert_not_called()
@@ -1608,7 +1615,10 @@ def test_set_host_enabled_with_enable_state_enabled(self, mock_svc,
16081615
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
16091616
svc = self._create_service(disabled=False, host='fake-mini')
16101617
mock_svc.return_value = svc
1611-
drvr._set_host_enabled(True)
1618+
with mock.patch.object(
1619+
drvr, '_update_compute_provider_status') as ucps:
1620+
drvr._set_host_enabled(True)
1621+
ucps.assert_not_called()
16121622
self.assertFalse(svc.disabled)
16131623
mock_save.assert_not_called()
16141624

@@ -1620,7 +1630,10 @@ def test_set_host_enabled_with_disable_state_disabled(self, mock_svc,
16201630
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
16211631
svc = self._create_service(disabled=True, host='fake-mini')
16221632
mock_svc.return_value = svc
1623-
drvr._set_host_enabled(False)
1633+
with mock.patch.object(
1634+
drvr, '_update_compute_provider_status') as ucps:
1635+
drvr._set_host_enabled(False)
1636+
ucps.assert_not_called()
16241637
mock_save.assert_not_called()
16251638
self.assertTrue(svc.disabled)
16261639

@@ -1635,6 +1648,47 @@ def test_set_host_enabled_swallows_exceptions(self):
16351648
db_mock.side_effect = exception.NovaException
16361649
drvr._set_host_enabled(False)
16371650

1651+
def test_update_compute_provider_status(self):
1652+
"""Tests happy path of calling _update_compute_provider_status"""
1653+
virtapi = mock.Mock()
1654+
drvr = libvirt_driver.LibvirtDriver(virtapi, read_only=True)
1655+
ctxt = context.get_admin_context()
1656+
service = self._create_service()
1657+
service.compute_node = objects.ComputeNode(uuid=uuids.rp_uuid)
1658+
drvr._update_compute_provider_status(ctxt, service)
1659+
virtapi.update_compute_provider_status.assert_called_once_with(
1660+
ctxt, uuids.rp_uuid, enabled=not service.disabled)
1661+
1662+
def test_update_compute_provider_status_swallows_exceptions(self):
1663+
"""Tests error path handling in _update_compute_provider_status"""
1664+
# First we'll make Service.compute_node loading raise an exception
1665+
# by not setting the field and we cannot lazy-load it from an orphaned
1666+
# Service object.
1667+
virtapi = mock.Mock()
1668+
drvr = libvirt_driver.LibvirtDriver(virtapi, read_only=True)
1669+
ctxt = context.get_admin_context()
1670+
service = self._create_service(host='fake-host', disabled=True)
1671+
drvr._update_compute_provider_status(ctxt, service)
1672+
virtapi.update_compute_provider_status.assert_not_called()
1673+
self.assertIn('An error occurred while updating compute node resource '
1674+
'provider status to "disabled" for provider: fake-host',
1675+
self.stdlog.logger.output)
1676+
1677+
# Now fix Service.compute_node loading but make the VirtAPI call fail.
1678+
service.compute_node = objects.ComputeNode(uuid=uuids.rp_uuid)
1679+
service.disabled = False # make sure the log message logic works
1680+
error = exception.TraitRetrievalFailed(error='oops')
1681+
virtapi.update_compute_provider_status.side_effect = error
1682+
drvr._update_compute_provider_status(ctxt, service)
1683+
virtapi.update_compute_provider_status.assert_called_once_with(
1684+
ctxt, uuids.rp_uuid, enabled=True)
1685+
log_output = self.stdlog.logger.output
1686+
self.assertIn('An error occurred while updating compute node resource '
1687+
'provider status to "enabled" for provider: %s' %
1688+
uuids.rp_uuid, log_output)
1689+
# The error should have been logged as well.
1690+
self.assertIn(six.text_type(error), log_output)
1691+
16381692
@mock.patch.object(fakelibvirt.virConnect, "nodeDeviceLookupByName")
16391693
def test_prepare_pci_device(self, mock_lookup):
16401694

nova/virt/libvirt/driver.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3894,6 +3894,25 @@ def _detach_direct_passthrough_ports(self, context, instance, guest):
38943894
if pci_dev.address in direct_passthrough_pci_addresses])
38953895
self._detach_pci_devices(guest, direct_passthrough_pci_addresses)
38963896

3897+
def _update_compute_provider_status(self, context, service):
3898+
"""Calls the ComputeVirtAPI.update_compute_provider_status method
3899+
3900+
:param context: nova auth RequestContext
3901+
:param service: nova.objects.Service record for this host which is
3902+
expected to only manage a single ComputeNode
3903+
"""
3904+
rp_uuid = None
3905+
try:
3906+
rp_uuid = service.compute_node.uuid
3907+
self.virtapi.update_compute_provider_status(
3908+
context, rp_uuid, enabled=not service.disabled)
3909+
except Exception:
3910+
LOG.warning(
3911+
'An error occurred while updating compute node '
3912+
'resource provider status to "%s" for provider: %s',
3913+
'disabled' if service.disabled else 'enabled',
3914+
rp_uuid or service.host, exc_info=True)
3915+
38973916
def _set_host_enabled(self, enabled,
38983917
disable_reason=DISABLE_REASON_UNDEFINED):
38993918
"""Enables / Disables the compute service on this host.
@@ -3930,6 +3949,9 @@ def _set_host_enabled(self, enabled,
39303949
service.save()
39313950
LOG.debug('Updating compute service status to %s',
39323951
status_name[disable_service])
3952+
# Update the disabled trait status on the corresponding
3953+
# compute node resource provider in placement.
3954+
self._update_compute_provider_status(ctx, service)
39333955
else:
39343956
LOG.debug('Not overriding manual compute service '
39353957
'status with: %s',

0 commit comments

Comments
 (0)