<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: tech_kitara</title>
    <description>The latest articles on DEV Community by tech_kitara (@tachashi).</description>
    <link>https://dev.to/tachashi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F302007%2Fe830a8e4-f0ae-4764-8354-79eedf78dc76.jpeg</url>
      <title>DEV Community: tech_kitara</title>
      <link>https://dev.to/tachashi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tachashi"/>
    <language>en</language>
    <item>
      <title>Generate Cisco Layer2 Switch Config from Port Management Table and Jinja2 Template</title>
      <dc:creator>tech_kitara</dc:creator>
      <pubDate>Tue, 31 Dec 2019 17:02:09 +0000</pubDate>
      <link>https://dev.to/tachashi/generate-cisco-layer2-switch-config-from-port-management-table-and-jinja2-template-3fap</link>
      <guid>https://dev.to/tachashi/generate-cisco-layer2-switch-config-from-port-management-table-and-jinja2-template-3fap</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;It is troublesome to create configs for network devices manually. In particular, when introducing a large amount of layer2 switches at once, it is easy to inadvertently forget to modify the unique settings.&lt;/p&gt;

&lt;p&gt;In this post, I tried to automatically generate the config from a port management table and parameter sheet by rendering Jinja2 template.&lt;/p&gt;

&lt;h1&gt;
  
  
  Port Management Table
&lt;/h1&gt;

&lt;p&gt;This time, I prepared the management table for Cisco Catalyst2960 switch with 8 + 2 ports.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;port_list_hqaccess1.csv&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TQsBaNTQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/6j3mgjbdqkh4gwm11l12.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TQsBaNTQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/6j3mgjbdqkh4gwm11l12.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The two uplink ports are connected to L3SW, and the eight downlink ports are connected to the terminal (status = o) or closed (status = x).&lt;br&gt;
In addition, the uplink ports are connected by trunk VLANs, and downlink access ports use VLAN 100 or 101 with STP portfast setting.&lt;/p&gt;
&lt;h1&gt;
  
  
  Parameter Sheet
&lt;/h1&gt;

&lt;p&gt;In this sheet, global settings unique to each device, such as the hostname, login information, and address, are defined in CSV format.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;parameter_list_hqaccess1.csv&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--H6Uio4IW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/rgi5o4adu7dks5ra7ocd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H6Uio4IW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/rgi5o4adu7dks5ra7ocd.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Jinja2 Template
&lt;/h1&gt;

&lt;p&gt;Settings that are different for each device are defined in &lt;code&gt;{{ var }}&lt;/code&gt;.&lt;br&gt;
Physical interface settings are enclosed by &lt;code&gt;{%- for item in interfaces %}&lt;/code&gt; and &lt;code&gt;{%- endfor %}&lt;/code&gt; to repeat the data in the port management table.&lt;/p&gt;

&lt;p&gt;Also, the types of interface (description, switchport mode, speed, duplex, portfast, and status) are defined like &lt;code&gt;{% if x == 'y' %}&lt;/code&gt;-&lt;code&gt;{% endif %}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;catalyst2960_template.txt&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jinja"&gt;&lt;code&gt;!
no service pad
service timestamps debug datetime localtime
service timestamps log datetime localtime
service password-encryption
!
hostname &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;hostname&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
!
no logging console
enable secret &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;secret&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
!
username &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;username&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt; privilege 15 password &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;password&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
clock timezone JST 9
ip subnet-zero
no ip domain-lookup
ip domain-name &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;hostname&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
ip ssh version 2
!
spanning-tree mode pvst
no spanning-tree optimize bpdu transmission
spanning-tree extend system-id
!
!
&lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;interfaces&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
interface &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;item.port_no&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
&lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;item.description&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
 description &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt; &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;item.description&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&amp;gt;
&lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;endif&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
&lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;item.mode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'access'&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
 switchport access &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;item.vlan&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
 switchport mode access
&lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;elif&lt;/span&gt; &lt;span class="nv"&gt;item.mode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'trunk'&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
 switchport mode trunk
&lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;endif&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
&lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;item.duplex&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s1"&gt;'auto'&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
 duplex &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;item.duplex&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
&lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;endif&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
&lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;item.speed&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s1"&gt;'auto'&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
 speed &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;item.speed&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
&lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;endif&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
&lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;item.status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'x'&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
 shutdown
&lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;endif&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
&lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;item.portfast&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'o'&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
 spanning-tree portfast
&lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;endif&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
!
&lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;endfor&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
!
interface Vlan1
 no ip address
 no ip route-cache
 shutdown
!
interface Vlan&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;vlan_num&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
 description &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;vlan_desc&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
 ip address &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;ip_address&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt; &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;subnet&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
 no ip route-cache
!
ip default-gateway &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;default_gw&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
no ip http server
no ip http secure-server
!
logging 192.168.100.107
snmp-server community C1sc0 RO
snmp-server host 192.168.100.107 C1sc0 
banner login ^C
============NOTICE==============
| This is test device for demo |
================================
^C
!
line con 0
line vty 0 4
 login local
line vty 5 15
 login local
!
ntp server &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;ntp_server&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
!
crypto key generate rsa modulus 2048
!
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Python Script
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;config_generation.py&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# -*- coding: utf-8 -*-
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;jinja2&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;csv&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;re&lt;/span&gt;

