Add shared field to SG API response and filter

Add the shared field to security group API responses and support
using shared as a query filter.

A follow-up patch will remove the temporary api def once it is merged
and released in neutron-lib.

Related-Bug: #1942615
Depends-On: https://review.opendev.org/c/openstack/neutron-lib/+/812617
Change-Id: Ic04be8f0b7097c8aed19365f06089aa7af333eb9
This commit is contained in:
Hang Yang 2021-09-27 17:29:33 -05:00
parent ccb70a60de
commit 4bd1c82213
12 changed files with 137 additions and 5 deletions

View File

@ -28,6 +28,8 @@ from oslo_log import log as logging
from neutron.agent import firewall
from neutron.conf.agent import securitygroups_rpc as sc_cfg
from neutron.extensions import security_groups_shared_filtering_lib \
as sg_shared_filtering
LOG = logging.getLogger(__name__)
@ -53,6 +55,7 @@ def disable_security_group_extension_by_config(aliases):
_disable_extension(stateful_sg.ALIAS, aliases)
_disable_extension(sgag_def.ALIAS, aliases)
_disable_extension(security_groups_normalized_cidr.ALIAS, aliases)
_disable_extension(sg_shared_filtering.ALIAS, aliases)
LOG.info('Disabled allowed-address-pairs extension.')
_disable_extension('allowed-address-pairs', aliases)
LOG.info('Disabled address-group extension.')

View File

