Merge "Support filtering port with IP address substring"
This commit is contained in:
commit
1813f7c497
23
neutron/extensions/ip_substring_port_filtering.py
Normal file
23
neutron/extensions/ip_substring_port_filtering.py
Normal file
@ -0,0 +1,23 @@
|
||||
# Copyright (c) 2017 Huawei Technology, 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 import extensions
|
||||
|
||||
from neutron.extensions import ip_substring_port_filtering_lib as apidef
|
||||
|
||||
|
||||
class Ip_substring_port_filtering(extensions.APIExtensionDescriptor):
|
||||
"""Extension class supporting IP substring port filtering."""
|
||||
|
||||
api_definition = apidef
|
64
neutron/extensions/ip_substring_port_filtering_lib.py
Normal file
64
neutron/extensions/ip_substring_port_filtering_lib.py
Normal file
@ -0,0 +1,64 @@
|
||||
# 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.
|
||||
|
||||
"""
|
||||
TODO(hongbin): This module should be deleted once neutron-lib containing
|
||||
https://review.openstack.org/#/c/525284/ change is released.
|
||||
"""
|
||||
|
||||
# The alias of the extension.
|
||||
ALIAS = 'ip-substring-filtering'
|
||||
|
||||
# Whether or not this extension is simply signaling behavior to the user
|
||||
# or it actively modifies the attribute map.
|
||||
IS_SHIM_EXTENSION = True
|
||||
|
||||
# Whether the extension is marking the adoption of standardattr model for
|
||||
# legacy resources, or introducing new standardattr attributes. False or
|
||||
# None if the standardattr model is adopted since the introduction of
|
||||
# resource extension.
|
||||
# If this is True, the alias for the extension should be prefixed with
|
||||
# 'standard-attr-'.
|
||||
IS_STANDARD_ATTR_EXTENSION = False
|
||||
|
||||
# The name of the extension.
|
||||
NAME = 'IP address substring filtering'
|
||||
|
||||
# The description of the extension.
|
||||
DESCRIPTION = "Provides IP address substring filtering when listing ports"
|
||||
|
||||
# A timestamp of when the extension was introduced.
|
||||
UPDATED_TIMESTAMP = "2017-11-28T09:00:00-00:00"
|
||||
|
||||
# The resource attribute map for the extension.
|
||||
RESOURCE_ATTRIBUTE_MAP = {
|
||||
}
|
||||
|
||||
# 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 = [
|
||||
]
|
||||
|
||||
# The list of optional extensions.
|
||||
OPTIONAL_EXTENSIONS = [
|
||||
]
|
@ -46,6 +46,7 @@ from oslo_utils import excutils
|
||||
from oslo_utils import importutils
|
||||
from oslo_utils import uuidutils
|
||||
import sqlalchemy
|
||||
from sqlalchemy import or_
|
||||
from sqlalchemy.orm import exc as sa_exc
|
||||
|
||||
from neutron._i18n import _
|
||||
@ -153,7 +154,8 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
"availability_zone",
|
||||
"network_availability_zone",
|
||||
"default-subnetpools",
|
||||
"subnet-service-types"]
|
||||
"subnet-service-types",
|
||||
"ip-substring-filtering"]
|
||||
|
||||
@property
|
||||
def supported_extension_aliases(self):
|
||||
@ -1849,6 +1851,19 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
return port.id
|
||||
return device
|
||||
|
||||
def _get_ports_query(self, context, filters=None, *args, **kwargs):
|
||||
filters = filters or {}
|
||||
fixed_ips = filters.get('fixed_ips', {})
|
||||
ip_addresses_s = fixed_ips.get('ip_address_substr')
|
||||
query = super(Ml2Plugin, self)._get_ports_query(context, filters,
|
||||
*args, **kwargs)
|
||||
if ip_addresses_s:
|
||||
substr_filter = or_(*[models_v2.Port.fixed_ips.any(
|
||||
models_v2.IPAllocation.ip_address.like('%%%s%%' % ip))
|
||||
for ip in ip_addresses_s])
|
||||
query = query.filter(substr_filter)
|
||||
return query
|
||||
|
||||
def filter_hosts_with_network_access(
|
||||
self, context, network_id, candidate_hosts):
|
||||
segments = segments_db.get_network_segments(context, network_id)
|
||||
|
@ -15,6 +15,7 @@ NETWORK_API_EXTENSIONS+=",external-net"
|
||||
NETWORK_API_EXTENSIONS+=",extra_dhcp_opt"
|
||||
NETWORK_API_EXTENSIONS+=",extraroute"
|
||||
NETWORK_API_EXTENSIONS+=",flavors"
|
||||
NETWORK_API_EXTENSIONS+=",ip-substring-filtering"
|
||||
NETWORK_API_EXTENSIONS+=",l3-flavors"
|
||||
NETWORK_API_EXTENSIONS+=",l3-ha"
|
||||
NETWORK_API_EXTENSIONS+=",l3_agent_scheduler"
|
||||
|
@ -1217,6 +1217,67 @@ class TestMl2PortsV2(test_plugin.TestPortsV2, Ml2PluginV2TestCase):
|
||||
# make sure that the grenade went off during the commit
|
||||
self.assertTrue(listener.except_raised)
|
||||
|
||||
def test_list_ports_filtered_by_fixed_ip_substring(self):
|
||||
# for this test we need to enable overlapping ips
|
||||
cfg.CONF.set_default('allow_overlapping_ips', True)
|
||||
with self.port() as port1, self.port():
|
||||
fixed_ips = port1['port']['fixed_ips'][0]
|
||||
query_params = """
|
||||
fixed_ips=ip_address_substr%%3D%s&fixed_ips=subnet_id%%3D%s
|
||||
""".strip() % (fixed_ips['ip_address'][:-1],
|
||||
fixed_ips['subnet_id'])
|
||||
self._test_list_resources('port', [port1],
|
||||
query_params=query_params)
|
||||
query_params = """
|
||||
fixed_ips=ip_address_substr%%3D%s&fixed_ips=subnet_id%%3D%s
|
||||
""".strip() % (fixed_ips['ip_address'][1:],
|
||||
fixed_ips['subnet_id'])
|
||||
self._test_list_resources('port', [port1],
|
||||
query_params=query_params)
|
||||
query_params = """
|
||||
fixed_ips=ip_address_substr%%3D%s&fixed_ips=subnet_id%%3D%s
|
||||
""".strip() % ('192.168.',
|
||||
fixed_ips['subnet_id'])
|
||||
self._test_list_resources('port', [],
|
||||
query_params=query_params)
|
||||
|
||||
def test_list_ports_filtered_by_fixed_ip_substring_dual_stack(self):
|
||||
with self.subnet() as subnet:
|
||||
# Get a IPv4 and IPv6 address
|
||||
tenant_id = subnet['subnet']['tenant_id']
|
||||
net_id = subnet['subnet']['network_id']
|
||||
res = self._create_subnet(
|
||||
self.fmt,
|
||||
tenant_id=tenant_id,
|
||||
net_id=net_id,
|
||||
cidr='2607:f0d0:1002:51::/124',
|
||||
ip_version=6,
|
||||
gateway_ip=constants.ATTR_NOT_SPECIFIED)
|
||||
subnet2 = self.deserialize(self.fmt, res)
|
||||
kwargs = {"fixed_ips":
|
||||
[{'subnet_id': subnet['subnet']['id']},
|
||||
{'subnet_id': subnet2['subnet']['id']}]}
|
||||
res = self._create_port(self.fmt, net_id=net_id, **kwargs)
|
||||
port1 = self.deserialize(self.fmt, res)
|
||||
res = self._create_port(self.fmt, net_id=net_id, **kwargs)
|
||||
port2 = self.deserialize(self.fmt, res)
|
||||
fixed_ips = port1['port']['fixed_ips']
|
||||
self.assertEqual(2, len(fixed_ips))
|
||||
query_params = """
|
||||
fixed_ips=ip_address_substr%%3D%s&fixed_ips=ip_address%%3D%s
|
||||
""".strip() % (fixed_ips[0]['ip_address'][:-1],
|
||||
fixed_ips[1]['ip_address'])
|
||||
self._test_list_resources('port', [port1],
|
||||
query_params=query_params)
|
||||
query_params = """
|
||||
fixed_ips=ip_address_substr%%3D%s&fixed_ips=ip_address%%3D%s
|
||||
""".strip() % ('192.168.',
|
||||
fixed_ips[1]['ip_address'])
|
||||
self._test_list_resources('port', [],
|
||||
query_params=query_params)
|
||||
self._delete('ports', port1['port']['id'])
|
||||
self._delete('ports', port2['port']['id'])
|
||||
|
||||
|
||||
class TestMl2PortsV2WithRevisionPlugin(Ml2PluginV2TestCase):
|
||||
|
||||
|
@ -0,0 +1,4 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Support substring matching when filtering ports by IP address.
|
Loading…
Reference in New Issue
Block a user