Example #1
0
def sign_envelope(envelope, keyfile, certfile, password=None):
    """Sign given SOAP envelope with WSSE sig using given key and cert.

    Sign the wsu:Timestamp node in the wsse:Security header and the soap:Body;
    both must be present.

    Add a ds:Signature node in the wsse:Security header containing the
    signature.

    Use EXCL-C14N transforms to normalize the signed XML (so that irrelevant
    whitespace or attribute ordering changes don't invalidate the
    signature). Use SHA1 signatures.

    Expects to sign an incoming document something like this (xmlns attributes
    omitted for readability):

    <soap:Envelope>
      <soap:Header>
        <wsse:Security mustUnderstand="true">
          <wsu:Timestamp>
            <wsu:Created>2015-06-25T21:53:25.246276+00:00</wsu:Created>
            <wsu:Expires>2015-06-25T21:58:25.246276+00:00</wsu:Expires>
          </wsu:Timestamp>
        </wsse:Security>
      </soap:Header>
      <soap:Body>
        ...
      </soap:Body>
    </soap:Envelope>

    After signing, the sample document would look something like this (note the
    added wsu:Id attr on the soap:Body and wsu:Timestamp nodes, and the added
    ds:Signature node in the header, with ds:Reference nodes with URI attribute
    referencing the wsu:Id of the signed nodes):

    <soap:Envelope>
      <soap:Header>
        <wsse:Security mustUnderstand="true">
          <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
            <SignedInfo>
              <CanonicalizationMethod
                  Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
              <SignatureMethod
                  Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
              <Reference URI="#id-d0f9fd77-f193-471f-8bab-ba9c5afa3e76">
                <Transforms>
                  <Transform
                      Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                </Transforms>
                <DigestMethod
                    Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
                <DigestValue>nnjjqTKxwl1hT/2RUsBuszgjTbI=</DigestValue>
              </Reference>
              <Reference URI="#id-7c425ac1-534a-4478-b5fe-6cae0690f08d">
                <Transforms>
                  <Transform
                      Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                </Transforms>
                <DigestMethod
                    Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
                <DigestValue>qAATZaSqAr9fta9ApbGrFWDuCCQ=</DigestValue>
              </Reference>
            </SignedInfo>
            <SignatureValue>Hz8jtQb...bOdT6ZdTQ==</SignatureValue>
            <KeyInfo>
              <wsse:SecurityTokenReference>
                <X509Data>
                  <X509Certificate>MIIDnzC...Ia2qKQ==</X509Certificate>
                  <X509IssuerSerial>
                    <X509IssuerName>...</X509IssuerName>
                    <X509SerialNumber>...</X509SerialNumber>
                  </X509IssuerSerial>
                </X509Data>
              </wsse:SecurityTokenReference>
            </KeyInfo>
          </Signature>
          <wsu:Timestamp wsu:Id="id-7c425ac1-534a-4478-b5fe-6cae0690f08d">
            <wsu:Created>2015-06-25T22:00:29.821700+00:00</wsu:Created>
            <wsu:Expires>2015-06-25T22:05:29.821700+00:00</wsu:Expires>
          </wsu:Timestamp>
        </wsse:Security>
      </soap:Header>
      <soap:Body wsu:Id="id-d0f9fd77-f193-471f-8bab-ba9c5afa3e76">
        ...
      </soap:Body>
    </soap:Envelope>

    """
    # Create the Signature node.
    signature = xmlsec.template.create(
        envelope,
        xmlsec.Transform.EXCL_C14N,
        xmlsec.Transform.RSA_SHA1,
    )

    # Add a KeyInfo node with X509Data child to the Signature. XMLSec will fill
    # in this template with the actual certificate details when it signs.
    key_info = xmlsec.template.ensure_key_info(signature)
    x509_data = xmlsec.template.add_x509_data(key_info)
    xmlsec.template.x509_data_add_issuer_serial(x509_data)
    xmlsec.template.x509_data_add_certificate(x509_data)

    # Load the signing key and certificate.
    key = xmlsec.Key.from_file(keyfile,
                               xmlsec.KeyFormat.PEM,
                               password=password)
    key.load_cert_from_file(certfile, xmlsec.KeyFormat.PEM)

    # Insert the Signature node in the wsse:Security header.
    security = get_security_header(envelope)
    security.insert(0, signature)

    # Perform the actual signing.
    ctx = xmlsec.SignatureContext()
    ctx.key = key

    security.append(etree.Element(QName(ns.WSU, 'Timestamp')))

    soap_env = detect_soap_env(envelope)
    _sign_node(ctx, signature, envelope.find(QName(soap_env, 'Body')))
    _sign_node(ctx, signature, security.find(QName(ns.WSU, 'Timestamp')))

    ctx.sign(signature)

    # Place the X509 data inside a WSSE SecurityTokenReference within
    # KeyInfo. The recipient expects this structure, but we can't rearrange
    # like this until after signing, because otherwise xmlsec won't populate
    # the X509 data (because it doesn't understand WSSE).
    sec_token_ref = etree.SubElement(key_info,
                                     QName(ns.WSSE, 'SecurityTokenReference'))
    sec_token_ref.append(x509_data)
Example #2
0
def parse_png(png, hname):
    neighbors = {}
    devices = {}
    console_dev = ''
    console_port = ''
    mgmt_dev = ''
    mgmt_port = ''
    for child in png:
        if child.tag == str(QName(ns, "DeviceInterfaceLinks")):
            for link in child.findall(str(QName(ns, "DeviceLinkBase"))):
                linktype = link.find(str(QName(ns, "ElementType"))).text
                if linktype != "DeviceInterfaceLink" and linktype != "UnderlayInterfaceLink":
                    continue

                enddevice = link.find(str(QName(ns, "EndDevice"))).text
                endport = link.find(str(QName(ns, "EndPort"))).text
                startdevice = link.find(str(QName(ns, "StartDevice"))).text
                startport = link.find(str(QName(ns, "StartPort"))).text

                if enddevice == hname:
                    if port_alias_map.has_key(endport):
                        endport = port_alias_map[endport]
                    neighbors[endport] = {
                        'name': startdevice,
                        'port': startport
                    }
                else:
                    if port_alias_map.has_key(startport):
                        startport = port_alias_map[startport]
                    neighbors[startport] = {'name': enddevice, 'port': endport}

        if child.tag == str(QName(ns, "Devices")):
            for device in child.findall(str(QName(ns, "Device"))):
                (lo_prefix, mgmt_prefix, name, hwsku,
                 d_type) = parse_device(device)
                device_data = {
                    'lo_addr': lo_prefix,
                    'type': d_type,
                    'mgmt_addr': mgmt_prefix,
                    'hwsku': hwsku
                }
                devices[name] = device_data

        if child.tag == str(QName(ns, "DeviceInterfaceLinks")):
            for if_link in child.findall(str(QName(ns, 'DeviceLinkBase'))):
                if str(QName(ns3, "type")) in if_link.attrib:
                    link_type = if_link.attrib[str(QName(ns3, "type"))]
                    if link_type == 'DeviceSerialLink':
                        for node in if_link:
                            if node.tag == str(QName(ns, "EndPort")):
                                console_port = node.text.split()[-1]
                            elif node.tag == str(QName(ns, "EndDevice")):
                                console_dev = node.text
                    elif link_type == 'DeviceMgmtLink':
                        for node in if_link:
                            if node.tag == str(QName(ns, "EndPort")):
                                mgmt_port = node.text.split()[-1]
                            elif node.tag == str(QName(ns, "EndDevice")):
                                mgmt_dev = node.text

    return (neighbors, devices, console_dev, console_port, mgmt_dev, mgmt_port)
Example #3
0
def parse_cpg(cpg, hname):
    bgp_sessions = {}
    myasn = None
    bgp_peers_with_range = {}
    for child in cpg:
        tag = child.tag
        if tag == str(QName(ns, "PeeringSessions")):
            for session in child.findall(str(QName(ns, "BGPSession"))):
                start_router = session.find(str(QName(ns, "StartRouter"))).text
                start_peer = session.find(str(QName(ns, "StartPeer"))).text
                end_router = session.find(str(QName(ns, "EndRouter"))).text
                end_peer = session.find(str(QName(ns, "EndPeer"))).text
                rrclient = 1 if session.find(str(QName(
                    ns, "RRClient"))) is not None else 0
                if session.find(str(QName(ns, "HoldTime"))) is not None:
                    holdtime = session.find(str(QName(ns, "HoldTime"))).text
                else:
                    holdtime = 180
                if session.find(str(QName(ns, "KeepAliveTime"))) is not None:
                    keepalive = session.find(str(QName(ns,
                                                       "KeepAliveTime"))).text
                else:
                    keepalive = 60
                nhopself = 1 if session.find(str(QName(
                    ns, "NextHopSelf"))) is not None else 0
                if end_router.lower() == hname.lower():
                    bgp_sessions[start_peer.lower()] = {
                        'name': start_router,
                        'local_addr': end_peer.lower(),
                        'rrclient': rrclient,
                        'holdtime': holdtime,
                        'keepalive': keepalive,
                        'nhopself': nhopself
                    }
                else:
                    bgp_sessions[end_peer.lower()] = {
                        'name': end_router,
                        'local_addr': start_peer.lower(),
                        'rrclient': rrclient,
                        'holdtime': holdtime,
                        'keepalive': keepalive,
                        'nhopself': nhopself
                    }
        elif child.tag == str(QName(ns, "Routers")):
            for router in child.findall(str(QName(ns1,
                                                  "BGPRouterDeclaration"))):
                asn = router.find(str(QName(ns1, "ASN"))).text
                hostname = router.find(str(QName(ns1, "Hostname"))).text
                if hostname.lower() == hname.lower():
                    myasn = asn
                    peers = router.find(str(QName(ns1, "Peers")))
                    for bgpPeer in peers.findall(str(QName(ns, "BGPPeer"))):
                        addr = bgpPeer.find(str(QName(ns, "Address"))).text
                        if bgpPeer.find(
                                str(QName(ns1, "PeersRange"))
                        ) is not None:  # FIXME: is better to check for type BGPPeerPassive
                            name = bgpPeer.find(str(QName(ns1, "Name"))).text
                            ip_range = bgpPeer.find(
                                str(QName(ns1, "PeersRange"))).text
                            ip_range_group = ip_range.split(
                                ';') if ip_range and ip_range != "" else []
                            bgp_peers_with_range[name] = {
                                'name': name,
                                'ip_range': ip_range_group
                            }
                            if bgpPeer.find(str(QName(ns1,
                                                      "Address"))) is not None:
                                bgp_peers_with_range[name][
                                    'src_address'] = bgpPeer.find(
                                        str(QName(ns1, "Address"))).text
                            if bgpPeer.find(str(QName(ns1,
                                                      "PeerAsn"))) is not None:
                                bgp_peers_with_range[name][
                                    'peer_asn'] = bgpPeer.find(
                                        str(QName(ns1, "PeerAsn"))).text
                else:
                    for peer in bgp_sessions:
                        bgp_session = bgp_sessions[peer]
                        if hostname.lower() == bgp_session['name'].lower():
                            bgp_session['asn'] = asn
    bgp_sessions = {
        key: bgp_sessions[key]
        for key in bgp_sessions if bgp_sessions[key].has_key('asn')
        and int(bgp_sessions[key]['asn']) != 0
    }
    return bgp_sessions, myasn, bgp_peers_with_range
