Source code for ironic.drivers.modules.inspector.hooks.ports
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from oslo_log import log as logging
from ironic.common import exception
from ironic.conf import CONF
from ironic.drivers.modules.inspector.hooks import base
from ironic import objects
LOG = logging.getLogger(__name__)
[docs]
class PortsHook(base.InspectionHook):
"""Hook to create ironic ports."""
dependencies = ['validate-interfaces']
def __call__(self, task, inventory, plugin_data):
if CONF.inspector.add_ports != 'disabled':
add_ports(task, plugin_data['valid_interfaces'])
update_ports(task, plugin_data['all_interfaces'], plugin_data['macs'])
[docs]
def add_ports(task, interfaces):
"""Add ports for all previously validated interfaces."""
for iface in interfaces.values():
mac = iface['mac_address']
extra = {}
if iface.get('client_id'):
extra['client-id'] = iface['client_id']
port_dict = {'address': mac, 'node_id': task.node.id,
'pxe_enabled': iface['pxe_enabled'], 'extra': extra}
port = objects.Port(task.context, **port_dict)
try:
port.create()
LOG.info("Port created for MAC address %(address)s for "
"node %(node)s%(pxe)s",
{'address': mac, 'node': task.node.uuid,
'pxe': ' (PXE booting)' if iface['pxe_enabled'] else ''})
except exception.MACAlreadyExists:
LOG.info("Port already exists for MAC address %(address)s "
"for node %(node)s",
{'address': mac, 'node': task.node.uuid})
[docs]
def update_ports(task, all_interfaces, valid_macs):
"""Update ports to match the valid MACs.
Depending on the value of ``[inspector]keep_ports``, some ports may be
removed.
"""
# TODO(dtantsur): no port update for active nodes (when supported)
if CONF.inspector.keep_ports == 'present':
expected_macs = {iface['mac_address']
for iface in all_interfaces.values()}
elif CONF.inspector.keep_ports == 'added':
expected_macs = set(valid_macs)
else:
expected_macs = None # unused
pxe_macs = {iface['mac_address'] for iface in all_interfaces.values()
if iface['pxe_enabled']}
for port in objects.Port.list_by_node_id(task.context, task.node.id):
if expected_macs and port.address not in expected_macs:
expected_str = ', '.join(sorted(expected_macs))
LOG.info("Deleting port %(port)s of node %(node)s as its MAC "
"%(mac)s is not in the expected MAC list [%(expected)s]",
{'port': port.uuid, 'mac': port.address,
'node': task.node.uuid, 'expected': expected_str})
port.destroy()
elif CONF.inspector.update_pxe_enabled:
pxe_enabled = port.address in pxe_macs
if pxe_enabled != port.pxe_enabled:
LOG.debug("Changing pxe_enabled=%(val)s on port %(port)s "
"of node %(node)s to match the inventory",
{'port': port.address, 'val': pxe_enabled,
'node': task.node.uuid})
port.pxe_enabled = pxe_enabled
port.save()