Merge "Central and local plugin (part3, security group)"

This commit is contained in:
Jenkins 2016-10-19 12:21:04 +00:00 committed by Gerrit Code Review
commit 21a6f9c215
9 changed files with 377 additions and 31 deletions

View File

@ -62,7 +62,13 @@ client_opts = [
cfg.StrOpt('admin_tenant_domain_name',
default='Default',
help='tenant domain name of admin account, needed when'
' auto_refresh_endpoint set to True')
' auto_refresh_endpoint set to True'),
cfg.StrOpt('ew_bridge_cidr',
default='100.0.0.0/9',
help='cidr pool of the east-west bridge network'),
cfg.StrOpt('ns_bridge_cidr',
default='100.128.0.0/9',
help='cidr pool of the north-south bridge network')
]
client_opt_group = cfg.OptGroup('client')
cfg.CONF.register_group(client_opt_group)

View File

@ -79,6 +79,7 @@ PROFILE_REGION = 'region'
JT_ROUTER = 'router'
JT_ROUTER_SETUP = 'router_setup'
JT_PORT_DELETE = 'port_delete'
JT_SEG_RULE_SETUP = 'seg_rule_setup'
# network type
NT_LOCAL = 'local'

View File

@ -94,3 +94,8 @@ class XJobAPI(object):
self.client.prepare(exchange='openstack').cast(
ctxt, 'delete_server_port',
payload={constants.JT_PORT_DELETE: port_id})
def configure_security_group_rules(self, ctxt, project_id):
self.client.prepare(exchange='openstack').cast(
ctxt, 'configure_security_group_rules',
payload={constants.JT_SEG_RULE_SETUP: project_id})

View File

