Merge "Add option to delete ports after introspection"

This commit is contained in:
Jenkins 2015-03-26 10:07:51 +00:00 committed by Gerrit Code Review
commit 16cc7323a5
4 changed files with 91 additions and 0 deletions

View File

@ -49,6 +49,13 @@
# Allowed values: all, active, pxe
#add_ports = pxe
# Which ports (already present on a node) to keep after introspection.
# Possible values: all (do not delete anything), present (keep ports
# which MACs were present in introspection data), added (keep only
# MACs that we added during introspection). (string value)
# Allowed values: all, present, added
#keep_ports = all
# Timeout after which introspection is considered failed, set to 0 to
# disable. (integer value)
#timeout = 3600

View File

@ -15,6 +15,7 @@ from oslo_config import cfg
VALID_ADD_PORTS_VALUES = ('all', 'active', 'pxe')
VALID_KEEP_PORTS_VALUES = ('all', 'present', 'added')
SERVICE_OPTS = [
cfg.StrOpt('os_auth_url',
@ -61,6 +62,14 @@ SERVICE_OPTS = [
'from, falls back to "active" if PXE MAC is not supplied '
'by the ramdisk).',
choices=VALID_ADD_PORTS_VALUES),
cfg.StrOpt('keep_ports',
default='all',
help='Which ports (already present on a node) to keep after '
'introspection. Possible values: '
'all (do not delete anything), present (keep ports which MACs '
'were present in introspection data), added (keep only MACs '
'that we added during introspection).',
choices=VALID_KEEP_PORTS_VALUES),
cfg.IntOpt('timeout',
default=3600,
help='Timeout after which introspection is considered failed, '

View File

@ -67,6 +67,13 @@ class ValidateInterfacesHook(base.ProcessingHook):
'actual': CONF.discoverd.add_ports})
sys.exit(1)
if CONF.discoverd.keep_ports not in conf.VALID_KEEP_PORTS_VALUES:
LOG.critical(_LC('Accepted values for [discoverd]keep_ports are '
'%(valid)s, got %(actual)s'),
{'valid': conf.VALID_KEEP_PORTS_VALUES,
'actual': CONF.discoverd.keep_ports})
sys.exit(1)
def _ports_to_add(self):
if CONF.discoverd.ports_for_inactive_interfaces:
LOG.warning(_LW('Using deprecated option '
@ -127,6 +134,28 @@ class ValidateInterfacesHook(base.ProcessingHook):
valid_macs = [iface['mac'] for iface in valid_interfaces.values()]
node_info['macs'] = valid_macs
def before_update(self, node, ports, node_info):
"""Drop ports that are not present in the data."""
if CONF.discoverd.keep_ports == 'present':
expected_macs = {iface['mac']
for iface in node_info['all_interfaces'].values()}
elif CONF.discoverd.keep_ports == 'added':
expected_macs = set(node_info['macs'])
else:
return
ironic = utils.get_client()
for port in ironic.node.list_ports(node.uuid, limit=0):
if port.address not in expected_macs:
LOG.info(_LI("Deleting port %(port)s as its MAC %(mac)s is "
"not in expected MAC list %(expected)s for node "
"%(node)s"),
{'port': port.uuid,
'mac': port.address,
'expected': list(sorted(expected_macs)),
'node': node.uuid})
ironic.port.delete(port.uuid)
class RamdiskErrorHook(base.ProcessingHook):
"""Hook to process error send from the ramdisk."""

View File

@ -325,6 +325,7 @@ class TestProcessNode(BaseTest):
'discoverd')
self.validate_attempts = 5
self.data['macs'] = self.macs # validate_interfaces hook
self.data['all_interfaces'] = self.data['interfaces']
self.ports = self.all_ports
self.cached_node = node_cache.NodeInfo(uuid=self.uuid,
started_at=self.started_at)
@ -509,8 +510,53 @@ class TestProcessNode(BaseTest):
error='Failed to power off node %s, check it\'s power management'
' configuration: boom' % self.uuid)
@mock.patch.object(utils, 'get_client')
def test_keep_ports_present(self, client_mock, filters_mock,
post_hook_mock):
CONF.set_override('keep_ports', 'present', 'discoverd')
# 2 MACs valid, one invalid, one not present in data
all_macs = self.all_macs + ['01:09:02:08:03:07']
all_ports = [
mock.Mock(uuid='port_uuid%d' % i, address=mac)
for i, mac in enumerate(all_macs)
]
client_mock.return_value = self.cli
self.cli.node.list_ports.return_value = all_ports
self.call()
self.cli.node.list_ports.assert_called_once_with(self.uuid, limit=0)
self.cli.port.delete.assert_called_once_with(all_ports[-1].uuid)
@mock.patch.object(utils, 'get_client')
def test_keep_ports_added(self, client_mock, filters_mock, post_hook_mock):
CONF.set_override('keep_ports', 'added', 'discoverd')
# 2 MACs valid, one invalid, one not present in data
all_macs = self.all_macs + ['01:09:02:08:03:07']
all_ports = [
mock.Mock(uuid='port_uuid%d' % i, address=mac)
for i, mac in enumerate(all_macs)
]
client_mock.return_value = self.cli
self.cli.node.list_ports.return_value = all_ports
self.call()
self.cli.node.list_ports.assert_called_once_with(self.uuid, limit=0)
for port in all_ports[2:]:
self.cli.port.delete.assert_any_call(port.uuid)
self.assertEqual(2, self.cli.port.delete.call_count)
class TestValidateInterfacesHook(test_base.BaseTest):
def test_wrong_add_ports(self):
CONF.set_override('add_ports', 'foobar', 'discoverd')
self.assertRaises(SystemExit, std_plugins.ValidateInterfacesHook)
def test_wrong_keep_ports(self):
CONF.set_override('keep_ports', 'foobar', 'discoverd')
self.assertRaises(SystemExit, std_plugins.ValidateInterfacesHook)