def static_routes(self, node):
        node.ipv4_static_routes = []
        if self.anm.has_overlay("ipv4"):
            ipv4_node = self.anm['ipv4'].node(node)
            if ipv4_node and ipv4_node.static_routes:
                for route in ipv4_node.static_routes:
                    stanza = ConfigStanza(
                        prefix=route.prefix,
                        netmask=route.netmask,
                        nexthop=route.nexthop,
                        metric=route.metric,
                    )
                    node.ipv4_static_routes.append(stanza)

        node.ipv6_static_routes = []
        if self.anm.has_overlay("ipv6"):
            ipv6_node = self.anm['ipv6'].node(node)
            if ipv6_node and ipv6_node.static_routes:
                for route in ipv6_node.static_routes:
                    stanza = ConfigStanza(
                        prefix=route.prefix,
                        nexthop=route.nexthop,
                        metric=route.metric,
                    )
                    node.ipv6_static_routes.append(stanza)
Example #2
0
    def eigrp(self, node):
        super(IosXrCompiler, self).eigrp(node)

        g_eigrp = self.anm['eigrp']
        ipv4_interfaces = []
        ipv6_interfaces = []

        for interface in node.physical_interfaces():
            if interface.exclude_igp:
                continue  # don't configure IGP for this interface

            eigrp_int = g_eigrp.interface(interface)
            if eigrp_int and eigrp_int.is_bound:
                # TODO: for here and below use stanza directly
                data = {'id': interface.id, 'passive': False}
                stanza = ConfigStanza(**data)
                if node.eigrp.use_ipv4:
                    ipv4_interfaces.append(stanza)
                if node.eigrp.use_ipv6:
                    ipv6_interfaces.append(stanza)

        loopback_zero = node.loopback_zero
        data = {'id': node.loopback_zero.id, 'passive': True}
        stanza = ConfigStanza(**data)
        if node.eigrp.use_ipv4:
            ipv4_interfaces.append(stanza)
        if node.eigrp.use_ipv6:
            ipv6_interfaces.append(stanza)

        node.eigrp.ipv4_interfaces = ipv4_interfaces
        node.eigrp.ipv6_interfaces = ipv6_interfaces
Example #3
0
    def nailed_up_routes(self, node):
        log.debug('Configuring nailed up routes')
        phy_node = self.anm['phy'].node(node)

        if node.is_ebgp_v4 and node.ip.use_ipv4:
            infra_blocks = self.anm['ipv4'].data['infra_blocks'].get(
                phy_node.asn) or []
            for infra_route in infra_blocks:
                stanza = ConfigStanza(
                    prefix=str(infra_route.network),
                    netmask=str(infra_route.netmask),
                    nexthop="Null0",
                    metric=254,
                )
                node.ipv4_static_routes.append(stanza)

        if node.is_ebgp_v6 and node.ip.use_ipv6:
            infra_blocks = self.anm['ipv6'].data['infra_blocks'].get(
                phy_node.asn) or []
            # TODO: setup schema with defaults
            for infra_route in infra_blocks:
                stanza = ConfigStanza(
                    prefix=str(infra_route),
                    nexthop="Null0",
                    metric=254,
                )
                node.ipv6_static_routes.append(stanza)
Example #4
0
    def gre(self, node):
        node.gre_tunnels = []
        if not self.anm.has_overlay('gre_tunnel'):
            return

        g_gre_tunnel = self.anm['gre_tunnel']
        if node not in g_gre_tunnel:
            return  # no gre tunnel for node

        gre_node = g_gre_tunnel.node(node)
        neighbors = gre_node.neighbors()
        for index, neigh in enumerate(neighbors, start=1):
            stanza = ConfigStanza(id=index, endpoint=neigh)

            # TODO: try/except here
            # TODO: Explain logic here
            src_int = g_gre_tunnel.edge(node, neigh).src_int
            tunnel_source = node.interface(src_int).id
            stanza.source = tunnel_source
            stanza.destination = "0.0.0.0"  # placeholder for user to replace

            if neigh.tunnel_enabled_ipv4:
                ip_address = neigh.tunnel_ipv4_address
                cidr = neigh.tunnel_ipv4_cidr
                stanza.ipv4_address = ip_address
                stanza.ipv4_subnet = cidr
                stanza.use_ipv4 = True

            if neigh.tunnel_enabled_ipv6:
                cidr = neigh.tunnel_ipv6_cidr
                stanza.ipv4_subnet = cidr
                stanza.use_ipv6 = True

            node.gre_tunnels.append(stanza)
Example #5
0
    def lab_topology(self):
        # TODO: replace name/label and use attribute from subgraph
        lab_topology = self.nidb.topology(self.host)
        lab_topology.render_template = os.path.join("templates",
                                                    "netkit_lab_conf.mako")
        lab_topology.render_dst_folder = os.path.join("rendered", self.host,
                                                      "netkit")
        lab_topology.render_dst_file = "lab.conf"
        lab_topology.description = "AutoNetkit Lab"
        lab_topology.author = "AutoNetkit"
        lab_topology.web = "www.autonetkit.org"
        host_nodes = list(self.nidb.nodes(host=self.host, platform="netkit"))
        if not len(host_nodes):
            log.debug("No Netkit hosts for %s" % self.host)
# also need collision domains for this host
        cd_nodes = self.nidb.nodes("broadcast_domain", host=self.host)
        host_nodes += cd_nodes
        subgraph = self.nidb.subgraph(host_nodes, self.host)

        lab_topology.machines = " ".join(
            alpha_sort(
                naming.network_hostname(phy_node)
                for phy_node in subgraph.l3devices()))

        lab_topology.config_items = []
        for node in sorted(subgraph.l3devices()):
            for interface in node.physical_interfaces():
                broadcast_domain = str(interface.ipv4_subnet).replace("/", ".")
                #netkit lab.conf uses 1 instead of eth1
                numeric_id = interface.numeric_id
                stanza = ConfigStanza(
                    device=naming.network_hostname(node),
                    key=numeric_id,
                    value=broadcast_domain,
                )
                lab_topology.config_items.append(stanza)

        lab_topology.tap_ips = []
        for node in subgraph:
            if node.tap:
                stanza = ConfigStanza(
                    device=naming.network_hostname(node),
                    id=node.tap.id.replace("eth", ""),  # strip ethx -> x
                    ip=node.tap.ip,
                )
                lab_topology.tap_ips.append(stanza)

        lab_topology.tap_ips = sorted(lab_topology.tap_ips, key=lambda x: x.ip)
        lab_topology.config_items = sorted(lab_topology.config_items,
                                           key=lambda x: x.device)
Example #6
0
    def gre(self, node):
        node.gre_tunnels = []
        if not self.anm.has_overlay('gre_tunnel'):
            return

        g_gre_tunnel = self.anm['gre_tunnel']
        if node not in g_gre_tunnel:
            return   # no gre tunnel for node

        gre_node = g_gre_tunnel.node(node)
        neighbors = gre_node.neighbors()
        for index, neigh in enumerate(neighbors, start=1):
            stanza = ConfigStanza(id=index, endpoint=neigh)

            # TODO: try/except here
            # TODO: Explain logic here
            src_int = g_gre_tunnel.edge(node, neigh).src_int
            tunnel_source = node.interface(src_int).id
            stanza.source = tunnel_source
            stanza.destination = "0.0.0.0"  # placeholder for user to replace

            if neigh.tunnel_enabled_ipv4:
                ip_address = neigh.tunnel_ipv4_address
                cidr = neigh.tunnel_ipv4_cidr
                stanza.ipv4_address = ip_address
                stanza.ipv4_subnet = cidr
                stanza.use_ipv4 = True

            if neigh.tunnel_enabled_ipv6:
                cidr = neigh.tunnel_ipv6_cidr
                stanza.ipv4_subnet = cidr
                stanza.use_ipv6 = True

            node.gre_tunnels.append(stanza)
Example #7
0
    def isis(self, node):
        super(IosXrCompiler, self).isis(node)
        node.isis.isis_links = []

        for interface in node.physical_interfaces():
            if interface.exclude_igp:
                continue  # don't configure IGP for this interface

            # print interface.isis.dump()
            # copy across attributes from the IosBaseCompiler setting step

            isis_int = self.anm['isis'].interface(interface)
            if isis_int and isis_int.is_bound:
                data = {
                    'id': interface.id,
                    'metric': isis_int.metric,
                    'multipoint': isis_int.multipoint
                }
                if interface.isis.hello_padding_disable is not None:
                    data['hello_padding_disable'] = \
                        interface.isis.hello_padding_disable
                if interface.isis.mtu is not None:
                    data['mtu'] = interface.isis.hello_padding_disable

                # TODO: make stanza
                stanza = ConfigStanza(**data)
                node.isis.isis_links.append(stanza)
Example #8
0
    def vrf(self, node):
        g_vrf = self.anm['vrf']
        vrf_node = self.anm['vrf'].node(node)
        node.add_stanza("vrf")
        node.add_stanza("mpls")
        node.vrf.vrfs = []
        if vrf_node and vrf_node.vrf_role is 'PE':

            # TODO: check if mpls ldp already set elsewhere

            for vrf in vrf_node.node_vrf_names:
                route_target = g_vrf.data.route_targets[node.asn][vrf]
                rd_index = vrf_node.rd_indices[vrf]
                rd = '%s:%s' % (node.asn, rd_index)

                stanza = ConfigStanza(vrf=vrf,
                                      rd=rd,
                                      route_target=route_target)
                node.vrf.vrfs.append(stanza)

            for interface in node.interfaces:
                vrf_int = self.anm['vrf'].interface(interface)
                if vrf_int.vrf_name:
                    # mark interface as being part of vrf
                    interface.vrf = vrf_int.vrf_name
                    if interface.physical:
                        interface.description += ' vrf %s' \
                            % vrf_int.vrf_name

        if vrf_node and vrf_node.vrf_role in ('P', 'PE'):

            # Add PE -> P, PE -> PE interfaces to MPLS LDP

            node.mpls.ldp_interfaces = []
            for interface in node.physical_interfaces():
                mpls_ldp_int = self.anm['mpls_ldp'].interface(interface)
                if mpls_ldp_int.is_bound:
                    node.mpls.ldp_interfaces.append(interface.id)
                    interface.use_mpls = True

        if vrf_node and vrf_node.vrf_role is 'P':
            node.mpls.ldp_interfaces = []
            for interface in node.physical_interfaces():
                node.mpls.ldp_interfaces.append(interface.id)

        vrf_node = self.anm['vrf'].node(node)

        node.vrf.use_ipv4 = node.ip.use_ipv4
        node.vrf.use_ipv6 = node.ip.use_ipv6
        node.vrf.vrfs = sorted(node.vrf.vrfs, key=lambda x: x.vrf)

        if self.anm.has_overlay('mpls_ldp') and node \
                in self.anm['mpls_ldp']:
            node.mpls.enabled = True
            node.mpls.router_id = node.loopback_zero.id
