diff --git a/neutron/api/rpc/handlers/securitygroups_rpc.py b/neutron/api/rpc/handlers/securitygroups_rpc.py index 89abcee7bdc..7bd54073dd2 100644 --- a/neutron/api/rpc/handlers/securitygroups_rpc.py +++ b/neutron/api/rpc/handlers/securitygroups_rpc.py @@ -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. + """ diff --git a/neutron/db/securitygroups_rpc_base.py b/neutron/db/securitygroups_rpc_base.py index 6245073cfd2..c11953b7dea 100644 --- a/neutron/db/securitygroups_rpc_base.py +++ b/neutron/db/securitygroups_rpc_base.py @@ -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): diff --git a/neutron/tests/unit/agent/test_securitygroups_rpc.py b/neutron/tests/unit/agent/test_securitygroups_rpc.py index 50259e48943..9bedcd04184 100644 --- a/neutron/tests/unit/agent/test_securitygroups_rpc.py +++ b/neutron/tests/unit/agent/test_securitygroups_rpc.py @@ -17,11 +17,11 @@ import collections import contextlib import mock +import netaddr from neutron_lib import constants as const 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) diff --git a/neutron/tests/unit/api/rpc/handlers/test_securitygroups_rpc.py b/neutron/tests/unit/api/rpc/handlers/test_securitygroups_rpc.py index 5cff29a6be3..688ef9b35dc 100644 --- a/neutron/tests/unit/api/rpc/handlers/test_securitygroups_rpc.py +++ b/neutron/tests/unit/api/rpc/handlers/test_securitygroups_rpc.py @@ -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)