@ -400,7 +400,11 @@ class TricirclePlugin(db_base_plugin_v2.NeutronDbPluginV2,
gateway_port_body)
return super(TricirclePlugin, self).get_port(context, t_gateway_id)
db_port = super(TricirclePlugin, self).create_port_db(context, port)
return self._make_port_dict(db_port)
self._ensure_default_security_group_on_port(context, port)
sgids = self._get_security_groups_on_port(context, port)
result = self._make_port_dict(db_port)
self._process_port_create_security_group(context, result, sgids)
return result
def update_port(self, context, port_id, port):
# TODO(zhiyuan) handle bottom port update
@ -419,6 +423,9 @@ class TricirclePlugin(db_base_plugin_v2.NeutronDbPluginV2,
t_constants.RT_SUBNET) for ip in res['fixed_ips']]
entries.append((res['network_id'], t_constants.RT_NETWORK))
entries.append((res['id'], t_constants.RT_PORT))
if res['security_groups']:
for sg_id in res['security_groups']:
entries.append((sg_id, t_constants.RT_SG))
for resource_id, resource_type in entries:
if db_api.get_bottom_id_by_top_id_pod_name(
@ -441,6 +448,8 @@ class TricirclePlugin(db_base_plugin_v2.NeutronDbPluginV2,
admin_context, res['network_id'],
interfaces[0]['device_id'], pod['pod_id'])
self.xjob_handler.configure_security_group_rules(t_ctx,
res['tenant_id'])
return res
def delete_port(self, context, port_id, l3_port_check=True):
@ -916,10 +925,10 @@ class TricirclePlugin(db_base_plugin_v2.NeutronDbPluginV2,
def _get_bridge_subnet_pool_id(self, t_ctx, q_ctx, project_id, pod, is_ew):
if is_ew:
pool_name = t_constants.ew_bridge_subnet_pool_name
pool_cidr = '100.0.0.0/9'
pool_cidr = cfg.CONF.client.ew_bridge_cidr
else:
pool_name = t_constants.ns_bridge_subnet_pool_name
pool_cidr = '100.128.0.0/9'
pool_cidr = cfg.CONF.client.ns_bridge_cidr
pool_ele = {'id': pool_name}
body = {'subnetpool': {'tenant_id': project_id,
'name': pool_name,

View File

@ -567,3 +567,18 @@ class NetworkHelper(object):
return getattr(self.call_obj, 'get_%s' % _type)(q_ctx, _id)
else:
return getattr(self._get_client(), 'get_%ss' % _type)(t_ctx, _id)
@staticmethod
def get_create_sg_rule_body(rule, sg_id, ip=None):
ip = ip or rule['remote_ip_prefix']
# if ip is passed, this is a extended rule for remote group
return {'security_group_rule': {
'tenant_id': rule['tenant_id'],
'remote_group_id': None,
'direction': rule['direction'],
'remote_ip_prefix': ip,
'protocol': rule.get('protocol'),
'ethertype': rule['ethertype'],
'port_range_max': rule.get('port_range_max'),
'port_range_min': rule.get('port_range_min'),
'security_group_id': sg_id}}

View File

@ -22,6 +22,7 @@ import neutron_lib.constants as q_constants
import neutron_lib.exceptions as q_exceptions
from neutron.common import utils
import neutron.extensions.securitygroup as ext_sg
from neutron.plugins.ml2 import plugin
from tricircle.common import client # noqa
@ -381,6 +382,8 @@ class TricirclePlugin(plugin.Ml2Plugin):
for field in ('name', 'device_id'):
if port_body.get(field):
t_port[field] = port_body[field]
self._handle_security_group(t_ctx, context, t_port)
b_port = self.core_plugin.create_port(context, {'port': t_port})
return b_port
@ -408,6 +411,7 @@ class TricirclePlugin(plugin.Ml2Plugin):
raise q_exceptions.PortNotFound(port_id=_id)
self._ensure_network_subnet(context, t_port)
self._adapt_port_body_for_call(t_port)
self._handle_security_group(t_ctx, context, t_port)
b_port = self.core_plugin.create_port(context, {'port': t_port})
return self._fields(b_port, fields)
@ -446,6 +450,7 @@ class TricirclePlugin(plugin.Ml2Plugin):
for port in t_ports:
self._ensure_network_subnet(context, port)
self._adapt_port_body_for_call(port)
self._handle_security_group(t_ctx, context, port)
b_port = self.core_plugin.create_port(context,
{'port': port})
b_ports.append(self._fields(b_port, fields))
@ -455,3 +460,68 @@ class TricirclePlugin(plugin.Ml2Plugin):
t_ctx = t_context.get_context_from_neutron_context(context)
self.neutron_handle.handle_delete(t_ctx, t_constants.RT_PORT, _id)
self.core_plugin.delete_port(context, _id, l3_port_check)
def _handle_security_group(self, t_ctx, q_ctx, port):
if not port['security_groups']:
raw_client = self.neutron_handle._get_client(t_ctx)
params = {'name': 'default'}
t_sgs = raw_client.list_security_groups(
**params)['security_groups']
if t_sgs:
port['security_groups'] = [t_sgs[0]['id']]
if port['security_groups'] is q_constants.ATTR_NOT_SPECIFIED:
return
for sg_id in port['security_groups']:
self.get_security_group(q_ctx, sg_id)
def get_security_group(self, context, _id, fields=None, tenant_id=None):
try:
return self.core_plugin.get_security_group(
context, _id, fields, tenant_id)
except q_exceptions.NotFound:
t_ctx = t_context.get_context_from_neutron_context(context)
t_sg = self.neutron_handle.handle_get(t_ctx,
'security_group', _id)
if not t_sg:
raise ext_sg.SecurityGroupNotFound(id=_id)
self.core_plugin.create_security_group(context,
{'security_group': t_sg})
return self.core_plugin.get_security_group(
context, _id, fields, tenant_id)
def get_security_groups(self, context, filters=None, fields=None,
sorts=None, limit=None, marker=None,
page_reverse=False, default_sg=False):
# if id is not specified in the filter, we just return security group
# data in local Neutron server, otherwise id is specified, we need to
# retrieve network data from central Neutron server and create network
# which doesn't exist in local Neutron server.
if not filters or 'id' not in filters:
return self.core_plugin.get_security_groups(
context, filters, fields, sorts, limit, marker, page_reverse,
default_sg)
b_sgs = self.core_plugin.get_security_groups(
context, filters, fields, sorts, limit, marker, page_reverse,
default_sg)
if len(b_sgs) == len(filters['id']):
return b_sgs
t_ctx = t_context.get_context_from_neutron_context(context)
raw_client = self.neutron_handle._get_client(t_ctx)
params = self._construct_params(filters, sorts, limit, marker,
page_reverse)
t_sgs = raw_client.list_security_groups(**params)['security_groups']
t_id_set = set([sg['id'] for sg in t_sgs])
b_id_set = set([sg['id'] for sg in b_sgs])
missing_id_set = t_id_set - b_id_set
if missing_id_set:
missing_sgs = [sg for sg in t_sgs if (
sg['id'] in missing_id_set)]
for sg in missing_sgs:
b_sg = self.core_plugin.create_security_group(
context, {'security_group': sg})
b_sgs.append(self.core_plugin.get_security_group(
context, b_sg['id'], fields))
return b_sgs

View File

@ -33,14 +33,17 @@ import tricircle.network.local_plugin as plugin
TOP_NETS = []
TOP_SUBNETS = []
TOP_PORTS = []
TOP_SGS = []
BOTTOM_NETS = []
BOTTOM_SUBNETS = []
BOTTOM_PORTS = []
RES_LIST = [TOP_NETS, TOP_SUBNETS, TOP_PORTS,
BOTTOM_NETS, BOTTOM_SUBNETS, BOTTOM_PORTS]
BOTTOM_SGS = []
RES_LIST = [TOP_NETS, TOP_SUBNETS, TOP_PORTS, TOP_SGS,
BOTTOM_NETS, BOTTOM_SUBNETS, BOTTOM_PORTS, BOTTOM_SGS]
RES_MAP = {'network': {True: TOP_NETS, False: BOTTOM_NETS},
'subnet': {True: TOP_SUBNETS, False: BOTTOM_SUBNETS},
'port': {True: TOP_PORTS, False: BOTTOM_PORTS}}
'port': {True: TOP_PORTS, False: BOTTOM_PORTS},
'security_group': {True: TOP_SGS, False: BOTTOM_SGS}}
def create_resource(_type, is_top, body):
@ -117,6 +120,14 @@ class FakeCorePlugin(object):
limit=None, marker=None, page_reverse=False):
return list_resource('port', False, filters)
def create_security_group(self, context, security_group, default_sg=False):
create_resource('security_group', False,
security_group['security_group'])
return security_group['security_group']
def get_security_group(self, context, _id, fields=None, tenant_id=None):
return get_resource('security_group', False, _id)
class FakeSession(object):
class WithWrapper(object):
@ -176,6 +187,10 @@ class FakeClient(object):
ports.append(copy.deepcopy(port))
return {'ports': ports}
def list_security_groups(self, **kwargs):
return {'security_groups': list_resource('security_group',
True, kwargs)}
class FakeNeutronHandle(object):
def _get_client(self, context):
@ -210,6 +225,7 @@ class PluginTest(unittest.TestCase):
network_id = uuidutils.generate_uuid()
subnet_id = uuidutils.generate_uuid()
port_id = uuidutils.generate_uuid()
sg_id = uuidutils.generate_uuid()
t_net = {'id': network_id,
'tenant_id': self.tenant_id,
'name': 'net1',
@ -235,10 +251,25 @@ class PluginTest(unittest.TestCase):
'fixed_ips': [{'subnet_id': subnet_id,
'ip_address': '10.0.1.2'}],
'binding:profile': {}}
t_sg = {
'id': sg_id,
'tenant_id': self.tenant_id,
'name': 'default',
'security_group_rules': [{
'remote_group_id': sg_id,
'direction': 'ingress',
'remote_ip_prefix': None,
'protocol': None,
'ethertype': 'IPv4',
'port_range_max': -1,
'port_range_min': -1,
'security_group_id': sg_id}]
}
TOP_NETS.append(t_net)
TOP_SUBNETS.append(t_subnet)
TOP_PORTS.append(t_port)
return t_net, t_subnet, t_port
TOP_SGS.append(t_sg)
return t_net, t_subnet, t_port, t_sg
def _validate(self, net, subnet, port):
b_net = self.plugin.get_network(self.context, net['id'])
@ -273,13 +304,13 @@ class PluginTest(unittest.TestCase):
@patch.object(t_context, 'get_context_from_neutron_context', new=mock.Mock)
def test_get_network(self):
t_net, t_subnet, t_port = self._prepare_resource()
t_net, t_subnet, t_port, _ = self._prepare_resource()
self._validate(t_net, t_subnet, t_port)
@patch.object(t_context, 'get_context_from_neutron_context', new=mock.Mock)
def test_get_networks(self):
t_net1, t_subnet1, t_port1 = self._prepare_resource()
t_net2, t_subnet2, t_port2 = self._prepare_resource()
t_net1, t_subnet1, t_port1, _ = self._prepare_resource()
t_net2, t_subnet2, t_port2, _ = self._prepare_resource()
self.plugin.get_networks(self.context,
{'id': [t_net1['id'], t_net2['id'],
'fake_net_id']})
@ -288,10 +319,11 @@ class PluginTest(unittest.TestCase):
@patch.object(t_context, 'get_context_from_neutron_context', new=mock.Mock)
def test_create_port(self):
t_net, t_subnet, t_port = self._prepare_resource()
t_net, t_subnet, t_port, _ = self._prepare_resource()
port = {
'port': {'network_id': t_net['id'],
'fixed_ips': q_constants.ATTR_NOT_SPECIFIED}
'fixed_ips': q_constants.ATTR_NOT_SPECIFIED,
'security_groups': []}
}
t_port = self.plugin.create_port(self.context, port)
b_port = get_resource('port', False, t_port['id'])
@ -299,7 +331,7 @@ class PluginTest(unittest.TestCase):
@patch.object(t_context, 'get_context_from_neutron_context', new=mock.Mock)
def test_create_port_ip_specified(self):
t_net, t_subnet, t_port = self._prepare_resource()
t_net, t_subnet, t_port, t_sg = self._prepare_resource()
port_body = {
'port': {'network_id': t_net['id'],
'fixed_ips': [{'ip_address': '10.0.1.4'}]}
@ -315,14 +347,15 @@ class PluginTest(unittest.TestCase):
'mac_address': 'fa:16:3e:96:41:04',
'fixed_ips': [{'subnet_id': t_subnet['id'],
'ip_address': '10.0.1.4'}],
'binding:profile': {}}
'binding:profile': {},
'security_groups': [t_sg['id']]}
TOP_PORTS.append(t_port)
b_port = self.plugin.create_port(self.context, port_body)
self.assertDictEqual(t_port, b_port)
@patch.object(t_context, 'get_context_from_neutron_context', new=mock.Mock)
def test_get_port(self):
t_net, t_subnet, t_port = self._prepare_resource()
t_net, t_subnet, t_port, _ = self._prepare_resource()
port_id = uuidutils.generate_uuid()
t_port = {'id': port_id,
'tenant_id': self.tenant_id,
@ -331,7 +364,8 @@ class PluginTest(unittest.TestCase):
'mac_address': 'fa:16:3e:96:41:04',
'fixed_ips': [{'subnet_id': t_subnet['id'],
'ip_address': '10.0.1.4'}],
'binding:profile': {}}
'binding:profile': {},
'security_groups': []}
TOP_PORTS.append(t_port)
t_port = self.plugin.get_port(self.context, port_id)
b_port = get_resource('port', False, t_port['id'])
@ -339,7 +373,7 @@ class PluginTest(unittest.TestCase):
@patch.object(t_context, 'get_context_from_neutron_context', new=mock.Mock)
def test_get_ports(self):
t_net, t_subnet, t_port = self._prepare_resource()
t_net, t_subnet, t_port, t_sg = self._prepare_resource()
t_ports = []
for i in (4, 5):
port_id = uuidutils.generate_uuid()
@ -350,7 +384,8 @@ class PluginTest(unittest.TestCase):
'mac_address': 'fa:16:3e:96:41:04',
'fixed_ips': [{'subnet_id': t_subnet['id'],
'ip_address': '10.0.1.%d' % i}],
'binding:profile': {}}
'binding:profile': {},
'security_groups': [t_sg['id']]}
TOP_PORTS.append(t_port)
t_ports.append(t_port)
self.plugin.get_ports(self.context,

View File

@ -30,34 +30,43 @@ from tricircle.xjob import xmanager
from tricircle.xjob import xservice
TOP_NETWORK = []
BOTTOM1_NETWORK = []
BOTTOM2_NETWORK = []
TOP_SUBNET = []
BOTTOM1_SUBNET = []
BOTTOM2_SUBNET = []
BOTTOM1_PORT = []
BOTTOM2_PORT = []
BOTTOM1_ROUTER = []
BOTTOM2_ROUTER = []
RES_LIST = [BOTTOM1_NETWORK, BOTTOM2_NETWORK, BOTTOM1_SUBNET, BOTTOM2_SUBNET,
BOTTOM1_PORT, BOTTOM2_PORT, BOTTOM1_ROUTER, BOTTOM2_ROUTER]
RES_MAP = {'pod_1': {'network': BOTTOM1_NETWORK,
TOP_SG = []
BOTTOM1_SG = []
BOTTOM2_SG = []
RES_LIST = [TOP_NETWORK, BOTTOM1_NETWORK, BOTTOM2_NETWORK, TOP_SUBNET,
BOTTOM1_SUBNET, BOTTOM2_SUBNET, BOTTOM1_PORT, BOTTOM2_PORT,
BOTTOM1_ROUTER, BOTTOM2_ROUTER, TOP_SG, BOTTOM1_SG, BOTTOM2_SG]
RES_MAP = {'top': {'network': TOP_NETWORK,
'subnet': TOP_SUBNET,
'security_group': TOP_SG},
'pod_1': {'network': BOTTOM1_NETWORK,
'subnet': BOTTOM1_SUBNET,
'port': BOTTOM1_PORT,
'router': BOTTOM1_ROUTER},
'router': BOTTOM1_ROUTER,
'security_group': BOTTOM1_SG},
'pod_2': {'network': BOTTOM2_NETWORK,
'subnet': BOTTOM2_SUBNET,
'port': BOTTOM2_PORT,
'router': BOTTOM2_ROUTER}}
'router': BOTTOM2_ROUTER,
'security_group': BOTTOM2_SG}}
class FakeXManager(xmanager.XManager):
def __init__(self):
self.clients = {'pod_1': FakeClient('pod_1'),
self.clients = {'top': FakeClient(),
'pod_1': FakeClient('pod_1'),
'pod_2': FakeClient('pod_2')}
def _get_client(self, pod_name=None):
return self.clients[pod_name]
class FakeClient(object):
def __init__(self, pod_name=None):
@ -85,6 +94,9 @@ class FakeClient(object):
def list_ports(self, cxt, filters=None):
return self.list_resources('port', cxt, filters)
def list_subnets(self, cxt, filters=None):
return self.list_resources('subnet', cxt, filters)
def get_subnets(self, cxt, subnet_id):
return self.list_resources(
'subnet', cxt,
@ -93,6 +105,20 @@ class FakeClient(object):
def update_routers(self, cxt, *args, **kwargs):
pass
def list_security_groups(self, cxt, filters=None):
return self.list_resources('security_group', cxt, filters)
def get_security_groups(self, cxt, sg_id):
return self.list_resources(
'security_group', cxt,
[{'key': 'id', 'comparator': 'eq', 'value': sg_id}])[0]
def delete_security_group_rules(self, cxt, sg_id):
pass
def create_security_group_rules(self, cxt, *args, **kwargs):
pass
class XManagerTest(unittest.TestCase):
def setUp(self):
@ -106,6 +132,7 @@ class XManagerTest(unittest.TestCase):
cfg.CONF.register_opt(opt)
self.context = context.Context()
self.xmanager = FakeXManager()
self.xmanager = FakeXManager()
@patch.object(FakeClient, 'update_routers')
def test_configure_extra_routes(self, mock_update):
@ -207,6 +234,77 @@ class XManagerTest(unittest.TestCase):
called = called and (mock_update.call_args_list[0] == calls[0])
self.assertTrue(called)
@patch.object(FakeClient, 'delete_security_group_rules')
@patch.object(FakeClient, 'create_security_group_rules')
def test_configure_security_group_rules(self, mock_create, mock_delete):
project_id = uuidutils.generate_uuid()
sg_id = uuidutils.generate_uuid()
sg_rule_id = uuidutils.generate_uuid()
sg = {'id': sg_id,
'tenant_id': project_id,
'name': 'default',
'security_group_rules': [{
'id': sg_rule_id,
'remote_group_id': sg_id,
'direction': 'ingress',
'remote_ip_prefix': None,
'protocol': None,
'ethertype': 'IPv4',
'port_range_max': -1,
'port_range_min': -1,
'security_group_id': sg_id}]}
RES_MAP['top']['security_group'].append(sg)
for i in xrange(1, 3):
pod_dict = {'pod_id': 'pod_id_%d' % i,
'pod_name': 'pod_%d' % i,
'az_name': 'az_name_%d' % i}
db_api.create_pod(self.context, pod_dict)
network = {'id': 'network_%d_id' % i,
'tenant_id': project_id}
subnet = {'id': 'subnet_%d_id' % i,
'network_id': network['id'],
'cidr': '10.0.%d.0/24' % i,
'gateway_ip': '10.0.%d.1' % i,
'tenant_id': project_id}
RES_MAP['top']['network'].append(network)
RES_MAP['top']['subnet'].append(subnet)
pod_name = 'pod_%d' % i
RES_MAP[pod_name]['security_group'].append(sg)
route = {'top_id': sg_id, 'bottom_id': sg_id,
'pod_id': pod_dict['pod_id'],
'resource_type': 'security_group'}
with self.context.session.begin():
core.create_resource(self.context, models.ResourceRouting,
route)
self.xmanager.configure_security_group_rules(
self.context, payload={'seg_rule_setup': project_id})
calls = [mock.call(self.context, sg_rule_id)]
mock_delete.assert_has_calls(calls)
calls = [mock.call(self.context,
{'security_group_rules': [
{'remote_group_id': None,
'direction': 'ingress',
'remote_ip_prefix': '10.0.1.0/24',
'protocol': None,
'ethertype': 'IPv4',
'port_range_max': -1,
'port_range_min': -1,
'security_group_id': sg_id},
{'remote_group_id': None,
'direction': 'ingress',
'remote_ip_prefix': '10.0.2.0/24',
'protocol': None,
'ethertype': 'IPv4',
'port_range_max': -1,
'port_range_min': -1,
'security_group_id': sg_id}]})]
mock_create.assert_has_calls(calls)
def test_job_handle(self):
@xmanager._job_handle('fake_resource')
def fake_handle(self, ctx, payload):

View File

@ -24,6 +24,7 @@ from oslo_log import log as logging
import oslo_messaging as messaging
from oslo_service import periodic_task
import neutron_lib.exceptions as q_exceptions
import neutronclient.common.exceptions as q_cli_exceptions
from tricircle.common import client
@ -150,7 +151,8 @@ class XManager(PeriodicTasks):
self.job_handles = {
constants.JT_ROUTER: self.configure_extra_routes,
constants.JT_ROUTER_SETUP: self.setup_bottom_router,
constants.JT_PORT_DELETE: self.delete_server_port}
constants.JT_PORT_DELETE: self.delete_server_port,
constants.JT_SEG_RULE_SETUP: self.configure_security_group_rules}
self.helper = helper.NetworkHelper()
self.xjob_handler = xrpcapi.XJobAPI()
super(XManager, self).__init__()
@ -611,8 +613,8 @@ class XManager(PeriodicTasks):
router_ips_map[b_router_ids[i]] = {}
for b_interface in b_interfaces:
ip = b_interface['fixed_ips'][0]['ip_address']
ew_bridge_cidr = '100.0.0.0/9'
ns_bridge_cidr = '100.128.0.0/9'
ew_bridge_cidr = CONF.client.ew_bridge_cidr
ns_bridge_cidr = CONF.client.ns_bridge_cidr
if netaddr.IPAddress(ip) in netaddr.IPNetwork(ew_bridge_cidr):
router_bridge_ip_map[b_router_ids[i]] = ip
continue
@ -655,3 +657,108 @@ class XManager(PeriodicTasks):
def delete_server_port(self, ctx, payload):
t_port_id = payload[constants.JT_PORT_DELETE]
self._get_client().delete_ports(ctx, t_port_id)
@staticmethod
def _safe_create_security_group_rule(context, client, body):
try:
client.create_security_group_rules(context, body)
except q_exceptions.Conflict:
return
@staticmethod
def _safe_delete_security_group_rule(context, client, _id):
try:
client.delete_security_group_rules(context, _id)
except q_exceptions.NotFound:
return
@staticmethod
def _construct_bottom_rule(rule, sg_id, ip=None):
ip = ip or rule['remote_ip_prefix']
# if ip is passed, this is a extended rule for remote group
return {'remote_group_id': None,
'direction': rule['direction'],
'remote_ip_prefix': ip,
'protocol': rule.get('protocol'),
'ethertype': rule['ethertype'],
'port_range_max': rule.get('port_range_max'),
'port_range_min': rule.get('port_range_min'),
'security_group_id': sg_id}
@staticmethod
def _compare_rule(rule1, rule2):
for key in ('direction', 'remote_ip_prefix', 'protocol', 'ethertype',
'port_range_max', 'port_range_min'):
if rule1[key] != rule2[key]:
return False
return True
@_job_handle(constants.JT_SEG_RULE_SETUP)
def configure_security_group_rules(self, ctx, payload):
project_id = payload[constants.JT_SEG_RULE_SETUP]
top_client = self._get_client()
sg_filters = [{'key': 'tenant_id', 'comparator': 'eq',
'value': project_id}]
top_sgs = top_client.list_security_groups(ctx, sg_filters)
for top_sg in top_sgs:
new_b_rules = []
for t_rule in top_sg['security_group_rules']:
if not t_rule['remote_group_id']:
# leave sg_id empty here
new_b_rules.append(
self._construct_bottom_rule(t_rule, ''))
continue
if top_sg['name'] != 'default':
# currently we only handle rules containing remote_group_id
# for default security group
continue
if t_rule['ethertype'] != 'IPv4':
continue
subnets = top_client.list_subnets(
ctx, [{'key': 'tenant_id', 'comparator': 'eq',
'value': project_id}])
ew_bridge_ip_net = netaddr.IPNetwork(
CONF.client.ew_bridge_cidr)
ns_bridge_ip_net = netaddr.IPNetwork(
CONF.client.ns_bridge_cidr)
for subnet in subnets:
ip_net = netaddr.IPNetwork(subnet['cidr'])
if ip_net in ew_bridge_ip_net or (
ip_net in ns_bridge_ip_net):
continue
# leave sg_id empty here
new_b_rules.append(
self._construct_bottom_rule(t_rule, '',
subnet['cidr']))
mappings = db_api.get_bottom_mappings_by_top_id(
ctx, top_sg['id'], constants.RT_SG)
for pod, b_sg_id in mappings:
client = self._get_client(pod['pod_name'])
b_sg = client.get_security_groups(ctx, b_sg_id)
add_rules = []
del_rules = []
match_index = set()
for b_rule in b_sg['security_group_rules']:
match = False
for i, rule in enumerate(new_b_rules):
if self._compare_rule(b_rule, rule):
match = True
match_index.add(i)
break
if not match:
del_rules.append(b_rule)
for i, rule in enumerate(new_b_rules):
if i not in match_index:
add_rules.append(rule)
for del_rule in del_rules:
self._safe_delete_security_group_rule(
ctx, client, del_rule['id'])
if add_rules:
rule_body = {'security_group_rules': []}
for add_rule in add_rules:
add_rule['security_group_id'] = b_sg_id
rule_body['security_group_rules'].append(add_rule)
self._safe_create_security_group_rule(
ctx, client, rule_body)