Example #9
0
    def ospf(self, node):
        """Quagga ospf compiler"""

        super(QuaggaCompiler, self).ospf(node)

        # add eBGP link subnets

        node.ospf.passive_interfaces = []

        for interface in node.physical_interfaces():
            if interface.exclude_igp:
                continue  # don't configure IGP for this interface

            if self.anm.has_overlay('ebgp_v4'):
                bgp_int = self.anm['ebgp_v4'].interface(interface)
                if bgp_int.is_bound:  # ebgp interface
                    node.ospf.passive_interfaces.append(
                        ConfigStanza(id=interface.id))
                    subnet = bgp_int['ipv4'].subnet
                    default_ebgp_area = 0
                    node.ospf.ospf_links.append(
                        ConfigStanza(network=subnet, area=default_ebgp_area))
    def snmp(self, node):
        g_snmp = self.anm['snmp']
        snmp_node = g_snmp.node(node)
        snmp_stanza = node.add_stanza("snmp")
        if snmp_node.snmp is None:
            node.snmp.enabled = False
            return
        else:
            node.snmp.enabled = True

        if 'servers' in snmp_node.snmp:
            node.snmp.server = []
            for server in snmp_node.snmp['servers']:
                snmp_server_stanza = ConfigStanza(
                    ip=server['ip'],
                    version=server['version'],
                    udp_port=server['udp_port'],
                    community=server['community'])
                node.snmp.server.append(snmp_server_stanza)

        if 'users' in snmp_node.snmp:
            node.snmp.users = []
            for user_prof in snmp_node.snmp['users']:
                snmp_user_stanza = ConfigStanza(
                    user=user_prof['user'],
                    auth=user_prof['auth'],
                    pwd=user_prof['pwd'],
                    priv_passphrase=user_prof['priv_passphrase'],
                    engine_id=user_prof['engineID'])
                node.snmp.users.append(snmp_user_stanza)

        if 'traps' in snmp_node.snmp:
            node.snmp.traps = []
            for trap in snmp_node.snmp['traps']:
                snmp_trap_stanza = ConfigStanza(id=trap['id'],
                                                enabled=trap['enabled'])
                node.snmp.traps.append(snmp_trap_stanza)
Example #11
0
    def rip(self, node):
        super(IosXrCompiler, self).rip(node)

        g_rip = self.anm['rip']
        ipv4_interfaces = []

        for interface in node.physical_interfaces():
            if interface.exclude_igp:
                continue  # discontinue configuring IGP for this interface

            rip_int = g_rip.interface(interface)
            if rip_int and rip_int.is_bound:
                data = {'id': interface.id, 'passive': False}
                stanza = ConfigStanza(**data)
                if node.rip.use_ipv4:
                    ipv4_interfaces.append(stanza)

        loopback_zero = node.loopback_zero
        data = {'id': node.loopback_zero.id, 'passive': True}
        stanza = ConfigStanza(**data)
        if node.rip.use_ipv4:
            ipv4_interfaces.append(stanza)

        node.rip.ipv4_interfaces = ipv4_interfaces
Example #12
0
    def interfaces(self, node):
        phy_loopback_zero = self.anm['phy'].interface(node.loopback_zero)
        if node.ip.use_ipv4:
            ipv4_loopback_subnet = netaddr.IPNetwork('0.0.0.0/32')
            ipv4_loopback_zero = phy_loopback_zero['ipv4']
            ipv4_address = ipv4_loopback_zero.ip_address
            node.loopback_zero.use_ipv4 = True
            node.loopback_zero.ipv4_address = ipv4_address
            node.loopback_zero.ipv4_subnet = ipv4_loopback_subnet
            node.loopback_zero.ipv4_cidr = \
                sn_preflen_to_network(ipv4_address,
                                      ipv4_loopback_subnet.prefixlen)

        if node.ip.use_ipv6:
            # TODO: clean this up so can set on router_base: call cidr not
            # address and update templates
            node.loopback_zero.use_ipv6 = True
            ipv6_loopback_zero = phy_loopback_zero['ipv6']
            node.loopback_zero.ipv6_address = \
                sn_preflen_to_network(ipv6_loopback_zero.ip_address,
                                      128)

        super(IosBaseCompiler, self).interfaces(node)

        for interface in node.physical_interfaces():
            interface.use_cdp = node.use_cdp  # use node value

        for interface in node.interfaces:
            interface.sub_ints = []  # temporary until full subinterfaces

        for interface in node.physical_interfaces():
            g_ext_conn = self.anm['ext_conn']
            if node not in g_ext_conn:
                continue

            node_ext_conn = g_ext_conn.node(node)
            ext_int = node_ext_conn.interface(interface)
            for sub_int in ext_int.sub_int or []:
                stanza = ConfigStanza(
                    id=sub_int['id'],
                    ipv4_address=sub_int['ipv4_address'],
                    ipv4_prefixlen=sub_int['ipv4_prefixlen'],
                    ipv4_subnet=sub_int['ipv4_subnet'],
                    dot1q=sub_int['dot1q'],
                )
                interface.sub_ints.append(stanza)
Example #13
0
    def mpls_te(self, node):
        super(IosXrCompiler, self).mpls_te(node)

        g_mpls_te = self.anm['mpls_te']
        if node not in g_mpls_te:
            return  # no mpls te configured

        rsvp_interfaces = []
        mpls_te_interfaces = []
        mpls_te_node = g_mpls_te.node(node)

        for interface in mpls_te_node.physical_interfaces():
            nidb_interface = self.nidb.interface(interface)
            stanza = ConfigStanza(id=nidb_interface.id, bandwidth_percent=100)
            rsvp_interfaces.append(stanza)

            mpls_te_interfaces.append(nidb_interface.id)

        node.add_stanza("rsvp")
        node.rsvp.interfaces = rsvp_interfaces
        node.mpls.te_interfaces = mpls_te_interfaces
    def vxlan(self, node):

        g_input = self.anm['input']
        node_profiles = g_input.data['profiles']

        g_vxlan = self.anm['vxlan']
        vxlan_global_config = g_vxlan.data['vxlan_global_config']
        g_ipv4 = self.anm['ipv4']
        vxlan_node = g_vxlan.node(node)
        vxlan_stanza = node.add_stanza("vxlan")
        l2_vni_info = vxlan_global_config['vni_info']['l2_vni_info']
        l3_vni_info = vxlan_global_config['vni_info']['l3_vni_info']

        if 'ingress_replication' in vxlan_global_config and vxlan_global_config[
                'ingress_replication'] == True:
            node.vxlan.ingress_replication = True

        if vxlan_node.vxlan_vni_configured is not None:
            ### if vni is configured on this device then we can assume that it will be a VTEP device
            ### To be precise, a leaf for ACI architecture
            node.vxlan.vtep = True
            node.vxlan.vrf_vni_vlan = []
            node.vxlan.vlan_vni_l2 = []
            node.vxlan.vni_mcast = []
            node.vxlan.svi = []
            if 'anycast_gateway_mac' in vxlan_global_config and vxlan_global_config[
                    'anycast_gateway_mac'] is not None:
                node.vxlan.anycast_gateway_mac = vxlan_global_config[
                    'anycast_gateway_mac']
            for tenant in vxlan_node.vxlan_vni_configured:
                flag_first_time = True  ## we will use this flag to fetch tenant info only once
                l2_vnis_configured = tenant['vni']
                for l2_vni in l2_vnis_configured:
                    vlan = l2_vni_info[l2_vni][1]
                    vlan_vni_l2_stanza = ConfigStanza(vlan=vlan, vni=l2_vni)
                    node.vxlan.vlan_vni_l2.append(vlan_vni_l2_stanza)
                    mcast_group = l2_vni_info[l2_vni][2]
                    if mcast_group is not None:
                        vni_mcast_stanza = ConfigStanza(vni=l2_vni,
                                                        mcast_grp=mcast_group)
                        node.vxlan.vni_mcast.append(vni_mcast_stanza)

                    if flag_first_time == True:
                        flag_first_time = False
                        l3_vni_data = l3_vni_info[tenant['tenant_id']]
                        if l3_vni_data is not None:
                            l3_vni = l3_vni_data[0]
                            control_vlan = l3_vni_data[1]
                            vrf = l3_vni_data[2]
                            vrf_vni_vlan_stanza = ConfigStanza(
                                vrf_context=vrf, vni=l3_vni, vlan=control_vlan)
                            node.vxlan.vrf_vni_vlan.append(vrf_vni_vlan_stanza)

                    if l3_vni is not None:
                        anycast_address = l2_vni_info[l2_vni][0]
                        vlan_svi_stanza = ConfigStanza(
                            vlan=vlan,
                            vrf_context=vrf,
                            anycast_gateway_ip=anycast_address)

                        node.vxlan.svi.append(vlan_svi_stanza)

        else:
            ###otherwise it will be a non vtep node
            node.vxlan.nonvtep = True
            if 'route_reflectors' in vxlan_global_config and vxlan_global_config[
                    'route_reflectors'] is not None:
                for rr in vxlan_global_config['route_reflectors']:
                    if vxlan_node.id == rr:
                        node.vxlan.rr = True
                        break
            if 'rendezvous_point' in vxlan_global_config and vxlan_global_config[
                    'rendezvous_point'] is not None:
                node.vxlan.rp = []
                for rp in vxlan_global_config['rendezvous_point']:
                    rp_stanza = ConfigStanza(ip=rp['node_id'],
                                             mcastgrp=rp['mcast_group'])
                    node.vxlan.rp.append(rp_stanza)
