Convert get_hypervisor_ip to use hostnames

Instead of using ID to lookup hypervisor IPs, use hostnames. IDs are
different in undercloud and overcloud (a compute node's Ironic node
UUID in the undercloud isn't the same as its hypervisor UUID in the
overcloud). In addition, Nova uses both integer IDs (before 2.53) and
UUIDs (2.53 and later) for hypervisors. Hostnames are common to both
undercloud and overcloud, and don't change depending on the
microversion.

Change-Id: I34445e0f566dd48271740c357f74f632152776ed
This commit is contained in:
Artom Lifshitz 2018-07-16 13:15:03 -04:00
parent b668dcea44
commit a2d308991e
4 changed files with 32 additions and 74 deletions

View File

@ -50,10 +50,8 @@ class PointerDeviceTypeFromImages(base.BaseTest):
def _verify_pointer_device_type_from_images(self, server_id): def _verify_pointer_device_type_from_images(self, server_id):
# Retrieve the server's hypervizor hostname # Retrieve the server's hypervizor hostname
server = self.servers_client.show_server(server_id)['server']
hostname = server['OS-EXT-SRV-ATTR:host']
compute_node_address = whitebox_utils.get_hypervisor_ip( compute_node_address = whitebox_utils.get_hypervisor_ip(
self.hypervisor_client, hostname) self.servers_client, server_id)
self.assertIsNotNone(compute_node_address) self.assertIsNotNone(compute_node_address)
# Retrieve input device from virsh dumpxml # Retrieve input device from virsh dumpxml

View File

@ -21,39 +21,11 @@ CONF = config.CONF
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
def _get_hv_ip_from_conf(id): def get_hypervisor_ip(admin_servers_client, server_id):
conf_hvs = CONF.whitebox.hypervisors server = admin_servers_client.show_server(server_id)
if conf_hvs: host = server['server']['OS-EXT-SRV-ATTR:host']
return conf_hvs.get(id) try:
return CONF.whitebox.hypervisors[host]
except KeyError:
def get_hypervisor_ip(client, hostname): LOG.error('Unable to find IP in conf. Server: %s, host: %s.',
"""Get the IP for a comute node's hypervisor. (server_id, host))
Finds the IP address of a compute node based on its hostname. This is
necessary in case a compute node isn't accessible by its IP address as it
appears in the nova API. Such a situation arises in infrared deployments of
OSP12, for example.
:param client: The hypervisors client to use.
:param hostname: The compute node's hostname, from the instance's
``OS-EXT-SRV-ATTR:host`` attribute.
:return: The IP address of the compute node - either as configuired in the
hypervisors section of our config file, or as returned by the nova API
as fallback.
"""
hvs = client.list_hypervisors(detail=True)['hypervisors']
compute_node_address = None
for hv in hvs:
if hv['service']['host'] == hostname:
hv_ip = _get_hv_ip_from_conf(str(hv['id']))
if hv_ip:
compute_node_address = hv_ip
LOG.info('Using %s for hypervisor %s from config file',
hv_ip, hv['id'])
else:
compute_node_address = hv['host_ip']
LOG.info('Using %s as fallback since hypervisor %s not in '
'config file', compute_node_address, hv['id'])
return compute_node_address

View File

@ -39,9 +39,11 @@ opts = [
help='Deployment is containerized.'), help='Deployment is containerized.'),
cfg.DictOpt( cfg.DictOpt(
'hypervisors', 'hypervisors',
help="Dictionary of hypervisor IP addresses, in the " help="Dictionary of hypervisor IP addresses. The keys are the "
"id => IP format. Should be used when the IP returned " "hostnames as they appear in the OS-EXT-SRV-ATTR:host field of "
"by 'nova hypervisor-show' isn't reachable from the " "Nova's show server details API. The values are the ctlplane IP "
"node running tempest. Starting with microversion " "addresses. For example:"
"2.53, the id is a UUID."), ""
" hypervisors = compute-0.localdomain:172.16.42.11,"
" controller-0.localdomain:172.16.42.10"),
] ]

View File

@ -18,40 +18,26 @@ from whitebox_tempest_plugin.common import utils
from whitebox_tempest_plugin.tests import base from whitebox_tempest_plugin.tests import base
def fake_show_server(server_id):
if server_id == 'fake-id':
return {'server': {'OS-EXT-SRV-ATTR:host': 'fake-host'}}
else:
return {'server': {'OS-EXT-SRV-ATTR:host': 'missing-host'}}
class UtilsTestCase(base.WhiteboxPluginTestCase): class UtilsTestCase(base.WhiteboxPluginTestCase):
def setUp(self): def setUp(self):
super(UtilsTestCase, self).setUp() super(UtilsTestCase, self).setUp()
self.client = mock.Mock() self.client = mock.Mock()
fake_hvs = { self.client.show_server = fake_show_server
'hypervisors': [ self.flags(hypervisors={'fake-host': 'fake-ip'}, group='whitebox')
{'service': {'host': 'host1'},
'host_ip': '192.168.0.1',
'id': 1},
{'service': {'host': 'host2'},
'host_ip': '192.168.0.2',
'id': 2},
{'service': {'host': 'host3'},
'host_ip': '192.168.0.3',
'id': 3}
]
}
self.client.list_hypervisors = mock.Mock(return_value=fake_hvs)
@mock.patch.object(utils.LOG, 'info') def test_get_hypervisor_ip(self):
def test_get_hypervisor_ip_hv_in_config(self, mock_log): self.assertEqual('fake-ip',
self.flags(hypervisors={'1': '10.0.0.1'}, group='whitebox') utils.get_hypervisor_ip(self.client, 'fake-id'))
self.assertEqual('10.0.0.1',
utils.get_hypervisor_ip(self.client, 'host1'))
self.assertIn('from config file', mock_log.call_args_list[0][0][0])
@mock.patch.object(utils.LOG, 'info') @mock.patch.object(utils.LOG, 'error')
def test_get_hypervisor_ip_hv_not_in_config(self, mock_log): def test_get_hypervisor_ip_keyerror(self, mock_log):
self.flags(hypervisors={'1': '10.0.0.1'}, group='whitebox') self.assertIsNone(utils.get_hypervisor_ip(self.client, 'missing-id'))
self.assertEqual('192.168.0.2', self.assertIn('Unable', mock_log.call_args_list[0][0][0])
utils.get_hypervisor_ip(self.client, 'host2'))
self.assertIn('not in config file', mock_log.call_args_list[0][0][0])
def test_get_hypervisor_ip_no_hvs_in_config(self):
self.assertEqual('192.168.0.3',
utils.get_hypervisor_ip(self.client, 'host3'))