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',
|
default='fake-hardware',
|
||||||
help=_('The name of the Ironic driver used by the enroll '
|
help=_('The name of the Ironic driver used by the enroll '
|
||||||
'hook when creating a new node in Ironic.')),
|
'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):
|
def _extract_node_driver_info(introspection_data):
|
||||||
node_driver_info = {}
|
node_driver_info = {}
|
||||||
ipmi_address = utils.get_ipmi_address_from_data(introspection_data)
|
for ip_version in CONF.discovery.enabled_bmc_address_version:
|
||||||
if ipmi_address:
|
address = None
|
||||||
node_driver_info['ipmi_address'] = ipmi_address
|
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:
|
else:
|
||||||
LOG.warning('No BMC address provided, discovered node will be '
|
LOG.warning('No BMC address provided, discovered node will be '
|
||||||
'created without ipmi address')
|
'created without ipmi address')
|
||||||
|
@ -243,9 +243,11 @@ class ValidateInterfacesHook(base.ProcessingHook):
|
|||||||
"""Validate information about network interfaces."""
|
"""Validate information about network interfaces."""
|
||||||
|
|
||||||
bmc_address = utils.get_ipmi_address_from_data(introspection_data)
|
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
|
# Overwrite the old ipmi_address field to avoid inconsistency
|
||||||
introspection_data['ipmi_address'] = bmc_address
|
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, '
|
LOG.debug('No BMC address provided in introspection data, '
|
||||||
'assuming virtual environment', data=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):
|
def _find_node_info(introspection_data, failures):
|
||||||
try:
|
try:
|
||||||
|
address = utils.get_ipmi_address_from_data(introspection_data)
|
||||||
|
v6address = utils.get_ipmi_v6address_from_data(introspection_data)
|
||||||
return node_cache.find_node(
|
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))
|
mac=utils.get_valid_macs(introspection_data))
|
||||||
except utils.NotFoundInCacheError as exc:
|
except utils.NotFoundInCacheError as exc:
|
||||||
not_found_hook = plugins_base.node_not_found_hook_manager()
|
not_found_hook = plugins_base.node_not_found_hook_manager()
|
||||||
|
@ -92,6 +92,7 @@ class InventoryTest(BaseTest):
|
|||||||
# Prepare some realistic inventory
|
# Prepare some realistic inventory
|
||||||
# https://github.com/openstack/ironic-inspector/blob/master/HTTP-API.rst # noqa
|
# https://github.com/openstack/ironic-inspector/blob/master/HTTP-API.rst # noqa
|
||||||
self.bmc_address = '1.2.3.4'
|
self.bmc_address = '1.2.3.4'
|
||||||
|
self.bmc_v6address = '2001:1234:1234:1234:1234:1234:1234:1234/64'
|
||||||
self.macs = (
|
self.macs = (
|
||||||
['11:22:33:44:55:66', '66:55:44:33:22:11', '7c:fe:90:29:26:52'])
|
['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']
|
self.ips = ['1.2.1.2', '1.2.1.1', '1.2.1.3']
|
||||||
@ -137,7 +138,8 @@ class InventoryTest(BaseTest):
|
|||||||
'memory': {
|
'memory': {
|
||||||
'physical_mb': 12288
|
'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',
|
'root_disk': {'name': '/dev/sda', 'model': 'Big Data Disk',
|
||||||
'size': 1000 * units.Gi,
|
'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,
|
def test_enroll_with_ipmi_address(self, mock_check_existing, mock_client,
|
||||||
mock_create_node):
|
mock_create_node):
|
||||||
mock_client.return_value = self.ironic
|
mock_client.return_value = self.ironic
|
||||||
introspection_data = {'ipmi_address': '1.2.3.4'}
|
expected_data = copy.deepcopy(self.data)
|
||||||
expected_data = introspection_data.copy()
|
|
||||||
mock_check_existing = copy_call_args(mock_check_existing)
|
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(
|
mock_create_node.assert_called_once_with(
|
||||||
'fake-hardware', ironic=self.ironic,
|
'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(
|
mock_check_existing.assert_called_once_with(
|
||||||
expected_data, {'ipmi_address': '1.2.3.4'}, self.ironic)
|
expected_data, {'ipmi_address': self.bmc_address}, self.ironic)
|
||||||
self.assertEqual({'ipmi_address': '1.2.3.4', 'auto_discovered': True},
|
self.assertTrue(self.data['auto_discovered'])
|
||||||
introspection_data)
|
|
||||||
|
@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(node_cache, 'create_node', autospec=True)
|
||||||
@mock.patch.object(ir_utils, 'get_client', 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.assertEqual(self.fake_result_json, res)
|
||||||
|
|
||||||
self.find_mock.assert_called_once_with(bmc_address=self.bmc_address,
|
self.find_mock.assert_called_once_with(
|
||||||
mac=mock.ANY)
|
bmc_address=[self.bmc_address, self.bmc_v6address],
|
||||||
|
mac=mock.ANY)
|
||||||
actual_macs = self.find_mock.call_args[1]['mac']
|
actual_macs = self.find_mock.call_args[1]['mac']
|
||||||
self.assertEqual(sorted(self.all_macs), sorted(actual_macs))
|
self.assertEqual(sorted(self.all_macs), sorted(actual_macs))
|
||||||
self.cli.node.get.assert_called_once_with(self.uuid)
|
self.cli.node.get.assert_called_once_with(self.uuid)
|
||||||
@ -99,9 +100,11 @@ class TestProcess(BaseProcessTest):
|
|||||||
|
|
||||||
def test_no_ipmi(self):
|
def test_no_ipmi(self):
|
||||||
del self.inventory['bmc_address']
|
del self.inventory['bmc_address']
|
||||||
|
del self.inventory['bmc_v6address']
|
||||||
process.process(self.data)
|
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']
|
actual_macs = self.find_mock.call_args[1]['mac']
|
||||||
self.assertEqual(sorted(self.all_macs), sorted(actual_macs))
|
self.assertEqual(sorted(self.all_macs), sorted(actual_macs))
|
||||||
self.cli.node.get.assert_called_once_with(self.uuid)
|
self.cli.node.get.assert_called_once_with(self.uuid)
|
||||||
@ -110,9 +113,11 @@ class TestProcess(BaseProcessTest):
|
|||||||
|
|
||||||
def test_ipmi_not_detected(self):
|
def test_ipmi_not_detected(self):
|
||||||
self.inventory['bmc_address'] = '0.0.0.0'
|
self.inventory['bmc_address'] = '0.0.0.0'
|
||||||
|
self.inventory['bmc_v6address'] = '::/0'
|
||||||
process.process(self.data)
|
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']
|
actual_macs = self.find_mock.call_args[1]['mac']
|
||||||
self.assertEqual(sorted(self.all_macs), sorted(actual_macs))
|
self.assertEqual(sorted(self.all_macs), sorted(actual_macs))
|
||||||
self.cli.node.get.assert_called_once_with(self.uuid)
|
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'
|
self.data['ipmi_address'] = '0.0.0.0'
|
||||||
process.process(self.data)
|
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']
|
actual_macs = self.find_mock.call_args[1]['mac']
|
||||||
self.assertEqual(sorted(self.all_macs), sorted(actual_macs))
|
self.assertEqual(sorted(self.all_macs), sorted(actual_macs))
|
||||||
self.cli.node.get.assert_called_once_with(self.uuid)
|
self.cli.node.get.assert_called_once_with(self.uuid)
|
||||||
|
@ -43,6 +43,19 @@ def get_ipmi_address_from_data(introspection_data):
|
|||||||
return result
|
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):
|
def get_pxe_mac(introspection_data):
|
||||||
pxe_mac = introspection_data.get('boot_interface')
|
pxe_mac = introspection_data.get('boot_interface')
|
||||||
if pxe_mac and '-' in pxe_mac:
|
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