parent
43b0e502de
commit
ed9c8fbe8e
5
rules/sonic-config.mk
Normal file
5
rules/sonic-config.mk
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# sonic-config-engine package
|
||||||
|
|
||||||
|
SONIC_CONFIG_ENGINE = sonic-config-engine_1.0-1_all.deb
|
||||||
|
$(SONIC_CONFIG_ENGINE)_SRC_PATH = $(SRC_PATH)/sonic-config-engine
|
||||||
|
SONIC_PYTHON_STDEB_DEBS += $(SONIC_CONFIG_ENGINE)
|
381
src/sonic-config-engine/minigraph.py
Normal file
381
src/sonic-config-engine/minigraph.py
Normal file
@ -0,0 +1,381 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
import calendar
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import socket
|
||||||
|
import struct
|
||||||
|
import json
|
||||||
|
import copy
|
||||||
|
import ipaddr as ipaddress
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
|
from lxml import etree as ET
|
||||||
|
from lxml.etree import QName
|
||||||
|
|
||||||
|
DOCUMENTATION = '''
|
||||||
|
---
|
||||||
|
module: minigraph_facts
|
||||||
|
version_added: "1.9"
|
||||||
|
author: Guohan Lu (gulv@microsoft.com)
|
||||||
|
short_description: Retrive minigraph facts for a device.
|
||||||
|
description:
|
||||||
|
- Retrieve minigraph facts for a device, the facts will be
|
||||||
|
inserted to the ansible_facts key.
|
||||||
|
options:
|
||||||
|
host:
|
||||||
|
description:
|
||||||
|
- Set to target snmp server (normally {{inventory_hostname}})
|
||||||
|
required: true
|
||||||
|
'''
|
||||||
|
|
||||||
|
EXAMPLES = '''
|
||||||
|
# Gather minigraph facts
|
||||||
|
- name: Gathering minigraph facts about the device
|
||||||
|
minigraph_facts: host={{ hostname }}
|
||||||
|
'''
|
||||||
|
|
||||||
|
ns = "Microsoft.Search.Autopilot.Evolution"
|
||||||
|
ns1 = "http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolution"
|
||||||
|
ns2 = "Microsoft.Search.Autopilot.NetMux"
|
||||||
|
ns3 = "http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
|
||||||
|
class minigraph_encoder(json.JSONEncoder):
|
||||||
|
def default(self, obj):
|
||||||
|
if isinstance(obj, (ipaddress.IPv4Network, ipaddress.IPv6Network, ipaddress.IPv4Address, ipaddress.IPv6Address)):
|
||||||
|
return str(obj)
|
||||||
|
return json.JSONEncoder.default(self, obj)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
def parse_cpg(cpg, hname):
|
||||||
|
bgp_sessions = []
|
||||||
|
myasn = None
|
||||||
|
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)
|
||||||
|
else:
|
||||||
|
for bgp_session in bgp_sessions:
|
||||||
|
if hostname == bgp_session['name']:
|
||||||
|
bgp_session['asn'] = int(asn)
|
||||||
|
|
||||||
|
return bgp_sessions, myasn
|
||||||
|
|
||||||
|
|
||||||
|
def get_console_info(devices, dev, port):
|
||||||
|
for k, v in devices.items():
|
||||||
|
if k == dev:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
ret_val = v
|
||||||
|
ret_val.update({
|
||||||
|
'ts_port': port,
|
||||||
|
'ts_dev': dev
|
||||||
|
})
|
||||||
|
|
||||||
|
return ret_val
|
||||||
|
|
||||||
|
def get_mgmt_info(devices, dev, port):
|
||||||
|
for k, v in devices.items():
|
||||||
|
if k == dev:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
ret_val = v
|
||||||
|
ret_val.update({
|
||||||
|
'mgmt_port': port,
|
||||||
|
'mgmt_dev': dev
|
||||||
|
})
|
||||||
|
|
||||||
|
return ret_val
|
||||||
|
|
||||||
|
def parse_xml(filename):
|
||||||
|
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
|
||||||
|
mgmt_intf = None
|
||||||
|
lo_intf = None
|
||||||
|
neighbors = None
|
||||||
|
devices = None
|
||||||
|
hostname = 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
|
||||||
|
|
||||||
|
# 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 == "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)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
# Replace port with alias in Vlan interfaces members
|
||||||
|
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
|
||||||
|
for pc in pc_intfs:
|
||||||
|
for i,member in enumerate(pc['members']):
|
||||||
|
pc['members'][i] = port_alias_map[member]
|
||||||
|
|
||||||
|
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
|
||||||
|
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['inventory_hostname'] = hostname
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
port_alias_map = {}
|
||||||
|
|
||||||
|
|
||||||
|
def print_parse_xml(filename):
|
||||||
|
results = parse_xml(filename)
|
||||||
|
print(json.dumps(results, indent=3, cls=minigraph_encoder))
|
||||||
|
|
||||||
|
|
14
src/sonic-config-engine/setup.py
Normal file
14
src/sonic-config-engine/setup.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
from setuptools import setup
|
||||||
|
|
||||||
|
setup(name='sonic-config-engine',
|
||||||
|
version='1.0',
|
||||||
|
description='Utilities for generating SONiC configuration files',
|
||||||
|
author='Taoyu Li',
|
||||||
|
author_email='taoyl@microsoft.com',
|
||||||
|
url='https://github.com/Azure/sonic-buildimage',
|
||||||
|
py_modules=['minigraph'],
|
||||||
|
scripts=['sonic-cfggen'],
|
||||||
|
install_requires=['lxml', 'jinja2', 'netaddr', 'ipaddr', 'yaml'],
|
||||||
|
)
|
63
src/sonic-config-engine/sonic-cfggen
Executable file
63
src/sonic-config-engine/sonic-cfggen
Executable file
@ -0,0 +1,63 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os.path
|
||||||
|
import argparse
|
||||||
|
import yaml
|
||||||
|
import jinja2
|
||||||
|
import netaddr
|
||||||
|
from minigraph import parse_xml
|
||||||
|
|
||||||
|
|
||||||
|
def is_ipv4(value):
|
||||||
|
if not value:
|
||||||
|
return False
|
||||||
|
if isinstance(value, netaddr.IPAddress):
|
||||||
|
addr = value
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
addr = netaddr.IPAddress(str(value))
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
return addr.version == 4
|
||||||
|
|
||||||
|
def is_ipv6(value):
|
||||||
|
if not value:
|
||||||
|
return False
|
||||||
|
if isinstance(value, netaddr.IPAddress):
|
||||||
|
addr = value
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
addr = netaddr.IPAddress(str(value))
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
return addr.version == 6
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser=argparse.ArgumentParser(description="Render configuration file from minigraph data and jinja2 template.")
|
||||||
|
parser.add_argument("template")
|
||||||
|
parser.add_argument("-m", "--minigraph", required=True, help="minigraph xml file")
|
||||||
|
parser.add_argument("-v", "--var-file", help="yaml file that contains addtional variables")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
minigraph = args.minigraph
|
||||||
|
template_file = os.path.abspath(args.template)
|
||||||
|
|
||||||
|
data = parse_xml(minigraph)
|
||||||
|
|
||||||
|
if args.var_file != None:
|
||||||
|
with open(args.var_file, 'r') as stream:
|
||||||
|
additional_data = yaml.load(stream)
|
||||||
|
data.update(additional_data)
|
||||||
|
|
||||||
|
env = jinja2.Environment(loader=jinja2.FileSystemLoader('/'), trim_blocks=True)
|
||||||
|
env.filters['ipv4'] = is_ipv4
|
||||||
|
env.filters['ipv6'] = is_ipv6
|
||||||
|
template = env.get_template(template_file)
|
||||||
|
|
||||||
|
print template.render(data)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
Reference in New Issue
Block a user