Example #4
0
def parse_xml(filename, platform=None, port_config_file=None):
    root = ET.parse(filename).getroot()
    mini_graph_path = filename

    u_neighbors = None
    u_devices = None
    hwsku = None
    bgp_sessions = None
    bgp_asn = None
    intfs = None
    vlan_intfs = None
    pc_intfs = None
    vlans = None
    pcs = None
    mgmt_intf = None
    lo_intf = None
    neighbors = None
    devices = None
    hostname = None
    syslog_servers = []
    dhcp_servers = []
    ntp_servers = []
    mgmt_routes = []
    erspan_dst = []
    bgp_peers_with_range = None
    deployment_id = None

    hwsku_qn = QName(ns, "HwSku")
    hostname_qn = QName(ns, "Hostname")
    for child in root:
        if child.tag == str(hwsku_qn):
            hwsku = child.text
        if child.tag == str(hostname_qn):
            hostname = child.text

    ports = parse_port_config(hwsku, platform, port_config_file)

    for child in root:
        if child.tag == str(QName(ns, "DpgDec")):
            (intfs, lo_intfs, mgmt_intf, vlans, pcs,
             acls) = parse_dpg(child, hostname)
        elif child.tag == str(QName(ns, "CpgDec")):
            (bgp_sessions, bgp_asn,
             bgp_peers_with_range) = parse_cpg(child, hostname)
        elif child.tag == str(QName(ns, "PngDec")):
            (neighbors, devices, console_dev, console_port, mgmt_dev,
             mgmt_port) = parse_png(child, hostname)
        elif child.tag == str(QName(ns, "UngDec")):
            (u_neighbors, u_devices, _, _, _, _) = parse_png(child, hostname)
        elif child.tag == str(QName(ns, "MetadataDeclaration")):
            (syslog_servers, dhcp_servers, ntp_servers, mgmt_routes,
             erspan_dst, deployment_id) = parse_meta(child, hostname)

    results = {}
    results['minigraph_hwsku'] = hwsku
    # sorting by lambdas are not easily done without custom filters.
    # TODO: add jinja2 filter to accept a lambda to sort a list of dictionaries by attribute.
    # TODO: alternatively (preferred), implement class containers for multiple-attribute entries, enabling sort by attr
    results['minigraph_bgp'] = sorted(bgp_sessions, key=lambda x: x['addr'])
    results['minigraph_bgp_asn'] = bgp_asn
    results['minigraph_bgp_peers_with_range'] = bgp_peers_with_range
    # TODO: sort does not work properly on all interfaces of varying lengths. Need to sort by integer group(s).

    phyport_intfs = []
    vlan_intfs = []
    pc_intfs = []
    for intf in intfs:
        intfname = intf['attachto']
        if intfname[0:4] == 'Vlan':
            vlan_intfs.append(intf)
        elif intfname[0:11] == 'PortChannel':
            pc_intfs.append(intf)
        else:
            phyport_intfs.append(intf)

    results['minigraph_interfaces'] = sorted(phyport_intfs,
                                             key=lambda x: x['attachto'])
    results['minigraph_vlan_interfaces'] = sorted(vlan_intfs,
                                                  key=lambda x: x['attachto'])
    results['minigraph_portchannel_interfaces'] = sorted(
        pc_intfs, key=lambda x: x['attachto'])
    results['minigraph_ports'] = ports
    results['minigraph_vlans'] = vlans
    results['minigraph_portchannels'] = pcs
    results['minigraph_mgmt_interface'] = mgmt_intf
    results['minigraph_lo_interfaces'] = lo_intfs
    results['minigraph_acls'] = acls
    results['minigraph_neighbors'] = neighbors
    results['minigraph_devices'] = devices
    results['minigraph_underlay_neighbors'] = u_neighbors
    results['minigraph_underlay_devices'] = u_devices
    results['minigraph_as_xml'] = mini_graph_path
    if devices != None:
        results['minigraph_console'] = get_console_info(
            devices, console_dev, console_port)
        results['minigraph_mgmt'] = get_mgmt_info(devices, mgmt_dev, mgmt_port)
    results['minigraph_hostname'] = hostname
    results['inventory_hostname'] = hostname
    results['syslog_servers'] = syslog_servers
    results['dhcp_servers'] = dhcp_servers
    results['ntp_servers'] = ntp_servers
    results['forced_mgmt_routes'] = mgmt_routes
    results['erspan_dst'] = erspan_dst
    results['deployment_id'] = deployment_id

    return results
Example #5
0
def parse_dpg(dpg, hname):
    for child in dpg:
        hostname = child.find(str(QName(ns, "Hostname")))
        if hostname.text != hname:
            continue

        ipintfs = child.find(str(QName(ns, "IPInterfaces")))
        intfs = {}
        for ipintf in ipintfs.findall(str(QName(ns, "IPInterface"))):
            intfalias = ipintf.find(str(QName(ns, "AttachTo"))).text
            intfname = port_alias_map.get(intfalias, intfalias)
            ipprefix = ipintf.find(str(QName(ns, "Prefix"))).text
            intfs[(intfname, ipprefix)] = {}

        lointfs = child.find(str(QName(ns, "LoopbackIPInterfaces")))
        lo_intfs = {}
        for lointf in lointfs.findall(str(QName(ns1, "LoopbackIPInterface"))):
            intfname = lointf.find(str(QName(ns, "AttachTo"))).text
            ipprefix = lointf.find(str(QName(ns1, "PrefixStr"))).text
            lo_intfs[(intfname, ipprefix)] = {}

        mgmtintfs = child.find(str(QName(ns, "ManagementIPInterfaces")))
        mgmt_intf = {}
        for mgmtintf in mgmtintfs.findall(
                str(QName(ns1, "ManagementIPInterface"))):
            intfname = mgmtintf.find(str(QName(ns, "AttachTo"))).text
            ipprefix = mgmtintf.find(str(QName(ns1, "PrefixStr"))).text
            mgmtipn = ipaddress.IPNetwork(ipprefix)
            gwaddr = ipaddress.IPAddress(int(mgmtipn.network) + 1)
            mgmt_intf[(intfname, ipprefix)] = {'gwaddr': gwaddr}

        pcintfs = child.find(str(QName(ns, "PortChannelInterfaces")))
        pc_intfs = []
        pcs = {}
        for pcintf in pcintfs.findall(str(QName(ns, "PortChannel"))):
            pcintfname = pcintf.find(str(QName(ns, "Name"))).text
            pcintfmbr = pcintf.find(str(QName(ns, "AttachTo"))).text
            pcmbr_list = pcintfmbr.split(';')
            for i, member in enumerate(pcmbr_list):
                pcmbr_list[i] = port_alias_map.get(member, member)
            pcs[pcintfname] = {'members': pcmbr_list}

        vlanintfs = child.find(str(QName(ns, "VlanInterfaces")))
        vlan_intfs = []
        vlans = {}
        vlan_members = {}
        for vintf in vlanintfs.findall(str(QName(ns, "VlanInterface"))):
            vintfname = vintf.find(str(QName(ns, "Name"))).text
            vlanid = vintf.find(str(QName(ns, "VlanID"))).text
            vintfmbr = vintf.find(str(QName(ns, "AttachTo"))).text
            vmbr_list = vintfmbr.split(';')
            for i, member in enumerate(vmbr_list):
                vmbr_list[i] = port_alias_map.get(member, member)
                sonic_vlan_member_name = "Vlan%s%s%s" % (vlanid, KEY_SEPARATOR,
                                                         vmbr_list[i])
                vlan_members[sonic_vlan_member_name] = {
                    'tagging_mode': 'untagged'
                }

            vlan_attributes = {'vlanid': vlanid}

            # If this VLAN requires a DHCP relay agent, it will contain a <DhcpRelays> element
            # containing a list of DHCP server IPs
            if vintf.find(str(QName(ns, "DhcpRelays"))) is not None:
                vintfdhcpservers = vintf.find(str(QName(ns,
                                                        "DhcpRelays"))).text
                vdhcpserver_list = vintfdhcpservers.split(';')
                vlan_attributes['dhcp_servers'] = vdhcpserver_list

            sonic_vlan_name = "Vlan%s" % vlanid
            vlans[sonic_vlan_name] = vlan_attributes

        aclintfs = child.find(str(QName(ns, "AclInterfaces")))
        acls = {}
        for aclintf in aclintfs.findall(str(QName(ns, "AclInterface"))):
            aclname = aclintf.find(str(QName(ns,
                                             "InAcl"))).text.upper().replace(
                                                 " ", "_").replace("-", "_")
            aclattach = aclintf.find(str(QName(ns,
                                               "AttachTo"))).text.split(';')
            acl_intfs = []
            is_mirror = False
            for member in aclattach:
                member = member.strip()
                if pcs.has_key(member):
                    acl_intfs.extend(
                        pcs[member]['members']
                    )  # For ACL attaching to port channels, we break them into port channel members
                elif vlans.has_key(member):
                    print >> sys.stderr, "Warning: ACL " + aclname + " is attached to a Vlan interface, which is currently not supported"
                elif port_alias_map.has_key(member):
                    acl_intfs.append(port_alias_map[member])
                elif member.lower() == 'erspan':
                    is_mirror = True
                    # Erspan session will be attached to all front panel ports
                    acl_intfs = port_alias_map.values()
                    break
            if acl_intfs:
                acls[aclname] = {
                    'policy_desc': aclname,
                    'ports': acl_intfs,
                    'type': 'MIRROR' if is_mirror else 'L3'
                }
        return intfs, lo_intfs, mgmt_intf, vlans, vlan_members, pcs, acls
    return None, None, None, None, None, None, None
