Use bmc ipv6 address while processing introspection data
Change-Id: Id6d56860a4e47f28c875ed6032e1f99a997aea9b Story: #2005779 Task: #33503
This commit is contained in:
parent
9819bf3012
commit
fcb0ca8a6e
@ -21,6 +21,16 @@ _OPTS = [
|
||||
default='fake-hardware',
|
||||
help=_('The name of the Ironic driver used by the enroll '
|
||||
'hook when creating a new node in Ironic.')),
|
||||
cfg.ListOpt('enabled_bmc_address_version',
|
||||
default=['4', '6'],
|
||||
help=_('IP version of BMC address that will be '
|
||||
'used when enrolling a new node in Ironic. '
|
||||
'Defaults to "4,6". Could be "4" (use v4 address '
|
||||
'only), "4,6" (v4 address have higher priority and '
|
||||
'if both addresses found v6 version is ignored), '
|
||||
'"6,4" (v6 is desired but fall back to v4 address '
|
||||
'for BMCs having v4 address, opposite to "4,6"), '
|
||||
'"6" (use v6 address only and ignore v4 version).')),
|
||||
]
|
||||
|
||||
|
||||
|
@ -28,9 +28,16 @@ LOG = utils.getProcessingLogger(__name__)
|
||||
|
||||
def _extract_node_driver_info(introspection_data):
|
||||
node_driver_info = {}
|
||||
ipmi_address = utils.get_ipmi_address_from_data(introspection_data)
|
||||
if ipmi_address:
|
||||
node_driver_info['ipmi_address'] = ipmi_address
|
||||
for ip_version in CONF.discovery.enabled_bmc_address_version:
|
||||
address = None
|
||||
if ip_version == '4':
|
||||
address = utils.get_ipmi_address_from_data(introspection_data)
|
||||
elif ip_version == '6':
|
||||
address = utils.get_ipmi_v6address_from_data(introspection_data)
|
||||
|
||||
if address:
|
||||
node_driver_info['ipmi_address'] = address
|
||||
break
|
||||
else:
|
||||
LOG.warning('No BMC address provided, discovered node will be '
|
||||
'created without ipmi address')
|
||||
|
@ -243,9 +243,11 @@ class ValidateInterfacesHook(base.ProcessingHook):
|
||||
"""Validate information about network interfaces."""
|
||||
|
||||
bmc_address = utils.get_ipmi_address_from_data(introspection_data)
|
||||
bmc_v6address = utils.get_ipmi_v6address_from_data(introspection_data)
|
||||
# Overwrite the old ipmi_address field to avoid inconsistency
|
||||
introspection_data['ipmi_address'] = bmc_address
|
||||
if not bmc_address:
|
||||
introspection_data['ipmi_v6address'] = bmc_v6address
|
||||
if not (bmc_address or bmc_v6address):
|
||||
LOG.debug('No BMC address provided in introspection data, '
|
||||
'assuming virtual environment', data=introspection_data)
|
||||
|
||||
|
@ -79,8 +79,10 @@ def _store_logs(introspection_data, node_info):
|
||||
|
||||
def _find_node_info(introspection_data, failures):
|
||||
try:
|
||||
address = utils.get_ipmi_address_from_data(introspection_data)
|
||||
v6address = utils.get_ipmi_v6address_from_data(introspection_data)
|
||||
return node_cache.find_node(
|
||||
bmc_address=utils.get_ipmi_address_from_data(introspection_data),
|
||||
bmc_address=[address, v6address],
|
||||
mac=utils.get_valid_macs(introspection_data))
|
||||
except utils.NotFoundInCacheError as exc:
|
||||
not_found_hook = plugins_base.node_not_found_hook_manager()
|
||||
|
@ -92,6 +92,7 @@ class InventoryTest(BaseTest):
|
||||
# Prepare some realistic inventory
|
||||
# https://github.com/openstack/ironic-inspector/blob/master/HTTP-API.rst # noqa
|
||||
self.bmc_address = '1.2.3.4'
|
||||
self.bmc_v6address = '2001:1234:1234:1234:1234:1234:1234:1234/64'
|
||||
self.macs = (
|
||||
['11:22:33:44:55:66', '66:55:44:33:22:11', '7c:fe:90:29:26:52'])
|
||||
self.ips = ['1.2.1.2', '1.2.1.1', '1.2.1.3']
|
||||
@ -137,7 +138,8 @@ class InventoryTest(BaseTest):
|
||||
'memory': {
|
||||
'physical_mb': 12288
|
||||
},
|
||||
'bmc_address': self.bmc_address
|
||||
'bmc_address': self.bmc_address,
|
||||
'bmc_v6address': self.bmc_v6address
|
||||
},
|
||||
'root_disk': {'name': '/dev/sda', 'model': 'Big Data Disk',
|
||||
'size': 1000 * units.Gi,
|
||||
|
@ -60,19 +60,39 @@ class TestEnrollNodeNotFoundHook(test_base.NodeTest):
|
||||
def test_enroll_with_ipmi_address(self, mock_check_existing, mock_client,
|
||||
mock_create_node):
|
||||
mock_client.return_value = self.ironic
|
||||
introspection_data = {'ipmi_address': '1.2.3.4'}
|
||||
expected_data = introspection_data.copy()
|
||||
expected_data = copy.deepcopy(self.data)
|
||||
mock_check_existing = copy_call_args(mock_check_existing)
|
||||
|
||||
discovery.enroll_node_not_found_hook(introspection_data)
|
||||
discovery.enroll_node_not_found_hook(self.data)
|
||||
|
||||
mock_create_node.assert_called_once_with(
|
||||
'fake-hardware', ironic=self.ironic,
|
||||
driver_info={'ipmi_address': '1.2.3.4'})
|
||||
driver_info={'ipmi_address': self.bmc_address})
|
||||
mock_check_existing.assert_called_once_with(
|
||||
expected_data, {'ipmi_address': '1.2.3.4'}, self.ironic)
|
||||
self.assertEqual({'ipmi_address': '1.2.3.4', 'auto_discovered': True},
|
||||
introspection_data)
|
||||
expected_data, {'ipmi_address': self.bmc_address}, self.ironic)
|
||||
self.assertTrue(self.data['auto_discovered'])
|
||||
|
||||
@mock.patch.object(node_cache, 'create_node', autospec=True)
|
||||
@mock.patch.object(ir_utils, 'get_client', autospec=True)
|
||||
@mock.patch.object(discovery, '_check_existing_nodes', autospec=True)
|
||||
def test_enroll_with_ipmi_v6address(self, mock_check_existing, mock_client,
|
||||
mock_create_node):
|
||||
mock_client.return_value = self.ironic
|
||||
# By default enabled_bmc_address_version="4,6".
|
||||
# Because bmc_address is not set (pop it) _extract_node_driver_info
|
||||
# method returns bmc_v6address
|
||||
self.data['inventory'].pop('bmc_address')
|
||||
expected_data = copy.deepcopy(self.data)
|
||||
mock_check_existing = copy_call_args(mock_check_existing)
|
||||
|
||||
discovery.enroll_node_not_found_hook(self.data)
|
||||
|
||||
mock_create_node.assert_called_once_with(
|
||||
'fake-hardware', ironic=self.ironic,
|
||||
driver_info={'ipmi_address': self.bmc_v6address})
|
||||
mock_check_existing.assert_called_once_with(
|
||||
expected_data, {'ipmi_address': self.bmc_v6address}, self.ironic)
|
||||
self.assertTrue(self.data['auto_discovered'])
|
||||
|
||||
@mock.patch.object(node_cache, 'create_node', autospec=True)
|
||||
@mock.patch.object(ir_utils, 'get_client', autospec=True)
|
||||
|
@ -89,8 +89,9 @@ class TestProcess(BaseProcessTest):
|
||||
|
||||
self.assertEqual(self.fake_result_json, res)
|
||||
|
||||
self.find_mock.assert_called_once_with(bmc_address=self.bmc_address,
|
||||
mac=mock.ANY)
|
||||
self.find_mock.assert_called_once_with(
|
||||
bmc_address=[self.bmc_address, self.bmc_v6address],
|
||||
mac=mock.ANY)
|
||||
actual_macs = self.find_mock.call_args[1]['mac']
|
||||
self.assertEqual(sorted(self.all_macs), sorted(actual_macs))
|
||||
self.cli.node.get.assert_called_once_with(self.uuid)
|
||||
@ -99,9 +100,11 @@ class TestProcess(BaseProcessTest):
|
||||
|
||||
def test_no_ipmi(self):
|
||||
del self.inventory['bmc_address']
|
||||
del self.inventory['bmc_v6address']
|
||||
process.process(self.data)
|
||||
|
||||
self.find_mock.assert_called_once_with(bmc_address=None, mac=mock.ANY)
|
||||
self.find_mock.assert_called_once_with(bmc_address=[None, None],
|
||||
mac=mock.ANY)
|
||||
actual_macs = self.find_mock.call_args[1]['mac']
|
||||
self.assertEqual(sorted(self.all_macs), sorted(actual_macs))
|
||||
self.cli.node.get.assert_called_once_with(self.uuid)
|
||||
@ -110,9 +113,11 @@ class TestProcess(BaseProcessTest):
|
||||
|
||||
def test_ipmi_not_detected(self):
|
||||
self.inventory['bmc_address'] = '0.0.0.0'
|
||||
self.inventory['bmc_v6address'] = '::/0'
|
||||
process.process(self.data)
|
||||
|
||||
self.find_mock.assert_called_once_with(bmc_address=None, mac=mock.ANY)
|
||||
self.find_mock.assert_called_once_with(bmc_address=[None, None],
|
||||
mac=mock.ANY)
|
||||
actual_macs = self.find_mock.call_args[1]['mac']
|
||||
self.assertEqual(sorted(self.all_macs), sorted(actual_macs))
|
||||
self.cli.node.get.assert_called_once_with(self.uuid)
|
||||
@ -124,7 +129,9 @@ class TestProcess(BaseProcessTest):
|
||||
self.data['ipmi_address'] = '0.0.0.0'
|
||||
process.process(self.data)
|
||||
|
||||
self.find_mock.assert_called_once_with(bmc_address=None, mac=mock.ANY)
|
||||
self.find_mock.assert_called_once_with(
|
||||
bmc_address=[None, self.bmc_v6address],
|
||||
mac=mock.ANY)
|
||||
actual_macs = self.find_mock.call_args[1]['mac']
|
||||
self.assertEqual(sorted(self.all_macs), sorted(actual_macs))
|
||||
self.cli.node.get.assert_called_once_with(self.uuid)
|
||||
|
@ -43,6 +43,19 @@ def get_ipmi_address_from_data(introspection_data):
|
||||
return result
|
||||
|
||||
|
||||
def get_ipmi_v6address_from_data(introspection_data):
|
||||
try:
|
||||
result = introspection_data['inventory']['bmc_v6address']
|
||||
except KeyError:
|
||||
result = introspection_data.get('ipmi_v6address')
|
||||
|
||||
if result in ('', '::/0'):
|
||||
# ipmitool can return these values, if it does not know the address
|
||||
return None
|
||||
else:
|
||||
return result
|
||||
|
||||
|
||||
def get_pxe_mac(introspection_data):
|
||||
pxe_mac = introspection_data.get('boot_interface')
|
||||
if pxe_mac and '-' in pxe_mac:
|
||||
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Adds support to enroll node with IPv6 BMC address. Introduces
|
||||
a configuration option ``[discovery]enabled_bmc_address_version``
|
||||
to specify the order of preferred IP version of the BMC address.
|
Loading…
Reference in New Issue
Block a user