Example #15
0
    def ospf(self, node):
        """Returns OSPF links, also sets process_id
        """

        g_ospf = self.anm['ospf']
        g_ipv4 = self.anm['ipv4']
        ospf_node = g_ospf.node(node)
        ospf_stanza = node.add_stanza("ospf")

        ospf_stanza.custom_config = ospf_node.custom_config

        # default, inherited enable if necessary
        node.ospf.ipv4_mpls_te = False

        node.ospf.loopback_area = g_ospf.node(node).area or 0

        node.ospf.process_id = ospf_node.process_id
        node.ospf.lo_interface = self.lo_interface

        node.ospf.ospf_links = []

        # aggregate by area
        from collections import defaultdict
        interfaces_by_area = defaultdict(list)

        for interface in node.physical_interfaces():
            if interface.exclude_igp:
                continue  # don't configure IGP for this interface

            ospf_int = g_ospf.interface(interface)
            if ospf_int and ospf_int.is_bound:
                area = ospf_int.area
                # TODO: can we remove the next line?
                area = str(area)  # can't serialize IPAddress object to JSON
                # TODO: put in interface rather than interface.id for
                # consistency
                try:
                    cost = int(ospf_int.cost)
                except TypeError:
                    #TODO: log warning here
                    cost = 1
                stanza = ConfigStanza(id=interface.id,
                                      cost=cost, passive=False)

                if node.ip.use_ipv4:
                    stanza.ipv4_address = ospf_int['ipv4'].ip_address
                    stanza.ipv4_subnet = ospf_int['ipv4'].subnet
                if node.ip.use_ipv6:
                    stanza.ipv6_address = ospf_int['ipv6'].ip_address
                    stanza.ipv6_subnet = ospf_int['ipv6'].subnet

                interfaces_by_area[area].append(stanza)

        loopback_zero = node.loopback_zero
        ospf_loopback_zero = g_ospf.interface(loopback_zero)
        router_area = ospf_loopback_zero.area  # area assigned to router
        # can't serialize IPAddress object to JSON
        router_area = str(router_area)
        stanza = ConfigStanza(id=node.loopback_zero.id,
                              cost=0, passive=True)
        interfaces_by_area[router_area].append(stanza)

        node.ospf.interfaces_by_area = ConfigStanza(**interfaces_by_area)

        # TODO: split this into a generic IGP function
        added_networks = set()
        for interface in node.physical_interfaces():
            if interface.exclude_igp:
                continue  # don't configure IGP for this interface
            if not interface.use_ipv4:
                continue
            ipv4_int = g_ipv4.interface(interface)
            ospf_int = g_ospf.interface(interface)
            if not ospf_int.is_bound:
                continue  # not an OSPF interface
            try:
                ospf_cost = int(ospf_int.cost)
            except TypeError:
                try:
                    ospf_cost = netaddr.IPAddress(ospf_int.cost)
                except (TypeError, netaddr.AddrFormatError):
                    log.debug('Using default OSPF cost of 1 for %s on %s',
                              ospf_int, node)
                    ospf_cost = 1  # default
            interface.ospf_cost = ospf_cost
            network = ipv4_int.subnet

            #TODO: refactor to allow injecting loopback IPs, etc into IGP
            if ospf_int and ospf_int.is_bound and network \
                    not in added_networks:  # don't add more than once
                added_networks.add(network)
                link_stanza = ConfigStanza(
                    network=network, interface=interface, area=ospf_int.area)
                node.ospf.ospf_links.append(link_stanza)

        for interface in node.loopback_interfaces():
            phy_int = self.anm['phy'].interface(interface)
            ipv4_int = g_ipv4.interface(interface)
            if not phy_int.inject_to_igp:
                #TODO: need to confirm which area to use
                continue

            network = ipv4_int.subnet
            if network in added_networks:
                #TODO: may want to warn here
                continue # already advertised ("how? - warn if so!)

            # Use the same area as Loopback Zero
            area = node.ospf.loopback_area

            if not network:
                log.info("Not injecting unset network on loopback %s "
                    "to IGP", interface)
                continue

            link_stanza = ConfigStanza(
             network=network, interface=interface, area=area)
            node.ospf.ospf_links.append(link_stanza)
    def bgp(self, node):
        phy_node = self.anm['phy'].node(node)
        g_ipv4 = self.anm['ipv4']
        if node.ip.use_ipv6:
            g_ipv6 = self.anm['ipv6']
        asn = phy_node.asn
        node.asn = asn
        bgp_stanza = node.add_stanza("bgp")
        if self.anm.has_overlay("bgp"):
            bgp_stanza.custom_config = phy_node['bgp'].custom_config
        else:
            bgp_stanza.custom_config = ""

        node.bgp.ipv4_advertise_subnets = []
        if node.ip.use_ipv4:
            node.bgp.ipv4_advertise_subnets = \
                g_ipv4.data.infra_blocks.get(
                    asn) or []  # could be none (one-node AS) default empty list
        node.bgp.ipv6_advertise_subnets = []
        if node.ip.use_ipv6:
            g_ipv6 = self.anm['ipv6']
            node.bgp.ipv6_advertise_subnets = \
                g_ipv6.data.infra_blocks.get(asn) or []

        ibgp_neighbors = []
        ibgp_rr_clients = []
        ibgp_rr_parents = []

        g_ibgp_v4 = self.anm['ibgp_v4']
        bgp_node = g_ibgp_v4.node(node)

        if bgp_node.route_reflector == True:
            node.bgp.route_reflector = True

        for session in sort_sessions(g_ibgp_v4.edges(phy_node)):
            if session.exclude:
                log.debug('Skipping excluded ibgp session %s', session)
                # exclude from regular ibgp config (eg VRF, VPLS, etc)
                continue

            data = self.ibgp_session_data(session, ip_version=4)
            bgp_stanza = ConfigStanza(**data)

            direction = session.direction
            if direction == 'down':
                ibgp_rr_clients.append(bgp_stanza)
            elif direction == 'up':
                ibgp_rr_parents.append(bgp_stanza)
            else:
                ibgp_neighbors.append(bgp_stanza)

        # TODO: check v6 hierarchy only created if node set to being v4 or v6

        if node.ip.use_ipv6:
            g_ibgp_v6 = self.anm['ibgp_v6']
            for session in sort_sessions(g_ibgp_v6.edges(phy_node)):
                if session.exclude:
                    log.debug('Skipping excluded ibgp session %s', session)
                    # exclude from regular ibgp config (eg VRF, VPLS, etc)
                    continue
                data = self.ibgp_session_data(session, ip_version=6)
                bgp_stanza = ConfigStanza(**data)

                direction = session.direction
                if direction == 'down':
                    ibgp_rr_clients.append(bgp_stanza)
                elif direction == 'up':
                    ibgp_rr_parents.append(bgp_stanza)
                else:
                    ibgp_neighbors.append(bgp_stanza)

        # TODO: update this to use ibgp_v4 and ibgp_v6 overlays

        node.bgp.ibgp_neighbors = ibgp_neighbors
        node.bgp.ibgp_rr_clients = ibgp_rr_clients
        node.bgp.ibgp_rr_parents = ibgp_rr_parents

        # ebgp

        ebgp_neighbors = []
        g_ebgp_v4 = self.anm['ebgp_v4']
        for session in sort_sessions(g_ebgp_v4.edges(phy_node)):
            if session.exclude:
                log.debug('Skipping excluded ebgp session %s', session)
                # exclude from regular ibgp config (eg VRF, VPLS, etc)
                continue
            data = self.ebgp_session_data(session, ip_version=4)
            bgp_stanza = ConfigStanza(**data)
            ebgp_neighbors.append(bgp_stanza)

        if node.ip.use_ipv6:
            g_ebgp_v6 = self.anm['ebgp_v6']
            for session in sort_sessions(g_ebgp_v6.edges(phy_node)):
                if session.exclude:
                    log.debug('Skipping excluded ebgp session %s', session)
                    # exclude from regular ibgp config (eg VRF, VPLS, etc)
                    continue
                data = self.ebgp_session_data(session, ip_version=6)
                bgp_stanza = ConfigStanza(**data)
                ebgp_neighbors.append(bgp_stanza)

        ebgp_neighbors = sorted(ebgp_neighbors, key=lambda x: x.asn)
        node.bgp.ebgp_neighbors = ebgp_neighbors

        return
Example #17
0
    def static_routes(self, node):
        node.static_routes_v4 = [
        ]  # initialise for case of no routes -> simplifies template logic
        node.host_routes_v4 = [
        ]  # initialise for case of no routes -> simplifies template logic
        node.static_routes_v6 = [
        ]  # initialise for case of no routes -> simplifies template logic
        node.host_routes_v6 = [
        ]  # initialise for case of no routes -> simplifies template logic
        if not self.anm['phy'].data.enable_routing:
            log.info(
                'Routing disabled, not configuring static routes for Ubuntu server %s'
                % node)
            return

        if self.anm['phy'].node(node).dont_configure_static_routing:
            log.info('Static routing disabled for server %s' % node)
            return

        l3_node = self.anm['layer3'].node(node)
        gateway_list = [n for n in l3_node.neighbors() if n.is_router()]
        if not len(gateway_list):
            log.warning('Server %s is not directly connected to any routers' %
                        node)
            return
        elif len(gateway_list) > 1:
            log.info('Server %s is multi-homed: using gateways %s' %
                     (node, sorted(gateway_list)))

        # TODO: warn if server has no neighbors in same ASN (either in design or verification steps)
        # TODO: need to check that servers don't have any direct ebgp connections

        cloud_init_static_routes = []

        for gateway in sorted(gateway_list):
            gateway_edge_l3 = self.anm['layer3'].edge(node, gateway)
            server_interface = gateway_edge_l3.src_int
            server_interface_id = self.nidb.interface(server_interface).id

            gateway_interface = gateway_edge_l3.dst_int

            gateway_ipv4 = gateway_ipv6 = None
            node.add_stanza("ip")
            if node.ip.use_ipv4:
                gateway_ipv4 = gateway_interface['ipv4'].ip_address
            if node.ip.use_ipv6:
                gateway_ipv6 = gateway_interface['ipv6'].ip_address

            # TODO: look at aggregation
            # TODO: catch case of ip addressing being disabled

            # TODO: handle both ipv4 and ipv6

            # IGP advertised infrastructure pool from same AS
            static_routes_v4 = []
            host_routes_v4 = []
            for (asn,
                 asn_routes) in self.anm['ipv4'].data['infra_blocks'].items():

                # host_routes_v4
                for infra_route in asn_routes:
                    route_entry = {
                    'network': infra_route,
                    'prefix': infra_route.network,
                    'gw': gateway_ipv4,
                    'interface': server_interface_id,
                    'description': 'Route to infra subnet in AS %s via %s' \
                    % (asn, gateway),
                    }
                    route_entry = ConfigStanza(**route_entry)
                    if infra_route.prefixlen == 32:
                        host_routes_v4.append(route_entry)
                    else:
                        static_routes_v4.append(route_entry)

            # eBGP advertised loopbacks in all (same + other) ASes

            for (asn, asn_routes
                 ) in self.anm['ipv4'].data['loopback_blocks'].items():
                for asn_route in asn_routes:
                    route_entry = {
                        'network': asn_route,
                        'prefix': asn_route.network,
                        'gw': gateway_ipv4,
                        'interface': server_interface_id,
                        'description': 'Route to loopback subnet in AS %s via %s' \
                            % (asn, gateway),
                        }
                    route_entry = ConfigStanza(**route_entry)
                    if asn_route.prefixlen == 32:
                        host_routes_v4.append(route_entry)
                    else:
                        static_routes_v4.append(route_entry)

            # TODO: combine the above logic into single step rather than creating dict then formatting with it

            for entry in static_routes_v4:
                formatted = 'route add -net %s gw %s dev %s' \
                    % (entry.network, entry.gw, entry.interface)
                cloud_init_static_routes.append(formatted)
            for entry in host_routes_v4:
                formatted = 'route add -host %s gw %s dev %s' \
                    % (entry.prefix, entry.gw, entry.interface)
                cloud_init_static_routes.append(formatted)

        node.add_stanza("cloud_init")
        node.cloud_init.static_routes = cloud_init_static_routes