Example #6
0
    def _setitem(
        self,
        key: Union[str, QName],
        val: Union[Set[str], List[str], str],
        applying_mark: bool = False,
    ):
        if not self._updating:
            raise RuntimeError(
                "Metadata not opened for editing, use with block")

        qkey = self._qname(key)
        if (self.mark and not applying_mark and qkey in (
                self._qname('xmp:MetadataDate'),
                self._qname('pdf:Producer'),
        )):
            # Complain if user writes self[pdf:Producer] = ... and because it will
            # be overwritten on save, unless self._updating_mark, in which case
            # the action was initiated internally
            log.warning(
                f"Update to {key} will be overwritten because metadata was opened "
                "with set_pikepdf_as_editor=True")
        if isinstance(val, str) and qkey in (self._qname('dc:creator')):
            log.error(f"{key} should be set to a list of strings")

        def add_array(node, items: Iterable):
            rdf_type = next(c.rdf_type for c in XMP_CONTAINERS
                            if isinstance(items, c.py_type))
            seq = etree.SubElement(node, str(QName(XMP_NS_RDF, rdf_type)))
            tag_attrib: Optional[Dict[str, str]] = None
            if rdf_type == 'Alt':
                tag_attrib = {str(QName(XMP_NS_XML, 'lang')): 'x-default'}
            for item in items:
                el = etree.SubElement(seq,
                                      str(QName(XMP_NS_RDF, 'li')),
                                      attrib=tag_attrib)
                el.text = _clean(item)

        try:
            # Locate existing node to replace
            node, attrib, _oldval, _parent = next(self._get_elements(key))
            if attrib:
                if not isinstance(val, str):
                    raise TypeError(val)
                node.set(attrib, _clean(val))
            elif isinstance(val, (list, set)):
                for child in node.findall('*'):
                    node.remove(child)
                add_array(node, val)
            elif isinstance(val, str):
                for child in node.findall('*'):
                    node.remove(child)
                if str(self._qname(key)) in LANG_ALTS:
                    add_array(node, AltList([_clean(val)]))
                else:
                    node.text = _clean(val)
            else:
                raise TypeError(val)
        except StopIteration:
            # Insert a new node
            rdf = self._get_rdf_root()
            if str(self._qname(key)) in LANG_ALTS:
                val = AltList([_clean(val)])
            if isinstance(val, (list, set)):
                rdfdesc = etree.SubElement(
                    rdf,
                    str(QName(XMP_NS_RDF, 'Description')),
                    attrib={str(QName(XMP_NS_RDF, 'about')): ''},
                )
                node = etree.SubElement(rdfdesc, self._qname(key))
                add_array(node, val)
            elif isinstance(val, str):
                _rdfdesc = etree.SubElement(  # lgtm [py/unused-local-variable]
                    rdf,
                    str(QName(XMP_NS_RDF, 'Description')),
                    attrib={
                        QName(XMP_NS_RDF, 'about'): '',
                        self._qname(key): _clean(val),
                    },
                )
            else:
                raise TypeError(val) from None
Example #7
0
def parse_dpg(dpg, hname):
    for child in dpg:
        hostname = child.find(str(QName(ns, "Hostname")))
        if hostname.text != hname:
            continue

        ipintfs = child.find(str(QName(ns, "IPInterfaces")))
        intfs = []
        for ipintf in ipintfs.findall(str(QName(ns, "IPInterface"))):
            intfalias = ipintf.find(str(QName(ns, "AttachTo"))).text
            intfname = port_alias_map.get(intfalias, intfalias)
            ipprefix = ipintf.find(str(QName(ns, "Prefix"))).text
            ipn = ipaddress.IPNetwork(ipprefix)
            ipaddr = ipn.ip
            prefix_len = ipn.prefixlen
            addr_bits = ipn.max_prefixlen
            subnet = ipaddress.IPNetwork(
                str(ipn.network) + '/' + str(prefix_len))
            ipmask = ipn.netmask

            intf = {'addr': ipaddr, 'subnet': subnet}
            if isinstance(ipn, ipaddress.IPv4Network):
                intf['mask'] = ipmask
            else:
                intf['mask'] = str(prefix_len)
            intf.update({'attachto': intfname, 'prefixlen': int(prefix_len)})

            # TODO: remove peer_addr after dependency removed
            ipaddr_val = int(ipn.ip)
            peer_addr_val = None
            if int(prefix_len) == addr_bits - 2:
                if ipaddr_val & 0x3 == 1:
                    peer_addr_val = ipaddr_val + 1
                else:
                    peer_addr_val = ipaddr_val - 1
            elif int(prefix_len) == addr_bits - 1:
                if ipaddr_val & 0x1 == 0:
                    peer_addr_val = ipaddr_val + 1
                else:
                    peer_addr_val = ipaddr_val - 1
            if peer_addr_val is not None:
                intf['peer_addr'] = ipaddress.IPAddress(peer_addr_val)
            intfs.append(intf)

        lointfs = child.find(str(QName(ns, "LoopbackIPInterfaces")))
        lo_intfs = []
        for lointf in lointfs.findall(str(QName(ns1, "LoopbackIPInterface"))):
            intfname = lointf.find(str(QName(ns, "AttachTo"))).text
            ipprefix = lointf.find(str(QName(ns1, "PrefixStr"))).text
            ipn = ipaddress.IPNetwork(ipprefix)
            ipaddr = ipn.ip
            prefix_len = ipn.prefixlen
            ipmask = ipn.netmask
            lo_intf = {
                'name': intfname,
                'addr': ipaddr,
                'prefixlen': prefix_len
            }
            if isinstance(ipn, ipaddress.IPv4Network):
                lo_intf['mask'] = ipmask
            else:
                lo_intf['mask'] = str(prefix_len)
            lo_intfs.append(lo_intf)

        mgmtintfs = child.find(str(QName(ns, "ManagementIPInterfaces")))
        mgmt_intf = None
        for mgmtintf in mgmtintfs.findall(
                str(QName(ns1, "ManagementIPInterface"))):
            ipprefix = mgmtintf.find(str(QName(ns1, "PrefixStr"))).text
            mgmtipn = ipaddress.IPNetwork(ipprefix)
            ipaddr = mgmtipn.ip
            prefix_len = str(mgmtipn.prefixlen)
            ipmask = mgmtipn.netmask
            gwaddr = ipaddress.IPAddress(int(mgmtipn.network) + 1)
            mgmt_intf = {
                'addr': ipaddr,
                'prefixlen': prefix_len,
                'mask': ipmask,
                'gwaddr': gwaddr
            }

        pcintfs = child.find(str(QName(ns, "PortChannelInterfaces")))
        pc_intfs = []
        pcs = {}
        for pcintf in pcintfs.findall(str(QName(ns, "PortChannel"))):
            pcintfname = pcintf.find(str(QName(ns, "Name"))).text
            pcintfmbr = pcintf.find(str(QName(ns, "AttachTo"))).text
            pcmbr_list = pcintfmbr.split(';')
            for i, member in enumerate(pcmbr_list):
                pcmbr_list[i] = port_alias_map.get(member, member)
            pcs[pcintfname] = {'name': pcintfname, 'members': pcmbr_list}

        vlanintfs = child.find(str(QName(ns, "VlanInterfaces")))
        vlan_intfs = []
        vlans = {}
        for vintf in vlanintfs.findall(str(QName(ns, "VlanInterface"))):
            vintfname = vintf.find(str(QName(ns, "Name"))).text
            vlanid = vintf.find(str(QName(ns, "VlanID"))).text
            vintfmbr = vintf.find(str(QName(ns, "AttachTo"))).text
            vmbr_list = vintfmbr.split(';')
            for i, member in enumerate(vmbr_list):
                vmbr_list[i] = port_alias_map.get(member, member)
            vlan_attributes = {
                'name': vintfname,
                'members': vmbr_list,
                'vlanid': vlanid
            }
            sonic_vlan_name = "Vlan%s" % vlanid
            vlans[sonic_vlan_name] = vlan_attributes

        aclintfs = child.find(str(QName(ns, "AclInterfaces")))
        acls = {}
        for aclintf in aclintfs.findall(str(QName(ns, "AclInterface"))):
            aclname = aclintf.find(str(QName(ns,
                                             "InAcl"))).text.lower().replace(
                                                 " ", "_").replace("-", "_")
            aclattach = aclintf.find(str(QName(ns,
                                               "AttachTo"))).text.split(';')
            acl_intfs = []
            is_mirror = False
            for member in aclattach:
                member = member.strip()
                if pcs.has_key(member):
                    acl_intfs.extend(
                        pcs[member]['members']
                    )  # For ACL attaching to port channels, we break them into port channel members
                elif vlans.has_key(member):
                    print >> sys.stderr, "Warning: ACL " + aclname + " is attached to a Vlan interface, which is currently not supported"
                elif port_alias_map.has_key(member):
                    acl_intfs.append(port_alias_map[member])
                elif member.lower() == 'erspan':
                    is_mirror = True
                    # Erspan session will be attached to all front panel ports
                    acl_intfs = port_alias_map.values()
                    break
            if acl_intfs:
                acls[aclname] = {'AttachTo': acl_intfs, 'IsMirror': is_mirror}
        return intfs, lo_intfs, mgmt_intf, vlans, pcs, acls
    return None, None, None, None, None, None
Example #8
0
    def test_property_is_element(self):
        var = XmlElement(name="foo", qname=QName("foo"))

        self.assertIsInstance(var, XmlVar)
        self.assertTrue(var.is_element)
Example #9
0
    def test_property_is_wildcard(self):
        var = XmlWildcard(name="foo", qname=QName("foo"))

        self.assertIsInstance(var, XmlVar)
        self.assertTrue(var.is_wildcard)
Example #10
0
    def test_property_is_list(self):
        var = XmlVar(name="foo", qname=QName("foo"))
        self.assertFalse(var.is_list)

        var = XmlVar(name="foo", qname=QName("foo"), types=[int], default=list)
        self.assertTrue(var.is_list)
Example #11
0
 def test_matches(self):
     var = XmlVar(name="foo", qname=QName("foo"))
     self.assertTrue(var.matches(QNames.ALL))
     self.assertTrue(var.matches(var.qname))
     self.assertFalse(var.matches(QName("bar")))
