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 {
|
||||
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 trunk
|
||||
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 vpn
|
||||
from neutron_lib.api.definitions import vpn_endpoint_groups
|
||||
@ -209,5 +210,6 @@ ML2_SUPPORTED_API_EXTENSIONS = [
|
||||
firewall_v2.ALIAS,
|
||||
firewall_v2_stdattrs.ALIAS,
|
||||
uplink_status_propagation.ALIAS,
|
||||
uplink_status_propagation_updatable.ALIAS,
|
||||
tap_mirror.ALIAS,
|
||||
]
|
||||
|
@ -26,6 +26,17 @@ class UplinkStatusPropagationMixin:
|
||||
obj.create()
|
||||
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
|
||||
def _extend_port_dict(port_res, port_db):
|
||||
# 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-details"
|
||||
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_trusted = neutron.plugins.ml2.extensions.port_trusted:PortTrustedExtensionDriver
|
||||
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
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user