diff options
author | Hamdy Khader <hamdyk@mellanox.com> | 2019-01-13 15:40:30 +0200 |
---|---|---|
committer | Hamdy Khader <hamdyk@mellanox.com> | 2019-02-10 12:10:00 +0200 |
commit | 6325b6c13c82911cb144646a614b943bdf496518 (patch) | |
tree | 6aed938e0e69556403e0f1738ad3ff8b0d622678 /ironic/api/controllers | |
parent | 506cb121609b73a9174bf2676c32c8ac7421a441 (diff) | |
download | ironic-6325b6c13c82911cb144646a614b943bdf496518.tar.gz |
Expose is_smartnic in port API
Changes are made to support ironic handling is_smarting port attribute
that was added in this change Ic2ffbd6f1035907ea5a18bda6d2b21e617194195
This change expose is_smartnic port field in REST API, updated API
reference to include is_smartnic field and relevent documentations.
API version updated to 1.53.
Story: #2003346
Change-Id: I89ce54a0c034f2a5f82ff961ab06cfcc6d853bd4
Diffstat (limited to 'ironic/api/controllers')
-rw-r--r-- | ironic/api/controllers/v1/port.py | 21 | ||||
-rw-r--r-- | ironic/api/controllers/v1/types.py | 58 | ||||
-rw-r--r-- | ironic/api/controllers/v1/utils.py | 10 | ||||
-rw-r--r-- | ironic/api/controllers/v1/versions.py | 4 |
4 files changed, 82 insertions, 11 deletions
diff --git a/ironic/api/controllers/v1/port.py b/ironic/api/controllers/v1/port.py index b72f0ddbf..c16ff7231 100644 --- a/ironic/api/controllers/v1/port.py +++ b/ironic/api/controllers/v1/port.py @@ -59,6 +59,9 @@ def hide_fields_in_newer_versions(obj): # if requested version is < 1.34, hide physical_network field. if not api_utils.allow_port_physical_network(): obj.physical_network = wsme.Unset + # if requested version is < 1.53, hide is_smartnic field. + if not api_utils.allow_port_is_smartnic(): + obj.is_smartnic = wsme.Unset class Port(base.APIBase): @@ -156,6 +159,9 @@ class Port(base.APIBase): links = wsme.wsattr([link.Link], readonly=True) """A list containing a self link and associated port links""" + is_smartnic = types.boolean + """Indicates whether this port is a Smart NIC port.""" + def __init__(self, **kwargs): self.fields = [] fields = list(objects.Port.fields) @@ -245,7 +251,8 @@ class Port(base.APIBase): local_link_connection={ 'switch_info': 'host', 'port_id': 'Gig0/1', 'switch_id': 'aa:bb:cc:dd:ee:ff'}, - physical_network='physnet1') + physical_network='physnet1', + is_smartnic=False) # NOTE(lucasagomes): node_uuid getter() method look at the # _node_uuid variable sample._node_uuid = '7ae81bb3-dec3-4289-8d6c-da80bd8001ae' @@ -425,6 +432,9 @@ class PortsController(rest.RestController): if ('physical_network' in fields and not api_utils.allow_port_physical_network()): raise exception.NotAcceptable() + if ('is_smartnic' in fields + and not api_utils.allow_port_is_smartnic()): + raise exception.NotAcceptable() @METRICS.timer('PortsController.get_all') @expose.expose(PortCollection, types.uuid_or_name, types.uuid, @@ -577,6 +587,12 @@ class PortsController(rest.RestController): pdict = port.as_dict() self._check_allowed_port_fields(pdict) + if (port.is_smartnic and not types.locallinkconnectiontype + .validate_for_smart_nic(port.local_link_connection)): + raise exception.Invalid( + "Smart NIC port must have port_id " + "and hostname in local_link_connection") + create_remotely = pecan.request.rpcapi.can_send_create_port() if (not create_remotely and pdict.get('portgroup_uuid')): # NOTE(mgoddard): In RPC API v1.41, port creation was moved to the @@ -652,7 +668,8 @@ class PortsController(rest.RestController): fields_to_check = set() for field in (self.advanced_net_fields - + ['portgroup_uuid', 'physical_network']): + + ['portgroup_uuid', 'physical_network', + 'is_smartnic']): field_path = '/%s' % field if (api_utils.get_patch_values(patch, field_path) or api_utils.is_path_removed(patch, field_path)): diff --git a/ironic/api/controllers/v1/types.py b/ironic/api/controllers/v1/types.py index 87f574954..e2b04bd72 100644 --- a/ironic/api/controllers/v1/types.py +++ b/ironic/api/controllers/v1/types.py @@ -18,6 +18,7 @@ import inspect import json +from oslo_log import log from oslo_utils import strutils from oslo_utils import uuidutils import six @@ -30,6 +31,9 @@ from ironic.common.i18n import _ from ironic.common import utils +LOG = log.getLogger(__name__) + + class MacAddressType(wtypes.UserType): """A simple MAC address type.""" @@ -266,9 +270,12 @@ class LocalLinkConnectionType(wtypes.UserType): basetype = wtypes.DictType name = 'locallinkconnection' - mandatory_fields = {'switch_id', - 'port_id'} - valid_fields = mandatory_fields.union({'switch_info'}) + local_link_mandatory_fields = {'port_id', 'switch_id'} + smart_nic_mandatory_fields = {'port_id', 'hostname'} + mandatory_fields_list = [local_link_mandatory_fields, + smart_nic_mandatory_fields] + optional_field = {'switch_info'} + valid_fields = set.union(optional_field, *mandatory_fields_list) @staticmethod def validate(value): @@ -276,7 +283,7 @@ class LocalLinkConnectionType(wtypes.UserType): :param value: A dictionary of values to validate, switch_id is a MAC address or an OpenFlow based datapath_id, switch_info is an - optional field. + optional field. Required Smart NIC fields are port_id and hostname. For example:: @@ -286,6 +293,13 @@ class LocalLinkConnectionType(wtypes.UserType): 'switch_info': 'switch1' } + Or for Smart NIC:: + + { + 'port_id': 'rep0-0', + 'hostname': 'host1-bf' + } + :returns: A dictionary. :raises: Invalid if some of the keys in the dictionary being validated are unknown, invalid, or some required ones are missing. @@ -304,10 +318,20 @@ class LocalLinkConnectionType(wtypes.UserType): if invalid: raise exception.Invalid(_('%s are invalid keys') % (invalid)) - # Check all mandatory fields are present - missing = LocalLinkConnectionType.mandatory_fields - keys - if missing: - msg = _('Missing mandatory keys: %s') % missing + # Check any mandatory fields sets are present + for mandatory_set in LocalLinkConnectionType.mandatory_fields_list: + if mandatory_set <= keys: + break + else: + msg = _('Missing mandatory keys. Required keys are ' + '%(required_fields)s. Or in case of Smart NIC ' + '%(smart_nic_required_fields)s. ' + 'Submitted keys are %(keys)s .') % { + 'required_fields': + LocalLinkConnectionType.local_link_mandatory_fields, + 'smart_nic_required_fields': + LocalLinkConnectionType.smart_nic_mandatory_fields, + 'keys': keys} raise exception.Invalid(msg) # Check switch_id is either a valid mac address or @@ -321,6 +345,9 @@ class LocalLinkConnectionType(wtypes.UserType): value['switch_id']) except exception.InvalidDatapathID: raise exception.InvalidSwitchID(switch_id=value['switch_id']) + except KeyError: + # In Smart NIC case 'switch_id' is optional. + pass return value @@ -330,6 +357,21 @@ class LocalLinkConnectionType(wtypes.UserType): return None return LocalLinkConnectionType.validate(value) + @staticmethod + def validate_for_smart_nic(value): + """Validates Smart NIC field are present 'port_id' and 'hostname' + + :param value: local link information of type Dictionary. + :return: True if both fields 'port_id' and 'hostname' are present + in 'value', False otherwise. + """ + wtypes.DictType(wtypes.text, wtypes.text).validate(value) + keys = set(value) + + if LocalLinkConnectionType.smart_nic_mandatory_fields <= keys: + return True + return False + locallinkconnectiontype = LocalLinkConnectionType() diff --git a/ironic/api/controllers/v1/utils.py b/ironic/api/controllers/v1/utils.py index 770dec62d..f2c7a5ec9 100644 --- a/ironic/api/controllers/v1/utils.py +++ b/ironic/api/controllers/v1/utils.py @@ -1012,3 +1012,13 @@ def allow_allocations(): field for the node. """ return pecan.request.version.minor >= versions.MINOR_52_ALLOCATION + + +def allow_port_is_smartnic(): + """Check if port is_smartnic field is allowed. + + Version 1.53 of the API added is_smartnic field to the port object. + """ + return ((pecan.request.version.minor + >= versions.MINOR_53_PORT_SMARTNIC) + and objects.Port.supports_is_smartnic()) diff --git a/ironic/api/controllers/v1/versions.py b/ironic/api/controllers/v1/versions.py index d456738de..5c5da878e 100644 --- a/ironic/api/controllers/v1/versions.py +++ b/ironic/api/controllers/v1/versions.py @@ -90,6 +90,7 @@ BASE_VERSION = 1 # v1.50: Add owner to the node object. # v1.51: Add description to the node object. # v1.52: Add allocation API. +# v1.53: Add support for Smart NIC port MINOR_0_JUNO = 0 MINOR_1_INITIAL_VERSION = 1 @@ -144,6 +145,7 @@ MINOR_49_CONDUCTORS = 49 MINOR_50_NODE_OWNER = 50 MINOR_51_NODE_DESCRIPTION = 51 MINOR_52_ALLOCATION = 52 +MINOR_53_PORT_SMARTNIC = 53 # When adding another version, update: # - MINOR_MAX_VERSION @@ -151,7 +153,7 @@ MINOR_52_ALLOCATION = 52 # explanation of what changed in the new version # - common/release_mappings.py, RELEASE_MAPPING['master']['api'] -MINOR_MAX_VERSION = MINOR_52_ALLOCATION +MINOR_MAX_VERSION = MINOR_53_PORT_SMARTNIC # String representations of the minor and maximum versions _MIN_VERSION_STRING = '{}.{}'.format(BASE_VERSION, MINOR_1_INITIAL_VERSION) |