Example #12
0
    def test_property_is_tokens(self):
        var = XmlText(name="foo", qname=QName("foo"))
        self.assertFalse(var.is_tokens)

        var = XmlText(name="foo", qname=QName("foo"), default=list)
        self.assertTrue(var.is_tokens)
Example #13
0
    def test_property_is_attributes(self):
        var = XmlAttributes(name="foo", qname=QName("foo"))

        self.assertIsInstance(var, XmlVar)
        self.assertTrue(var.is_attributes)
Example #14
0
def is_text_property(property):
    tag = QName(property).localname
    return tag in ['bstr', 'lpstr', 'lpwstr']
Example #15
0
    def compose(self, data_dict, root_name=None):
        root_name = root_name or self.root_name
        root = Element(QName(NS.ds, root_name), nsmap=vars(NS))

        return root
Example #16
0
 def test_property_is_any_type(self):
     var = XmlWildcard(name="foo", qname=QName("foo"))
     self.assertTrue(var.is_any_type)
Example #17
0
    pass  # pylint: disable=unnecessary-pass


class AltList(list):
    pass


XMP_CONTAINERS = [
    XmpContainer('Alt', AltList, AltList.append),
    XmpContainer('Bag', set, set.add),
    XmpContainer('Seq', list, list.append),
]

LANG_ALTS = frozenset([
    str(QName(XMP_NS_DC, 'title')),
    str(QName(XMP_NS_DC, 'description')),
    str(QName(XMP_NS_DC, 'rights')),
    str(QName(XMP_NS_XMP_RIGHTS, 'UsageTerms')),
])

# These are the illegal characters in XML 1.0. (XML 1.1 is a bit more permissive,
# but we'll be strict to ensure wider compatibility.)
re_xml_illegal_chars = re.compile(
    r"(?u)[^\x09\x0A\x0D\x20-\U0000D7FF\U0000E000-\U0000FFFD\U00010000-\U0010FFFF]"
)
re_xml_illegal_bytes = re.compile(
    br"[^\x09\x0A\x0D\x20-\xFF]|&#0;"
    # br"&#(?:[0-9]|0[0-9]|1[0-9]|2[0-9]|3[0-1]|x[0-9A-Fa-f]|x0[0-9A-Fa-f]|x1[0-9A-Fa-f]);"
)
Example #18
0
    def test_matches(self):
        var = XmlWildcard(name="foo", qname=QName("foo"))
        self.assertTrue(var.matches(QNames.ALL))
        self.assertTrue(var.matches(QName("a")))

        var = XmlWildcard(name="foo", qname=QName("foo"), namespaces=["tns"])
        self.assertFalse(var.matches(QName("a")))
        self.assertTrue(var.matches(QName("tns", "a")))

        var = XmlWildcard(name="foo", qname=QName("foo"), namespaces=["##any"])
        self.assertTrue(var.matches(QName("a")))
        self.assertTrue(var.matches(QName("tns", "a")))

        var = XmlWildcard(name="foo", qname=QName("foo"), namespaces=[""])
        self.assertTrue(var.matches(QName("a")))
        self.assertFalse(var.matches(QName("tns", "a")))

        var = XmlWildcard(name="foo", qname=QName("foo"), namespaces=["!tns"])
        self.assertTrue(var.matches(QName("foo", "a")))
        self.assertFalse(var.matches(QName("tns", "a")))
Example #19
0
def test_compose(composer, data_dict, schema):
    billing_reference = composer.compose(data_dict)

    assert billing_reference.tag == QName(NS.cac, "BillingReference").text

    additional_document_reference = billing_reference.find(
        QName(NS.cac, "AdditionalDocumentReference"))
    assert additional_document_reference.find(QName(NS.cbc,
                                                    "ID")).text == "JD-11-2018"
    assert additional_document_reference.find(QName(
        NS.cbc, "IssueDate")).text == "2018-11-30"
    assert additional_document_reference.find(QName(
        NS.cbc, "DocumentType")).text == u"Decisión de la JD"

    billing_reference_line = billing_reference.find(
        QName(NS.cac, "BillingReferenceLine"))
    assert billing_reference_line.find(QName(NS.cbc, "ID")) is not None
    assert billing_reference_line.find(QName(NS.cbc,
                                             "Amount")).text == ("15031725.00")
    assert billing_reference_line.find(QName(
        NS.cbc, "Amount")).attrib.get('currencyID') == 'COP'

    invoice_document_reference = billing_reference.find(
        QName(NS.cac, "InvoiceDocumentReference"))
    assert invoice_document_reference.find(QName(NS.cbc,
                                                 "ID")).text == "PRUE980000094"
    assert invoice_document_reference.find(QName(
        NS.cbc, "UUID")).text == ("3d5a434b014429b551864c49a84164d58b11ea02")
    assert invoice_document_reference.find(QName(
        NS.cbc, "IssueDate")).text == "2018-11-30"

    schema.assertValid(billing_reference)
Example #20
0
def _fields(self):
    fields = []
    field = None
    # noinspection PyPep8Naming
    fldCharType = qn('w:fldCharType')
    instr = qn('w:instr')
    root = self._p.getroottree()
    instructions = ''

    for run in self.runs:
        for chld in run._r.getchildren():
            tag = QName(chld.tag).localname
            if tag == 'fldChar':
                if chld.attrib.get(fldCharType) == 'begin':
                    field = Field(self)
                    field.xpath_start = root.getpath(run._r)
                elif chld.attrib.get(
                        fldCharType) == 'end' and field is not None:
                    if instructions:
                        lex = shlex.shlex(instructions, posix=True)
                        lex.whitespace_split = True
                        lex.commenters = ''
                        lex.escape = ''
                        try:
                            tokens = list(lex)
                        except ValueError as e:
                            raise ParserException(str(e) + chld.text, chld)

                        field.code = tokens[0]
                        fmt_target = None
                        for token in tokens[1:]:
                            if fmt_target is not None:
                                field.format[fmt_target].append(token)
                                fmt_target = None
                            elif token.startswith('\\'):
                                fmt_target = token[1:]
                            else:
                                field.extra.append(token)
                    field.xpath_end = root.getpath(run._r)
                    fields.append(field)
                    field = None
                    instructions = ''
            elif field:
                if tag == 't':
                    field.default = chld.text
                elif tag == 'instrText' and chld.text.strip():
                    instructions += chld.text

    for fld in self._p.xpath('./w:fldSimple'):
        if fld.attrib.get(instr):
            field = Field(self)
            field.xpath_start = root.getpath(fld)
            field.xpath_end = root.getpath(fld)
            if fld.find(qn('w:r')):
                field.default = fld.find(qn('w:r'))[0].text
            lex = shlex.shlex(fld.attrib.get(instr), posix=True)
            lex.whitespace_split = True
            lex.commenters = ''
            lex.escape = ''
            tokens = list(lex)
            field.code = tokens[0]
            fmt_target = None
            for token in tokens[1:]:
                if fmt_target is not None:
                    field.format[fmt_target].append(token)
                    fmt_target = None
                elif token.startswith('\\'):
                    fmt_target = token[1:]
                else:
                    field.extra.append(token)
            fields.append(field)
    return fields
Example #21
0
def parse_cpg(cpg, hname):
    bgp_sessions = []
    myasn = None
    bgp_peers_with_range = []
    for child in cpg:
        tag = child.tag
        if tag == str(QName(ns, "PeeringSessions")):
            for session in child.findall(str(QName(ns, "BGPSession"))):
                start_router = session.find(str(QName(ns, "StartRouter"))).text
                start_peer = session.find(str(QName(ns, "StartPeer"))).text
                end_router = session.find(str(QName(ns, "EndRouter"))).text
                end_peer = session.find(str(QName(ns, "EndPeer"))).text
                if end_router == hname:
                    bgp_sessions.append({
                        'name': start_router,
                        'addr': start_peer,
                        'peer_addr': end_peer
                    })
                else:
                    bgp_sessions.append({
                        'name': end_router,
                        'addr': end_peer,
                        'peer_addr': start_peer
                    })
        elif child.tag == str(QName(ns, "Routers")):
            for router in child.findall(str(QName(ns1,
                                                  "BGPRouterDeclaration"))):
                asn = router.find(str(QName(ns1, "ASN"))).text
                hostname = router.find(str(QName(ns1, "Hostname"))).text
                if hostname == hname:
                    myasn = int(asn)
                    peers = router.find(str(QName(ns1, "Peers")))
                    for bgpPeer in peers.findall(str(QName(ns, "BGPPeer"))):
                        addr = bgpPeer.find(str(QName(ns, "Address"))).text
                        if bgpPeer.find(str(QName(ns1,
                                                  "PeersRange"))) is not None:
                            name = bgpPeer.find(str(QName(ns1, "Name"))).text
                            ip_range = bgpPeer.find(
                                str(QName(ns1, "PeersRange"))).text
                            ip_range_group = ip_range.split(
                                ';') if ip_range and ip_range != "" else []
                            bgp_peers_with_range.append({
                                'name':
                                name,
                                'ip_range':
                                ip_range_group
                            })
                else:
                    for bgp_session in bgp_sessions:
                        if hostname == bgp_session['name']:
                            bgp_session['asn'] = int(asn)

    return bgp_sessions, myasn, bgp_peers_with_range