Example #18
0
    def bgp(self, node):
        super(IosClassicCompiler, self).bgp(node)

        node.bgp.use_ipv4 = node.ip.use_ipv4
        node.bgp.use_ipv6 = node.ip.use_ipv6

        # Seperate by address family

        ipv4_peers = []
        ipv6_peers = []

        # Note cast to dict - #TODO revisit this requirement
        # TODO: revisit and tidy up the logic here: split iBGP and eBGP
        # TODO: sort the peer list by peer IP

        for peer in node.bgp.ibgp_neighbors:
            peer = ConfigStanza(peer)
            peer.remote_ip = peer.loopback
            if peer.use_ipv4:
                if node.is_ebgp_v4:
                    peer.next_hop_self = True
                ipv4_peers.append(peer)
            if peer.use_ipv6:
                if node.is_ebgp_v6:
                    peer.next_hop_self = True
                ipv6_peers.append(peer)

        for peer in node.bgp.ibgp_rr_parents:
            peer = ConfigStanza(peer)
            peer.remote_ip = peer.loopback
            if peer.use_ipv4:
                if node.is_ebgp_v4:
                    peer.next_hop_self = True
                ipv4_peers.append(peer)
            if peer.use_ipv6:
                if node.is_ebgp_v6:
                    peer.next_hop_self = True
                ipv6_peers.append(peer)

        for peer in node.bgp.ibgp_rr_clients:
            peer = ConfigStanza(peer)
            peer.rr_client = True
            peer.remote_ip = peer.loopback
            if peer.use_ipv4:
                if node.is_ebgp_v4:
                    peer.next_hop_self = True
                ipv4_peers.append(peer)
            if peer.use_ipv6:
                if node.is_ebgp_v6:
                    peer.next_hop_self = True
                ipv6_peers.append(peer)

        for peer in node.bgp.ebgp_neighbors:
            peer = ConfigStanza(peer)
            peer.is_ebgp = True
            peer.remote_ip = peer.dst_int_ip
            if peer.use_ipv4:
                peer.next_hop_self = True
                ipv4_peers.append(peer)
            if peer.use_ipv6:
                peer.next_hop_self = True
                ipv6_peers.append(peer)

        node.bgp.ipv4_peers = ipv4_peers
        node.bgp.ipv6_peers = ipv6_peers

        vpnv4_neighbors = []
        if node.bgp.vpnv4:
            for neigh in node.bgp.ibgp_neighbors:
                if not neigh.use_ipv4:
                    continue

                neigh_data = ConfigStanza(neigh)
                vpnv4_neighbors.append(neigh_data)

            for neigh in node.bgp.ibgp_rr_clients:
                if not neigh.use_ipv4:
                    continue
                neigh_data = ConfigStanza(neigh)
                neigh_data.rr_client = True
                vpnv4_neighbors.append(neigh_data)

            for neigh in node.bgp.ibgp_rr_parents:
                if not neigh.use_ipv4:
                    continue
                neigh_data = ConfigStanza(neigh)
                vpnv4_neighbors.append(neigh_data)

        vpnv4_neighbors = sorted(vpnv4_neighbors, key=lambda x: x['loopback'])
        node.bgp.vpnv4_neighbors = vpnv4_neighbors
    def ospf(self, node):
        """Returns OSPF links, also sets process_id
        """

        g_ospf = self.anm['ospf']
        g_ipv4 = self.anm['ipv4']
        ospf_node = g_ospf.node(node)
        ospf_stanza = node.add_stanza("ospf")

        ospf_stanza.custom_config = ospf_node.custom_config

        # default, inherited enable if necessary
        node.ospf.ipv4_mpls_te = False

        node.ospf.loopback_area = g_ospf.node(node).area or 0
        node.ospf.process_id = ospf_node.process_id
        node.ospf.lo_interface = self.lo_interface

        node.ospf.ospf_links = []

        # aggregate by area
        from collections import defaultdict
        interfaces_by_area = defaultdict(list)
        for interface in node.physical_interfaces():
            if interface.exclude_igp:
                continue  # don't configure IGP for this interface

            ospf_int = g_ospf.interface(interface)
            if ospf_int and ospf_int.is_bound:
                area = ospf_int.area
                # TODO: can we remove the next line?
                area = str(area)  # can't serialize IPAddress object to JSON
                # TODO: put in interface rather than interface.id for
                # consistency
                try:
                    cost = int(ospf_int.cost)
                except TypeError:
                    #TODO: log warning here
                    cost = 1
                stanza = ConfigStanza(id=interface.id,
                                      cost=cost,
                                      passive=False)

                if node.ip.use_ipv4:
                    stanza.ipv4_address = ospf_int['ipv4'].ip_address
                    stanza.ipv4_subnet = ospf_int['ipv4'].subnet
                if node.ip.use_ipv6:
                    stanza.ipv6_address = ospf_int['ipv6'].ip_address
                    stanza.ipv6_subnet = ospf_int['ipv6'].subnet

                interfaces_by_area[area].append(stanza)

        for interface in node.portchannel_interfaces():
            if interface.exclude_igp:
                continue  # don't configure IGP for this interface

            ospf_int = g_ospf.interface(interface)
            if ospf_int and ospf_int.is_bound:
                area = ospf_int.area
                # TODO: can we remove the next line?
                area = str(area)  # can't serialize IPAddress object to JSON
                # TODO: put in interface rather than interface.id for
                # consistency
                try:
                    cost = int(ospf_int.cost)
                except TypeError:
                    #TODO: log warning here
                    cost = 1
                stanza = ConfigStanza(id=interface.id,
                                      cost=cost,
                                      passive=False)

                if node.ip.use_ipv4:
                    stanza.ipv4_address = ospf_int['ipv4'].ip_address
                    stanza.ipv4_subnet = ospf_int['ipv4'].subnet
                if node.ip.use_ipv6:
                    stanza.ipv6_address = ospf_int['ipv6'].ip_address
                    stanza.ipv6_subnet = ospf_int['ipv6'].subnet

                interfaces_by_area[area].append(stanza)

        loopback_zero = node.loopback_zero
        ospf_loopback_zero = g_ospf.interface(loopback_zero)
        router_area = ospf_loopback_zero.area  # area assigned to router
        # can't serialize IPAddress object to JSON
        router_area = str(router_area)
        stanza = ConfigStanza(id=node.loopback_zero.id, cost=0, passive=True)
        interfaces_by_area[router_area].append(stanza)

        node.ospf.interfaces_by_area = ConfigStanza(**interfaces_by_area)

        # TODO: split this into a generic IGP function
        added_networks = set()
        for interface in node.physical_interfaces():
            if interface.exclude_igp:
                continue  # don't configure IGP for this interface
            if not interface.use_ipv4:
                continue
            ipv4_int = g_ipv4.interface(interface)
            ospf_int = g_ospf.interface(interface)
            if not ospf_int.is_bound:
                continue  # not an OSPF interface
            try:
                ospf_cost = int(ospf_int.cost)
            except TypeError:
                try:
                    ospf_cost = netaddr.IPAddress(ospf_int.cost)
                except (TypeError, netaddr.AddrFormatError):
                    log.debug('Using default OSPF cost of 1 for %s on %s',
                              ospf_int, node)
                    ospf_cost = 1  # default
            interface.ospf_cost = ospf_cost
            network = ipv4_int.subnet

            #TODO: refactor to allow injecting loopback IPs, etc into IGP
            if ospf_int and ospf_int.is_bound and network \
                    not in added_networks:  # don't add more than once
                added_networks.add(network)
                link_stanza = ConfigStanza(network=network,
                                           interface=interface,
                                           area=ospf_int.area)
                node.ospf.ospf_links.append(link_stanza)

        for interface in node.portchannel_interfaces():
            if interface.exclude_igp:
                continue  # don't configure IGP for this interface
            if not interface.use_ipv4:
                continue
            ipv4_int = g_ipv4.interface(interface)
            ospf_int = g_ospf.interface(interface)
            if not ospf_int.is_bound:
                continue  # not an OSPF interface
            try:
                ospf_cost = int(ospf_int.cost)
            except TypeError:
                try:
                    ospf_cost = netaddr.IPAddress(ospf_int.cost)
                except (TypeError, netaddr.AddrFormatError):
                    log.debug('Using default OSPF cost of 1 for %s on %s',
                              ospf_int, node)
                    ospf_cost = 1  # default
            interface.ospf_cost = ospf_cost
            network = ipv4_int.subnet

            #TODO: refactor to allow injecting loopback IPs, etc into IGP
            if ospf_int and ospf_int.is_bound and network \
                    not in added_networks:  # don't add more than once
                added_networks.add(network)
                link_stanza = ConfigStanza(network=network,
                                           interface=interface,
                                           area=ospf_int.area)
                node.ospf.ospf_links.append(link_stanza)

        for interface in node.loopback_interfaces():
            phy_int = self.anm['phy'].interface(interface)
            ipv4_int = g_ipv4.interface(interface)
            if not phy_int.inject_to_igp:
                #TODO: need to confirm which area to use
                continue

            network = ipv4_int.subnet
            if network in added_networks:
                #TODO: may want to warn here
                continue  # already advertised ("how? - warn if so!)

            # Use the same area as Loopback Zero
            area = node.ospf.loopback_area

            if not network:
                log.info(
                    "Not injecting unset network on loopback %s "
                    "to IGP", interface)
                continue

            link_stanza = ConfigStanza(network=network,
                                       interface=interface,
                                       area=area)
            node.ospf.ospf_links.append(link_stanza)
