Skip to content

Commit 22d1a26

Browse files
committed
Neutron port hints
Introduce the hints port attribute that allows passing in backend specific hints mainly to allow backend specific performance tuning. Enable: openstack port create --hint ALIAS=VALUE openstack port set --hint ALIAS=VALUE openstack port unset --hints Required neutron extension: port-hints port-hint-ovs-tx-steering Valid hint aliases and values: ovs-tx-steering=hash ovs-tx-steering=thread The same hints in JSON format, as expected by the Neutron API: {"openvswitch": {"other_config": {"tx-steering": "hash"}}} {"openvswitch": {"other_config": {"tx-steering": "thread"}}} Change-Id: I4c7142909b1e4fb26fc77ad9ba08ec994cc450b2 Depends-On: https://review.opendev.org/c/openstack/neutron/+/873113 Partial-Bug: #1990842 Related-Change (server side): https://review.opendev.org/c/openstack/neutron/+/873113 Related-Change (spec): https://review.opendev.org/c/openstack/neutron-specs/+/862133
1 parent f3a51b0 commit 22d1a26

4 files changed

Lines changed: 366 additions & 2 deletions

File tree

openstackclient/network/v2/port.py

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,22 @@ def _add_updatable_args(parser):
322322
action='store_true',
323323
help=_("NUMA affinity policy using legacy mode to schedule this port"),
324324
)
325+
parser.add_argument(
326+
'--hint',
327+
metavar='<alias=value>',
328+
action=JSONKeyValueAction,
329+
default={},
330+
help=_(
331+
'Port hints as ALIAS=VALUE or as JSON. '
332+
'Valid hint aliases/values: '
333+
'ovs-tx-steering=thread, ovs-tx-steering=hash. '
334+
'Valid JSON values are as specified by the Neutron API. '
335+
'(requires port-hints extension) '
336+
'(requires port-hint-ovs-tx-steering extension for alias: '
337+
'ovs-tx-steering) '
338+
'(repeat option to set multiple hints)'
339+
),
340+
)
325341

326342

327343
# TODO(abhiraut): Use the SDK resource mapped attribute names once the
@@ -350,6 +366,34 @@ def _convert_extra_dhcp_options(parsed_args):
350366
return dhcp_options
351367

352368

369+
# When we have multiple hints, we'll need to refactor this to allow
370+
# arbitrary combinations. But until then let's have it as simple as possible.
371+
def _validate_port_hints(hints):
372+
if hints not in (
373+
{},
374+
# by hint alias
375+
{'ovs-tx-steering': 'thread'},
376+
{'ovs-tx-steering': 'hash'},
377+
# by fully specified value of the port's hints field
378+
{'openvswitch': {'other_config': {'tx-steering': 'thread'}}},
379+
{'openvswitch': {'other_config': {'tx-steering': 'hash'}}},
380+
):
381+
msg = _("Invalid value to --hints, see --help for valid values.")
382+
raise argparse.ArgumentTypeError(msg)
383+
384+
385+
# When we have multiple hints, we'll need to refactor this to expand aliases
386+
# without losing other hints. But until then let's have it as simple as
387+
# possible.
388+
def _expand_port_hint_aliases(hints):
389+
if hints == {'ovs-tx-steering': 'thread'}:
390+
return {'openvswitch': {'other_config': {'tx-steering': 'thread'}}}
391+
elif hints == {'ovs-tx-steering': 'hash'}:
392+
return {'openvswitch': {'other_config': {'tx-steering': 'hash'}}}
393+
else:
394+
return hints
395+
396+
353397
class CreatePort(command.ShowOne, common.NeutronCommandWithExtraArgs):
354398
_description = _("Create a new port")
355399

@@ -527,6 +571,29 @@ def take_action(self, parsed_args):
527571
parsed_args.qos_policy, ignore_missing=False
528572
).id
529573

574+
if parsed_args.hint:
575+
_validate_port_hints(parsed_args.hint)
576+
expanded_hints = _expand_port_hint_aliases(parsed_args.hint)
577+
try:
578+
client.find_extension('port-hints', ignore_missing=False)
579+
except Exception as e:
580+
msg = _('Not supported by Network API: %(e)s') % {'e': e}
581+
raise exceptions.CommandError(msg)
582+
if (
583+
'openvswitch' in expanded_hints
584+
and 'other_config' in expanded_hints['openvswitch']
585+
and 'tx-steering'
586+
in expanded_hints['openvswitch']['other_config']
587+
):
588+
try:
589+
client.find_extension(
590+
'port-hint-ovs-tx-steering', ignore_missing=False
591+
)
592+
except Exception as e:
593+
msg = _('Not supported by Network API: %(e)s') % {'e': e}
594+
raise exceptions.CommandError(msg)
595+
attrs['hints'] = expanded_hints
596+
530597
set_tags_in_post = bool(
531598
client.find_extension('tag-ports-during-bulk-creation')
532599
)
@@ -972,6 +1039,29 @@ def take_action(self, parsed_args):
9721039
if parsed_args.data_plane_status:
9731040
attrs['data_plane_status'] = parsed_args.data_plane_status
9741041

1042+
if parsed_args.hint:
1043+
_validate_port_hints(parsed_args.hint)
1044+
expanded_hints = _expand_port_hint_aliases(parsed_args.hint)
1045+
try:
1046+
client.find_extension('port-hints', ignore_missing=False)
1047+
except Exception as e:
1048+
msg = _('Not supported by Network API: %(e)s') % {'e': e}
1049+
raise exceptions.CommandError(msg)
1050+
if (
1051+
'openvswitch' in expanded_hints
1052+
and 'other_config' in expanded_hints['openvswitch']
1053+
and 'tx-steering'
1054+
in expanded_hints['openvswitch']['other_config']
1055+
):
1056+
try:
1057+
client.find_extension(
1058+
'port-hint-ovs-tx-steering', ignore_missing=False
1059+
)
1060+
except Exception as e:
1061+
msg = _('Not supported by Network API: %(e)s') % {'e': e}
1062+
raise exceptions.CommandError(msg)
1063+
attrs['hints'] = expanded_hints
1064+
9751065
attrs.update(
9761066
self._parse_extra_properties(parsed_args.extra_properties)
9771067
)
@@ -1083,6 +1173,12 @@ def get_parser(self, prog_name):
10831173
default=False,
10841174
help=_("Clear host binding for the port."),
10851175
)
1176+
parser.add_argument(
1177+
'--hints',
1178+
action='store_true',
1179+
default=False,
1180+
help=_("Clear hints for the port."),
1181+
)
10861182

10871183
_tag.add_tag_option_to_parser_for_unset(parser, _('port'))
10881184

@@ -1143,6 +1239,8 @@ def take_action(self, parsed_args):
11431239
attrs['numa_affinity_policy'] = None
11441240
if parsed_args.host:
11451241
attrs['binding:host_id'] = None
1242+
if parsed_args.hints:
1243+
attrs['hints'] = None
11461244

11471245
attrs.update(
11481246
self._parse_extra_properties(parsed_args.extra_properties)

openstackclient/tests/unit/network/v2/fakes.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1778,6 +1778,7 @@ def create_one_port(attrs=None):
17781778
'subnet_id': 'subnet-id-' + uuid.uuid4().hex,
17791779
}
17801780
],
1781+
'hints': {},
17811782
'id': 'port-id-' + uuid.uuid4().hex,
17821783
'mac_address': 'fa:16:3e:a9:4e:72',
17831784
'name': 'port-name-' + uuid.uuid4().hex,

0 commit comments

Comments
 (0)