Example #22
0
def parse_dpg(dpg, hname):
    for child in dpg:
        hostname = child.find(str(QName(ns, "Hostname")))
        if hostname.text != hname:
            continue

        ipintfs = child.find(str(QName(ns, "IPInterfaces")))
        intfs = []
        vlan_map = {}
        for ipintf in ipintfs.findall(str(QName(ns, "IPInterface"))):
            intfname = ipintf.find(str(QName(ns, "AttachTo"))).text
            ipprefix = ipintf.find(str(QName(ns, "Prefix"))).text
            ipn = ipaddress.IPNetwork(ipprefix)
            ipaddr = ipn.ip
            prefix_len = ipn.prefixlen
            addr_bits = ipn.max_prefixlen
            subnet = ipaddress.IPNetwork(
                str(ipn.network) + '/' + str(prefix_len))
            ipmask = ipn.netmask

            intf = {'addr': ipaddr, 'subnet': subnet}
            if isinstance(ipn, ipaddress.IPv4Network):
                intf['mask'] = ipmask
            else:
                intf['mask'] = str(prefix_len)

            if intfname[0:4] == "Vlan":
                if intfname in vlan_map:
                    vlan_map[intfname].append(intf)

                else:
                    vlan_map[intfname] = [intf]
            else:
                intf.update({'name': intfname, 'prefixlen': int(prefix_len)})

                if port_alias_map.has_key(intfname):
                    intf['alias'] = port_alias_map[intfname]
                else:
                    intf['alias'] = intfname

                # TODO: remove peer_addr after dependency removed
                ipaddr_val = int(ipn.ip)
                peer_addr_val = None
                if int(prefix_len) == addr_bits - 2:
                    if ipaddr_val & 0x3 == 1:
                        peer_addr_val = ipaddr_val + 1
                    else:
                        peer_addr_val = ipaddr_val - 1
                elif int(prefix_len) == addr_bits - 1:
                    if ipaddr_val & 0x1 == 0:
                        peer_addr_val = ipaddr_val + 1
                    else:
                        peer_addr_val = ipaddr_val - 1

                if peer_addr_val is not None:
                    intf['peer_addr'] = ipaddress.IPAddress(peer_addr_val)
                intfs.append(intf)

        pcintfs = child.find(str(QName(ns, "PortChannelInterfaces")))
        pc_intfs = []
        for pcintf in pcintfs.findall(str(QName(ns, "PortChannel"))):
            pcintfname = pcintf.find(str(QName(ns, "Name"))).text
            pcintfmbr = pcintf.find(str(QName(ns, "AttachTo"))).text
            pcmbr_list = pcintfmbr.split(';', 1)
            pc_intfs.append({'name': pcintfname, 'members': pcmbr_list})

        lointfs = child.find(str(QName(ns, "LoopbackIPInterfaces")))
        lo_intfs = []
        for lointf in lointfs.findall(str(QName(ns1, "LoopbackIPInterface"))):
            intfname = lointf.find(str(QName(ns, "AttachTo"))).text
            ipprefix = lointf.find(str(QName(ns1, "PrefixStr"))).text
            ipn = ipaddress.IPNetwork(ipprefix)
            ipaddr = ipn.ip
            prefix_len = ipn.prefixlen
            ipmask = ipn.netmask
            lo_intf = {
                'name': intfname,
                'addr': ipaddr,
                'prefixlen': prefix_len
            }
            if isinstance(ipn, ipaddress.IPv4Network):
                lo_intf['mask'] = ipmask
            else:
                lo_intf['mask'] = str(prefix_len)
            lo_intfs.append(lo_intf)

        mgmtintfs = child.find(str(QName(ns, "ManagementIPInterfaces")))
        mgmt_intf = None
        for mgmtintf in mgmtintfs.findall(
                str(QName(ns1, "ManagementIPInterface"))):
            ipprefix = mgmtintf.find(str(QName(ns1, "PrefixStr"))).text
            mgmtipn = ipaddress.IPNetwork(ipprefix)
            ipaddr = mgmtipn.ip
            prefix_len = str(mgmtipn.prefixlen)
            ipmask = mgmtipn.netmask
            gwaddr = ipaddress.IPAddress(int(mgmtipn.network) + 1)
            mgmt_intf = {
                'addr': ipaddr,
                'prefixlen': prefix_len,
                'mask': ipmask,
                'gwaddr': gwaddr
            }

        vlanintfs = child.find(str(QName(ns, "VlanInterfaces")))
        vlan_intfs = []
        for vintf in vlanintfs.findall(str(QName(ns, "VlanInterface"))):
            vintfname = vintf.find(str(QName(ns, "Name"))).text
            vlanid = vintf.find(str(QName(ns, "VlanID"))).text
            vintfmbr = vintf.find(str(QName(ns, "AttachTo"))).text
            vmbr_list = vintfmbr.split(';')
            vlan_attributes = {
                'name': vintfname,
                'members': vmbr_list,
                'vlanid': vlanid
            }
            for addrtuple in vlan_map.get(vintfname, []):
                vlan_attributes.update(addrtuple)
                vlan_intfs.append(copy.deepcopy(vlan_attributes))

        return intfs, lo_intfs, mgmt_intf, vlan_intfs, pc_intfs
    return None, None, None, None, None
Example #23
0
def test_compose(composer, data_dict, schema):
    debit_note_line = composer.compose(data_dict)

    assert debit_note_line.tag == QName(NS.cac, "DebitNoteLine").text
    assert debit_note_line.findtext(QName(NS.cbc, 'ID')) == '1'
    assert debit_note_line.findtext(QName(NS.cbc, 'UUID')) == 'abcd123'

    line_extension_amount = debit_note_line.find(
        QName(NS.cbc, "LineExtensionAmount"))
    assert line_extension_amount.text == "3456788.00"
    assert line_extension_amount.attrib['currencyID'] == 'COP'

    discrepancy_response = debit_note_line.find(
        QName(NS.cac, "DiscrepancyResponse"))
    response_code = discrepancy_response.find(QName(NS.cbc, "ResponseCode"))
    assert response_code.text == "2"

    assert debit_note_line.find(QName(NS.cac, "BillingReference")) is not None

    tax_total = debit_note_line.find(QName(NS.cac, "TaxTotal"))
    assert tax_total.find(QName(NS.cbc, "TaxAmount")).text == "2856027.75"
    assert tax_total.find(QName(NS.cbc,
                                "TaxAmount")).attrib.get('currencyID') == "COP"

    item = debit_note_line.find(QName(NS.cac, "Item"))
    assert item.find(QName(NS.cbc,
                           "Description")).text == ("[CARD] Graphics Card")
    assert item.find(QName(NS.cbc, "AdditionalInformation")).text == (
        "El sistema de la DIAN indico que la firma digital "
        "esta fallida")
    schema.assertValid(debit_note_line)
Example #24
0
def parse_xml(filename, hostname):
    mini_graph_path, root = reconcile_mini_graph_locations(filename, hostname)

    u_neighbors = None
    u_devices = None
    hwsku = None
    bgp_sessions = None
    bgp_asn = None
    intfs = None
    vlan_intfs = None
    pc_intfs = None
    mgmt_intf = None
    lo_intf = None
    neighbors = None
    devices = None
    syslog_servers = []
    dhcp_servers = []
    ntp_servers = []

    hwsku_qn = QName(ns, "HwSku")
    for child in root:
        if child.tag == str(hwsku_qn):
            hwsku = child.text

    # port_alias_map maps ngs port name to sonic port name
    if hwsku == "Force10-S6000":
        for i in range(0, 128, 4):
            port_alias_map["fortyGigE0/%d" % i] = "Ethernet%d" % i
    elif hwsku == "Force10-S6100":
        for i in range(0, 4):
            for j in range(0, 16):
                port_alias_map["fortyGigE1/%d/%d" %
                               (i + 1, j + 1)] = "Ethernet%d" % (i * 16 + j)
    elif hwsku == "Arista-7050-QX32":
        for i in range(1, 25):
            port_alias_map["Ethernet%d/1" % i] = "Ethernet%d" % ((i - 1) * 4)
        for i in range(25, 33):
            port_alias_map["Ethernet%d" % i] = "Ethernet%d" % ((i - 1) * 4)
    else:
        for i in range(0, 128, 4):
            port_alias_map["Ethernet%d" % i] = "Ethernet%d" % i

    for child in root:
        if child.tag == str(QName(ns, "DpgDec")):
            (intfs, lo_intfs, mgmt_intf, vlan_intfs,
             pc_intfs) = parse_dpg(child, hostname)
        elif child.tag == str(QName(ns, "CpgDec")):
            (bgp_sessions, bgp_asn) = parse_cpg(child, hostname)
        elif child.tag == str(QName(ns, "PngDec")):
            (neighbors, devices, console_dev, console_port, mgmt_dev,
             mgmt_port) = parse_png(child, hostname)
        elif child.tag == str(QName(ns, "UngDec")):
            (u_neighbors, u_devices, _, _, _, _) = parse_png(child, hostname)
        elif child.tag == str(QName(ns, "MetadataDeclaration")):
            (syslog_servers, dhcp_servers,
             ntp_servers) = parse_meta(child, hostname)

    # Replace port with alias in Vlan interfaces members
    if vlan_intfs is not None:
        for vlan in vlan_intfs:
            for i, member in enumerate(vlan['members']):
                vlan['members'][i] = port_alias_map[member]
            # Convert vlan members into a space-delimited string
            vlan['members'] = " ".join(vlan['members'])

    # Replace port with alias in port channel interfaces members
    if pc_intfs is not None:
        for pc in pc_intfs:
            for i, member in enumerate(pc['members']):
                pc['members'][i] = port_alias_map[member]

    # Create port index map. Since we currently output a mix of NGS names
    # and SONiC mapped names, we include both in this map.
    # SONiC aliases, when sorted in natural sort order, match the phyical port
    # index order, so we sort by SONiC port alias, and map
    # back to NGS names after sorting using this inverted map
    #
    # TODO: Move all alias-related code out of minigraph_facts.py and into
    # its own module to be used as another layer after parsing the minigraph.
    inverted_port_alias_map = {v: k for k, v in port_alias_map.iteritems()}

    # Start by creating a list of all port aliases
    port_alias_list = []
    for k, v in port_alias_map.iteritems():
        port_alias_list.append(v)

    # Sort the list in natural order
    port_alias_list_sorted = natsorted(port_alias_list)

    # Create map from SONiC alias to physical index and NGS name to physical index
    port_index_map = {}
    for idx, val in enumerate(port_alias_list_sorted):
        port_index_map[val] = idx
        port_index_map[inverted_port_alias_map[val]] = idx

    # Create maps:
    #  from SONiC phy iface name to NGS phy iface name
    #  from NGS phy iface name to SONiC phy iface name
    # These maps include mappings from original name to original name too
    iface_map_sonic_to_ngs = {}
    iface_map_ngs_to_sonic = {}
    for val in port_alias_list_sorted:
        iface_map_sonic_to_ngs[val] = inverted_port_alias_map[val]
        iface_map_sonic_to_ngs[
            inverted_port_alias_map[val]] = inverted_port_alias_map[val]
        iface_map_ngs_to_sonic[inverted_port_alias_map[val]] = val
        iface_map_ngs_to_sonic[val] = val

    # Generate results
    Tree = lambda: defaultdict(Tree)

    results = Tree()
    results['minigraph_hwsku'] = hwsku
    # sorting by lambdas are not easily done without custom filters.
    # TODO: add jinja2 filter to accept a lambda to sort a list of dictionaries by attribute.
    # TODO: alternatively (preferred), implement class containers for multiple-attribute entries, enabling sort by attr
    results['minigraph_bgp'] = sorted(bgp_sessions, key=lambda x: x['addr'])
    results['minigraph_bgp_asn'] = bgp_asn
    # TODO: sort does not work properly on all interfaces of varying lengths. Need to sort by integer group(s).
    results['minigraph_interfaces'] = sorted(intfs, key=lambda x: x['name'])
    results['minigraph_vlan_interfaces'] = vlan_intfs
    results['minigraph_portchannel_interfaces'] = pc_intfs
    results['minigraph_mgmt_interface'] = mgmt_intf
    results['minigraph_lo_interfaces'] = lo_intfs
    results['minigraph_neighbors'] = neighbors
    results['minigraph_devices'] = devices
    results['minigraph_underlay_neighbors'] = u_neighbors
    results['minigraph_underlay_devices'] = u_devices
    # note - this may include files under acs/ansible/minigraph, or those under the default cache folder.
    # (see ANSIBLE_USER_MINIGRAPH_PATH at the top of the module)
    results['minigraph_as_xml'] = mini_graph_path
    results['minigraph_console'] = get_console_info(devices, console_dev,
                                                    console_port)
    results['minigraph_mgmt'] = get_mgmt_info(devices, mgmt_dev, mgmt_port)
    results['minigraph_port_indices'] = port_index_map
    results['minigraph_map_sonic_to_ngs'] = iface_map_sonic_to_ngs
    results['minigraph_map_ngs_to_sonic'] = iface_map_ngs_to_sonic
    results['syslog_servers'] = syslog_servers
    results['dhcp_servers'] = dhcp_servers
    results['ntp_servers'] = ntp_servers

    return results
