ovs-agent: Report pkt processing info in heartbeat
OVS agent configuration is extended to support new configuration options: - 'resource_provider_packet_processing_without_direction' - 'resource_provider_packet_processing_with_direction' - 'resource_provider_packet_processing_inventory_defaults' OVS agent RPC hearthbeat now reports this information to neutron server in 'configuration' field . Example config: ml2_conf.ini: [ovs] resource_provider_packet_processing_with_direction = :1000:1000 Partial-Bug: #1922237 See-Also: https://review.opendev.org/785236 Change-Id: Ief554bc445dfd93ea6995bb42b4d010674c7a091
This commit is contained in:
parent
56044db26d
commit
1ea26616b4
@ -88,6 +88,35 @@ ovs_opts = [
|
|||||||
"the resource_provider_default_hypervisor config "
|
"the resource_provider_default_hypervisor config "
|
||||||
"option value as known by the nova-compute managing "
|
"option value as known by the nova-compute managing "
|
||||||
"that hypervisor.")),
|
"that hypervisor.")),
|
||||||
|
cfg.ListOpt('resource_provider_packet_processing_without_direction',
|
||||||
|
default=[],
|
||||||
|
help=_("Comma-separated list of "
|
||||||
|
"<hypervisor>:<packet_rate> tuples, defining the "
|
||||||
|
"minimum packet rate the OVS backend can guarantee in "
|
||||||
|
"kilo (1000) packet per second. The hypervisor name is "
|
||||||
|
"used to locate the parent of the resource provider "
|
||||||
|
"tree. Only needs to be set in the rare case when the "
|
||||||
|
"hypervisor name is different from the DEFAULT.host "
|
||||||
|
"config option value as known by the nova-compute "
|
||||||
|
"managing that hypervisor or if multiple hypervisors "
|
||||||
|
"are served by the same OVS backend. The default is :0 "
|
||||||
|
"which means no packet processing capacity is "
|
||||||
|
"guaranteed on the hypervisor named according to "
|
||||||
|
"DEFAULT.host.")),
|
||||||
|
cfg.ListOpt('resource_provider_packet_processing_with_direction',
|
||||||
|
default=[],
|
||||||
|
help=_("Similar to the "
|
||||||
|
"resource_provider_packet_processing_without_direction "
|
||||||
|
"but used in case the OVS backend has hardware offload "
|
||||||
|
"capabilities. In this case the format is "
|
||||||
|
"<hypervisor>:<egress_pkt_rate>:<ingress_pkt_rate> "
|
||||||
|
"which allows defining packet processing capacity per "
|
||||||
|
"traffic direction. The direction is meant from the VM "
|
||||||
|
"perspective. Note that the "
|
||||||
|
"resource_provider_packet_processing_without_direction "
|
||||||
|
"and the "
|
||||||
|
"resource_provider_packet_processing_with_direction "
|
||||||
|
"are mutually exclusive options.")),
|
||||||
cfg.StrOpt('resource_provider_default_hypervisor',
|
cfg.StrOpt('resource_provider_default_hypervisor',
|
||||||
help=_("The default hypervisor name used to locate the parent "
|
help=_("The default hypervisor name used to locate the parent "
|
||||||
"of the resource provider. If this option is not set, "
|
"of the resource provider. If this option is not set, "
|
||||||
@ -106,6 +135,20 @@ ovs_opts = [
|
|||||||
"See also: "
|
"See also: "
|
||||||
"https://docs.openstack.org/api-ref/placement/"
|
"https://docs.openstack.org/api-ref/placement/"
|
||||||
"#update-resource-provider-inventories")),
|
"#update-resource-provider-inventories")),
|
||||||
|
cfg.DictOpt('resource_provider_packet_processing_inventory_defaults',
|
||||||
|
default={'allocation_ratio': 1.0,
|
||||||
|
'min_unit': 1,
|
||||||
|
'step_size': 1,
|
||||||
|
'reserved': 0},
|
||||||
|
help=_("Key:value pairs to specify defaults used "
|
||||||
|
"while reporting packet rate inventories. "
|
||||||
|
"Possible keys with their types: "
|
||||||
|
"allocation_ratio:float, "
|
||||||
|
"max_unit:int, min_unit:int, "
|
||||||
|
"reserved:int, step_size:int, "
|
||||||
|
"See also: "
|
||||||
|
"https://docs.openstack.org/api-ref/placement/"
|
||||||
|
"#update-resource-provider-inventories")),
|
||||||
cfg.StrOpt('datapath_type', default=constants.OVS_DATAPATH_SYSTEM,
|
cfg.StrOpt('datapath_type', default=constants.OVS_DATAPATH_SYSTEM,
|
||||||
choices=[constants.OVS_DATAPATH_SYSTEM,
|
choices=[constants.OVS_DATAPATH_SYSTEM,
|
||||||
constants.OVS_DATAPATH_NETDEV],
|
constants.OVS_DATAPATH_NETDEV],
|
||||||
|
@ -216,12 +216,30 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin,
|
|||||||
ovs_conf.bridge_mappings)
|
ovs_conf.bridge_mappings)
|
||||||
self.rp_bandwidths = place_utils.parse_rp_bandwidths(
|
self.rp_bandwidths = place_utils.parse_rp_bandwidths(
|
||||||
ovs_conf.resource_provider_bandwidths)
|
ovs_conf.resource_provider_bandwidths)
|
||||||
|
self.rp_pp_without_direction = (
|
||||||
|
place_utils.parse_rp_pp_without_direction(
|
||||||
|
ovs_conf.resource_provider_packet_processing_without_direction,
|
||||||
|
self.host))
|
||||||
|
self.rp_pp_with_direction = place_utils.parse_rp_pp_with_direction(
|
||||||
|
ovs_conf.resource_provider_packet_processing_with_direction,
|
||||||
|
self.host)
|
||||||
|
self._validate_rp_pkt_processing_cfg()
|
||||||
|
|
||||||
br_set = set(self.bridge_mappings.values())
|
br_set = set(self.bridge_mappings.values())
|
||||||
n_utils.validate_rp_bandwidth(self.rp_bandwidths,
|
n_utils.validate_rp_bandwidth(self.rp_bandwidths,
|
||||||
br_set)
|
br_set)
|
||||||
self.rp_inventory_defaults = place_utils.parse_rp_inventory_defaults(
|
self.rp_inventory_defaults = place_utils.parse_rp_inventory_defaults(
|
||||||
ovs_conf.resource_provider_inventory_defaults)
|
ovs_conf.resource_provider_inventory_defaults)
|
||||||
|
# At the moment the format of
|
||||||
|
# resource_provider_packet_processing_inventory_defaults is exactly
|
||||||
|
# the same as resource_provider_inventory_defaults, so we can simply
|
||||||
|
# use parse_rp_inventory_defaults() to parse it. However, if at some
|
||||||
|
# point the formats become different, we'll have to add a dedicated
|
||||||
|
# function to parse this option.
|
||||||
|
self.rp_pp_inventory_defaults = (
|
||||||
|
place_utils.parse_rp_inventory_defaults(
|
||||||
|
ovs_conf.resource_provider_packet_processing_inventory_defaults
|
||||||
|
))
|
||||||
self.rp_hypervisors = utils.default_rp_hypervisors(
|
self.rp_hypervisors = utils.default_rp_hypervisors(
|
||||||
ovs_conf.resource_provider_hypervisors,
|
ovs_conf.resource_provider_hypervisors,
|
||||||
{k: [v] for k, v in self.bridge_mappings.items()},
|
{k: [v] for k, v in self.bridge_mappings.items()},
|
||||||
@ -326,6 +344,12 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin,
|
|||||||
n_const.RP_BANDWIDTHS: self.rp_bandwidths,
|
n_const.RP_BANDWIDTHS: self.rp_bandwidths,
|
||||||
n_const.RP_INVENTORY_DEFAULTS:
|
n_const.RP_INVENTORY_DEFAULTS:
|
||||||
self.rp_inventory_defaults,
|
self.rp_inventory_defaults,
|
||||||
|
n_const.RP_PP_WITHOUT_DIRECTION:
|
||||||
|
self.rp_pp_without_direction,
|
||||||
|
n_const.RP_PP_WITH_DIRECTION:
|
||||||
|
self.rp_pp_with_direction,
|
||||||
|
n_const.RP_PP_INVENTORY_DEFAULTS:
|
||||||
|
self.rp_pp_inventory_defaults,
|
||||||
'resource_provider_hypervisors':
|
'resource_provider_hypervisors':
|
||||||
self.rp_hypervisors,
|
self.rp_hypervisors,
|
||||||
'integration_bridge':
|
'integration_bridge':
|
||||||
@ -2777,6 +2801,13 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin,
|
|||||||
network_id, self.agent_id, self.conf.host)
|
network_id, self.agent_id, self.conf.host)
|
||||||
return port_network['mtu']
|
return port_network['mtu']
|
||||||
|
|
||||||
|
def _validate_rp_pkt_processing_cfg(self):
|
||||||
|
if self.rp_pp_with_direction and self.rp_pp_without_direction:
|
||||||
|
raise ValueError(_(
|
||||||
|
'%s and %s configuration options are mutually exclusive.') %
|
||||||
|
(n_const.RP_PP_WITHOUT_DIRECTION,
|
||||||
|
n_const.RP_PP_WITH_DIRECTION))
|
||||||
|
|
||||||
|
|
||||||
def validate_local_ip(local_ip):
|
def validate_local_ip(local_ip):
|
||||||
"""Verify if the ip exists on the agent's host."""
|
"""Verify if the ip exists on the agent's host."""
|
||||||
|
@ -2566,6 +2566,35 @@ class TestOvsNeutronAgent(object):
|
|||||||
self.assertIn(n_const.RP_BANDWIDTHS,
|
self.assertIn(n_const.RP_BANDWIDTHS,
|
||||||
self.agent.agent_state['configurations'])
|
self.agent.agent_state['configurations'])
|
||||||
|
|
||||||
|
def test_configurations_has_rp_pp_without_direction(self):
|
||||||
|
self.assertIn(n_const.RP_PP_WITHOUT_DIRECTION,
|
||||||
|
self.agent.agent_state['configurations'])
|
||||||
|
|
||||||
|
def test_configurations_has_rp_pp_with_direction(self):
|
||||||
|
self.assertIn(n_const.RP_PP_WITH_DIRECTION,
|
||||||
|
self.agent.agent_state['configurations'])
|
||||||
|
|
||||||
|
def test_configurations_has_rp_pp_default_inventory(self):
|
||||||
|
self.assertIn(n_const.RP_PP_INVENTORY_DEFAULTS,
|
||||||
|
self.agent.agent_state['configurations'])
|
||||||
|
rp_inv_defaults = \
|
||||||
|
self.agent.agent_state['configurations'][
|
||||||
|
n_const.RP_INVENTORY_DEFAULTS]
|
||||||
|
self.assertListEqual(
|
||||||
|
sorted(['reserved', 'min_unit', 'allocation_ratio', 'step_size']),
|
||||||
|
sorted(list(rp_inv_defaults)))
|
||||||
|
self.assertEqual(1.0, rp_inv_defaults['allocation_ratio'])
|
||||||
|
self.assertEqual(1, rp_inv_defaults['min_unit'])
|
||||||
|
self.assertEqual(1, rp_inv_defaults['step_size'])
|
||||||
|
self.assertEqual(0, rp_inv_defaults['reserved'])
|
||||||
|
|
||||||
|
def test__validate_rp_pkt_processing_cfg(self):
|
||||||
|
cfg.CONF.set_override(n_const.RP_PP_WITHOUT_DIRECTION,
|
||||||
|
[':0'], 'OVS')
|
||||||
|
cfg.CONF.set_override(n_const.RP_PP_WITH_DIRECTION,
|
||||||
|
[':0:0'], 'OVS')
|
||||||
|
self.assertRaises(ValueError, self._make_agent)
|
||||||
|
|
||||||
def test_configurations_has_rp_default_inventory(self):
|
def test_configurations_has_rp_default_inventory(self):
|
||||||
self.assertIn(n_const.RP_INVENTORY_DEFAULTS,
|
self.assertIn(n_const.RP_INVENTORY_DEFAULTS,
|
||||||
self.agent.agent_state['configurations'])
|
self.agent.agent_state['configurations'])
|
||||||
|
15
releasenotes/notes/pps-config-ovs-036b5940694f786c.yaml
Normal file
15
releasenotes/notes/pps-config-ovs-036b5940694f786c.yaml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
New configuration options for neutron-ovs-agent under section ``[ovs]``:
|
||||||
|
``resource_provider_packet_processing_without_direction``,
|
||||||
|
``resource_provider_packet_processing_with_direction`` and
|
||||||
|
``resource_provider_packet_processing_inventory_defaults``.
|
||||||
|
``resource_provider_packet_processing_without_direction`` controls the
|
||||||
|
minimum packet rate the OVS backend can guarantee in kilo (1000) packet per
|
||||||
|
second.
|
||||||
|
``resource_provider_packet_processing_with_direction`` is similar to the
|
||||||
|
first option, but used in case the OVS backend has hardware offload
|
||||||
|
capabilities. The last option can be used to tune the other fields
|
||||||
|
(``allocation_ratio``, ``min_unit``, ``max_unit``, ``reserved``,
|
||||||
|
``step_size``) of resource provider inventories.
|
Loading…
Reference in New Issue
Block a user