Example #20
0
    def l2tp_v3(self, node):
        node.l2tp_classes = []
        node.pseudowire_classes = []
        if not self.anm.has_overlay('l2tp_v3'):
            return

        g_l2tp_v3 = self.anm['l2tp_v3']
        g_phy = self.anm['phy']
        if node not in g_l2tp_v3:
            return  # no l2tp_v3 for node

        l2tp_v3_node = g_l2tp_v3.node(node)
        if l2tp_v3_node.role != "tunnel":
            return  # nothing to configure

        node.l2tp_classes = list(l2tp_v3_node.l2tp_classes)
        for l2tp_class in l2tp_v3_node.l2tp_classes:
            node.l2tp_classes

        node.pseudowire_classes = []
        for pwc in l2tp_v3_node.pseudowire_classes:
            stanza = ConfigStanza()
            stanza.name = pwc['name']
            stanza.encapsulation = pwc['encapsulation']
            stanza.protocol = pwc['protocol']
            stanza.l2tp_class_name = pwc['l2tp_class_name']
            local_interface = pwc['local_interface']

            # Lookup the interface ID allocated for this loopback by compiler
            local_interface_id = node.interface(local_interface).id
            stanza.local_interface = local_interface_id

            node.pseudowire_classes.append(stanza)

        for interface in node.physical_interfaces():
            phy_int = g_phy.interface(interface)
            if phy_int.xconnect_encapsulation != "l2tpv3":
                continue  # no l2tpv3 encap, no need to do anything

            tunnel_int = l2tp_v3_node.interface(interface)
            stanza = ConfigStanza()
            stanza.remote_ip = tunnel_int.xconnect_remote_ip
            stanza.vc_id = tunnel_int.xconnect_vc_id
            stanza.encapsulation = "l2tpv3"
            #TODO: need to be conscious of support for other xconnect types
            # in templates since pw_class may not apply if not l2tpv3, et
            stanza.pw_class = tunnel_int.xconnect_pw_class

            interface.xconnect = stanza
Example #21
0
    def compile_devices(self):
        import re
        g_phy = self.anm['phy']

        to_memory, use_mgmt_interfaces, dst_folder = self._parameters()

        if use_mgmt_interfaces:
            log.debug("Allocating VIRL management interfaces")
        else:
            log.debug("Not allocating VIRL management interfaces")

	pc_only_config = False
        vxlan_global_config = None
        if g_phy.data.vxlan_global_config is not None:
            vxlan_global_config = g_phy.data.vxlan_global_config
        if g_phy.data.pc_only is not None:
            pc_only_config = g_phy.data.pc_only
        use_ignite_pool = False
        if g_phy.data.mgmt_block is not None:
            mgmt_address_block = netaddr.IPNetwork(g_phy.data.mgmt_block).iter_hosts()
            mgmt_address_mask = (netaddr.IPNetwork(g_phy.data.mgmt_block)).netmask
        else:
            pool = g_phy.data.ignite
            if pool is not None:
                if 'mgmt_pool_id' in pool and pool['mgmt_pool_id'] is not None:
                    mgmt_pool_id = pool['mgmt_pool_id']
                    use_ignite_pool = True

        if g_phy.data.vpcid_block is not None:
            vpc_re = "([0-9]+)(-)([0-9]+)"
            #vpc_id_start = int(re.search(vpc_re, g_phy.data.vpcid_block).group(1))
            #vpc_id_end = int(re.search(vpc_re, g_phy.data.vpcid_block).group(3))
            #vpc_id_range = vpc_id_end-vpc_id_start

        vpc_id_range = 1000
# TODO: need to copy across the interface name from edge to the interface

# TODO: merge common router code, so end up with three loops: routers, ios
# routers, ios_xr routers

    # TODO: Split out each device compiler into own function

    # TODO: look for unused code paths here - especially for interface
    # allocation

        # store autonetkit_cisco version
        log.debug("Generating device configurations")
        from pkg_resources import get_distribution

        # Copy across indices for external connectors (e.g may want to copy
        # configs)
        external_connectors = [n for n in g_phy
                               if n.host == self.host and n.device_type == "external_connector"]
        for phy_node in external_connectors:
            DmNode = self.nidb.node(phy_node)
            DmNode.indices = phy_node.indices

        g_input = self.anm['input']

        managed_switches = [n for n in g_phy.switches()
        if n.host == self.host
        and n.device_subtype == "managed"]
        for phy_node in managed_switches:
            DmNode = self.nidb.node(phy_node)
            DmNode.indices = phy_node.indices

        for phy_node in g_phy.l3devices(host=self.host):
            loopback_ids = self.loopback_interface_ids()
            # allocate loopbacks to routes (same for all ios variants)
            DmNode = self.nidb.node(phy_node)
            DmNode.add_stanza("render")
            DmNode.indices = phy_node.indices


            DmNode.add_stanza("syslog")
            DmNode.add_stanza('mgmt')
            if use_ignite_pool == True:
                mgmt_ip = allocate_pool_entry(mgmt_pool_id,phy_node.name, None)
                pos_mask = mgmt_ip.find('/')
                if pos_mask != -1:
                    network = mgmt_ip[:pos_mask]
                    mask = int(mgmt_ip[pos_mask+1:])
                else:
                    network = mgmt_ip[:pos_mask]
                    mask = 32
                DmNode.mgmt.ip = network +  '/' + str(mask)
                DmNode.mgmt.mask = ""
            elif g_phy.data.mgmt_block is not None:
                DmNode.mgmt.ip = mgmt_address_block.next()
                DmNode.mgmt.mask = mgmt_address_mask