Example #25
0
def parse_xml(filename, platform=None, port_config_file=None):
    root = ET.parse(filename).getroot()
    mini_graph_path = filename

    u_neighbors = None
    u_devices = None
    hwsku = None
    bgp_sessions = None
    bgp_asn = None
    intfs = None
    vlan_intfs = None
    pc_intfs = None
    vlans = None
    vlan_members = None
    pcs = None
    mgmt_intf = None
    lo_intf = None
    neighbors = None
    devices = None
    hostname = None
    port_speeds = {}
    port_descriptions = {}
    syslog_servers = []
    dhcp_servers = []
    ntp_servers = []
    mgmt_routes = []
    erspan_dst = []
    bgp_peers_with_range = None
    deployment_id = None

    hwsku_qn = QName(ns, "HwSku")
    hostname_qn = QName(ns, "Hostname")
    for child in root:
        if child.tag == str(hwsku_qn):
            hwsku = child.text
        if child.tag == str(hostname_qn):
            hostname = child.text

    (ports, alias_map) = get_port_config(hwsku, platform, port_config_file)
    port_alias_map.update(alias_map)
    for child in root:
        if child.tag == str(QName(ns, "DpgDec")):
            (intfs, lo_intfs, mgmt_intf, vlans, vlan_members, pcs,
             acls) = parse_dpg(child, hostname)
        elif child.tag == str(QName(ns, "CpgDec")):
            (bgp_sessions, bgp_asn,
             bgp_peers_with_range) = parse_cpg(child, hostname)
        elif child.tag == str(QName(ns, "PngDec")):
            (neighbors, devices, console_dev, console_port, mgmt_dev,
             mgmt_port) = parse_png(child, hostname)
        elif child.tag == str(QName(ns, "UngDec")):
            (u_neighbors, u_devices, _, _, _, _) = parse_png(child, hostname)
        elif child.tag == str(QName(ns, "MetadataDeclaration")):
            (syslog_servers, dhcp_servers, ntp_servers, mgmt_routes,
             erspan_dst, deployment_id) = parse_meta(child, hostname)
        elif child.tag == str(QName(ns, "DeviceInfos")):
            (port_speeds, port_descriptions) = parse_deviceinfo(child, hwsku)

    results = {}
    results['DEVICE_METADATA'] = {
        'localhost': {
            'bgp_asn': bgp_asn,
            'deployment_id': deployment_id,
            'hostname': hostname,
            'hwsku': hwsku,
            'type': devices[hostname]['type']
        }
    }
    results['BGP_NEIGHBOR'] = bgp_sessions
    results['BGP_PEER_RANGE'] = bgp_peers_with_range
    if mgmt_routes:
        # TODO: differentiate v4 and v6
        mgmt_intf.itervalues().next()['forced_mgmt_routes'] = mgmt_routes
    results['MGMT_INTERFACE'] = mgmt_intf
    results['LOOPBACK_INTERFACE'] = lo_intfs

    phyport_intfs = {}
    vlan_intfs = {}
    pc_intfs = {}
    for intf in intfs:
        if intf[0][0:4] == 'Vlan':
            vlan_intfs[intf] = {}
        elif intf[0][0:11] == 'PortChannel':
            pc_intfs[intf] = {}
        else:
            phyport_intfs[intf] = {}

    results['INTERFACE'] = phyport_intfs
    results['VLAN_INTERFACE'] = vlan_intfs
    results['PORTCHANNEL_INTERFACE'] = pc_intfs

    for port_name in port_speeds:
        ports.setdefault(port_name, {})['speed'] = port_speeds[port_name]
    for port_name in port_descriptions:
        ports.setdefault(port_name,
                         {})['description'] = port_descriptions[port_name]

    results['PORT'] = ports
    results['PORTCHANNEL'] = pcs
    results['VLAN'] = vlans
    results['VLAN_MEMBER'] = vlan_members

    results['DEVICE_NEIGHBOR'] = neighbors
    results['DEVICE_NEIGHBOR_METADATA'] = {
        key: devices[key]
        for key in devices if key != hostname
    }
    results['SYSLOG_SERVER'] = dict((item, {}) for item in syslog_servers)
    results['DHCP_SERVER'] = dict((item, {}) for item in dhcp_servers)
    results['NTP_SERVER'] = dict((item, {}) for item in ntp_servers)

    results['ACL_TABLE'] = acls
    mirror_sessions = {}
    if erspan_dst:
        lo_addr = '0.0.0.0'
        for lo in lo_intfs:
            lo_network = ipaddress.IPNetwork(lo[1])
            if lo_network.version == 4:
                lo_addr = str(lo_network.ip)
                break
        count = 0
        for dst in erspan_dst:
            mirror_sessions['everflow{}'.format(count)] = {
                "dst_ip": dst,
                "src_ip": lo_addr
            }
            count += 1
        results['MIRROR_SESSION'] = mirror_sessions

    return results
Example #26
0
def parse_png(png, hname):
    neighbors = {}
    devices = {}
    console_dev = ''
    console_port = ''
    mgmt_dev = ''
    mgmt_port = ''
    for child in png:
        if child.tag == str(QName(ns, "DeviceInterfaceLinks")):
            for link in child.findall(str(QName(ns, "DeviceLinkBase"))):
                linktype = link.find(str(QName(ns, "ElementType"))).text
                if linktype != "DeviceInterfaceLink" and linktype != "UnderlayInterfaceLink":
                    continue

                enddevice = link.find(str(QName(ns, "EndDevice"))).text
                endport = link.find(str(QName(ns, "EndPort"))).text
                startdevice = link.find(str(QName(ns, "StartDevice"))).text
                startport = link.find(str(QName(ns, "StartPort"))).text

                if enddevice == hname:
                    neighbors[endport] = {
                        'name': startdevice,
                        'port': startport
                    }
                else:
                    neighbors[startport] = {'name': enddevice, 'port': endport}
        if child.tag == str(QName(ns, "Devices")):
            for device in child.findall(str(QName(ns, "Device"))):
                lo_addr = None
                # don't shadow type()
                d_type = None
                mgmt_addr = None
                hwsku = None
                if str(QName(ns3, "type")) in device.attrib:
                    d_type = device.attrib[str(QName(ns3, "type"))]

                for node in device:
                    if node.tag == str(QName(ns, "Address")):
                        lo_addr = node.find(str(QName(
                            ns2, "IPPrefix"))).text.split('/')[0]
                    elif node.tag == str(QName(ns, "ManagementAddress")):
                        mgmt_addr = node.find(str(QName(
                            ns2, "IPPrefix"))).text.split('/')[0]
                    elif node.tag == str(QName(ns, "Hostname")):
                        name = node.text
                    elif node.tag == str(QName(ns, "HwSku")):
                        hwsku = node.text

                devices[name] = {
                    'lo_addr': lo_addr,
                    'type': d_type,
                    'mgmt_addr': mgmt_addr,
                    'hwsku': hwsku
                }

        if child.tag == str(QName(ns, "DeviceInterfaceLinks")):
            for if_link in child.findall(str(QName(ns, 'DeviceLinkBase'))):
                if str(QName(ns3, "type")) in if_link.attrib:
                    link_type = if_link.attrib[str(QName(ns3, "type"))]
                    if link_type == 'DeviceSerialLink':
                        for node in if_link:
                            if node.tag == str(QName(ns, "EndPort")):
                                console_port = node.text.split()[-1]
                            elif node.tag == str(QName(ns, "EndDevice")):
                                console_dev = node.text
                    elif link_type == 'DeviceMgmtLink':
                        for node in if_link:
                            if node.tag == str(QName(ns, "EndPort")):
                                mgmt_port = node.text.split()[-1]
                            elif node.tag == str(QName(ns, "EndDevice")):
                                mgmt_dev = node.text

    return (neighbors, devices, console_dev, console_port, mgmt_dev, mgmt_port)