@ -52,6 +52,7 @@ from neutron_lib.api.definitions import qos_default
from neutron_lib.api.definitions import qos_rule_type_details
from neutron_lib.api.definitions import qos_rules_alias
from neutron_lib.api.definitions import rbac_address_scope
from neutron_lib.api.definitions import rbac_security_groups
from neutron_lib.api.definitions import router_availability_zone as raz_def
from neutron_lib.api.definitions import security_groups_normalized_cidr
from neutron_lib.api.definitions import security_groups_remote_address_group
@ -62,6 +63,8 @@ from neutron_lib.api.definitions import trunk
from neutron_lib.api.definitions import vlantransparent
from neutron_lib import constants
from neutron.extensions import security_groups_shared_filtering_lib
# NOTE(russellb) This remains in its own file (vs constants.py) because we want
# to be able to easily import it and export the info without any dependencies
# on external imports.
@ -116,10 +119,12 @@ ML2_SUPPORTED_API_EXTENSIONS = [
'quotas',
rbac_address_scope.ALIAS,
'rbac-policies',
rbac_security_groups.ALIAS,
'standard-attr-revisions',
'security-group',
security_groups_normalized_cidr.ALIAS,
security_groups_remote_address_group.ALIAS,
security_groups_shared_filtering_lib.ALIAS,
'standard-attr-description',
constants.SUBNET_ALLOCATION_EXT_ALIAS,
'standard-attr-tag',

View File

@ -342,6 +342,7 @@ class SecurityGroupDbMixin(ext_sg.SecurityGroupPluginBase,
'tenant_id': security_group['tenant_id'],
'description': security_group['description'],
'standard_attr_id': security_group.db_obj.standard_attr.id,
'shared': security_group['shared'],
}
if security_group.rules:
res['security_group_rules'] = [

View File

@ -0,0 +1,21 @@
# 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 import extensions
from neutron.extensions import security_groups_shared_filtering_lib
class Security_groups_shared_filtering(extensions.APIExtensionDescriptor):
"""Extension class supporting filtering SGs depend on the shared field."""
api_definition = security_groups_shared_filtering_lib

View File

@ -0,0 +1,67 @@
# 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.
# NOTE(hangyang): This file can be removed once the api def is merged
# to neutron-lib https://review.opendev.org/c/openstack/neutron-lib/+/812617
from neutron_lib.api import converters
from neutron_lib import constants
# The alias of the extension.
ALIAS = 'security-groups-shared-filtering'
IS_SHIM_EXTENSION = False
IS_STANDARD_ATTR_EXTENSION = False
# The name of the extension.
NAME = 'Security group filtering on the shared field'
# The description of the extension.
DESCRIPTION = "Support filtering security groups on the shared field"
# A timestamp of when the extension was introduced.
UPDATED_TIMESTAMP = "2021-10-05T09:00:00-00:00"
# The resource attribute map for the extension.
RESOURCE_ATTRIBUTE_MAP = {
'security_groups': {
constants.SHARED: {
'allow_post': False,
'allow_put': False,
'convert_to': converters.convert_to_boolean,
'is_visible': True,
'is_filter': True,
'required_by_policy': True,
'enforce_policy': True}
}
}
# The subresource attribute map for the extension.
SUB_RESOURCE_ATTRIBUTE_MAP = {
}
# The action map.
ACTION_MAP = {
}
# The action status.
ACTION_STATUS = {
}
# The list of required extensions.
REQUIRED_EXTENSIONS = ['rbac-security-groups']
# The list of optional extensions.
OPTIONAL_EXTENSIONS = [
]

View File

@ -40,7 +40,8 @@ class SecurityGroup(rbac_db.NeutronRbacObject):
# Version 1.2: Added stateful support
# Version 1.3: Added support for remote_address_group_id in rules
# Version 1.4: Added support for normalized_cidr in rules
VERSION = '1.4'
# Version 1.5: Make the shared field nullable
VERSION = '1.5'
# required by RbacNeutronMetaclass
rbac_db_cls = SecurityGroupRBAC
@ -50,7 +51,7 @@ class SecurityGroup(rbac_db.NeutronRbacObject):
'id': common_types.UUIDField(),
'name': obj_fields.StringField(nullable=True),
'project_id': obj_fields.StringField(nullable=True),
'shared': obj_fields.BooleanField(default=False),
'shared': obj_fields.BooleanField(nullable=True),
'stateful': obj_fields.BooleanField(default=True),
'is_default': obj_fields.BooleanField(default=False),
'rules': obj_fields.ListOfObjectsField(

View File

@ -121,6 +121,7 @@ from neutron.db import subnet_service_type_mixin
from neutron.db import vlantransparent_db
from neutron.extensions import dhcpagentscheduler as dhcp_ext
from neutron.extensions import filter_validation
from neutron.extensions import security_groups_shared_filtering_lib
from neutron.extensions import vlantransparent
from neutron.ipam import exceptions as ipam_exc
from neutron.objects import base as base_obj
@ -216,6 +217,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
security_groups_normalized_cidr.ALIAS,
security_groups_port_filtering.ALIAS,
security_groups_remote_address_group.ALIAS,
security_groups_shared_filtering_lib.ALIAS,
empty_string_filtering.ALIAS,
filter_apidef.ALIAS,
port_mac_address_regenerate.ALIAS,

View File

@ -55,6 +55,7 @@ NETWORK_API_EXTENSIONS+=",router-admin-state-down-before-update"
NETWORK_API_EXTENSIONS+=",router_availability_zone"
NETWORK_API_EXTENSIONS+=",security-group"
NETWORK_API_EXTENSIONS+=",security-groups-remote-address-group"
NETWORK_API_EXTENSIONS+=",security-groups-shared-filtering"
NETWORK_API_EXTENSIONS+=",port-device-profile"
NETWORK_API_EXTENSIONS+=",port-mac-address-regenerate"
NETWORK_API_EXTENSIONS+=",port-numa-affinity-policy"

View File

@ -292,6 +292,7 @@ class SecurityGroupDbMixinTestCase(testlib_api.SqlTestCase):
'description': 'Default security group',
'stateful': mock.ANY,
'standard_attr_id': mock.ANY,
'shared': False,
'security_group_rules': [
# Four rules for egress/ingress and ipv4/ipv6
mock.ANY, mock.ANY, mock.ANY, mock.ANY,

View File

@ -17,6 +17,7 @@ import contextlib
import copy
from unittest import mock
from neutron_lib.api.definitions import rbac_security_groups as rbac_sg_def
from neutron_lib.api.definitions import security_groups_remote_address_group \
as sgag_def
from neutron_lib.api import validators
@ -35,6 +36,8 @@ from neutron.db import address_group_db
from neutron.db import db_base_plugin_v2
from neutron.db import securitygroups_db
from neutron.extensions import address_group as ext_ag
from neutron.extensions import security_groups_shared_filtering_lib \
as sg_shared_filter_def
from neutron.extensions import securitygroup as ext_sg
from neutron.extensions import standardattrdescription
from neutron.tests import base
@ -68,6 +71,9 @@ class SecurityGroupTestExtensionManager(object):
# update with the remote address group api definition
ext_sg.Securitygroup().update_attributes_map(
sgag_def.RESOURCE_ATTRIBUTE_MAP)
# update with the shared field api definition
ext_sg.Securitygroup().update_attributes_map(
sg_shared_filter_def.RESOURCE_ATTRIBUTE_MAP)
return (ext_sg.Securitygroup.get_resources() +
ext_ag.Address_group().get_resources())
@ -225,7 +231,9 @@ class SecurityGroupTestPlugin(db_base_plugin_v2.NeutronDbPluginV2,
__native_pagination_support = True
__native_sorting_support = True
supported_extension_aliases = ["security-group"]
supported_extension_aliases = [
"security-group", sgag_def.ALIAS,
rbac_sg_def.ALIAS, sg_shared_filter_def.ALIAS]
def create_port(self, context, port):
tenant_id = port['port']['tenant_id']
@ -289,7 +297,8 @@ class TestSecurityGroups(SecurityGroupDBTestCase):
def test_create_security_group(self):
name = 'webservers'
description = 'my webservers'
keys = [('name', name,), ('description', description)]
keys = [('name', name,), ('description', description),
('shared', False)]
with self.security_group(name, description) as security_group:
for k, v, in keys:
self.assertEqual(v, security_group['security_group'][k])
@ -498,6 +507,20 @@ class TestSecurityGroups(SecurityGroupDBTestCase):
security_groups,
query_params='description=sg')
def test_list_security_groups_with_shared_filter_true(self):
with self.security_group(name='sg1', description='sg'):
security_groups = ()
self._test_list_resources('security-group',
security_groups,
query_params='name=sg1&shared=True')
def test_list_security_groups_with_shared_filter_false(self):
with self.security_group(name='sg1', description='sg') as sg1:
security_groups = (sg1, )
self._test_list_resources('security-group',
security_groups,
query_params='name=sg1&shared=False')
def test_list_security_groups_with_sort(self):
with self.security_group(name='sg1', description='sg') as sg1,\
self.security_group(name='sg2', description='sg') as sg2,\

View File

@ -105,7 +105,7 @@ object_data = {
'RouterL3AgentBinding': '1.0-c5ba6c95e3a4c1236a55f490cd67da82',
'RouterPort': '1.0-c8c8f499bcdd59186fcd83f323106908',
'RouterRoute': '1.0-07fc5337c801fb8c6ccfbcc5afb45907',
'SecurityGroup': '1.4-7b63b834e511856f54a09282d6843ecc',
'SecurityGroup': '1.5-7eb8e44c327512e7bb1759ab41ede44b',
'SecurityGroupPortBinding': '1.0-6879d5c0af80396ef5a72934b6a6ef20',
'SecurityGroupRBAC': '1.0-192845c5ed0718e1c54fac36936fcd7d',
'SecurityGroupRule': '1.2-27793368d4ac35f2ed6e0bb653c6aaad',

View File

@ -0,0 +1,7 @@
---
features:
- |
Add the shared field to security group API responses and support
using shared as a query filter.
For more information see bug
`1942615 <https://bugs.launchpad.net/neutron/+bug/1942615>`_.