#           for node_data in phy_node._graph.node:

            for interface in DmNode.loopback_interfaces():
                if interface != DmNode.loopback_zero:
                    interface.id = loopback_ids.next()

            # numeric ids
            numeric_int_ids = self.numeric_interface_ids()
            for interface in DmNode.physical_interfaces():
                phy_numeric_id = phy_node.interface(interface).numeric_id
                if phy_numeric_id is None:
                    # TODO: remove numeric ID code
                    interface.numeric_id = numeric_int_ids.next()
                else:
                    interface.numeric_id = int(phy_numeric_id)

                phy_specified_id = phy_node.interface(interface).specified_id
                if phy_specified_id is not None:
                    interface.id = phy_specified_id


            # numeric ids
            numeric_po_ids = self.numeric_portchannel_ids()
            for interface in DmNode.portchannel_interfaces():
                po_interface = phy_node.interface(interface)
                interface.numeric_id =  int(po_interface.id[po_interface.id.rfind('_')+1:])

                po_specified_id = phy_node.interface(interface).specified_id
                if po_specified_id is not None:
                    interface.id = po_specified_id
                interface.pc = True
                for po_mem_int in DmNode.physical_interfaces():
                    po_mem_interface = phy_node.interface(po_mem_int)
                    if po_mem_interface.id in po_interface.members:
                        po_mem_int.channel_group = interface.numeric_id
                        po_interface_int = po_interface._interface
                        if po_interface_int.has_key('subcat_prot'):
                            if po_interface.subcat_prot == "vpc":
                                po_mem_int.keepalive_port_vpc = True# is a member port of VPC peer link
                                interface.virt_port_channel = True# is a VPC interface
                                DmNode.add_stanza('vpc')
                            if po_interface.subcat_prot == "vpc-member":
                                po_mem_int.member_port_vpc = True
                                interface.vpc_member_id = interface.numeric_id 
                                interface.member_vpc = True

        ##adding rp's
        if vxlan_global_config is not None and 'rendezvous_point' in vxlan_global_config:
            for rp in vxlan_global_config['rendezvous_point']:
                for phy_node in g_phy.l3devices(host=self.host):
                    DmNode = self.nidb.node(phy_node)
                    if phy_node.id == rp['node_id']:
                        rp['node_id'] = DmNode.interfaces[0]._port['ipv4_address']

            #from autonetkit.compilers.device.ubuntu import UbuntuCompiler
        #from autonetkit_cisco.compilers.device.ubuntu import UbuntuCompiler

        #ubuntu_compiler = UbuntuCompiler(self.nidb, self.anm)
        for phy_node in g_phy.servers(host=self.host):
            DmNode = self.nidb.node(phy_node)
            DmNode.add_stanza("render")
            DmNode.add_stanza("ip")

            #interface.id = self.numeric_to_interface_label_linux(interface.numeric_id)
            # print "numeric", interface.numeric_id, interface.id
            DmNode.ip.use_ipv4 = phy_node.use_ipv4
            DmNode.ip.use_ipv6 = phy_node.use_ipv6

            # TODO: clean up interface handling
            numeric_int_ids = self.numeric_interface_ids()
            for interface in DmNode.physical_interfaces():
                phy_numeric_id = phy_node.interface(interface).numeric_id
                if phy_numeric_id is None:
                    # TODO: remove numeric ID code
                    interface.numeric_id = numeric_int_ids.next()
                else:
                    interface.numeric_id = int(phy_numeric_id)

                phy_specified_id = phy_node.interface(interface).specified_id
                if phy_specified_id is not None:
                    interface.id = phy_specified_id

            # numeric ids
            numeric_po_ids = self.numeric_portchannel_ids()
            for interface in DmNode.portchannel_interfaces():
                phy_numeric_id = phy_node.interface(interface).numeric_id
                if phy_numeric_id is None:
                    # TODO: remove numeric ID code
                    interface.numeric_id = numeric_po_ids.next()
                else:
                    interface.numeric_id = int(phy_numeric_id)

                phy_specified_id = phy_node.interface(interface).specified_id
                if phy_specified_id is not None:
                    interface.id = phy_specified_id

                # TODO: make this part of the base device compiler, which
                # server/router inherits

            # not these are physical interfaces; configure after previous
            # config steps
            if use_mgmt_interfaces:
                mgmt_int = DmNode.add_interface(
                    management=True, description="eth0")
                mgmt_int_id = "eth0"
                mgmt_int.id = mgmt_int_id

                # render route config
            DmNode = self.nidb.node(phy_node)
            #ubuntu_compiler.compile(DmNode)

            if not phy_node.dont_configure_static_routing:
                DmNode.render.template = os.path.join(
                    "templates", "linux", "static_route.mako")
                if to_memory:
                    DmNode.render.to_memory = True
                else:
                    DmNode.render.dst_folder = dst_folder
                    DmNode.render.dst_file = "%s.conf" % naming.network_hostname(
                        phy_node)

        # TODO: refactor out common logic

        ios_compiler = IosClassicCompiler(self.nidb, self.anm)
        host_routers = g_phy.routers(host=self.host)
        ios_nodes = (n for n in host_routers if n.syntax in ("ios", "ios_xe"))
        for phy_node in ios_nodes:
            if (phy_node.devsubtype == "core" or phy_node.devsubtype == "border"):
                continue
            DmNode = self.nidb.node(phy_node)
            DmNode.add_stanza("render")

            DmNode.render.template = os.path.join("templates", "ios.mako")
            to_memory = False

            if to_memory:
                DmNode.render.to_memory = True
            else:
                DmNode.render.dst_folder = dst_folder
                DmNode.render.dst_file = "%s.conf" % naming.network_hostname(
                    phy_node)

            # TODO: write function that assigns interface number excluding
            # those already taken

            # Assign interfaces
            if phy_node.device_subtype == "IOSv":
                int_ids = self.interface_ids_ios()
                numeric_to_interface_label = self.numeric_to_interface_label_ios
            elif phy_node.device_subtype == "CSR1000v":
                int_ids = self.interface_ids_csr1000v()
                numeric_to_interface_label = self.numeric_to_interface_label_ra
            else:
                # default if no subtype specified
                # TODO: need to set default in the load module
                log.warning("Unexpected subtype %s for %s" %
                            (phy_node.device_subtype, phy_node))
                int_ids = self.interface_ids_ios()
                numeric_to_interface_label = self.numeric_to_interface_label_ios
                numeric_to_portchannel_interface_label = self.numeric_to_portchannel_interface_label_ios

            if use_mgmt_interfaces:
                if phy_node.device_subtype == "IOSv":
                    # TODO: make these configured in the internal config file
                    # for platform/device_subtype keying
                    mgmt_int_id = "GigabitEthernet0/0"
                if phy_node.device_subtype == "CSR1000v":
                    mgmt_int_id = "GigabitEthernet1"

            for interface in DmNode.physical_interfaces():
                # TODO: use this code block once for all routers
                if not interface.id:
                    interface.id = numeric_to_interface_label(
                        interface.numeric_id)
                else:
                    if interface.id[0] == 'e' or interface.id[0] == 'E':
                        #import re
                        port_re = "([a-zA-Z]+)([0-9]+/[0-9]+)"
                        interface.id = "%s %s"%((re.search(port_re,interface.id)).group(1),
                                                (re.search(port_re,interface.id)).group(2))

            for interface in DmNode.portchannel_interfaces():
                # TODO: use this code block once for all routers
                #if not interface.id:
                interface.id = numeric_to_portchannel_interface_label(
                        interface.numeric_id)

            ios_compiler.compile(DmNode)
            if use_mgmt_interfaces:
                mgmt_int = DmNode.add_interface(management=True)
                mgmt_int.id = mgmt_int_id

        nxos_compiler = NxOsCompiler(self.nidb, self.anm)
        for phy_node in g_phy.routers(host=self.host, syntax='nx_os'):
            if (phy_node.devsubtype == "core" or phy_node.devsubtype == "border"):
                continue
            DmNode = self.nidb.node(phy_node)
            DmNode.add_stanza("render")
            if pc_only_config == True:
                DmNode.render.template = os.path.join("templates", "nexus_os_pc_only.mako")
	    else:
                DmNode.render.template = os.path.join("templates", "nexus_os.mako")
            #if to_memory:
            #    DmNode.render.to_memory = True
            #else:
            DmNode.render.dst_folder = dst_folder
            DmNode.render.dst_file = "%s.conf" % phy_node.name

            # Assign interfaces
            int_ids = self.interface_ids_nxos()
            numeric_to_interface_label = self.numeric_to_interface_label_nxos
            numeric_to_portchannel_interface_label = self.numeric_to_portchannel_interface_label_nxos
            for interface in DmNode.physical_interfaces():
                if not interface.id:
                    interface.id = self.numeric_to_interface_label_nxos(
                        interface.numeric_id)
                elif interface.id[0] == 'e' or interface.id[0] == 'E':
                    import re
                    port_re = "([a-zA-Z]+)([0-9]+/[0-9]+)"
                    interface.id = "%s %s"%((re.search(port_re,interface.id)).group(1),
                                            (re.search(port_re,interface.id)).group(2))
                else:
                    interface.id = 'Ethernet ' + interface.id


            for interface in DmNode.portchannel_interfaces():
                # TODO: use this code block once for all routers
                #if not interface.id:
                interface.id = numeric_to_portchannel_interface_label(
                        interface.numeric_id)

            DmNode.supported_features = ConfigStanza(
                mpls_te=False, mpls_oam=False, vrf=False)

            nxos_compiler.compile(DmNode)
            # TODO: make this work other way around

            if use_mgmt_interfaces:
                mgmt_int_id = "mgmt0"
                mgmt_int = DmNode.add_interface(management=True)
                mgmt_int.id = mgmt_int_id

        staros_compiler = StarOsCompiler(self.nidb, self.anm)
        for phy_node in g_phy.routers(host=self.host, syntax='StarOS'):
            DmNode = self.nidb.node(phy_node)
            DmNode.add_stanza("render")
            DmNode.render.template = os.path.join("templates", "staros.mako")
            if to_memory:
                DmNode.render.to_memory = True
            else:
                DmNode.render.dst_folder = dst_folder
                DmNode.render.dst_file = "%s.conf" % naming.network_hostname(
                    phy_node)

            # Assign interfaces
            int_ids = self.interface_ids_nxos()
            for interface in DmNode.physical_interfaces():
                if not interface.id:
                    interface.id = self.numeric_to_interface_label_star_os(
                        interface.numeric_id)

            staros_compiler.compile(DmNode)
            # TODO: make this work other way around

            if use_mgmt_interfaces:
                mgmt_int_id = "ethernet 1/1"
                mgmt_int = DmNode.add_interface(management=True)
                mgmt_int.id = mgmt_int_id
Example #22
0
    def ospf(self, node):
        """Returns OSPF links, also sets process_id
        """

        g_ospf = self.anm['ospf']
        g_ipv4 = self.anm['ipv4']
        ospf_node = g_ospf.node(node)
        ospf_stanza = node.add_stanza("ospf")

        ospf_stanza.custom_config = ospf_node.custom_config

        node.ospf.ipv4_mpls_te = False  # default, inherited enable if necessary

        node.ospf.loopback_area = g_ospf.node(node).area or 0

        node.ospf.process_id = ospf_node.process_id
        node.ospf.lo_interface = self.lo_interface

        node.ospf.ospf_links = []

        # aggregate by area
        from collections import defaultdict
        interfaces_by_area = defaultdict(list)

        for interface in node.physical_interfaces():
            if interface.exclude_igp:
                continue  # don't configure IGP for this interface

            ospf_int = g_ospf.interface(interface)
            if ospf_int and ospf_int.is_bound:
                area = ospf_int.area
                #TODO: can we remove the next line?
                area = str(area)  # can't serialize IPAddress object to JSON
                #TODO: put in interface rather than interface.id for consistency
                stanza = ConfigStanza(id=interface.id,
                                      cost=int(ospf_int.cost),
                                      passive=False)

                if node.ip.use_ipv4:
                    stanza.ipv4_address = ospf_int['ipv4'].ip_address
                    stanza.ipv4_subnet = ospf_int['ipv4'].subnet
                if node.ip.use_ipv6:
                    stanza.ipv6_address = ospf_int['ipv6'].ip_address
                    stanza.ipv6_subnet = ospf_int['ipv6'].subnet

                interfaces_by_area[area].append(stanza)

        loopback_zero = node.loopback_zero
        ospf_loopback_zero = g_ospf.interface(loopback_zero)
        router_area = ospf_loopback_zero.area  # area assigned to router
        router_area = str(
            router_area)  # can't serialize IPAddress object to JSON
        stanza = ConfigStanza(id=node.loopback_zero.id, cost=0, passive=True)
        interfaces_by_area[router_area].append(stanza)

        node.ospf.interfaces_by_area = ConfigStanza(**interfaces_by_area)

        added_networks = set()
        for interface in node.physical_interfaces():
            if interface.exclude_igp:
                continue  # don't configure IGP for this interface
            ipv4_int = g_ipv4.interface(interface)
            ospf_int = g_ospf.interface(interface)
            if not ospf_int.is_bound:
                continue  # not an OSPF interface
            try:
                ospf_cost = int(ospf_int.cost)
            except TypeError:
                try:
                    ospf_cost = netaddr.IPAddress(ospf_int.cost)
                except (TypeError, netaddr.AddrFormatError):
                    log.debug('Using default OSPF cost of 1 for %s on %s' %
                              (ospf_int, node))
                    ospf_cost = 1  # default
            interface.ospf_cost = ospf_cost
            network = ipv4_int.subnet

            if ospf_int and ospf_int.is_bound and network \
                not in added_networks:  # don't add more than once
                added_networks.add(network)
                link_stanza = ConfigStanza(network=network,
                                           interface=interface,
                                           area=ospf_int.area)
                node.ospf.ospf_links.append(link_stanza)
Example #23
0
    def compile_devices(self):
        g_phy = self.anm['phy']

        to_memory, use_mgmt_interfaces, dst_folder = self._parameters()
        if use_mgmt_interfaces:
            log.debug("Allocating VIRL management interfaces")
        else:
            log.debug("Not allocating VIRL management interfaces")
# TODO: need to copy across the interface name from edge to the interface

# TODO: merge common router code, so end up with three loops: routers, ios
# routers, ios_xr routers

# TODO: Split out each device compiler into own function

# TODO: look for unused code paths here - especially for interface
# allocation