Example #27
0
def parse_dpg(dpg, hname):
    for child in dpg:
        hostname = child.find(str(QName(ns, "Hostname")))
        if hostname.text.lower() != hname.lower():
            continue

        ipintfs = child.find(str(QName(ns, "IPInterfaces")))
        intfs = {}
        for ipintf in ipintfs.findall(str(QName(ns, "IPInterface"))):
            intfalias = ipintf.find(str(QName(ns, "AttachTo"))).text
            intfname = port_alias_map.get(intfalias, intfalias)
            ipprefix = ipintf.find(str(QName(ns, "Prefix"))).text
            intfs[(intfname, ipprefix)] = {}

        lointfs = child.find(str(QName(ns, "LoopbackIPInterfaces")))
        lo_intfs = {}
        for lointf in lointfs.findall(str(QName(ns1, "LoopbackIPInterface"))):
            intfname = lointf.find(str(QName(ns, "AttachTo"))).text
            ipprefix = lointf.find(str(QName(ns1, "PrefixStr"))).text
            lo_intfs[(intfname, ipprefix)] = {}

        mgmtintfs = child.find(str(QName(ns, "ManagementIPInterfaces")))
        mgmt_intf = {}
        for mgmtintf in mgmtintfs.findall(
                str(QName(ns1, "ManagementIPInterface"))):
            intfname = mgmtintf.find(str(QName(ns, "AttachTo"))).text
            ipprefix = mgmtintf.find(str(QName(ns1, "PrefixStr"))).text
            mgmtipn = ipaddress.IPNetwork(ipprefix)
            gwaddr = ipaddress.IPAddress(int(mgmtipn.network) + 1)
            mgmt_intf[(intfname, ipprefix)] = {'gwaddr': gwaddr}

        pcintfs = child.find(str(QName(ns, "PortChannelInterfaces")))
        pc_intfs = []
        pcs = {}
        pc_members = {}
        intfs_inpc = []  # List to hold all the LAG member interfaces
        for pcintf in pcintfs.findall(str(QName(ns, "PortChannel"))):
            pcintfname = pcintf.find(str(QName(ns, "Name"))).text
            pcintfmbr = pcintf.find(str(QName(ns, "AttachTo"))).text
            pcmbr_list = pcintfmbr.split(';')
            pc_intfs.append(pcintfname)
            for i, member in enumerate(pcmbr_list):
                pcmbr_list[i] = port_alias_map.get(member, member)
                intfs_inpc.append(pcmbr_list[i])
                pc_members[(pcintfname, pcmbr_list[i])] = {'NULL': 'NULL'}
            if pcintf.find(str(QName(ns, "Fallback"))) != None:
                pcs[pcintfname] = {
                    'members': pcmbr_list,
                    'fallback': pcintf.find(str(QName(ns, "Fallback"))).text,
                    'min_links': str(int(math.ceil(len() * 0.75)))
                }
            else:
                pcs[pcintfname] = {
                    'members': pcmbr_list,
                    'min_links': str(int(math.ceil(len(pcmbr_list) * 0.75)))
                }

        vlanintfs = child.find(str(QName(ns, "VlanInterfaces")))
        vlan_intfs = []
        vlans = {}
        vlan_members = {}
        for vintf in vlanintfs.findall(str(QName(ns, "VlanInterface"))):
            vintfname = vintf.find(str(QName(ns, "Name"))).text
            vlanid = vintf.find(str(QName(ns, "VlanID"))).text
            vintfmbr = vintf.find(str(QName(ns, "AttachTo"))).text
            vmbr_list = vintfmbr.split(';')
            for i, member in enumerate(vmbr_list):
                vmbr_list[i] = port_alias_map.get(member, member)
                sonic_vlan_member_name = "Vlan%s" % (vlanid)
                vlan_members[(sonic_vlan_member_name, vmbr_list[i])] = {
                    'tagging_mode': 'untagged'
                }

            vlan_attributes = {'vlanid': vlanid}

            # If this VLAN requires a DHCP relay agent, it will contain a <DhcpRelays> element
            # containing a list of DHCP server IPs
            vintf_node = vintf.find(str(QName(ns, "DhcpRelays")))
            if vintf_node is not None and vintf_node.text is not None:
                vintfdhcpservers = vintf_node.text
                vdhcpserver_list = vintfdhcpservers.split(';')
                vlan_attributes['dhcp_servers'] = vdhcpserver_list

            sonic_vlan_name = "Vlan%s" % vlanid
            if sonic_vlan_name != vintfname:
                vlan_attributes['alias'] = vintfname
            vlans[sonic_vlan_name] = vlan_attributes

        aclintfs = child.find(str(QName(ns, "AclInterfaces")))
        acls = {}
        for aclintf in aclintfs.findall(str(QName(ns, "AclInterface"))):
            aclname = aclintf.find(str(QName(ns,
                                             "InAcl"))).text.upper().replace(
                                                 " ", "_").replace("-", "_")
            aclattach = aclintf.find(str(QName(ns,
                                               "AttachTo"))).text.split(';')
            acl_intfs = []
            is_mirror = False

            # TODO: Ensure that acl_intfs will only ever contain front-panel interfaces (e.g.,
            # maybe we should explicity ignore management and loopback interfaces?) because we
            # decide an ACL is a Control Plane ACL if acl_intfs is empty below.
            for member in aclattach:
                member = member.strip()
                if pcs.has_key(member):
                    # If try to attach ACL to a LAG interface then we shall add the LAG to
                    # to acl_intfs directly instead of break it into member ports, ACL attach
                    # to LAG will be applied to all the LAG members internally by SAI/SDK
                    acl_intfs.append(member)
                elif vlans.has_key(member):
                    print >> sys.stderr, "Warning: ACL " + aclname + " is attached to a Vlan interface, which is currently not supported"
                elif port_alias_map.has_key(member):
                    acl_intfs.append(port_alias_map[member])
                    # Give a warning if trying to attach ACL to a LAG member interface, correct way is to attach ACL to the LAG interface
                    if port_alias_map[member] in intfs_inpc:
                        print >> sys.stderr, "Warning: ACL " + aclname + " is attached to a LAG member interface " + port_alias_map[
                            member] + ", instead of LAG interface"
                elif member.lower().startswith('erspan'):
                    is_mirror = True
                    # Erspan session will be attached to all front panel ports,
                    # if panel ports is a member port of LAG, should add the LAG
                    # to acl table instead of the panel ports
                    acl_intfs = pc_intfs[:]
                    for panel_port in port_alias_map.values():
                        if panel_port not in intfs_inpc:
                            acl_intfs.append(panel_port)
                    break
            if acl_intfs:
                acls[aclname] = {
                    'policy_desc': aclname,
                    'ports': acl_intfs,
                    'type': 'MIRROR' if is_mirror else 'L3'
                }
            elif is_mirror:
                acls[aclname] = {'policy_desc': aclname, 'type': 'MIRROR'}
            else:
                # This ACL has no interfaces to attach to -- consider this a control plane ACL
                try:
                    aclservice = aclintf.find(str(QName(ns, "Type"))).text

                    # If we already have an ACL with this name and this ACL is bound to a different service,
                    # append the service to our list of services
                    if aclname in acls:
                        if acls[aclname]['type'] != 'CTRLPLANE':
                            print >> sys.stderr, "Warning: ACL '%s' type mismatch. Not updating ACL." % aclname
                        elif acls[aclname]['services'] == aclservice:
                            print >> sys.stderr, "Warning: ACL '%s' already contains service '%s'. Not updating ACL." % (
                                aclname, aclservice)
                        else:
                            acls[aclname]['services'].append(aclservice)
                    else:
                        acls[aclname] = {
                            'policy_desc': aclname,
                            'type': 'CTRLPLANE',
                            'services': [aclservice]
                        }
                except:
                    print >> sys.stderr, "Warning: Ignoring Control Plane ACL %s without type" % aclname

        return intfs, lo_intfs, mgmt_intf, vlans, vlan_members, pcs, pc_members, acls
    return None, None, None, None, None, None, None
Example #28
0
def parse_png(png, hname):
    neighbors = {}
    devices = {}
    console_dev = ''
    console_port = ''
    mgmt_dev = ''
    mgmt_port = ''
    port_speeds = {}
    console_ports = {}
    for child in png:
        if child.tag == str(QName(ns, "DeviceInterfaceLinks")):
            for link in child.findall(str(QName(ns, "DeviceLinkBase"))):
                linktype = link.find(str(QName(ns, "ElementType"))).text
                if linktype == "DeviceSerialLink":
                    enddevice = link.find(str(QName(ns, "EndDevice"))).text
                    endport = link.find(str(QName(ns, "EndPort"))).text
                    startdevice = link.find(str(QName(ns, "StartDevice"))).text
                    startport = link.find(str(QName(ns, "StartPort"))).text
                    baudrate = link.find(str(QName(ns, "Bandwidth"))).text
                    flowcontrol = 1 if link.find(str(QName(ns, "FlowControl"))) is not None and link.find(str(QName(ns, "FlowControl"))).text == 'true' else 0
                    if enddevice.lower() == hname.lower():
                        console_ports[endport] = {
                            'remote_device': startdevice,
                            'baud_rate': baudrate,
                            'flow_control': flowcontrol
                            }
                    else:
                        console_ports[startport] = {
                            'remote_device': enddevice,
                            'baud_rate': baudrate,
                            'flow_control': flowcontrol
                            }
                    continue

                if linktype != "DeviceInterfaceLink" and linktype != "UnderlayInterfaceLink":
                    continue

                enddevice = link.find(str(QName(ns, "EndDevice"))).text
                endport = link.find(str(QName(ns, "EndPort"))).text
                startdevice = link.find(str(QName(ns, "StartDevice"))).text
                startport = link.find(str(QName(ns, "StartPort"))).text
                bandwidth_node = link.find(str(QName(ns, "Bandwidth")))
                bandwidth = bandwidth_node.text if bandwidth_node is not None else None

                if enddevice.lower() == hname.lower():
                    if port_alias_map.has_key(endport):
                        endport = port_alias_map[endport]
                    neighbors[endport] = {'name': startdevice, 'port': startport}
                    if bandwidth:
                        port_speeds[endport] = bandwidth
                else:
                    if port_alias_map.has_key(startport):
                        startport = port_alias_map[startport]
                    neighbors[startport] = {'name': enddevice, 'port': endport}
                    if bandwidth:
                        port_speeds[startport] = bandwidth

        if child.tag == str(QName(ns, "Devices")):
            for device in child.findall(str(QName(ns, "Device"))):
                (lo_prefix, mgmt_prefix, name, hwsku, d_type, deployment_id) = parse_device(device)
                device_data = {'lo_addr': lo_prefix, 'type': d_type, 'mgmt_addr': mgmt_prefix, 'hwsku': hwsku }
                if deployment_id:
                    device_data['deployment_id'] = deployment_id
                devices[name] = device_data

        if child.tag == str(QName(ns, "DeviceInterfaceLinks")):
            for if_link in child.findall(str(QName(ns, 'DeviceLinkBase'))):
                if str(QName(ns3, "type")) in if_link.attrib:
                    link_type = if_link.attrib[str(QName(ns3, "type"))]
                    if link_type == 'DeviceSerialLink':
                        for node in if_link:
                            if node.tag == str(QName(ns, "EndPort")):
                                console_port = node.text.split()[-1]
                            elif node.tag == str(QName(ns, "EndDevice")):
                                console_dev = node.text
                    elif link_type == 'DeviceMgmtLink':
                        for node in if_link:
                            if node.tag == str(QName(ns, "EndPort")):
                                mgmt_port = node.text.split()[-1]
                            elif node.tag == str(QName(ns, "EndDevice")):
                                mgmt_dev = node.text

    return (neighbors, devices, console_dev, console_port, mgmt_dev, mgmt_port, port_speeds, console_ports)
