Skip to content

Commit

Permalink
Merge "Adding support for any in network policies with service chains"
Browse files Browse the repository at this point in the history
  • Loading branch information
Zuul authored and opencontrail-ci-admin committed Nov 16, 2015
2 parents 8a46aba + f500907 commit 7ee63e8
Show file tree
Hide file tree
Showing 4 changed files with 296 additions and 180 deletions.
19 changes: 12 additions & 7 deletions src/config/common/tests/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ def create_virtual_network(self, vn_name, vn_subnet):
return vn_obj
# end create_virtual_network

def _create_service(self, vn1, vn2, si_name, auto_policy, **kwargs):
def _create_service(self, vn1_name, vn2_name, si_name, auto_policy, **kwargs):
sti = [ServiceTemplateInterfaceType(
'left'), ServiceTemplateInterfaceType('right')]
st_prop = ServiceTemplateType(
Expand All @@ -487,8 +487,8 @@ def _create_service(self, vn1, vn2, si_name, auto_policy, **kwargs):
self._vnc_lib.service_template_create(service_template)
scale_out = ServiceScaleOutType()
if kwargs.get('service_mode') == 'in-network':
if_list = [ServiceInstanceInterfaceType(virtual_network=vn1.get_fq_name_str()),
ServiceInstanceInterfaceType(virtual_network=vn2.get_fq_name_str())]
if_list = [ServiceInstanceInterfaceType(virtual_network=vn1_name),
ServiceInstanceInterfaceType(virtual_network=vn2_name)]
si_props = ServiceInstanceType(
auto_policy=auto_policy, interface_list=if_list,
scale_out=scale_out)
Expand All @@ -505,16 +505,21 @@ def _create_service(self, vn1, vn2, si_name, auto_policy, **kwargs):

def create_network_policy(self, vn1, vn2, service_list=None, mirror_service=None,
auto_policy=False, **kwargs):
addr1 = AddressType(virtual_network=vn1.get_fq_name_str())
addr2 = AddressType(virtual_network=vn2.get_fq_name_str())
vn1_name = vn1 if isinstance(vn1, basestring) else vn1.get_fq_name_str()
vn2_name = vn2 if isinstance(vn2, basestring) else vn2.get_fq_name_str()
addr1 = AddressType(virtual_network=vn1_name)
addr2 = AddressType(virtual_network=vn2_name)
port = PortType(-1, 0)
service_name_list = []
si_list = service_list or []
if service_list:
for service in si_list:
service_name_list.append(self._create_service(vn1, vn2, service, auto_policy, **kwargs))
service_name_list.append(self._create_service(
vn1_name, vn2_name, service, auto_policy, **kwargs))
if mirror_service:
mirror_si = self._create_service(vn1, vn2, mirror_service, False, service_mode='transparent', service_type='analyzer')
mirror_si = self._create_service(
vn1_name, vn2_name, mirror_service, False,
service_mode='transparent', service_type='analyzer')
action_list = ActionListType()
if mirror_service:
mirror = MirrorActionType(analyzer_name=mirror_si)
Expand Down
5 changes: 5 additions & 0 deletions src/config/common/vnc_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ def items(cls):
for i in cls._dict.items():
yield i
# end items

def __contains__(cls, item):
# check for 'item in cls'
return item in cls._dict
# end __contains__
# end __metaclass__

@classmethod
Expand Down
225 changes: 118 additions & 107 deletions src/config/schema-transformer/config_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import copy
import uuid

import re
import itertools
import cfgm_common as common
from netaddr import IPNetwork, IPAddress
from cfgm_common.exceptions import *
Expand Down Expand Up @@ -184,6 +184,9 @@ class VirtualNetworkST(DBBaseST):
_dict = {}
obj_type = 'virtual_network'

def me(self, name):
return name in (self.name, 'any')

def __init__(self, name, obj=None, acl_dict=None):
self.obj = obj or self.read_vnc_obj(fq_name=name)
self.name = name
Expand Down Expand Up @@ -430,23 +433,54 @@ def delete_ri_connection(self, vn2_name):
vn2.uve_send()
# end delete_ri_connection

def add_service_chain(self, remote_vn, left_vn, right_vn, direction,
sp_list, dp_list, proto, service_list):
service_chain_list = self.service_chains.setdefault(remote_vn, [])
service_chain = ServiceChain.find_or_create(left_vn, right_vn,
direction, sp_list, dp_list, proto,
service_list)
if service_chain.service_list != service_list:
if service_chain.created:
service_chain.destroy()
service_chain.service_list = service_list
service_chain.create()
def add_service_chain(self, svn, dvn, proto, prule):
if self.me(dvn):
remote_vn = svn
elif self.me(svn):
remote_vn = dvn
else:
return {}
if self.name == remote_vn:
self._logger.error("Service chain source and dest vn are same: %s",
self.name)
return None
if remote_vn == 'any':
remote_vns = self.get_vns_in_project()
else:
remote_vns = [remote_vn]
service_chain_ris = {}
for remote_vn in remote_vns:
if remote_vn not in VirtualNetworkST:
self._logger.error("Network %s not found while apply service "
"chain to network %s", remote_vn, self.name)
continue
services = prule.action_list.apply_service
service_chain_list = self.service_chains.setdefault(remote_vn, [])
if self.me(dvn):
service_chain = ServiceChain.find_or_create(
remote_vn, self.name, prule.direction, prule.src_ports,
prule.dst_ports, proto, services)
service_chain_ris[remote_vn] = (
None, self.get_service_name(service_chain.name,
services[-1]))
else:
service_chain.service_list = service_list
service_chain = ServiceChain.find_or_create(
self.name, remote_vn, prule.direction, prule.src_ports,
prule.dst_ports, proto, services)
service_chain_ris[remote_vn] = (
self.get_service_name(service_chain.name, services[0]),
None)
if service_chain.service_list != services:
if service_chain.created:
service_chain.destroy()
service_chain.service_list = list(services)
service_chain.create()
else:
service_chain.service_list = list(services)

if service_chain not in service_chain_list:
service_chain_list.append(service_chain)
return service_chain.name
if service_chain not in service_chain_list:
service_chain_list.append(service_chain)
return service_chain_ris
# end add_service_chain

def get_vns_in_project(self):
Expand Down Expand Up @@ -840,6 +874,21 @@ def protocol_policy_to_acl(pproto):
return _PROTO_STR_TO_NUM.get(pproto.lower())
# end protocol_policy_to_acl

def address_list_policy_to_acl(self, addr):
if addr.network_policy:
pol = NetworkPolicyST.get(addr.network_policy)
if not pol:
self._logger.error(
"Policy %s not found while applying policy "
"to network %s", addr.network_policy,
self.name)
return []
return [AddressType(virtual_network=x)
for x in pol.virtual_networks]
else:
return [addr]
# end address_list_policy_to_acl

def policy_to_acl_rule(self, prule, dynamic):
result_acl_rule_list = AclRuleListST(dynamic=dynamic)
saddr_list = prule.src_addresses
Expand All @@ -850,7 +899,7 @@ def policy_to_acl_rule(self, prule, dynamic):

arule_proto = self.protocol_policy_to_acl(prule.protocol)
if arule_proto is None:
# TODO log unknown protocol
self._logger.error("Unknown protocol %s" % prule.protocol)
return result_acl_rule_list

if prule.action_list is None:
Expand All @@ -875,9 +924,9 @@ def policy_to_acl_rule(self, prule, dynamic):
if dvn == "local":
dvn = self.name
daddr_match.virtual_network = self.name
if dvn in [self.name, 'any']:
if self.me(dvn):
remote_network_name = svn
elif svn in [self.name, 'any']:
elif self.me(svn):
remote_network_name = dvn
elif not dvn and dpol:
dp_obj = NetworkPolicyST.get(dpol)
Expand All @@ -896,7 +945,7 @@ def policy_to_acl_rule(self, prule, dynamic):
sp_obj = NetworkPolicyST.get(spol)
if self.name in sp_obj.virtual_networks:
remote_network_name = dvn
daddr_match.network_policy = None
saddr_match.network_policy = None
saddr_match.virtual_network = self.name
else:
self._logger.error(
Expand All @@ -918,95 +967,57 @@ def policy_to_acl_rule(self, prule, dynamic):
self.name, svn, dvn)
continue

service_list = None
if prule.action_list.apply_service != []:
if remote_network_name == self.name:
self._logger.error("Service chain source and dest "
"vn are same: %s", self.name)
continue
remote_vn = VirtualNetworkST.get(remote_network_name)
if remote_vn is None:
self._logger.error(
"Network %s not found while apply service chain "
"to network %s", remote_network_name, self.name)
action = prule.action_list
if action.mirror_to and action.mirror_to.analyzer_name:
if self.me(svn) or self.me(dvn):
self.process_analyzer(action)

sa_list = self.address_list_policy_to_acl(saddr_match)
da_list = self.address_list_policy_to_acl(daddr_match)

service_ris = {}
service_list = prule.action_list.apply_service
if service_list:
service_ris = self.add_service_chain(svn, dvn, arule_proto,
prule)
if not service_ris:
continue
service_list = copy.deepcopy(
prule.action_list.apply_service)
sc_name = self.add_service_chain(remote_network_name, svn,
dvn, prule.direction, sp_list, dp_list, arule_proto,
service_list)

for sp in sp_list:
for dp in dp_list:
action = copy.deepcopy(prule.action_list)
if (service_list and svn in [self.name, 'any']):
service_ri = self.get_service_name(sc_name,
service_list[0])
action.set_assign_routing_instance(service_ri)
else:
action.assign_routing_instance = None

if action.mirror_to and action.mirror_to.analyzer_name:
if ((svn in [self.name, 'any']) or
(dvn in [self.name, 'any'])):
self.process_analyzer(action)

if saddr_match.network_policy:
pol = NetworkPolicyST.get(saddr_match.network_policy)
if not pol:
self._logger.error(
"Policy %s not found while applying policy "
"to network %s", saddr_match.network_policy,
self.name)
continue
sa_list = [AddressType(virtual_network=x)
for x in pol.virtual_networks]
else:
sa_list = [saddr_match]

if daddr_match.network_policy:
pol = NetworkPolicyST.get(daddr_match.network_policy)
if not pol:
self._logger.error(
"Policy %s not found while applying policy "
"to network %s", daddr_match.network_policy,
self.name)
continue
da_list = [AddressType(virtual_network=x)
for x in pol.virtual_networks]
else:
da_list = [daddr_match]

for sa in sa_list:
for da in da_list:
match = MatchConditionType(arule_proto,
sa, sp,
da, dp)
acl = AclRuleType(match, action, rule_uuid)
result_acl_rule_list.append(acl)
if ((prule.direction == "<>") and
(sa != da or sp != dp)):
rmatch = MatchConditionType(arule_proto,
da, dp,
sa, sp)
raction = copy.deepcopy(action)
if (service_list and dvn in [self.name, 'any']):
service_ri = self.get_service_name(
sc_name, service_list[-1])
raction.set_assign_routing_instance(
service_ri)
else:
raction.assign_routing_instance = None

acl = AclRuleType(rmatch, raction, rule_uuid)
result_acl_rule_list.append(acl)
# end for dp
# end for sp
if self.me(svn):
da_list = [AddressType(virtual_network=x)
for x in service_ris]
elif self.me(dvn):
sa_list = [AddressType(virtual_network=x)
for x in service_ris]

for sp, dp, sa, da in itertools.product(sp_list, dp_list,
sa_list, da_list):
acl = self.add_acl_rule(
sa, sp, da, dp, arule_proto, rule_uuid,
prule.action_list, prule.direction,
service_ris.get(da, [None])[0])
result_acl_rule_list.append(acl)
if ((prule.direction == "<>") and
(sa != da or sp != dp)):
acl = self.add_acl_rule(
da, dp, sa, sp, arule_proto, rule_uuid,
prule.action_list, prule.direction,
service_ris.get(sa, [None, None])[1])

result_acl_rule_list.append(acl)
# end for sp, dp
# end for daddr
# end for saddr
return result_acl_rule_list
# end policy_to_acl_rule

def add_acl_rule(self, sa, sp, da, dp, proto, rule_uuid, action, direction,
service_ri):
action_list = copy.deepcopy(action)
action_list.set_assign_routing_instance(service_ri)
match = MatchConditionType(proto, sa, sp, da, dp)
acl = AclRuleType(match, action_list, rule_uuid)
return acl

def update_pnf_presence(self):
has_pnf = False
for ri_name in self.routing_instances:
Expand Down Expand Up @@ -1057,9 +1068,9 @@ def evaluate(self):
if action.simple_action == 'deny':
continue
connected_network = None
if (match.dst_address.virtual_network in [self.name, "any"]):
if self.me(match.dst_address.virtual_network):
connected_network = match.src_address.virtual_network
elif (match.src_address.virtual_network in [self.name, "any"]):
elif self.me(match.src_address.virtual_network):
connected_network = match.dst_address.virtual_network
if action.apply_service:
# if a service was applied, the ACL should have a
Expand Down Expand Up @@ -2013,14 +2024,14 @@ def init(cls):
# end init

def __init__(self, name, left_vn, right_vn, direction, sp_list, dp_list,
protocol, service_list):
protocol, services):
self.name = name
self.left_vn = left_vn
self.right_vn = right_vn
self.direction = direction
self.sp_list = sp_list
self.dp_list = dp_list
self.service_list = service_list
self.service_list = list(services)

self.protocol = protocol
self.created = False
Expand Down

0 comments on commit 7ee63e8

Please sign in to comment.