# store autonetkit_cisco version
        log.debug("Generating device configurations")
        from pkg_resources import get_distribution

        # Copy across indices for external connectors (e.g may want to copy
        # configs)
        external_connectors = [
            n for n in g_phy
            if n.host == self.host and n.device_type == "external_connector"
        ]
        for phy_node in external_connectors:
            DmNode = self.nidb.node(phy_node)
            DmNode.indices = phy_node.indices

        managed_switches = [
            n for n in g_phy.switches()
            if n.host == self.host and n.device_subtype == "managed"
        ]
        for phy_node in managed_switches:
            DmNode = self.nidb.node(phy_node)
            DmNode.indices = phy_node.indices

        for phy_node in g_phy.l3devices(host=self.host):
            loopback_ids = self.loopback_interface_ids()
            # allocate loopbacks to routes (same for all ios variants)
            DmNode = self.nidb.node(phy_node)
            DmNode.add_stanza("render")
            DmNode.indices = phy_node.indices

            for interface in DmNode.loopback_interfaces():
                if interface != DmNode.loopback_zero:
                    interface.id = loopback_ids.next()

            # numeric ids
            numeric_int_ids = self.numeric_interface_ids()
            for interface in DmNode.physical_interfaces():
                phy_numeric_id = phy_node.interface(interface).numeric_id
                if phy_numeric_id is None:
                    # TODO: remove numeric ID code
                    interface.numeric_id = numeric_int_ids.next()
                else:
                    interface.numeric_id = int(phy_numeric_id)

                phy_specified_id = phy_node.interface(interface).specified_id
                if phy_specified_id is not None:
                    interface.id = phy_specified_id

        #from autonetkit.compilers.device.ubuntu import UbuntuCompiler
        from autonetkit_cisco.compilers.device.ubuntu import UbuntuCompiler

        ubuntu_compiler = UbuntuCompiler(self.nidb, self.anm)
        for phy_node in g_phy.servers(host=self.host):
            DmNode = self.nidb.node(phy_node)
            DmNode.add_stanza("render")
            DmNode.add_stanza("ip")

            # TODO: look at server syntax also, same as for routers
            for interface in DmNode.physical_interfaces():
                phy_specified_id = phy_node.interface(interface).specified_id
                if phy_specified_id is not None:
                    interface.id = phy_specified_id

                #interface.id = self.numeric_to_interface_label_linux(interface.numeric_id)
                # print "numeric", interface.numeric_id, interface.id
                DmNode.ip.use_ipv4 = phy_node.use_ipv4
                DmNode.ip.use_ipv6 = phy_node.use_ipv6

                # TODO: clean up interface handling
            numeric_int_ids = self.numeric_interface_ids()
            for interface in DmNode.physical_interfaces():
                phy_int = phy_node.interface(interface)
                phy_numeric_id = phy_node.interface(interface).numeric_id
                if phy_numeric_id is None:
                    # TODO: remove numeric ID code
                    interface.numeric_id = numeric_int_ids.next()
                else:
                    interface.numeric_id = int(phy_numeric_id)

                phy_specified_id = phy_node.interface(interface).specified_id
                if phy_specified_id is not None:
                    interface.id = phy_specified_id

                # TODO: make this part of the base device compiler, which
                # server/router inherits

            # not these are physical interfaces; configure after previous
            # config steps
            if use_mgmt_interfaces:
                mgmt_int = DmNode.add_interface(management=True,
                                                description="eth0")
                mgmt_int_id = "eth0"
                mgmt_int.id = mgmt_int_id

                # render route config
            DmNode = self.nidb.node(phy_node)
            ubuntu_compiler.compile(DmNode)

            if not phy_node.dont_configure_static_routing:
                DmNode.render.template = os.path.join("templates", "linux",
                                                      "static_route.mako")
                if to_memory:
                    DmNode.render.to_memory = True
                else:
                    DmNode.render.dst_folder = dst_folder
                    DmNode.render.dst_file = "%s.conf" % naming.network_hostname(
                        phy_node)

        # TODO: refactor out common logic

        ios_compiler = IosClassicCompiler(self.nidb, self.anm)
        host_routers = g_phy.routers(host=self.host)
        ios_nodes = (n for n in host_routers if n.syntax in ("ios", "ios_xe"))
        for phy_node in ios_nodes:
            DmNode = self.nidb.node(phy_node)
            DmNode.add_stanza("render")
            DmNode.render.template = os.path.join("templates", "ios.mako")
            if to_memory:
                DmNode.render.to_memory = True
            else:
                DmNode.render.dst_folder = dst_folder
                DmNode.render.dst_file = "%s.conf" % naming.network_hostname(
                    phy_node)

            # TODO: write function that assigns interface number excluding
            # those already taken

            # Assign interfaces
            if phy_node.device_subtype == "IOSv":
                int_ids = self.interface_ids_ios()
                numeric_to_interface_label = self.numeric_to_interface_label_ios
            elif phy_node.device_subtype == "CSR1000v":
                int_ids = self.interface_ids_csr1000v()
                numeric_to_interface_label = self.numeric_to_interface_label_ra
            else:
                # default if no subtype specified
                # TODO: need to set default in the load module
                log.warning("Unexpected subtype %s for %s" %
                            (phy_node.device_subtype, phy_node))
                int_ids = self.interface_ids_ios()
                numeric_to_interface_label = self.numeric_to_interface_label_ios

            if use_mgmt_interfaces:
                if phy_node.device_subtype == "IOSv":
                    # TODO: make these configured in the internal config file
                    # for platform/device_subtype keying
                    mgmt_int_id = "GigabitEthernet0/0"
                if phy_node.device_subtype == "CSR1000v":
                    mgmt_int_id = "GigabitEthernet1"

            for interface in DmNode.physical_interfaces():
                # TODO: use this code block once for all routers
                if not interface.id:
                    interface.id = numeric_to_interface_label(
                        interface.numeric_id)

            ios_compiler.compile(DmNode)
            if use_mgmt_interfaces:
                mgmt_int = DmNode.add_interface(management=True)
                mgmt_int.id = mgmt_int_id

        try:
            from autonetkit_cisco.compilers.device.cisco import IosXrCompiler
            ios_xr_compiler = IosXrCompiler(self.nidb, self.anm)
        except ImportError:
            ios_xr_compiler = IosXrCompiler(self.nidb, self.anm)

        for phy_node in g_phy.routers(host=self.host, syntax='ios_xr'):
            DmNode = self.nidb.node(phy_node)
            DmNode.add_stanza("render")
            DmNode.render.template = os.path.join("templates", "ios_xr",
                                                  "router.conf.mako")
            if to_memory:
                DmNode.render.to_memory = True
            else:
                DmNode.render.dst_folder = dst_folder
                DmNode.render.dst_file = "%s.conf" % naming.network_hostname(
                    phy_node)

            # Assign interfaces
            int_ids = self.interface_ids_ios_xr()
            for interface in DmNode.physical_interfaces():
                if not interface.id:
                    interface.id = self.numeric_to_interface_label_ios_xr(
                        interface.numeric_id)

            ios_xr_compiler.compile(DmNode)

            if use_mgmt_interfaces:
                mgmt_int_id = "mgmteth0/0/CPU0/0"
                mgmt_int = DmNode.add_interface(management=True)
                mgmt_int.id = mgmt_int_id

        nxos_compiler = NxOsCompiler(self.nidb, self.anm)
        for phy_node in g_phy.routers(host=self.host, syntax='nx_os'):
            DmNode = self.nidb.node(phy_node)
            DmNode.add_stanza("render")
            DmNode.render.template = os.path.join("templates", "nx_os.mako")
            if to_memory:
                DmNode.render.to_memory = True
            else:
                DmNode.render.dst_folder = dst_folder
                DmNode.render.dst_file = "%s.conf" % naming.network_hostname(
                    phy_node)

            # Assign interfaces
            int_ids = self.interface_ids_nxos()
            for interface in DmNode.physical_interfaces():
                if not interface.id:
                    interface.id = self.numeric_to_interface_label_nxos(
                        interface.numeric_id)

            DmNode.supported_features = ConfigStanza(mpls_te=False,
                                                     mpls_oam=False,
                                                     vrf=False)

            nxos_compiler.compile(DmNode)
            # TODO: make this work other way around

            if use_mgmt_interfaces:
                mgmt_int_id = "mgmt0"
                mgmt_int = DmNode.add_interface(management=True)
                mgmt_int.id = mgmt_int_id

        staros_compiler = StarOsCompiler(self.nidb, self.anm)
        for phy_node in g_phy.routers(host=self.host, syntax='StarOS'):
            DmNode = self.nidb.node(phy_node)
            DmNode.add_stanza("render")
            DmNode.render.template = os.path.join("templates", "staros.mako")
            if to_memory:
                DmNode.render.to_memory = True
            else:
                DmNode.render.dst_folder = dst_folder
                DmNode.render.dst_file = "%s.conf" % naming.network_hostname(
                    phy_node)

            # Assign interfaces
            int_ids = self.interface_ids_nxos()
            for interface in DmNode.physical_interfaces():
                if not interface.id:
                    interface.id = self.numeric_to_interface_label_star_os(
                        interface.numeric_id)

            staros_compiler.compile(DmNode)
            # TODO: make this work other way around

            if use_mgmt_interfaces:
                mgmt_int_id = "ethernet 1/1"
                mgmt_int = DmNode.add_interface(management=True)
                mgmt_int.id = mgmt_int_id
Example #24
0
    def bgp(self, node):
        super(IosClassicCompiler, self).bgp(node)

        node.bgp.use_ipv4 = node.ip.use_ipv4
        node.bgp.use_ipv6 = node.ip.use_ipv6

        # Seperate by address family

        ipv4_peers = []
        ipv6_peers = []

        # Note cast to dict - #TODO revisit this requirement
        # TODO: revisit and tidy up the logic here: split iBGP and eBGP
        # TODO: sort the peer list by peer IP

        for peer in node.bgp.ibgp_neighbors:
            peer = ConfigStanza(peer)
            peer.remote_ip = peer.loopback
            if peer.use_ipv4:
                if node.is_ebgp_v4:
                    peer.next_hop_self = True
                ipv4_peers.append(peer)
            if peer.use_ipv6:
                if node.is_ebgp_v6:
                    peer.next_hop_self = True
                ipv6_peers.append(peer)

        for peer in node.bgp.ibgp_rr_parents:
            peer = ConfigStanza(peer)
            peer.remote_ip = peer.loopback
            if peer.use_ipv4:
                if node.is_ebgp_v4:
                    peer.next_hop_self = True
                ipv4_peers.append(peer)
            if peer.use_ipv6:
                if node.is_ebgp_v6:
                    peer.next_hop_self = True
                ipv6_peers.append(peer)

        for peer in node.bgp.ibgp_rr_clients:
            peer = ConfigStanza(peer)
            peer.rr_client = True
            peer.remote_ip = peer.loopback
            if peer.use_ipv4:
                if node.is_ebgp_v4:
                    peer.next_hop_self = True
                ipv4_peers.append(peer)
            if peer.use_ipv6:
                if node.is_ebgp_v6:
                    peer.next_hop_self = True
                ipv6_peers.append(peer)

        for peer in node.bgp.ebgp_neighbors:
            peer = ConfigStanza(peer)
            peer.is_ebgp = True
            peer.remote_ip = peer.dst_int_ip
            if peer.use_ipv4:
                peer.next_hop_self = True
                ipv4_peers.append(peer)
            if peer.use_ipv6:
                peer.next_hop_self = True
                ipv6_peers.append(peer)

        node.bgp.ipv4_peers = ipv4_peers
        node.bgp.ipv6_peers = ipv6_peers

        vpnv4_neighbors = []
        if node.bgp.vpnv4:
            for neigh in node.bgp.ibgp_neighbors:
                if not neigh.use_ipv4:
                    continue

                neigh_data = ConfigStanza(neigh)
                vpnv4_neighbors.append(neigh_data)

            for neigh in node.bgp.ibgp_rr_clients:
                if not neigh.use_ipv4:
                    continue
                neigh_data = ConfigStanza(neigh)
                neigh_data.rr_client = True
                vpnv4_neighbors.append(neigh_data)

            for neigh in node.bgp.ibgp_rr_parents:
                if not neigh.use_ipv4:
                    continue
                neigh_data = ConfigStanza(neigh)
                vpnv4_neighbors.append(neigh_data)

        vpnv4_neighbors = sorted(vpnv4_neighbors, key=lambda x:
                                 x['loopback'])
        node.bgp.vpnv4_neighbors = vpnv4_neighbors