Example #29
0
def parse_xml(filename, platform=None, port_config_file=None):
    root = ET.parse(filename).getroot()
    mini_graph_path = filename

    u_neighbors = None
    u_devices = None
    hwsku = None
    bgp_sessions = None
    bgp_asn = None
    intfs = None
    vlan_intfs = None
    pc_intfs = None
    vlans = None
    vlan_members = None
    pcs = None
    mgmt_intf = None
    lo_intf = None
    neighbors = None
    devices = None
    hostname = None
    docker_routing_config_mode = "unified"
    port_speeds_default = {}
    port_speed_png = {}
    port_descriptions = {}
    console_ports = {}
    syslog_servers = []
    dhcp_servers = []
    ntp_servers = []
    tacacs_servers = []
    mgmt_routes = []
    erspan_dst = []
    bgp_peers_with_range = None
    deployment_id = None

    hwsku_qn = QName(ns, "HwSku")
    hostname_qn = QName(ns, "Hostname")
    docker_routing_config_mode_qn = QName(ns, "DockerRoutingConfigMode")
    for child in root:
        if child.tag == str(hwsku_qn):
            hwsku = child.text
        if child.tag == str(hostname_qn):
            hostname = child.text
        if child.tag == str(docker_routing_config_mode_qn):
            docker_routing_config_mode = child.text

    (ports, alias_map) = get_port_config(hwsku, platform, port_config_file)
    port_alias_map.update(alias_map)
    for child in root:
        if child.tag == str(QName(ns, "DpgDec")):
            (intfs, lo_intfs, mgmt_intf, vlans, vlan_members, pcs, pc_members,
             acls) = parse_dpg(child, hostname)
        elif child.tag == str(QName(ns, "CpgDec")):
            (bgp_sessions, bgp_asn,
             bgp_peers_with_range) = parse_cpg(child, hostname)
        elif child.tag == str(QName(ns, "PngDec")):
            (neighbors, devices, console_dev, console_port, mgmt_dev,
             mgmt_port, port_speed_png,
             console_ports) = parse_png(child, hostname)
        elif child.tag == str(QName(ns, "UngDec")):
            (u_neighbors, u_devices, _, _, _, _, _,
             _) = parse_png(child, hostname)
        elif child.tag == str(QName(ns, "MetadataDeclaration")):
            (syslog_servers, dhcp_servers, ntp_servers, tacacs_servers,
             mgmt_routes, erspan_dst,
             deployment_id) = parse_meta(child, hostname)
        elif child.tag == str(QName(ns, "DeviceInfos")):
            (port_speeds_default,
             port_descriptions) = parse_deviceinfo(child, hwsku)

    current_device = [
        devices[key] for key in devices if key.lower() == hostname.lower()
    ][0]
    results = {}
    results['DEVICE_METADATA'] = {
        'localhost': {
            'bgp_asn': bgp_asn,
            'deployment_id': deployment_id,
            'docker_routing_config_mode': docker_routing_config_mode,
            'hostname': hostname,
            'hwsku': hwsku,
            'type': current_device['type']
        }
    }
    results['BGP_NEIGHBOR'] = bgp_sessions
    results['BGP_PEER_RANGE'] = bgp_peers_with_range
    if mgmt_routes:
        # TODO: differentiate v4 and v6
        mgmt_intf.itervalues().next()['forced_mgmt_routes'] = mgmt_routes
    results['MGMT_PORT'] = {}
    results['MGMT_INTERFACE'] = {}
    mgmt_intf_count = 0
    mgmt_alias_reverse_mapping = {}
    for key in mgmt_intf:
        alias = key[0]
        if mgmt_alias_reverse_mapping.has_key(alias):
            name = mgmt_alias_reverse_mapping[alias]
        else:
            name = 'eth' + str(mgmt_intf_count)
            mgmt_intf_count += 1
            mgmt_alias_reverse_mapping[alias] = name
        results['MGMT_PORT'][name] = {'alias': alias, 'admin_status': 'up'}
        results['MGMT_INTERFACE'][(name, key[1])] = mgmt_intf[key]
    results['LOOPBACK_INTERFACE'] = lo_intfs

    phyport_intfs = {}
    vlan_intfs = {}
    pc_intfs = {}
    vlan_invert_mapping = {
        v['alias']: k
        for k, v in vlans.items() if v.has_key('alias')
    }

    for intf in intfs:
        if intf[0][0:4] == 'Vlan':
            vlan_intfs[intf] = {}
        elif vlan_invert_mapping.has_key(intf[0]):
            vlan_intfs[(vlan_invert_mapping[intf[0]], intf[1])] = {}
        elif intf[0][0:11] == 'PortChannel':
            pc_intfs[intf] = {}
        else:
            phyport_intfs[intf] = {}

    results['INTERFACE'] = phyport_intfs
    results['VLAN_INTERFACE'] = vlan_intfs

    for port_name in port_speeds_default:
        # ignore port not in port_config.ini
        if not ports.has_key(port_name):
            continue

        ports.setdefault(port_name,
                         {})['speed'] = port_speeds_default[port_name]

    for port_name in port_speed_png:
        # not consider port not in port_config.ini
        if port_name not in ports:
            print >> sys.stderr, "Warning: ignore interface '%s' as it is not in the port_config.ini" % port_name
            continue

        ports.setdefault(port_name, {})['speed'] = port_speed_png[port_name]

    for port_name, port in ports.items():
        if port.get('speed') == '100000':
            port['fec'] = 'rs'

    # set port description if parsed from deviceinfo
    for port_name in port_descriptions:
        # ignore port not in port_config.ini
        if not ports.has_key(port_name):
            continue

        ports.setdefault(port_name,
                         {})['description'] = port_descriptions[port_name]

    for port_name, port in ports.items():
        if not port.get('description'):
            if neighbors.has_key(port_name):
                # for the ports w/o description set it to neighbor name:port
                port['description'] = "%s:%s" % (neighbors[port_name]['name'],
                                                 neighbors[port_name]['port'])
            else:
                # for the ports w/o neighbor info, set it to port alias
                port['description'] = port.get('alias', port_name)

    # set default port MTU as 9100
    for port in ports.itervalues():
        port['mtu'] = '9100'

    # asymmetric PFC is disabled by default
    for port in ports.itervalues():
        port['pfc_asym'] = 'off'

    # set physical port default admin status up
    for port in phyport_intfs:
        if port[0] in ports:
            ports.get(port[0])['admin_status'] = 'up'

    for member in pc_members.keys() + vlan_members.keys():
        port = ports.get(member[1])
        if port:
            port['admin_status'] = 'up'

    results['PORT'] = ports
    results['CONSOLE_PORT'] = console_ports

    if port_config_file:
        port_set = set(ports.keys())
        for (pc_name, mbr_map) in pcs.items():
            # remove portchannels that contain ports not existing in port_config.ini
            # when port_config.ini exists
            if not set(mbr_map['members']).issubset(port_set):
                print >> sys.stderr, "Warning: ignore '%s' as part of its member interfaces is not in the port_config.ini" % pc_name
                del pcs[pc_name]

    # set default port channel MTU as 9100 and admin status up
    for pc in pcs.itervalues():
        pc['mtu'] = '9100'
        pc['admin_status'] = 'up'

    results['PORTCHANNEL'] = pcs
    results['PORTCHANNEL_MEMBER'] = pc_members

    for pc_intf in pc_intfs.keys():
        # remove portchannels not in PORTCHANNEL dictionary
        if pc_intf[0] not in pcs:
            print >> sys.stderr, "Warning: ignore '%s' interface '%s' as '%s' is not in the valid PortChannel list" % (
                pc_intf[0], pc_intf[1], pc_intf[0])
            del pc_intfs[pc_intf]

    results['PORTCHANNEL_INTERFACE'] = pc_intfs

    results['VLAN'] = vlans
    results['VLAN_MEMBER'] = vlan_members

    for nghbr in neighbors.keys():
        # remove port not in port_config.ini
        if nghbr not in ports:
            print >> sys.stderr, "Warning: ignore interface '%s' in DEVICE_NEIGHBOR as it is not in the port_config.ini" % nghbr
            del neighbors[nghbr]

    results['DEVICE_NEIGHBOR'] = neighbors
    results['DEVICE_NEIGHBOR_METADATA'] = {
        key: devices[key]
        for key in devices if key.lower() != hostname.lower()
    }
    results['SYSLOG_SERVER'] = dict((item, {}) for item in syslog_servers)
    results['DHCP_SERVER'] = dict((item, {}) for item in dhcp_servers)
    results['NTP_SERVER'] = dict((item, {}) for item in ntp_servers)
    results['TACPLUS_SERVER'] = dict((item, {
        'priority': '1',
        'tcp_port': '49'
    }) for item in tacacs_servers)

    results['ACL_TABLE'] = acls
    mirror_sessions = {}
    if erspan_dst:
        lo_addr = '0.0.0.0'
        for lo in lo_intfs:
            lo_network = ipaddress.IPNetwork(lo[1])
            if lo_network.version == 4:
                lo_addr = str(lo_network.ip)
                break
        count = 0
        for dst in erspan_dst:
            mirror_sessions['everflow{}'.format(count)] = {
                "dst_ip": dst,
                "src_ip": lo_addr
            }
            count += 1
        results['MIRROR_SESSION'] = mirror_sessions

    return results
Example #30
0
def _etree_mutate_fix_localname(etree):
    for _x in etree.iter(Element):    # side-effect to remove some (wrongfully) surviving namespace stuff from HTML(5)Parser
        if _x.tag != QName(_x).localname:
            _x.tag = QName(_x).localname

    return etree