Merge "Add special treatment for 'any' in SG rule API"
This commit is contained in:
commit
0c8db6d457
@ -45,6 +45,13 @@ IPTABLES_MULTIPORT_ONLY_PROTOCOLS = [
|
|||||||
IPV6_ICMP_LEGACY_PROTO_LIST = [constants.PROTO_NAME_ICMP,
|
IPV6_ICMP_LEGACY_PROTO_LIST = [constants.PROTO_NAME_ICMP,
|
||||||
constants.PROTO_NAME_IPV6_ICMP_LEGACY]
|
constants.PROTO_NAME_IPV6_ICMP_LEGACY]
|
||||||
|
|
||||||
|
# Protocol 'any', which is treated the same way as 'no protocol' in the API.
|
||||||
|
# The openstack client changes 'any' to None for the API call, but we want
|
||||||
|
# to accept both as being the same, for example, if it was passed directly
|
||||||
|
# via the curl command.
|
||||||
|
PROTO_NAME_ANY = 'any'
|
||||||
|
SG_RULE_PROTO_ANY = (None, PROTO_NAME_ANY)
|
||||||
|
|
||||||
# Number of resources for neutron agent side functions to deal
|
# Number of resources for neutron agent side functions to deal
|
||||||
# with large sets.
|
# with large sets.
|
||||||
# Setting this value does not count on special conditions, it is just a human
|
# Setting this value does not count on special conditions, it is just a human
|
||||||
|
@ -686,7 +686,7 @@ class SecurityGroupDbMixin(
|
|||||||
rule_obj, fields=fields)
|
rule_obj, fields=fields)
|
||||||
|
|
||||||
def _get_ip_proto_number(self, protocol):
|
def _get_ip_proto_number(self, protocol):
|
||||||
if protocol is None:
|
if protocol in const.SG_RULE_PROTO_ANY:
|
||||||
return
|
return
|
||||||
# According to bug 1381379, protocol is always set to string to avoid
|
# According to bug 1381379, protocol is always set to string to avoid
|
||||||
# problems with comparing int and string in PostgreSQL. Here this
|
# problems with comparing int and string in PostgreSQL. Here this
|
||||||
@ -697,7 +697,7 @@ class SecurityGroupDbMixin(
|
|||||||
return int(constants.IP_PROTOCOL_MAP.get(protocol, protocol))
|
return int(constants.IP_PROTOCOL_MAP.get(protocol, protocol))
|
||||||
|
|
||||||
def _get_ip_proto_name_and_num(self, protocol, ethertype=None):
|
def _get_ip_proto_name_and_num(self, protocol, ethertype=None):
|
||||||
if protocol is None:
|
if protocol in const.SG_RULE_PROTO_ANY:
|
||||||
return
|
return
|
||||||
protocol = str(protocol)
|
protocol = str(protocol)
|
||||||
# Force all legacy IPv6 ICMP protocol names to be 'ipv6-icmp', and
|
# Force all legacy IPv6 ICMP protocol names to be 'ipv6-icmp', and
|
||||||
|
@ -28,6 +28,7 @@ from oslo_utils import netutils
|
|||||||
from neutron._i18n import _
|
from neutron._i18n import _
|
||||||
from neutron.api import extensions
|
from neutron.api import extensions
|
||||||
from neutron.api.v2 import base
|
from neutron.api.v2 import base
|
||||||
|
from neutron.common import _constants
|
||||||
from neutron.conf import quota
|
from neutron.conf import quota
|
||||||
from neutron.extensions import standardattrdescription as stdattr_ext
|
from neutron.extensions import standardattrdescription as stdattr_ext
|
||||||
from neutron.quota import resource_registry
|
from neutron.quota import resource_registry
|
||||||
@ -148,7 +149,7 @@ class SecurityGroupRuleInvalidEtherType(exceptions.InvalidInput):
|
|||||||
|
|
||||||
|
|
||||||
def convert_protocol(value):
|
def convert_protocol(value):
|
||||||
if value is None:
|
if value in _constants.SG_RULE_PROTO_ANY:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
val = int(value)
|
val = int(value)
|
||||||
@ -208,7 +209,8 @@ def _validate_name_not_default(data, max_len=db_const.NAME_FIELD_SIZE):
|
|||||||
|
|
||||||
validators.add_validator('name_not_default', _validate_name_not_default)
|
validators.add_validator('name_not_default', _validate_name_not_default)
|
||||||
|
|
||||||
sg_supported_protocols = ([None] + list(const.IP_PROTOCOL_MAP.keys()))
|
sg_supported_protocols = (_constants.SG_RULE_PROTO_ANY +
|
||||||
|
tuple(const.IP_PROTOCOL_MAP.keys()))
|
||||||
sg_supported_ethertypes = ['IPv4', 'IPv6']
|
sg_supported_ethertypes = ['IPv4', 'IPv6']
|
||||||
SECURITYGROUPS = 'security_groups'
|
SECURITYGROUPS = 'security_groups'
|
||||||
SECURITYGROUPRULES = 'security_group_rules'
|
SECURITYGROUPRULES = 'security_group_rules'
|
||||||
|
@ -24,6 +24,7 @@ from neutron_lib.objects import exceptions as obj_exc
|
|||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
import testtools
|
import testtools
|
||||||
|
|
||||||
|
from neutron.common import _constants as const
|
||||||
from neutron.db import securitygroups_db
|
from neutron.db import securitygroups_db
|
||||||
from neutron.extensions import security_groups_default_rules as \
|
from neutron.extensions import security_groups_default_rules as \
|
||||||
ext_sg_default_rules
|
ext_sg_default_rules
|
||||||
@ -499,10 +500,13 @@ class SecurityGroupDbMixinTestCase(testlib_api.SqlTestCase):
|
|||||||
|
|
||||||
def test_get_ip_proto_name_and_num(self):
|
def test_get_ip_proto_name_and_num(self):
|
||||||
protocols = [constants.PROTO_NAME_UDP, str(constants.PROTO_NUM_TCP),
|
protocols = [constants.PROTO_NAME_UDP, str(constants.PROTO_NUM_TCP),
|
||||||
|
constants.PROTO_NAME_IP, None, const.PROTO_NAME_ANY,
|
||||||
'blah', '111']
|
'blah', '111']
|
||||||
protocol_names_nums = (
|
protocol_names_nums = (
|
||||||
[[constants.PROTO_NAME_UDP, str(constants.PROTO_NUM_UDP)],
|
[[constants.PROTO_NAME_UDP, str(constants.PROTO_NUM_UDP)],
|
||||||
[constants.PROTO_NAME_TCP, str(constants.PROTO_NUM_TCP)],
|
[constants.PROTO_NAME_TCP, str(constants.PROTO_NUM_TCP)],
|
||||||
|
[constants.PROTO_NAME_IP, str(constants.PROTO_NUM_IP)],
|
||||||
|
None, None,
|
||||||
['blah', 'blah'], ['111', '111']])
|
['blah', 'blah'], ['111', '111']])
|
||||||
|
|
||||||
for i, protocol in enumerate(protocols):
|
for i, protocol in enumerate(protocols):
|
||||||
|
@ -703,6 +703,18 @@ class TestSecurityGroups(SecurityGroupDBTestCase):
|
|||||||
self.deserialize(self.fmt, res)
|
self.deserialize(self.fmt, res)
|
||||||
self.assertEqual(webob.exc.HTTPCreated.code, res.status_int)
|
self.assertEqual(webob.exc.HTTPCreated.code, res.status_int)
|
||||||
|
|
||||||
|
def test_create_security_group_rule_protocol_as_any(self):
|
||||||
|
name = 'webservers'
|
||||||
|
description = 'my webservers'
|
||||||
|
with self.security_group(name, description) as sg:
|
||||||
|
security_group_id = sg['security_group']['id']
|
||||||
|
protocol = 'any'
|
||||||
|
rule = self._build_security_group_rule(
|
||||||
|
security_group_id, 'ingress', protocol)
|
||||||
|
res = self._create_security_group_rule(self.fmt, rule)
|
||||||
|
self.deserialize(self.fmt, res)
|
||||||
|
self.assertEqual(webob.exc.HTTPCreated.code, res.status_int)
|
||||||
|
|
||||||
def test_create_security_group_rule_protocol_as_number_with_port_bad(self):
|
def test_create_security_group_rule_protocol_as_number_with_port_bad(self):
|
||||||
# When specifying ports, neither can be None
|
# When specifying ports, neither can be None
|
||||||
name = 'webservers'
|
name = 'webservers'
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
Add special treatment for the keyword ``any`` in the security group rule
|
||||||
|
API protocol field to match what is documented in the api-ref itself.
|
||||||
|
It is already supported in the client, where ``any`` is simply changed
|
||||||
|
to ``None``, so do the same in the API itself. For more information,
|
||||||
|
see bug `2074056 <https://bugs.launchpad.net/neutron/+bug/2074056>`_.
|
Loading…
Reference in New Issue
Block a user