&lt;span class="c1"&gt;# Define the path of each files
&lt;/span&gt;&lt;span class="n"&gt;TEMPLATE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'./catalyst2960_template.txt'&lt;/span&gt;
&lt;span class="n"&gt;PARAMETER_LIST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'./parameter_list_hqaccess1.csv'&lt;/span&gt;
&lt;span class="n"&gt;PORT_LIST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'./port_list_hqaccess1.csv'&lt;/span&gt;
&lt;span class="n"&gt;CONFIG_FILENAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'./config_hqaccess1.txt'&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;build_templates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;template_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parameter_list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port_list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config_filename&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="n"&gt;templateLoader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jinja2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FileSystemLoader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'./'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;templateEnv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jinja2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loader&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;templateLoader&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;templateEnv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;template_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Read the parameter sheet and convert it to a dictionary format
&lt;/span&gt;    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parameter_list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'rt'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;reader_param&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DictReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;dict_row1&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;reader_param&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;dict_param&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_row1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Read the port management table and convert it to a dictionary format
&lt;/span&gt;    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port_list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'rt'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;fl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;reader_port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DictReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;dict_port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'interfaces'&lt;/span&gt;&lt;span class="p"&gt;:[]}&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;dict_row2&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;reader_port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;dict_port&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'interfaces'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_row2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c1"&gt;# Combine the port table to the parameter sheet
&lt;/span&gt;    &lt;span class="n"&gt;dict_param&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_param&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Render the combined data to Jinja2 template and output the config
&lt;/span&gt;    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config_filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'w'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;cf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;outputText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dict_param&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;cf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outputText&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Config File: %s"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;config_filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"__main__"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;build_templates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TEMPLATE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PARAMETER_LIST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PORT_LIST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CONFIG_FILENAME&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The point is that the port management table and parameter sheet are converted from CSV format to dictionary format when rendering to Jinja2 template.&lt;br&gt;
The following is the contents of the dictionary variable &lt;code&gt;dict_param&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{'hostname': 'hqaccess1', 'hardware': 'Catalyst2960', 'secret': 'test', 'username': 'test', 'password': 'cisco', 'vlan_num': '100', 'vlan_desc': '&amp;lt;&amp;lt; Server Segment &amp;gt;&amp;gt;', 'ip_address': '192.168.100.47', 'subnet': '255.255.255.0', 'default_gw': '192.168.100.150', 'ntp_server': '192.168.100.44', 'interfaces': [{'port_no': 'FastEthernet0/1', 'speed': 'auto', 'duplex': 'auto', 'mode': 'access', 'vlan': '100', 'portfast': 'o', 'status': 'o', 'description': 'To PC1'}, {'port_no': 'FastEthernet0/2', 'speed': 'auto', 'duplex': 'auto', 'mode': 'access', 'vlan': '100', 'portfast': 'o', 'status': 'o', 'description': 'To PC2'}, {'port_no': 'FastEthernet0/3', 'speed': 'auto', 'duplex': 'auto', 'mode': 'access', 'vlan': '100', 'portfast': 'o', 'status': 'x', 'description': ''}, {'port_no': 'FastEthernet0/4', 'speed': 'auto', 'duplex': 'auto', 'mode': 'access', 'vlan': '100', 'portfast': 'o', 'status': 'x', 'description': ''}, {'port_no': 'FastEthernet0/5', 'speed': 'auto', 'duplex': 'auto', 'mode': 'access', 'vlan': '101', 'portfast': 'o', 'status': 'o', 'description': 'To PC3'}, {'port_no': 'FastEthernet0/6', 'speed': 'auto', 'duplex': 'auto', 'mode': 'access', 'vlan': '101', 'portfast': 'o', 'status': 'o', 'description': 'To PC4'}, {'port_no': 'FastEthernet0/7', 'speed': 'auto', 'duplex': 'auto', 'mode': 'access', 'vlan': '101', 'portfast': 'o', 'status': 'x', 'description': ''}, {'port_no': 'FastEthernet0/8', 'speed': 'auto', 'duplex': 'auto', 'mode': 'access', 'vlan': '101', 'portfast': 'o', 'status': 'x', 'description': ''}, {'port_no': 'GigabitEthernet0/1', 'speed': '1000', 'duplex': 'full', 'mode': 'trunk', 'vlan': '', 'portfast': 'x', 'status': 'o', 'description': 'To hqdist1 Gi0/1'}, {'port_no': 'GigabitEthernet0/2', 'speed': '1000', 'duplex': 'full', 'mode': 'trunk', 'vlan': '', 'portfast': 'x', 'status': 'o', 'description': 'To hqdist2 Gi0/1'}]}
Config File: ./config_hqaccess1.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Generated Config
&lt;/h1&gt;

&lt;p&gt;Jinja2 template (left) and generated config (right) are compared.&lt;br&gt;
You can see that the expected values ​​are embedded in the config.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--E8IG5pEP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/b2f32sxcislov6nbt6d0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E8IG5pEP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/b2f32sxcislov6nbt6d0.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>network</category>
      <category>jinja2</category>
      <category>cisco</category>
    </item>
  </channel>
</rss>