Example #25
0
    def l2tp_v3(self, node):
        node.l2tp_classes = []
        node.pseudowire_classes = []
        if not self.anm.has_overlay('l2tp_v3'):
            return

        g_l2tp_v3 = self.anm['l2tp_v3']
        g_phy = self.anm['phy']
        if node not in g_l2tp_v3:
            return   # no l2tp_v3 for node

        l2tp_v3_node = g_l2tp_v3.node(node)
        if l2tp_v3_node.role != "tunnel":
            return # nothing to configure

        node.l2tp_classes = list(l2tp_v3_node.l2tp_classes)
        for l2tp_class in l2tp_v3_node.l2tp_classes:
            node.l2tp_classes

        node.pseudowire_classes = []
        for pwc in l2tp_v3_node.pseudowire_classes:
            stanza = ConfigStanza()
            stanza.name = pwc['name']
            stanza.encapsulation = pwc['encapsulation']
            stanza.protocol = pwc['protocol']
            stanza.l2tp_class_name = pwc['l2tp_class_name']
            local_interface = pwc['local_interface']

            # Lookup the interface ID allocated for this loopback by compiler
            local_interface_id = node.interface(local_interface).id
            stanza.local_interface = local_interface_id

            node.pseudowire_classes.append(stanza)

        for interface in node.physical_interfaces():
            phy_int = g_phy.interface(interface)
            if phy_int.xconnect_encapsulation != "l2tpv3":
                continue # no l2tpv3 encap, no need to do anything

            tunnel_int = l2tp_v3_node.interface(interface)
            stanza = ConfigStanza()
            stanza.remote_ip = tunnel_int.xconnect_remote_ip
            stanza.vc_id = tunnel_int.xconnect_vc_id
            stanza.encapsulation = "l2tpv3"
            #TODO: need to be conscious of support for other xconnect types
            # in templates since pw_class may not apply if not l2tpv3, et
            stanza.pw_class = tunnel_int.xconnect_pw_class

            interface.xconnect = stanza
Example #26
0
    def ospf(self, node):
        """Returns OSPF links, also sets process_id
        """

        g_ospf = self.anm['ospf']
        g_ipv4 = self.anm['ipv4']
        ospf_node = g_ospf.node(node)
        ospf_stanza = node.add_stanza("ospf")

        ospf_stanza.custom_config = ospf_node.custom_config

        node.ospf.ipv4_mpls_te = False  # default, inherited enable if necessary

        node.ospf.loopback_area = g_ospf.node(node).area or 0

        node.ospf.process_id = ospf_node.process_id
        node.ospf.lo_interface = self.lo_interface

        node.ospf.ospf_links = []

        # aggregate by area
        from collections import defaultdict
        interfaces_by_area = defaultdict(list)

        for interface in node.physical_interfaces:
            if interface.exclude_igp:
                continue  # don't configure IGP for this interface

            ospf_int = g_ospf.interface(interface)
            if ospf_int and ospf_int.is_bound:
                area = ospf_int.area
                #TODO: can we remove the next line?
                area = str(area)  # can't serialize IPAddress object to JSON
                #TODO: put in interface rather than interface.id for consistency
                stanza = ConfigStanza(id = interface.id,
                        cost = int(ospf_int.cost), passive = False)

                if node.ip.use_ipv4:
                    stanza.ipv4_address = ospf_int['ipv4'].ip_address
                    stanza.ipv4_subnet = ospf_int['ipv4'].subnet
                if node.ip.use_ipv6:
                    stanza.ipv6_address = ospf_int['ipv6'].ip_address
                    stanza.ipv6_subnet = ospf_int['ipv6'].subnet

                interfaces_by_area[area].append(stanza)

        loopback_zero = node.loopback_zero
        ospf_loopback_zero = g_ospf.interface(loopback_zero)
        router_area = ospf_loopback_zero.area  # area assigned to router
        router_area = str(router_area)  # can't serialize IPAddress object to JSON
        stanza = ConfigStanza(id = node.loopback_zero.id,
            cost = 0, passive = True)
        interfaces_by_area[router_area].append(stanza)

        node.ospf.interfaces_by_area = ConfigStanza(**interfaces_by_area)

        added_networks = set()
        for interface in node.physical_interfaces:
            if interface.exclude_igp:
                continue  # don't configure IGP for this interface
            ipv4_int = g_ipv4.interface(interface)
            ospf_int = g_ospf.interface(interface)
            if not ospf_int.is_bound:
                continue  # not an OSPF interface
            try:
                ospf_cost = int(ospf_int.cost)
            except TypeError:
                try:
                    ospf_cost = netaddr.IPAddress(ospf_int.cost)
                except (TypeError, netaddr.AddrFormatError):
                    log.debug('Using default OSPF cost of 1 for %s on %s'
                               % (ospf_int, node))
                    ospf_cost = 1  # default
            interface.ospf_cost = ospf_cost
            network = ipv4_int.subnet

            if ospf_int and ospf_int.is_bound and network \
                not in added_networks:  # don't add more than once
                added_networks.add(network)
                link_stanza = ConfigStanza(network = network, interface = interface, area = ospf_int.area)
                node.ospf.ospf_links.append(link_stanza)
Example #27
0
    def bgp(self, node):
        node.add_stanza("bgp")
        node.bgp.lo_interface = self.lo_interface
        super(IosBaseCompiler, self).bgp(node)
        phy_node = self.anm['phy'].node(node)
        asn = phy_node.asn
        g_ebgp_v4 = self.anm['ebgp_v4']
        g_ebgp_v6 = self.anm['ebgp_v6']

        if node in g_ebgp_v4 \
                and len(list(g_ebgp_v4.node(node).edges())) > 0:
            node.is_ebgp_v4 = True
        else:
            node.is_ebgp_v4 = False

        if node in g_ebgp_v6 \
                and len(list(g_ebgp_v6.node(node).edges())) > 0:
            node.is_ebgp_v6 = True
        else:
            node.is_ebgp_v6 = False

        node.bgp.ipv4_advertise_subnets = []
        node.bgp.ipv6_advertise_subnets = []

        # Advertise loopbacks into BGP

        if node.ip.use_ipv4:
            node.bgp.ipv4_advertise_subnets = \
                [node.loopback_zero.ipv4_cidr]
        if node.ip.use_ipv6:
            node.bgp.ipv6_advertise_subnets = \
                [node.loopback_zero.ipv6_address]

        # Advertise infrastructure into eBGP

        if node.ip.use_ipv4 and node.is_ebgp_v4:
            infra_blocks = self.anm['ipv4'].data['infra_blocks'].get(asn) or []
            for infra_route in infra_blocks:
                node.bgp.ipv4_advertise_subnets.append(infra_route)

        if node.ip.use_ipv6 and node.is_ebgp_v6:
            infra_blocks = self.anm['ipv6'].data['infra_blocks'].get(asn) or []
            for infra_route in infra_blocks:
                node.bgp.ipv6_advertise_subnets.append(infra_route)

        self.nailed_up_routes(node)

        # vrf
        # TODO: this should be inside vrf section?

        node.bgp.vrfs = []

        vrf_node = self.anm['vrf'].node(node)
        if vrf_node and vrf_node.vrf_role is 'PE':

            # iBGP sessions for this VRF

            vrf_ibgp_neighbors = defaultdict(list)

            g_ibgp_v4 = self.anm['ibgp_v4']
            for session in sort_sessions(g_ibgp_v4.edges(vrf_node)):
                if session.exclude and session.vrf:
                    data = self.ibgp_session_data(session, ip_version=4)
                    stanza = ConfigStanza(data)
                    vrf_ibgp_neighbors[session.vrf].append(stanza)

            g_ibgp_v6 = self.anm['ibgp_v6']
            for session in sort_sessions(g_ibgp_v6.edges(vrf_node)):
                if session.exclude and session.vrf:
                    data = self.ibgp_session_data(session, ip_version=6)
                    stanza = ConfigStanza(data)
                    vrf_ibgp_neighbors[session.vrf].append(stanza)

            # eBGP sessions for this VRF

            vrf_ebgp_neighbors = defaultdict(list)

            for session in sort_sessions(g_ebgp_v4.edges(vrf_node)):
                if session.exclude and session.vrf:
                    data = self.ebgp_session_data(session, ip_version=4)
                    stanza = ConfigStanza(data)
                    vrf_ebgp_neighbors[session.vrf].append(stanza)

            for session in sort_sessions(g_ebgp_v6.edges(vrf_node)):
                if session.exclude and session.vrf:
                    data = self.ebgp_session_data(session, ip_version=6)
                    stanza = ConfigStanza(data)
                    vrf_ebgp_neighbors[session.vrf].append(stanza)

            for vrf in vrf_node.node_vrf_names:
                rd_index = vrf_node.rd_indices[vrf]
                rd = '%s:%s' % (node.asn, rd_index)
                stanza = ConfigStanza(
                    vrf=vrf,
                    rd=rd,
                    use_ipv4=node.ip.use_ipv4,
                    use_ipv6=node.ip.use_ipv6,
                    vrf_ebgp_neighbors=vrf_ebgp_neighbors[vrf],
                    vrf_ibgp_neighbors=vrf_ibgp_neighbors[vrf],
                )
                node.bgp.vrfs.append(stanza)

        # Retain route_target if in ibgp_vpn_v4 and RR or HRR (set in design)

        vpnv4_node = self.anm['ibgp_vpn_v4'].node(node)
        if vpnv4_node:
            retain = False
            if vpnv4_node.retain_route_target:
                retain = True
            node.bgp.vpnv4 = ConfigStanza(retain_route_target=retain)