Merge "Stop making IP-specific provider rules in SG code"
This commit is contained in:
commit
62fb7b1fef
|
@ -156,6 +156,7 @@ class SecurityGroupAgentRpcApiMixin(object):
|
|||
def security_groups_provider_updated(self, context,
|
||||
devices_to_update=None):
|
||||
"""Notify provider updated security groups."""
|
||||
# TODO(kevinbenton): remove in Queens
|
||||
# NOTE(ihrachys) the version here should really be 1.3, but since we
|
||||
# don't support proper version pinning yet, we leave it intact to allow
|
||||
# to work with older agents. The reason why we should not require the
|
||||
|
@ -214,9 +215,9 @@ class SecurityGroupAgentRpcCallbackMixin(object):
|
|||
self.sg_agent.security_groups_member_updated(security_groups)
|
||||
|
||||
def security_groups_provider_updated(self, context, **kwargs):
|
||||
"""Callback for security group provider update."""
|
||||
LOG.debug("Provider rule updated")
|
||||
devices_to_update = kwargs.get('devices_to_update')
|
||||
if not self.sg_agent:
|
||||
return self._security_groups_agent_not_set()
|
||||
self.sg_agent.security_groups_provider_updated(devices_to_update)
|
||||
"""Callback for security group provider update.
|
||||
|
||||
This is now a NOOP since provider rules are static. The server just
|
||||
generates the notification for agents running older versions that have
|
||||
IP-specific rules.
|
||||
"""
|
||||
|
|
|
@ -17,10 +17,8 @@ import netaddr
|
|||
from neutron_lib import constants as const
|
||||
from neutron_lib.utils import helpers
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import netutils
|
||||
from sqlalchemy.orm import exc
|
||||
|
||||
from neutron._i18n import _, _LW
|
||||
from neutron._i18n import _
|
||||
from neutron.db import api as db_api
|
||||
from neutron.db.models import allowed_address_pair as aap_models
|
||||
from neutron.db.models import securitygroup as sg_models
|
||||
|
@ -300,92 +298,6 @@ class SecurityGroupServerRpcMixin(sg_db.SecurityGroupDbMixin):
|
|||
remote_group_ids.append(remote_group_id)
|
||||
return remote_group_ids
|
||||
|
||||
def _select_network_ids(self, ports):
|
||||
return set((port['network_id'] for port in ports.values()))
|
||||
|
||||
def _select_dhcp_ips_for_network_ids(self, context, network_ids):
|
||||
if not network_ids:
|
||||
return {}
|
||||
query = context.session.query(models_v2.Port.mac_address,
|
||||
models_v2.Port.network_id,
|
||||
models_v2.IPAllocation.ip_address)
|
||||
query = query.join(models_v2.IPAllocation)
|
||||
query = query.filter(models_v2.Port.network_id.in_(network_ids))
|
||||
owner = const.DEVICE_OWNER_DHCP
|
||||
query = query.filter(models_v2.Port.device_owner == owner)
|
||||
ips = {}
|
||||
|
||||
for network_id in network_ids:
|
||||
ips[network_id] = []
|
||||
|
||||
for mac_address, network_id, ip in query:
|
||||
if (netaddr.IPAddress(ip).version == 6
|
||||
and not netaddr.IPAddress(ip).is_link_local()):
|
||||
ip = str(netutils.get_ipv6_addr_by_EUI64(const.IPv6_LLA_PREFIX,
|
||||
mac_address))
|
||||
if ip not in ips[network_id]:
|
||||
ips[network_id].append(ip)
|
||||
|
||||
return ips
|
||||
|
||||
def _select_ra_ips_for_network_ids(self, context, network_ids):
|
||||
"""Select IP addresses to allow sending router advertisement from.
|
||||
|
||||
If the OpenStack managed radvd process sends an RA, get link local
|
||||
address of gateway and allow RA from this Link Local address.
|
||||
The gateway port link local address will only be obtained
|
||||
when router is created before VM instance is booted and
|
||||
subnet is attached to router.
|
||||
|
||||
If OpenStack doesn't send RA, allow RA from gateway IP.
|
||||
Currently, the gateway IP needs to be link local to be able
|
||||
to send RA to VM.
|
||||
"""
|
||||
if not network_ids:
|
||||
return {}
|
||||
ips = {}
|
||||
for network_id in network_ids:
|
||||
ips[network_id] = set([])
|
||||
query = context.session.query(models_v2.Subnet)
|
||||
subnets = query.filter(models_v2.Subnet.network_id.in_(network_ids))
|
||||
for subnet in subnets:
|
||||
gateway_ip = subnet['gateway_ip']
|
||||
if subnet['ip_version'] != 6 or not gateway_ip:
|
||||
continue
|
||||
if not netaddr.IPAddress(gateway_ip).is_link_local():
|
||||
if subnet['ipv6_ra_mode']:
|
||||
gateway_ip = self._get_lla_gateway_ip_for_subnet(context,
|
||||
subnet)
|
||||
else:
|
||||
# TODO(xuhanp):Figure out how to allow gateway IP from
|
||||
# existing device to be global address and figure out the
|
||||
# link local address by other method.
|
||||
continue
|
||||
if gateway_ip:
|
||||
ips[subnet['network_id']].add(gateway_ip)
|
||||
|
||||
return ips
|
||||
|
||||
def _get_lla_gateway_ip_for_subnet(self, context, subnet):
|
||||
query = context.session.query(models_v2.Port.mac_address)
|
||||
query = query.join(models_v2.IPAllocation)
|
||||
query = query.filter(
|
||||
models_v2.IPAllocation.subnet_id == subnet['id'])
|
||||
query = query.filter(
|
||||
models_v2.IPAllocation.ip_address == subnet['gateway_ip'])
|
||||
query = query.filter(
|
||||
models_v2.Port.device_owner.in_(const.ROUTER_INTERFACE_OWNERS))
|
||||
try:
|
||||
mac_address = query.one()[0]
|
||||
except (exc.NoResultFound, exc.MultipleResultsFound):
|
||||
LOG.warning(_LW('No valid gateway port on subnet %s is '
|
||||
'found for IPv6 RA'), subnet['id'])
|
||||
return
|
||||
lla_ip = str(netutils.get_ipv6_addr_by_EUI64(
|
||||
const.IPv6_LLA_PREFIX,
|
||||
mac_address))
|
||||
return lla_ip
|
||||
|
||||
def _convert_remote_group_id_to_ip_prefix(self, context, ports):
|
||||
remote_group_ids = self._select_remote_group_ids(ports)
|
||||
ips = self._select_ips_for_remote_group(context, remote_group_ids)
|
||||
|
@ -415,38 +327,43 @@ class SecurityGroupServerRpcMixin(sg_db.SecurityGroupDbMixin):
|
|||
port['security_group_rules'] = updated_rule
|
||||
return ports
|
||||
|
||||
def _add_ingress_dhcp_rule(self, port, ips):
|
||||
dhcp_ips = ips.get(port['network_id'])
|
||||
for dhcp_ip in dhcp_ips:
|
||||
source_port, dest_port, ethertype = DHCP_RULE_PORT[
|
||||
netaddr.IPAddress(dhcp_ip).version]
|
||||
dhcp_rule = {'direction': 'ingress',
|
||||
'ethertype': ethertype,
|
||||
'protocol': 'udp',
|
||||
'port_range_min': dest_port,
|
||||
'port_range_max': dest_port,
|
||||
'source_port_range_min': source_port,
|
||||
'source_port_range_max': source_port,
|
||||
'source_ip_prefix': dhcp_ip}
|
||||
port['security_group_rules'].append(dhcp_rule)
|
||||
def _add_ingress_dhcp_rule(self, port):
|
||||
for ip_version in (4, 6):
|
||||
# only allow DHCP servers to talk to the appropriate IP address
|
||||
# to avoid getting leases that don't match the Neutron IPs
|
||||
prefix = '32' if ip_version == 4 else '128'
|
||||
dests = ['%s/%s' % (ip, prefix) for ip in port['fixed_ips']
|
||||
if netaddr.IPNetwork(ip).version == ip_version]
|
||||
if ip_version == 4:
|
||||
# v4 dhcp servers can also talk to broadcast
|
||||
dests.append('255.255.255.255/32')
|
||||
source_port, dest_port, ethertype = DHCP_RULE_PORT[ip_version]
|
||||
for dest in dests:
|
||||
dhcp_rule = {'direction': 'ingress',
|
||||
'ethertype': ethertype,
|
||||
'protocol': 'udp',
|
||||
'port_range_min': dest_port,
|
||||
'port_range_max': dest_port,
|
||||
'source_port_range_min': source_port,
|
||||
'source_port_range_max': source_port,
|
||||
'dest_ip_prefix': dest}
|
||||
port['security_group_rules'].append(dhcp_rule)
|
||||
|
||||
def _add_ingress_ra_rule(self, port, ips):
|
||||
ra_ips = ips.get(port['network_id'])
|
||||
for ra_ip in ra_ips:
|
||||
ra_rule = {'direction': 'ingress',
|
||||
'ethertype': const.IPv6,
|
||||
'protocol': const.PROTO_NAME_IPV6_ICMP,
|
||||
'source_ip_prefix': ra_ip,
|
||||
'source_port_range_min': const.ICMPV6_TYPE_RA}
|
||||
port['security_group_rules'].append(ra_rule)
|
||||
def _add_ingress_ra_rule(self, port):
|
||||
has_v6 = [ip for ip in port['fixed_ips']
|
||||
if netaddr.IPNetwork(ip).version == 6]
|
||||
if not has_v6:
|
||||
return
|
||||
ra_rule = {'direction': 'ingress',
|
||||
'ethertype': const.IPv6,
|
||||
'protocol': const.PROTO_NAME_IPV6_ICMP,
|
||||
'source_port_range_min': const.ICMPV6_TYPE_RA}
|
||||
port['security_group_rules'].append(ra_rule)
|
||||
|
||||
def _apply_provider_rule(self, context, ports):
|
||||
network_ids = self._select_network_ids(ports)
|
||||
ips_dhcp = self._select_dhcp_ips_for_network_ids(context, network_ids)
|
||||
ips_ra = self._select_ra_ips_for_network_ids(context, network_ids)
|
||||
for port in ports.values():
|
||||
self._add_ingress_ra_rule(port, ips_ra)
|
||||
self._add_ingress_dhcp_rule(port, ips_dhcp)
|
||||
self._add_ingress_ra_rule(port)
|
||||
self._add_ingress_dhcp_rule(port)
|
||||
|
||||
@db_api.retry_if_session_inactive()
|
||||
def security_group_rules_for_ports(self, context, ports):
|
||||
|
|
|
@ -17,12 +17,12 @@ import collections
|
|||
import contextlib
|
||||
|
||||
import mock
|
||||
import netaddr
|
||||
from neutron_lib import constants as const
|
||||
from neutron_lib import context
|
||||
from neutron_lib.plugins import directory
|
||||
from oslo_config import cfg
|
||||
import oslo_messaging
|
||||
from oslo_utils import netutils
|
||||
from testtools import matchers
|
||||
import webob.exc
|
||||
|
||||
|
@ -57,6 +57,38 @@ FIREWALL_HYBRID_DRIVER = (FIREWALL_BASE_PACKAGE +
|
|||
FIREWALL_NOOP_DRIVER = 'neutron.agent.firewall.NoopFirewallDriver'
|
||||
|
||||
|
||||
def ingress_address_assignment_rules(port):
|
||||
rules = []
|
||||
v4_addrs = [ip['ip_address'] for ip in port['port']['fixed_ips']
|
||||
if netaddr.IPNetwork(ip['ip_address']).version == 4]
|
||||
v6_addrs = [ip['ip_address'] for ip in port['port']['fixed_ips']
|
||||
if netaddr.IPNetwork(ip['ip_address']).version == 6]
|
||||
if v6_addrs:
|
||||
rules.append({'direction': 'ingress',
|
||||
'ethertype': 'IPv6',
|
||||
'protocol': 'ipv6-icmp',
|
||||
'source_port_range_min': 134})
|
||||
for dest in v4_addrs + ['255.255.255.255']:
|
||||
rules.append({'direction': 'ingress',
|
||||
'ethertype': 'IPv4',
|
||||
'port_range_max': 68,
|
||||
'port_range_min': 68,
|
||||
'protocol': 'udp',
|
||||
'source_port_range_max': 67,
|
||||
'source_port_range_min': 67,
|
||||
'dest_ip_prefix': '%s/32' % dest})
|
||||
for dest in v6_addrs:
|
||||
rules.append({'direction': 'ingress',
|
||||
'ethertype': 'IPv6',
|
||||
'port_range_max': 546,
|
||||
'port_range_min': 546,
|
||||
'protocol': 'udp',
|
||||
'source_port_range_max': 547,
|
||||
'source_port_range_min': 547,
|
||||
'dest_ip_prefix': '%s/128' % dest})
|
||||
return rules
|
||||
|
||||
|
||||
def set_enable_security_groups(enabled):
|
||||
cfg.CONF.set_override('enable_security_group', enabled,
|
||||
group='SECURITYGROUP')
|
||||
|
@ -252,7 +284,7 @@ class SGServerRpcCallBackTestCase(test_sg.SecurityGroupDBTestCase):
|
|||
'port_range_max': 23, 'security_group_id': sg1_id,
|
||||
'port_range_min': 23,
|
||||
'source_ip_prefix': fake_prefix},
|
||||
]
|
||||
] + ingress_address_assignment_rules(ports_rest1)
|
||||
self.assertEqual(port_rpc['security_group_rules'],
|
||||
expected)
|
||||
self._delete('ports', port_id1)
|
||||
|
@ -368,7 +400,7 @@ class SGServerRpcCallBackTestCase(test_sg.SecurityGroupDBTestCase):
|
|||
'port_range_max': 23, 'security_group_id': sg_id,
|
||||
'port_range_min': 23,
|
||||
'source_ip_prefix': fake_prefix},
|
||||
]
|
||||
] + ingress_address_assignment_rules(port)
|
||||
expected = tools.UnorderedList(expected)
|
||||
self.assertEqual(expected,
|
||||
port_rpc['security_group_rules'])
|
||||
|
@ -424,7 +456,7 @@ class SGServerRpcCallBackTestCase(test_sg.SecurityGroupDBTestCase):
|
|||
'port_range_max': 23, 'security_group_id': sg1_id,
|
||||
'port_range_min': 23,
|
||||
'dest_ip_prefix': fake_prefix},
|
||||
]
|
||||
] + ingress_address_assignment_rules(ports_rest1)
|
||||
self.assertEqual(port_rpc['security_group_rules'],
|
||||
expected)
|
||||
self._delete('ports', port_id1)
|
||||
|
@ -481,7 +513,7 @@ class SGServerRpcCallBackTestCase(test_sg.SecurityGroupDBTestCase):
|
|||
'port_range_max': 25, 'port_range_min': 24,
|
||||
'remote_group_id': sg2_id,
|
||||
'security_group_id': sg1_id},
|
||||
]
|
||||
] + ingress_address_assignment_rules(ports_rest1)
|
||||
self.assertEqual(port_rpc['security_group_rules'],
|
||||
expected)
|
||||
self._delete('ports', port_id1)
|
||||
|
@ -570,17 +602,12 @@ class SGServerRpcCallBackTestCase(test_sg.SecurityGroupDBTestCase):
|
|||
self.deserialize(self.fmt, res)
|
||||
self.assertEqual(webob.exc.HTTPCreated.code, res.status_int)
|
||||
|
||||
dhcp_port = self._create_port(
|
||||
self._create_port(
|
||||
self.fmt, n['network']['id'],
|
||||
fixed_ips=[{'subnet_id': subnet_v6['subnet']['id'],
|
||||
'ip_address': FAKE_IP['IPv6_DHCP']}],
|
||||
device_owner=const.DEVICE_OWNER_DHCP,
|
||||
security_groups=[sg1_id])
|
||||
dhcp_rest = self.deserialize(self.fmt, dhcp_port)
|
||||
dhcp_mac = dhcp_rest['port']['mac_address']
|
||||
dhcp_lla_ip = str(netutils.get_ipv6_addr_by_EUI64(
|
||||
const.IPv6_LLA_PREFIX,
|
||||
dhcp_mac))
|
||||
|
||||
res1 = self._create_port(
|
||||
self.fmt, n['network']['id'],
|
||||
|
@ -612,20 +639,7 @@ class SGServerRpcCallBackTestCase(test_sg.SecurityGroupDBTestCase):
|
|||
'security_group_id': sg1_id,
|
||||
'port_range_min': 23,
|
||||
'source_ip_prefix': fake_prefix},
|
||||
{'direction': 'ingress',
|
||||
'protocol': const.PROTO_NAME_IPV6_ICMP,
|
||||
'ethertype': const.IPv6,
|
||||
'source_ip_prefix': fake_gateway,
|
||||
'source_port_range_min': const.ICMPV6_TYPE_RA},
|
||||
{'direction': 'ingress',
|
||||
'ethertype': ethertype,
|
||||
'port_range_max': dest_port,
|
||||
'port_range_min': dest_port,
|
||||
'protocol': const.PROTO_NAME_UDP,
|
||||
'source_ip_prefix': dhcp_lla_ip,
|
||||
'source_port_range_max': source_port,
|
||||
'source_port_range_min': source_port}
|
||||
]
|
||||
] + ingress_address_assignment_rules(ports_rest1)
|
||||
self.assertEqual(port_rpc['security_group_rules'],
|
||||
expected)
|
||||
self._delete('ports', port_id1)
|
||||
|
@ -675,310 +689,6 @@ class SGServerRpcCallBackTestCase(test_sg.SecurityGroupDBTestCase):
|
|||
ports_rpc['sg_member_ips'][sg1_id]['IPv6'])
|
||||
self._delete('ports', port_id1)
|
||||
|
||||
def test_security_group_ra_rules_for_devices_ipv6_gateway_global(self):
|
||||
fake_prefix = FAKE_PREFIX[const.IPv6]
|
||||
fake_gateway = FAKE_IP['IPv6_GLOBAL']
|
||||
with self.network() as n,\
|
||||
self.subnet(n, gateway_ip=fake_gateway,
|
||||
cidr=fake_prefix, ip_version=6,
|
||||
ipv6_ra_mode=const.IPV6_SLAAC
|
||||
) as subnet_v6,\
|
||||
self.security_group() as sg1:
|
||||
sg1_id = sg1['security_group']['id']
|
||||
rule1 = self._build_security_group_rule(
|
||||
sg1_id,
|
||||
'ingress', const.PROTO_NAME_TCP, '22',
|
||||
'22',
|
||||
ethertype=const.IPv6)
|
||||
rules = {
|
||||
'security_group_rules': [rule1['security_group_rule']]}
|
||||
self._make_security_group_rule(self.fmt, rules)
|
||||
|
||||
# Create gateway port
|
||||
gateway_res = self._make_port(
|
||||
self.fmt, n['network']['id'],
|
||||
fixed_ips=[{'subnet_id': subnet_v6['subnet']['id'],
|
||||
'ip_address': fake_gateway}],
|
||||
device_owner=const.DEVICE_OWNER_ROUTER_INTF)
|
||||
gateway_mac = gateway_res['port']['mac_address']
|
||||
gateway_port_id = gateway_res['port']['id']
|
||||
gateway_lla_ip = str(netutils.get_ipv6_addr_by_EUI64(
|
||||
const.IPv6_LLA_PREFIX,
|
||||
gateway_mac))
|
||||
|
||||
ports_rest1 = self._make_port(
|
||||
self.fmt, n['network']['id'],
|
||||
fixed_ips=[{'subnet_id': subnet_v6['subnet']['id']}],
|
||||
security_groups=[sg1_id])
|
||||
port_id1 = ports_rest1['port']['id']
|
||||
self.rpc.devices = {port_id1: ports_rest1['port']}
|
||||
devices = [port_id1, 'no_exist_device']
|
||||
ctx = context.get_admin_context()
|
||||
ports_rpc = self.rpc.security_group_rules_for_devices(
|
||||
ctx, devices=devices)
|
||||
port_rpc = ports_rpc[port_id1]
|
||||
expected = [{'direction': 'egress', 'ethertype': const.IPv4,
|
||||
'security_group_id': sg1_id},
|
||||
{'direction': 'egress', 'ethertype': const.IPv6,
|
||||
'security_group_id': sg1_id},
|
||||
{'direction': 'ingress',
|
||||
'protocol': const.PROTO_NAME_TCP,
|
||||
'ethertype': const.IPv6,
|
||||
'port_range_max': 22,
|
||||
'security_group_id': sg1_id,
|
||||
'port_range_min': 22},
|
||||
{'direction': 'ingress',
|
||||
'protocol': const.PROTO_NAME_IPV6_ICMP,
|
||||
'ethertype': const.IPv6,
|
||||
'source_ip_prefix': gateway_lla_ip,
|
||||
'source_port_range_min': const.ICMPV6_TYPE_RA},
|
||||
]
|
||||
self.assertEqual(port_rpc['security_group_rules'],
|
||||
expected)
|
||||
self._delete('ports', port_id1)
|
||||
# Note(xuhanp): remove gateway port's fixed_ips or gateway port
|
||||
# deletion will be prevented.
|
||||
data = {'port': {'fixed_ips': []}}
|
||||
req = self.new_update_request('ports', data, gateway_port_id)
|
||||
self.deserialize(self.fmt, req.get_response(self.api))
|
||||
self._delete('ports', gateway_port_id)
|
||||
|
||||
def test_security_group_rule_for_device_ipv6_multi_router_interfaces(self):
|
||||
fake_prefix = FAKE_PREFIX[const.IPv6]
|
||||
fake_gateway = FAKE_IP['IPv6_GLOBAL']
|
||||
with self.network() as n,\
|
||||
self.subnet(n, gateway_ip=fake_gateway,
|
||||
cidr=fake_prefix, ip_version=6,
|
||||
ipv6_ra_mode=const.IPV6_SLAAC
|
||||
) as subnet_v6,\
|
||||
self.security_group() as sg1:
|
||||
sg1_id = sg1['security_group']['id']
|
||||
rule1 = self._build_security_group_rule(
|
||||
sg1_id,
|
||||
'ingress', const.PROTO_NAME_TCP, '22',
|
||||
'22',
|
||||
ethertype=const.IPv6)
|
||||
rules = {
|
||||
'security_group_rules': [rule1['security_group_rule']]}
|
||||
self._make_security_group_rule(self.fmt, rules)
|
||||
|
||||
# Create gateway port
|
||||
gateway_res = self._make_port(
|
||||
self.fmt, n['network']['id'],
|
||||
fixed_ips=[{'subnet_id': subnet_v6['subnet']['id'],
|
||||
'ip_address': fake_gateway}],
|
||||
device_owner=const.DEVICE_OWNER_ROUTER_INTF)
|
||||
gateway_mac = gateway_res['port']['mac_address']
|
||||
gateway_port_id = gateway_res['port']['id']
|
||||
gateway_lla_ip = str(netutils.get_ipv6_addr_by_EUI64(
|
||||
const.IPv6_LLA_PREFIX,
|
||||
gateway_mac))
|
||||
# Create another router interface port
|
||||
interface_res = self._make_port(
|
||||
self.fmt, n['network']['id'],
|
||||
fixed_ips=[{'subnet_id': subnet_v6['subnet']['id']}],
|
||||
device_owner=const.DEVICE_OWNER_ROUTER_INTF)
|
||||
interface_port_id = interface_res['port']['id']
|
||||
|
||||
ports_rest1 = self._make_port(
|
||||
self.fmt, n['network']['id'],
|
||||
fixed_ips=[{'subnet_id': subnet_v6['subnet']['id']}],
|
||||
security_groups=[sg1_id])
|
||||
port_id1 = ports_rest1['port']['id']
|
||||
self.rpc.devices = {port_id1: ports_rest1['port']}
|
||||
devices = [port_id1, 'no_exist_device']
|
||||
ctx = context.get_admin_context()
|
||||
ports_rpc = self.rpc.security_group_rules_for_devices(
|
||||
ctx, devices=devices)
|
||||
port_rpc = ports_rpc[port_id1]
|
||||
expected = [{'direction': 'egress', 'ethertype': const.IPv4,
|
||||
'security_group_id': sg1_id},
|
||||
{'direction': 'egress', 'ethertype': const.IPv6,
|
||||
'security_group_id': sg1_id},
|
||||
{'direction': 'ingress',
|
||||
'protocol': const.PROTO_NAME_TCP,
|
||||
'ethertype': const.IPv6,
|
||||
'port_range_max': 22,
|
||||
'security_group_id': sg1_id,
|
||||
'port_range_min': 22},
|
||||
{'direction': 'ingress',
|
||||
'protocol': const.PROTO_NAME_IPV6_ICMP,
|
||||
'ethertype': const.IPv6,
|
||||
'source_ip_prefix': gateway_lla_ip,
|
||||
'source_port_range_min': const.ICMPV6_TYPE_RA},
|
||||
]
|
||||
self.assertEqual(port_rpc['security_group_rules'],
|
||||
expected)
|
||||
self._delete('ports', port_id1)
|
||||
data = {'port': {'fixed_ips': []}}
|
||||
req = self.new_update_request('ports', data, gateway_port_id)
|
||||
self.deserialize(self.fmt, req.get_response(self.api))
|
||||
req = self.new_update_request('ports', data, interface_port_id)
|
||||
self.deserialize(self.fmt, req.get_response(self.api))
|
||||
self._delete('ports', gateway_port_id)
|
||||
self._delete('ports', interface_port_id)
|
||||
|
||||
def test_security_group_ra_rules_for_devices_ipv6_dvr(self):
|
||||
fake_prefix = FAKE_PREFIX[const.IPv6]
|
||||
fake_gateway = FAKE_IP['IPv6_GLOBAL']
|
||||
with self.network() as n,\
|
||||
self.subnet(n, gateway_ip=fake_gateway,
|
||||
cidr=fake_prefix, ip_version=6,
|
||||
ipv6_ra_mode=const.IPV6_SLAAC
|
||||
) as subnet_v6,\
|
||||
self.security_group() as sg1:
|
||||
sg1_id = sg1['security_group']['id']
|
||||
rule1 = self._build_security_group_rule(
|
||||
sg1_id,
|
||||
'ingress', const.PROTO_NAME_TCP, '22',
|
||||
'22',
|
||||
ethertype=const.IPv6)
|
||||
rules = {
|
||||
'security_group_rules': [rule1['security_group_rule']]}
|
||||
self._make_security_group_rule(self.fmt, rules)
|
||||
|
||||
# Create DVR router interface port
|
||||
gateway_res = self._make_port(
|
||||
self.fmt, n['network']['id'],
|
||||
fixed_ips=[{'subnet_id': subnet_v6['subnet']['id'],
|
||||
'ip_address': fake_gateway}],
|
||||
device_owner=const.DEVICE_OWNER_DVR_INTERFACE)
|
||||
gateway_mac = gateway_res['port']['mac_address']
|
||||
gateway_port_id = gateway_res['port']['id']
|
||||
gateway_lla_ip = str(netutils.get_ipv6_addr_by_EUI64(
|
||||
const.IPv6_LLA_PREFIX,
|
||||
gateway_mac))
|
||||
|
||||
ports_rest1 = self._make_port(
|
||||
self.fmt, n['network']['id'],
|
||||
fixed_ips=[{'subnet_id': subnet_v6['subnet']['id']}],
|
||||
security_groups=[sg1_id])
|
||||
port_id1 = ports_rest1['port']['id']
|
||||
self.rpc.devices = {port_id1: ports_rest1['port']}
|
||||
devices = [port_id1, 'no_exist_device']
|
||||
ctx = context.get_admin_context()
|
||||
ports_rpc = self.rpc.security_group_rules_for_devices(
|
||||
ctx, devices=devices)
|
||||
port_rpc = ports_rpc[port_id1]
|
||||
expected = [{'direction': 'egress', 'ethertype': const.IPv4,
|
||||
'security_group_id': sg1_id},
|
||||
{'direction': 'egress', 'ethertype': const.IPv6,
|
||||
'security_group_id': sg1_id},
|
||||
{'direction': 'ingress',
|
||||
'protocol': const.PROTO_NAME_TCP,
|
||||
'ethertype': const.IPv6,
|
||||
'port_range_max': 22,
|
||||
'security_group_id': sg1_id,
|
||||
'port_range_min': 22},
|
||||
{'direction': 'ingress',
|
||||
'protocol': const.PROTO_NAME_IPV6_ICMP,
|
||||
'ethertype': const.IPv6,
|
||||
'source_ip_prefix': gateway_lla_ip,
|
||||
'source_port_range_min': const.ICMPV6_TYPE_RA},
|
||||
]
|
||||
self.assertEqual(port_rpc['security_group_rules'],
|
||||
expected)
|
||||
self._delete('ports', port_id1)
|
||||
# Note(xuhanp): remove gateway port's fixed_ips or gateway port
|
||||
# deletion will be prevented.
|
||||
data = {'port': {'fixed_ips': []}}
|
||||
req = self.new_update_request('ports', data, gateway_port_id)
|
||||
self.deserialize(self.fmt, req.get_response(self.api))
|
||||
self._delete('ports', gateway_port_id)
|
||||
|
||||
def test_security_group_ra_rules_for_devices_ipv6_gateway_lla(self):
|
||||
fake_prefix = FAKE_PREFIX[const.IPv6]
|
||||
fake_gateway = FAKE_IP['IPv6_LLA']
|
||||
with self.network() as n,\
|
||||
self.subnet(n, gateway_ip=fake_gateway,
|
||||
cidr=fake_prefix, ip_version=6,
|
||||
ipv6_ra_mode=const.IPV6_SLAAC
|
||||
) as subnet_v6,\
|
||||
self.security_group() as sg1:
|
||||
sg1_id = sg1['security_group']['id']
|
||||
rule1 = self._build_security_group_rule(
|
||||
sg1_id,
|
||||
'ingress', const.PROTO_NAME_TCP, '22',
|
||||
'22',
|
||||
ethertype=const.IPv6)
|
||||
rules = {
|
||||
'security_group_rules': [rule1['security_group_rule']]}
|
||||
self._make_security_group_rule(self.fmt, rules)
|
||||
|
||||
ports_rest1 = self._make_port(
|
||||
self.fmt, n['network']['id'],
|
||||
fixed_ips=[{'subnet_id': subnet_v6['subnet']['id']}],
|
||||
security_groups=[sg1_id])
|
||||
port_id1 = ports_rest1['port']['id']
|
||||
self.rpc.devices = {port_id1: ports_rest1['port']}
|
||||
devices = [port_id1, 'no_exist_device']
|
||||
ctx = context.get_admin_context()
|
||||
ports_rpc = self.rpc.security_group_rules_for_devices(
|
||||
ctx, devices=devices)
|
||||
port_rpc = ports_rpc[port_id1]
|
||||
expected = [{'direction': 'egress', 'ethertype': const.IPv4,
|
||||
'security_group_id': sg1_id},
|
||||
{'direction': 'egress', 'ethertype': const.IPv6,
|
||||
'security_group_id': sg1_id},
|
||||
{'direction': 'ingress',
|
||||
'protocol': const.PROTO_NAME_TCP,
|
||||
'ethertype': const.IPv6,
|
||||
'port_range_max': 22,
|
||||
'security_group_id': sg1_id,
|
||||
'port_range_min': 22},
|
||||
{'direction': 'ingress',
|
||||
'protocol': const.PROTO_NAME_IPV6_ICMP,
|
||||
'ethertype': const.IPv6,
|
||||
'source_ip_prefix': fake_gateway,
|
||||
'source_port_range_min': const.ICMPV6_TYPE_RA},
|
||||
]
|
||||
self.assertEqual(port_rpc['security_group_rules'],
|
||||
expected)
|
||||
self._delete('ports', port_id1)
|
||||
|
||||
def test_security_group_ra_rules_for_devices_ipv6_no_gateway_port(self):
|
||||
fake_prefix = FAKE_PREFIX[const.IPv6]
|
||||
with self.network() as n,\
|
||||
self.subnet(n, gateway_ip=None, cidr=fake_prefix,
|
||||
ip_version=6, ipv6_ra_mode=const.IPV6_SLAAC
|
||||
) as subnet_v6,\
|
||||
self.security_group() as sg1:
|
||||
sg1_id = sg1['security_group']['id']
|
||||
rule1 = self._build_security_group_rule(
|
||||
sg1_id,
|
||||
'ingress', const.PROTO_NAME_TCP, '22',
|
||||
'22',
|
||||
ethertype=const.IPv6)
|
||||
rules = {
|
||||
'security_group_rules': [rule1['security_group_rule']]}
|
||||
self._make_security_group_rule(self.fmt, rules)
|
||||
|
||||
ports_rest1 = self._make_port(
|
||||
self.fmt, n['network']['id'],
|
||||
fixed_ips=[{'subnet_id': subnet_v6['subnet']['id']}],
|
||||
security_groups=[sg1_id])
|
||||
port_id1 = ports_rest1['port']['id']
|
||||
self.rpc.devices = {port_id1: ports_rest1['port']}
|
||||
devices = [port_id1, 'no_exist_device']
|
||||
ctx = context.get_admin_context()
|
||||
ports_rpc = self.rpc.security_group_rules_for_devices(
|
||||
ctx, devices=devices)
|
||||
port_rpc = ports_rpc[port_id1]
|
||||
expected = [{'direction': 'egress', 'ethertype': const.IPv4,
|
||||
'security_group_id': sg1_id},
|
||||
{'direction': 'egress', 'ethertype': const.IPv6,
|
||||
'security_group_id': sg1_id},
|
||||
{'direction': 'ingress',
|
||||
'protocol': const.PROTO_NAME_TCP,
|
||||
'ethertype': const.IPv6,
|
||||
'port_range_max': 22,
|
||||
'security_group_id': sg1_id,
|
||||
'port_range_min': 22},
|
||||
]
|
||||
self.assertEqual(port_rpc['security_group_rules'],
|
||||
expected)
|
||||
self._delete('ports', port_id1)
|
||||
|
||||
def test_security_group_rules_for_devices_ipv6_egress(self):
|
||||
fake_prefix = FAKE_PREFIX[const.IPv6]
|
||||
fake_gateway = FAKE_IP[const.IPv6]
|
||||
|
@ -1032,12 +742,7 @@ class SGServerRpcCallBackTestCase(test_sg.SecurityGroupDBTestCase):
|
|||
'security_group_id': sg1_id,
|
||||
'port_range_min': 23,
|
||||
'dest_ip_prefix': fake_prefix},
|
||||
{'direction': 'ingress',
|
||||
'protocol': const.PROTO_NAME_IPV6_ICMP,
|
||||
'ethertype': const.IPv6,
|
||||
'source_ip_prefix': fake_gateway,
|
||||
'source_port_range_min': const.ICMPV6_TYPE_RA},
|
||||
]
|
||||
] + ingress_address_assignment_rules(ports_rest1)
|
||||
self.assertEqual(port_rpc['security_group_rules'],
|
||||
expected)
|
||||
self._delete('ports', port_id1)
|
||||
|
@ -1098,12 +803,7 @@ class SGServerRpcCallBackTestCase(test_sg.SecurityGroupDBTestCase):
|
|||
'port_range_max': 25, 'port_range_min': 24,
|
||||
'remote_group_id': sg2_id,
|
||||
'security_group_id': sg1_id},
|
||||
{'direction': 'ingress',
|
||||
'protocol': const.PROTO_NAME_IPV6_ICMP,
|
||||
'ethertype': const.IPv6,
|
||||
'source_ip_prefix': fake_gateway,
|
||||
'source_port_range_min': const.ICMPV6_TYPE_RA},
|
||||
]
|
||||
] + ingress_address_assignment_rules(ports_rest1)
|
||||
self.assertEqual(port_rpc['security_group_rules'],
|
||||
expected)
|
||||
self._delete('ports', port_id1)
|
||||
|
|
|
@ -55,5 +55,5 @@ class SGAgentRpcCallBackMixinTestCase(base.BaseTestCase):
|
|||
|
||||
def test_security_groups_provider_updated(self):
|
||||
self.rpc.security_groups_provider_updated(None)
|
||||
self.rpc.sg_agent.assert_has_calls(
|
||||
[mock.call.security_groups_provider_updated(None)])
|
||||
# this is now a NOOP on the agent side. provider rules don't change
|
||||
self.assertFalse(self.rpc.sg_agent.called)
|
||||
|
|
Loading…
Reference in New Issue