Add extension "uplink-status-propagation-updatable"
This extension allows to update the port flag "propagate_uplink_status", used by the ML2/SR-IOV agent to define a VF port link state as "auto" (the VF will mimic the PF port link status). The neutron-lib version required is at least 3.16.0, that includes [1]. [1]https://review.opendev.org/c/openstack/neutron-lib/+/927820 Closes-Bug: #2078661 Change-Id: Ic3c85d296cf3391b157c531d7bde90c6dbee2f8e
This commit is contained in:
parent
ed7431fe43
commit
498be543e0
@ -1,3 +1,4 @@
|
|||||||
function configure_uplink_status_propagation_extension {
|
function configure_uplink_status_propagation_extension {
|
||||||
neutron_ml2_extension_driver_add "uplink_status_propagation"
|
neutron_ml2_extension_driver_add "uplink_status_propagation"
|
||||||
|
neutron_ml2_extension_driver_add "uplink_status_propagation_updatable"
|
||||||
}
|
}
|
||||||
|
@ -93,6 +93,7 @@ from neutron_lib.api.definitions import tag_creation
|
|||||||
from neutron_lib.api.definitions import tap_mirror
|
from neutron_lib.api.definitions import tap_mirror
|
||||||
from neutron_lib.api.definitions import trunk
|
from neutron_lib.api.definitions import trunk
|
||||||
from neutron_lib.api.definitions import uplink_status_propagation
|
from neutron_lib.api.definitions import uplink_status_propagation
|
||||||
|
from neutron_lib.api.definitions import uplink_status_propagation_updatable
|
||||||
from neutron_lib.api.definitions import vlantransparent
|
from neutron_lib.api.definitions import vlantransparent
|
||||||
from neutron_lib.api.definitions import vpn
|
from neutron_lib.api.definitions import vpn
|
||||||
from neutron_lib.api.definitions import vpn_endpoint_groups
|
from neutron_lib.api.definitions import vpn_endpoint_groups
|
||||||
@ -209,5 +210,6 @@ ML2_SUPPORTED_API_EXTENSIONS = [
|
|||||||
firewall_v2.ALIAS,
|
firewall_v2.ALIAS,
|
||||||
firewall_v2_stdattrs.ALIAS,
|
firewall_v2_stdattrs.ALIAS,
|
||||||
uplink_status_propagation.ALIAS,
|
uplink_status_propagation.ALIAS,
|
||||||
|
uplink_status_propagation_updatable.ALIAS,
|
||||||
tap_mirror.ALIAS,
|
tap_mirror.ALIAS,
|
||||||
]
|
]
|
||||||
|
@ -26,6 +26,17 @@ class UplinkStatusPropagationMixin:
|
|||||||
obj.create()
|
obj.create()
|
||||||
res[usp.PROPAGATE_UPLINK_STATUS] = data[usp.PROPAGATE_UPLINK_STATUS]
|
res[usp.PROPAGATE_UPLINK_STATUS] = data[usp.PROPAGATE_UPLINK_STATUS]
|
||||||
|
|
||||||
|
def _process_update_port(self, context, data, res):
|
||||||
|
obj = usp_obj.PortUplinkStatusPropagation.get_object(
|
||||||
|
context, port_id=res['id'])
|
||||||
|
if obj:
|
||||||
|
obj.propagate_uplink_status = data[usp.PROPAGATE_UPLINK_STATUS]
|
||||||
|
obj.update()
|
||||||
|
res[usp.PROPAGATE_UPLINK_STATUS] = data[
|
||||||
|
usp.PROPAGATE_UPLINK_STATUS]
|
||||||
|
else:
|
||||||
|
self._process_create_port(context, data, res)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _extend_port_dict(port_res, port_db):
|
def _extend_port_dict(port_res, port_db):
|
||||||
# NOTE(ralonsoh): the default value is "True". Ports created before
|
# NOTE(ralonsoh): the default value is "True". Ports created before
|
||||||
|
19
neutron/extensions/uplink_status_propagation_updatable.py
Normal file
19
neutron/extensions/uplink_status_propagation_updatable.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# 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 neutron_lib.api.definitions import uplink_status_propagation_updatable \
|
||||||
|
as apidef
|
||||||
|
from neutron_lib.api import extensions
|
||||||
|
|
||||||
|
|
||||||
|
class Uplink_status_propagation_updatable(extensions.APIExtensionDescriptor):
|
||||||
|
api_definition = apidef
|
@ -0,0 +1,42 @@
|
|||||||
|
# Copyright (c) 2024 Red Hat Inc.
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# 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 neutron_lib.api.definitions import uplink_status_propagation_updatable \
|
||||||
|
as uspu
|
||||||
|
from neutron_lib.plugins.ml2 import api
|
||||||
|
from oslo_log import log as logging
|
||||||
|
|
||||||
|
from neutron.db import uplink_status_propagation_db as usp_db
|
||||||
|
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class UplinkStatusPropagationUpdatableExtensionDriver(
|
||||||
|
api.ExtensionDriver, usp_db.UplinkStatusPropagationMixin):
|
||||||
|
|
||||||
|
_supported_extension_alias = uspu.ALIAS
|
||||||
|
|
||||||
|
def initialize(self):
|
||||||
|
LOG.info('UplinkStatusPropagationUpdatableExtensionDriver '
|
||||||
|
'initialization complete')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def extension_alias(self):
|
||||||
|
return self._supported_extension_alias
|
||||||
|
|
||||||
|
def process_update_port(self, context, data, result):
|
||||||
|
if uspu.PROPAGATE_UPLINK_STATUS in data:
|
||||||
|
self._process_update_port(context, data, result)
|
@ -84,3 +84,4 @@ NETWORK_API_EXTENSIONS+=",tag-ports-during-bulk-creation"
|
|||||||
NETWORK_API_EXTENSIONS+=",trunk"
|
NETWORK_API_EXTENSIONS+=",trunk"
|
||||||
NETWORK_API_EXTENSIONS+=",trunk-details"
|
NETWORK_API_EXTENSIONS+=",trunk-details"
|
||||||
NETWORK_API_EXTENSIONS+=",uplink-status-propagation"
|
NETWORK_API_EXTENSIONS+=",uplink-status-propagation"
|
||||||
|
NETWORK_API_EXTENSIONS+=",uplink-status-propagation-updatable"
|
||||||
|
@ -0,0 +1,97 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
import ddt
|
||||||
|
from neutron_lib.api.definitions import uplink_status_propagation as usp
|
||||||
|
from neutron_lib.api.definitions import uplink_status_propagation_updatable \
|
||||||
|
as apidef
|
||||||
|
from neutron_lib.db import api as db_api
|
||||||
|
from neutron_lib.db import resource_extend
|
||||||
|
|
||||||
|
from neutron.db import db_base_plugin_v2
|
||||||
|
from neutron.db import uplink_status_propagation_db as usp_db
|
||||||
|
from neutron.tests.common import test_db_base_plugin_v2
|
||||||
|
|
||||||
|
|
||||||
|
class UplinkStatusPropagationUpdatableExtensionTestPlugin(
|
||||||
|
db_base_plugin_v2.NeutronDbPluginV2,
|
||||||
|
usp_db.UplinkStatusPropagationMixin):
|
||||||
|
"""Test plugin to mixin the uplink status propagation extension.
|
||||||
|
"""
|
||||||
|
|
||||||
|
supported_extension_aliases = [usp.ALIAS, apidef.ALIAS]
|
||||||
|
|
||||||
|
# TODO(ralonsoh): update ``uplink_status_propagation_updatable`` with
|
||||||
|
# COLLECTION_NAME=neutron_lib.api.definitions.port.COLLECTION_NAME
|
||||||
|
@staticmethod
|
||||||
|
@resource_extend.extends([usp.COLLECTION_NAME])
|
||||||
|
def _extend_network_project_default(port_res, port_db):
|
||||||
|
return usp_db.UplinkStatusPropagationMixin._extend_port_dict(
|
||||||
|
port_res, port_db)
|
||||||
|
|
||||||
|
def create_port(self, context, port):
|
||||||
|
with db_api.CONTEXT_WRITER.using(context):
|
||||||
|
new_port = super().create_port(context, port)
|
||||||
|
# Update the propagate_uplink_status in the database
|
||||||
|
p = port['port']
|
||||||
|
if 'propagate_uplink_status' not in p:
|
||||||
|
p['propagate_uplink_status'] = False
|
||||||
|
self._process_create_port(context, p, new_port)
|
||||||
|
return new_port
|
||||||
|
|
||||||
|
def update_port(self, context, port_id, port, **kwargs):
|
||||||
|
with db_api.CONTEXT_WRITER.using(context):
|
||||||
|
new_port = super().update_port(context, port_id, port)
|
||||||
|
# Update the propagate_uplink_status in the database
|
||||||
|
p = port['port']
|
||||||
|
if 'propagate_uplink_status' not in p:
|
||||||
|
p['propagate_uplink_status'] = False
|
||||||
|
self._process_update_port(context, p, new_port)
|
||||||
|
return new_port
|
||||||
|
|
||||||
|
|
||||||
|
@ddt.ddt
|
||||||
|
class UplinkStatusPropagationUpdatableExtensionTestCase(
|
||||||
|
test_db_base_plugin_v2.NeutronDbPluginV2TestCase):
|
||||||
|
"""Test API extension ``uplink-status-propagation-updatable`` attributes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def setUp(self, **kwargs):
|
||||||
|
plugin = ('neutron.tests.unit.extensions.test_uplink_status_'
|
||||||
|
'propagation_updatable.'
|
||||||
|
'UplinkStatusPropagationUpdatableExtensionTestPlugin')
|
||||||
|
super().setUp(plugin=plugin)
|
||||||
|
|
||||||
|
@ddt.data(True, False)
|
||||||
|
def test_update_port_propagate_uplink_status(
|
||||||
|
self, propagate_uplink_status):
|
||||||
|
name = 'propagate_uplink_status'
|
||||||
|
keys = [('name', name), ('admin_state_up', True),
|
||||||
|
('status', self.port_create_status),
|
||||||
|
(usp.PROPAGATE_UPLINK_STATUS, propagate_uplink_status)]
|
||||||
|
with self.port(name=name,
|
||||||
|
propagate_uplink_status=propagate_uplink_status
|
||||||
|
) as port:
|
||||||
|
for k, v in keys:
|
||||||
|
self.assertEqual(v, port['port'][k])
|
||||||
|
|
||||||
|
# Update the port with the opposite ``propagate_uplink_status``
|
||||||
|
# value and check it.
|
||||||
|
data = {'port': {usp.PROPAGATE_UPLINK_STATUS:
|
||||||
|
not propagate_uplink_status}}
|
||||||
|
req = self.new_update_request('ports', data, port['port']['id'])
|
||||||
|
req.get_response(self.api)
|
||||||
|
req = self.new_show_request('ports', port['port']['id'])
|
||||||
|
res = req.get_response(self.api)
|
||||||
|
port = self.deserialize(self.fmt, res)['port']
|
||||||
|
self.assertEqual(not propagate_uplink_status,
|
||||||
|
port[usp.PROPAGATE_UPLINK_STATUS])
|
@ -0,0 +1,60 @@
|
|||||||
|
# Copyright (c) 2024 Red Hat Inc.
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
import ddt
|
||||||
|
from neutron_lib.api.definitions import uplink_status_propagation as usp_def
|
||||||
|
from neutron_lib.api.definitions import uplink_status_propagation_updatable \
|
||||||
|
as uspu_def
|
||||||
|
from neutron_lib.plugins import directory
|
||||||
|
from oslo_config import cfg
|
||||||
|
|
||||||
|
from neutron.tests.unit.plugins.ml2 import test_plugin
|
||||||
|
|
||||||
|
|
||||||
|
@ddt.ddt
|
||||||
|
class UplinkStatusPropagationUpdatableML2ExtDriverTestCase(
|
||||||
|
test_plugin.Ml2PluginV2TestCase):
|
||||||
|
|
||||||
|
_extension_drivers = [usp_def.ALIAS.replace('-', '_'),
|
||||||
|
uspu_def.ALIAS.replace('-', '_')]
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
cfg.CONF.set_override('extension_drivers',
|
||||||
|
self._extension_drivers,
|
||||||
|
group='ml2')
|
||||||
|
super().setUp()
|
||||||
|
self.plugin = directory.get_plugin()
|
||||||
|
|
||||||
|
@ddt.data(True, False)
|
||||||
|
def test_port_update_propagate_uplink_status(self, _status):
|
||||||
|
with self.network() as n:
|
||||||
|
args = {'port': {'name': 'test',
|
||||||
|
'network_id': n['network']['id'],
|
||||||
|
'tenant_id': n['network']['id'],
|
||||||
|
'device_id': '',
|
||||||
|
'device_owner': '',
|
||||||
|
'fixed_ips': '',
|
||||||
|
'propagate_uplink_status': _status,
|
||||||
|
'admin_state_up': True,
|
||||||
|
'status': 'ACTIVE'}}
|
||||||
|
try:
|
||||||
|
port = self.plugin.create_port(self.context, args)
|
||||||
|
args = {'port': {'propagate_uplink_status': not _status}}
|
||||||
|
self.plugin.update_port(self.context, port['id'], args)
|
||||||
|
port = self.plugin.get_port(self.context, port['id'])
|
||||||
|
self.assertEqual(not _status, port['propagate_uplink_status'])
|
||||||
|
finally:
|
||||||
|
if port:
|
||||||
|
self.plugin.delete_port(self.context, port['id'])
|
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Added a new API extension ``uplink_status_propagation_updatable``. Now the
|
||||||
|
port attribute `propagate_uplink_status`` can be updated once the port is
|
||||||
|
created. The backend (ML2/SR-IOV) will receive the update and update the
|
||||||
|
VF state.
|
@ -124,6 +124,7 @@ neutron.ml2.extension_drivers =
|
|||||||
port_numa_affinity_policy = neutron.plugins.ml2.extensions.port_numa_affinity_policy:PortNumaAffinityPolicyExtensionDriver
|
port_numa_affinity_policy = neutron.plugins.ml2.extensions.port_numa_affinity_policy:PortNumaAffinityPolicyExtensionDriver
|
||||||
port_trusted = neutron.plugins.ml2.extensions.port_trusted:PortTrustedExtensionDriver
|
port_trusted = neutron.plugins.ml2.extensions.port_trusted:PortTrustedExtensionDriver
|
||||||
uplink_status_propagation = neutron.plugins.ml2.extensions.uplink_status_propagation:UplinkStatusPropagationExtensionDriver
|
uplink_status_propagation = neutron.plugins.ml2.extensions.uplink_status_propagation:UplinkStatusPropagationExtensionDriver
|
||||||
|
uplink_status_propagation_updatable = neutron.plugins.ml2.extensions.uplink_status_propagation_updatable:UplinkStatusPropagationUpdatableExtensionDriver
|
||||||
tag_ports_during_bulk_creation = neutron.plugins.ml2.extensions.tag_ports_during_bulk_creation:TagPortsDuringBulkCreationExtensionDriver
|
tag_ports_during_bulk_creation = neutron.plugins.ml2.extensions.tag_ports_during_bulk_creation:TagPortsDuringBulkCreationExtensionDriver
|
||||||
subnet_dns_publish_fixed_ip = neutron.plugins.ml2.extensions.subnet_dns_publish_fixed_ip:SubnetDNSPublishFixedIPExtensionDriver
|
subnet_dns_publish_fixed_ip = neutron.plugins.ml2.extensions.subnet_dns_publish_fixed_ip:SubnetDNSPublishFixedIPExtensionDriver
|
||||||
dns_domain_keywords = neutron.plugins.ml2.extensions.dns_domain_keywords:DnsDomainKeywordsExtensionDriver
|
dns_domain_keywords = neutron.plugins.ml2.extensions.dns_domain_keywords:DnsDomainKeywordsExtensionDriver
|
||||||
|
Loading…
x
Reference in New Issue
Block a user