From 91fbdb6187dc2932e3ccc0c7435365a1e88a5b73 Mon Sep 17 00:00:00 2001 From: sbalineni Date: Thu, 25 Jun 2015 14:08:30 -0700 Subject: [PATCH] DM: fixes ported from R2.20 Change-Id: Ie5e87314202a45b7863960d9d68a29121d30a22a Closes-Bug: #1468209 Closes-Bug: #1468145 Closes-Bug: #1468143 Closes-Bug: #1466721 Closes-Bug: #1466719 Closes-Bug: #1466717 Closes-Bug: #1466437 --- .../device-manager/device_manager/db.py | 58 ++++++--- .../device_manager/physical_router_config.py | 122 ++++++++++-------- 2 files changed, 108 insertions(+), 72 deletions(-) diff --git a/src/config/device-manager/device_manager/db.py b/src/config/device-manager/device_manager/db.py index 84ded59193f..3dcb77a0593 100644 --- a/src/config/device-manager/device_manager/db.py +++ b/src/config/device-manager/device_manager/db.py @@ -210,11 +210,9 @@ def push_config(self): else: vn_dict[vn_id] = [li.name] - #for now, assume service port ifls unit numbers are always starts with 0 and goes on - service_port_id = 1 for vn_id, interfaces in vn_dict.items(): vn_obj = VirtualNetworkDM.get(vn_id) - if vn_obj is None or vn_obj.vxlan_vni is None: + if vn_obj is None or vn_obj.vxlan_vni is None or vn_obj.vn_network_id is None: continue export_set = None import_set = None @@ -224,7 +222,6 @@ def push_config(self): if ri_obj is None: continue if ri_obj.fq_name[-1] == vn_obj.fq_name[-1]: - vrf_name = vn_obj.get_vrf_name() vrf_name_l2 = vn_obj.get_vrf_name(vrf_type='l2') vrf_name_l3 = vn_obj.get_vrf_name(vrf_type='l3') export_set = copy.copy(ri_obj.export_targets) @@ -264,16 +261,19 @@ def push_config(self): break if export_set is not None and self.is_junos_service_ports_enabled() and len(vn_obj.instance_ip_map) > 0: - vrf_name = vrf_name[:123] + '-nat' - interfaces = [] - service_ports = self.junos_service_ports.get('service_port') - interfaces.append(service_ports[0] + "." + str(service_port_id)) - service_port_id = service_port_id + 1 - interfaces.append(service_ports[0] + "." + str(service_port_id)) - service_port_id = service_port_id + 1 - self.config_manager.add_routing_instance(vrf_name, + service_port_id = 2*vn_obj.vn_network_id - 1 + if self.is_service_port_id_valid(service_port_id) == False: + self._logger.error("DM can't allocate service interfaces for \ + (vn, vn-id)=(%s,%s)" % (vn_obj.fq_name, vn_obj.vn_network_id)) + else: + vrf_name = vrf_name_l3[:123] + '-nat' + interfaces = [] + service_ports = self.junos_service_ports.get('service_port') + interfaces.append(service_ports[0] + "." + str(service_port_id)) + interfaces.append(service_ports[0] + "." + str(service_port_id + 1)) + self.config_manager.add_routing_instance(vrf_name, import_set, - export_set, + set(), None, None, False, @@ -285,6 +285,13 @@ def push_config(self): self.uve_send() # end push_config + def is_service_port_id_valid(self, service_port_id): + #mx allowed ifl unit number range is (1, 16385) for service ports + if service_port_id < 1 or service_port_id > 16384: + return False + return True + #end is_service_port_id_valid + def uve_send(self, deleted=False): pr_trace = UvePhysicalRouterConfig(name=self.name, ip_address=self.management_ip, @@ -549,12 +556,19 @@ def __init__(self, uuid, obj_dict=None): def update(self, obj=None): if obj is None: obj = self.read_obj(self.uuid) + self.device_owner = obj.get("virtual_machine_interface_device_owner") self.update_single_ref('logical_interface', obj) self.update_single_ref('virtual_network', obj) self.update_single_ref('floating_ip', obj) self.update_single_ref('instance_ip', obj) # end update + def is_device_owner_bms(self): + if not self.device_owner or self.device_owner.lower() == 'physicalrouter': + return True + return False + #end + @classmethod def delete(cls, uuid): if uuid not in cls._dict: @@ -593,6 +607,7 @@ def update(self, obj=None): self.router_external = obj['router_external'] except KeyError: self.router_external = False + self.vn_network_id = obj.get('virtual_network_network_id') self.set_vxlan_vni(obj) self.routing_instances = set([ri['uuid'] for ri in obj.get('routing_instances', [])]) @@ -609,13 +624,16 @@ def update(self, obj=None): self.gateways.add(subnet['default_gateway']) # end update - def get_vrf_name(self, vrf_type=None): + def get_vrf_name(self, vrf_type): + #this function must be called only after vn gets its vn_id + if self.vn_network_id is None: + self._logger.error("network id is null for vn: %s" % (self.fq_name[-1])) + return '_contrail_' + vrf_type + '_' + self.fq_name[-1] if vrf_type is None: - vrf_name = '__contrail__' + self.uuid + '_' + self.fq_name[-1] - elif vrf_type == 'l2': - vrf_name = '__contrail__l2_' + self.uuid + '_' + self.fq_name[-1] + self._logger.error("vrf type can't be null : %s" % (self.fq_name[-1])) + vrf_name = '_contrail_' + str(self.vn_network_id) + '_' + self.fq_name[-1] else: - vrf_name = '__contrail__l3_' + self.uuid + '_' + self.fq_name[-1] + vrf_name = '_contrail_' + vrf_type + '_' + str(self.vn_network_id) + '_' + self.fq_name[-1] #mx has limitation for vrf name, allowed max 127 chars return vrf_name[:127] #end @@ -639,7 +657,7 @@ def update_instance_ip_map(self): self.instance_ip_map = {} for vmi_uuid in self.virtual_machine_interfaces: vmi = VirtualMachineInterfaceDM.get(vmi_uuid) - if vmi is None: + if vmi is None or vmi.is_device_owner_bms() == False: continue if vmi.floating_ip is not None and vmi.instance_ip is not None: fip = FloatingIpDM.get(vmi.floating_ip) @@ -649,7 +667,7 @@ def update_instance_ip_map(self): instance_ip = inst_ip.instance_ip_address floating_ip = fip.floating_ip_address public_vn = VirtualNetworkDM.get(fip.public_network) - if public_vn is None: + if public_vn is None or public_vn.vn_network_id is None: continue public_vrf_name = public_vn.get_vrf_name(vrf_type='l3') self.instance_ip_map[instance_ip] = {'floating_ip': floating_ip, diff --git a/src/config/device-manager/device_manager/physical_router_config.py b/src/config/device-manager/device_manager/physical_router_config.py index 00be8639c17..2dc5b86bdc2 100644 --- a/src/config/device-manager/device_manager/physical_router_config.py +++ b/src/config/device-manager/device_manager/physical_router_config.py @@ -183,23 +183,23 @@ def add_routing_instance(self, ri_name, import_targets, export_targets, if_element = etree.SubElement(ri, "interface") etree.SubElement(if_element, "name").text = interface + if ri_opt is None: + ri_opt = etree.SubElement(ri, "routing-options") if prefixes and fip_map is None: - if ri_opt is None: - ri_opt = etree.SubElement(ri, "routing-options") - static_config = etree.SubElement(ri_opt, "static") + static_config = etree.SubElement(ri_opt, "static") for prefix in prefixes: route_config = etree.SubElement(static_config, "route") etree.SubElement(route_config, "name").text = prefix etree.SubElement(route_config, "discard") - auto_export = "" - ri_opt.append(etree.fromstring(auto_export)) + auto_export = "" + ri_opt.append(etree.fromstring(auto_export)) else: etree.SubElement(ri, "instance-type").text = "virtual-switch" if fip_map is not None: if ri_opt is None: ri_opt = etree.SubElement(ri, "routing-options") - static_config = etree.SubElement(ri_opt, "static") + static_config = etree.SubElement(ri_opt, "static") route_config = etree.SubElement(static_config, "route") etree.SubElement(route_config, "name").text = "0.0.0.0/0" etree.SubElement(route_config, "next-hop").text = interfaces[0] @@ -234,7 +234,11 @@ def add_routing_instance(self, ri_name, import_targets, export_targets, comm = etree.SubElement(then, "community") etree.SubElement(comm, "add") etree.SubElement(comm, "community-name").text = route_target.replace(':', '_') - etree.SubElement(then, "accept") + if fip_map is not None: + #for nat instance + etree.SubElement(then, "reject") + else: + etree.SubElement(then, "accept") # add policies for import route targets ps = etree.SubElement(policy_config, "policy-statement") @@ -253,45 +257,62 @@ def add_routing_instance(self, ri_name, import_targets, export_targets, # add firewall config for public VRF forwarding_options_config = self.forwarding_options_config firewall_config = self.firewall_config - if router_external or fip_map is not None: - forwarding_options_config = self.forwarding_options_config or etree.Element("forwarding-options") - fo = etree.SubElement(forwarding_options_config, "family") - inet = etree.SubElement(fo, "inet") - f = etree.SubElement(inet, "filter") - #mx has limitation for filter names, allowed max 63 chars - etree.SubElement(f, "input").text = "redirect_to_" + ri_name[:46] + "_vrf" + if router_external: + if self.forwarding_options_config is None: + forwarding_options_config = etree.Element("forwarding-options") + fo = etree.SubElement(forwarding_options_config, "family") + inet = etree.SubElement(fo, "inet") + f = etree.SubElement(inet, "filter") + etree.SubElement(f, "input").text = "redirect_to_public_vrf_filter" + firewall_config = self.firewall_config or etree.Element("firewall") + fc = etree.SubElement(firewall_config, "family") + inet = etree.SubElement(fc, "inet") + f = etree.SubElement(inet, "filter") + etree.SubElement(f, "name").text = "redirect_to_public_vrf_filter" + self.inet_forwarding_filter = f + term = etree.SubElement(f, "term") + etree.SubElement(term, "name").text= "default-term" + then_ = etree.SubElement(term, "then") + etree.SubElement(then_, "accept") + + term = etree.Element("term") + etree.SubElement(term, "name").text= "term-" + ri_name[:59] + if prefixes: + from_ = etree.SubElement(term, "from") + etree.SubElement(from_, "destination-address").text = ';'.join(prefixes) + then_ = etree.SubElement(term, "then") + etree.SubElement(then_, "routing-instance").text = ri_name + #insert after 'name' element but before the last term + self.inet_forwarding_filter.insert(1, term) + if fip_map is not None: firewall_config = self.firewall_config or etree.Element("firewall") fc = etree.SubElement(firewall_config, "family") inet = etree.SubElement(fc, "inet") f = etree.SubElement(inet, "filter") etree.SubElement(f, "name").text = "redirect_to_" + ri_name[:46] + "_vrf" term = etree.SubElement(f, "term") - etree.SubElement(term, "name").text= "t1" - if fip_map is not None: - from_ = etree.SubElement(term, "from") - etree.SubElement(from_, "destination-address").text = ';'.join(fip_map.keys()) - elif prefixes: - from_ = etree.SubElement(term, "from") - etree.SubElement(from_, "destination-address").text = ';'.join(prefixes) + etree.SubElement(term, "name").text= "term-" + ri_name[:59] + from_ = etree.SubElement(term, "from") + for fip_user_ip in fip_map.keys(): + etree.SubElement(from_, "source-address").text = fip_user_ip then_ = etree.SubElement(term, "then") etree.SubElement(then_, "routing-instance").text = ri_name term = etree.SubElement(f, "term") - etree.SubElement(term, "name").text= "t2" + etree.SubElement(term, "name").text= "default-term" then_ = etree.SubElement(term, "then") etree.SubElement(then_, "accept") - if fip_map is not None: - interfaces_config = self.interfaces_config or etree.Element("interfaces") - irb_intf = etree.SubElement(interfaces_config, "interface") - etree.SubElement(irb_intf, "name").text = "irb" - intf_unit = etree.SubElement(irb_intf, "unit") - etree.SubElement(intf_unit, "name").text = str(private_vni) - family = etree.SubElement(intf_unit, "family") - inet = etree.SubElement(family, "inet") - f = etree.SubElement(inet, "filter") - input = etree.SubElement(f, "input") - etree.SubElement(input, "filter-name").text = "redirect_to_" + ri_name[:46] + "_vrf" + interfaces_config = self.interfaces_config or etree.Element("interfaces") + irb_intf = etree.SubElement(interfaces_config, "interface") + etree.SubElement(irb_intf, "name").text = "irb" + intf_unit = etree.SubElement(irb_intf, "unit") + etree.SubElement(intf_unit, "name").text = str(private_vni) + family = etree.SubElement(intf_unit, "family") + inet = etree.SubElement(family, "inet") + f = etree.SubElement(inet, "filter") + iput = etree.SubElement(f, "input") + etree.SubElement(iput, "filter-name").text = "redirect_to_" + ri_name[:46] + "_vrf" # add L2 EVPN and BD config bd_config = None @@ -359,29 +380,29 @@ def add_routing_instance(self, ri_name, import_targets, export_targets, services_config = self.services_config or etree.Element("services") service_name = 'sv-' + ri_name #mx has limitation for service-set and nat-rule name length, allowed max 63 chars - service_name = service_name[:56] + service_name = service_name[:23] service_set = etree.SubElement(services_config, "service-set") etree.SubElement(service_set, "name").text = service_name - rule_count = len(fip_map) - for rule_id in range(0, rule_count): - nat_rule = etree.SubElement(service_set, "nat-rules") - etree.SubElement(nat_rule, "name").text = service_name + "-sn-" + str(rule_id) - nat_rule = etree.SubElement(service_set, "nat-rules") - etree.SubElement(nat_rule, "name").text = service_name + "-dn-" + str(rule_id) + nat_rule = etree.SubElement(service_set, "nat-rules") + etree.SubElement(nat_rule, "name").text = service_name + "-sn-rule" + nat_rule = etree.SubElement(service_set, "nat-rules") + etree.SubElement(nat_rule, "name").text = service_name + "-dn-rule" next_hop_service = etree.SubElement(service_set, "next-hop-service") etree.SubElement(next_hop_service , "inside-service-interface").text = interfaces[0] etree.SubElement(next_hop_service , "outside-service-interface").text = interfaces[1] nat = etree.SubElement(services_config, "nat") + snat_rule = etree.SubElement(nat, "rule") + etree.SubElement(snat_rule, "name").text = service_name + "-sn-rule" + etree.SubElement(snat_rule, "match-direction").text = "input" + dnat_rule = etree.SubElement(nat, "rule") + etree.SubElement(dnat_rule, "name").text = service_name + "-dn-rule" + etree.SubElement(dnat_rule, "match-direction").text = "output" - rule_id = 0 for pip, fip_vn in fip_map.items(): fip = fip_vn["floating_ip"] - rule = etree.SubElement(nat, "rule") - etree.SubElement(rule, "name").text = service_name + "-sn-" + str(rule_id) - etree.SubElement(rule, "match-direction").text = "input" - term = etree.SubElement(rule, "term") - etree.SubElement(term, "name").text = "t1" + term = etree.SubElement(snat_rule, "term") + etree.SubElement(term, "name").text = "term_" + pip.replace('.', '_') from_ = etree.SubElement(term, "from") src_addr = etree.SubElement(from_, "source-address") etree.SubElement(src_addr, "name").text = pip + "/32" # private ip @@ -391,11 +412,8 @@ def add_routing_instance(self, ri_name, import_targets, export_targets, translation_type = etree.SubElement(translated, "translation-type") etree.SubElement(translation_type, "basic-nat44") - rule = etree.SubElement(nat, "rule") - etree.SubElement(rule, "name").text = service_name + "-dn-" + str(rule_id) - etree.SubElement(rule, "match-direction").text = "output" - term = etree.SubElement(rule, "term") - etree.SubElement(term, "name").text = "t1" + term = etree.SubElement(dnat_rule, "term") + etree.SubElement(term, "name").text = "term_" + fip.replace('.', '_') from_ = etree.SubElement(term, "from") src_addr = etree.SubElement(from_, "destination-address") etree.SubElement(src_addr, "name").text = fip + "/32" #public ip @@ -404,7 +422,6 @@ def add_routing_instance(self, ri_name, import_targets, export_targets, etree.SubElement(translated , "destination-prefix").text = pip + "/32" #source ip translation_type = etree.SubElement(translated, "translation-type") etree.SubElement(translation_type, "dnat-44") - rule_id = rule_id + 1 interfaces_config = self.interfaces_config or etree.Element("interfaces") si_intf = etree.SubElement(interfaces_config, "interface") @@ -511,6 +528,7 @@ def reset_bgp_config(self): self.services_config = None self.policy_config = None self.firewall_config = None + self.inet_forwarding_filter = None self.forwarding_options_config = None self.global_routing_options_config = None self.proto_config = None