├── 10_get_config.py ├── 11_file_system.py ├── 12_utils_scp.py ├── 13_utils_sw_install.py ├── 14_utils_startshell.py ├── 1_gather_facts.py ├── 2_rpc_call.py ├── 3_cli_call.py ├── 4_load_text_config.py ├── 5_load_xml_config.py ├── 6_load_temp_conf.py ├── 7_rollback_config.py ├── 8_table_view.py ├── 9_user_defined_table.py ├── PyEZ_2_0_0.ipynb ├── PyEZ_demo_sept.ipynb ├── README.md ├── console.ipynb ├── fpc-info.py ├── generate_conf_from_template.py ├── images └── serial_conn.jpg ├── plot_tcp.py ├── protocol_data.yml ├── protocol_temp.j2 ├── table_view_from_existing_xml_file.py └── templates ├── 1_temp.j2 ├── create_vlans.conf ├── data_vars.yaml ├── filter.j2 ├── generate_conf_from_template.py ├── main.j2 ├── main_vlans.conf ├── remove_vlans.conf ├── sshkeys ├── lakhan ├── lakhan.pub ├── ram └── ram.pub ├── template.j2 ├── users.j2 ├── vlans.csv ├── yaml_jinja_demo.ipynb └── yaml_jinja_demo.md /10_get_config.py: -------------------------------------------------------------------------------- 1 | from jnpr.junos import Device 2 | from lxml import etree 3 | 4 | dev = Device(host='xxxx', user='demo', password='demo123', gather_facts=False) 5 | dev.open() 6 | 7 | cnf = dev.rpc.get_config() 8 | #cnf = dev.rpc.get_config(filter_xml=etree.XML('')) 9 | print etree.tostring(cnf) 10 | -------------------------------------------------------------------------------- /11_file_system.py: -------------------------------------------------------------------------------- 1 | from jnpr.junos.utils.fs import FS 2 | from jnpr.junos import Device 3 | 4 | dev = Device(host='xxxx', user='demo', password='demo123') 5 | dev.open() 6 | 7 | fs = FS(dev) 8 | pprint(fs.ls('/var/tmp')) 9 | 10 | dev.close() 11 | -------------------------------------------------------------------------------- /12_utils_scp.py: -------------------------------------------------------------------------------- 1 | from jnpr.junos import Device 2 | from jnpr.junos.utils.scp import SCP 3 | 4 | dev = Device(host='xxxx', user='demo', password='demo123') 5 | dev.open() 6 | 7 | with SCP(dev, progress=True) as scp: 8 | scp.get('/var/tmp/nitin.log','info.txt') 9 | dev.close() 10 | -------------------------------------------------------------------------------- /13_utils_sw_install.py: -------------------------------------------------------------------------------- 1 | from jnpr.junos import Device 2 | from jnpr.junos.utils.sw import SW 3 | 4 | dev = Device(host='xxxx', user='demo', password='demo123', gather_facts=False) 5 | dev.open() 6 | 7 | def update_progress(dev, report): 8 | print dev.hostname, '> ', report 9 | 10 | sw = SW(dev) 11 | ok = sw.install(package=r'/Users/nitinkr/Downloads/jinstall-1x.1xxxx.tgz', progress=update_progress) 12 | # progress takes boolean values too from 1.2.3 version onwards 13 | #ok = sw.install(package=r'/Users/nitinkr/Downloads/jinstall-1x.1xxxx.tgz', progress=True) 14 | if ok: 15 | print 'rebooting' 16 | sw.reboot() 17 | -------------------------------------------------------------------------------- /14_utils_startshell.py: -------------------------------------------------------------------------------- 1 | from jnpr.junos.utils.start_shell import StartShell 2 | from jnpr.junos import Device 3 | from jnpr.junos.utils.scp import SCP 4 | 5 | dev = Device(host='xxxx', user='demo', password='demo123') 6 | dev.open() 7 | 8 | ss = StartShell(dev) 9 | ss.open() 10 | ss.run('cli -c "request support information | save /var/tmp/information.txt"') 11 | with SCP(dev) as scp: 12 | scp.get('/var/tmp/information.txt','info.txt') 13 | 14 | ss.close() 15 | -------------------------------------------------------------------------------- /1_gather_facts.py: -------------------------------------------------------------------------------- 1 | from jnpr.junos import Device 2 | from pprint import pprint 3 | 4 | dev = Device(host='xxxx', user='demo', password='demo123') 5 | dev.open() 6 | 7 | pprint (dev.facts) 8 | -------------------------------------------------------------------------------- /2_rpc_call.py: -------------------------------------------------------------------------------- 1 | from jnpr.junos import Device 2 | from lxml import etree 3 | 4 | dev = Device(host='xxxx', user='demo', password='demo123', gather_facts=False) 5 | dev.open() 6 | 7 | op = dev.rpc.get_interface_information() 8 | #op = dev.rpc.get_interface_information({'format': 'text'}) 9 | #op = dev.rpc.get_interface_information(interface_name='lo0', terse=True) 10 | print (etree.tostring(op)) 11 | 12 | #for i in op.xpath('.//link-level-type'): 13 | # print i.text 14 | dev.close() 15 | -------------------------------------------------------------------------------- /3_cli_call.py: -------------------------------------------------------------------------------- 1 | from jnpr.junos import Device 2 | 3 | with Device(host='xxxx', user='demo', password='demo123') as dev: 4 | print (dev.cli("show version", warning=False)) 5 | -------------------------------------------------------------------------------- /4_load_text_config.py: -------------------------------------------------------------------------------- 1 | from jnpr.junos import Device 2 | from jnpr.junos.utils.config import Config 3 | 4 | dev = Device(host='xxxx', user='demo', password='demo123', gather_facts=False) 5 | dev.open() 6 | 7 | cu = Config(dev) 8 | data = """interfaces { 9 | ge-1/0/1 { 10 | description "MPLS interface"; 11 | unit 0 { 12 | family mpls; 13 | } 14 | } 15 | ge-1/0/2 { 16 | description "MPLS interface"; 17 | unit 0 { 18 | family mpls; 19 | } 20 | } 21 | } 22 | protocols { 23 | mpls { 24 | interface ge-1/0/1; 25 | interface ge-1/0/2; 26 | } 27 | } 28 | """ 29 | cu.load(data, format='text') 30 | cu.pdiff() 31 | if cu.commit_check(): 32 | cu.commit() 33 | else: 34 | cu.rollback() 35 | -------------------------------------------------------------------------------- /5_load_xml_config.py: -------------------------------------------------------------------------------- 1 | from jnpr.junos import Device 2 | from jnpr.junos.utils.config import Config 3 | 4 | dev = Device(host='xxxx', user='demo', password='demo123', gather_facts=False) 5 | dev.open() 6 | 7 | cu = Config(dev) 8 | data = """ 9 | 10 | F5-in 11 | 12 | test 13 | 14 | 15 | 16 | 17 | 18 | mpls 19 | 20 | 21 | """ 22 | 23 | 24 | cu.load(data) 25 | if cu.commit_check(): 26 | cu.commit() 27 | else: 28 | cu.rollback() 29 | -------------------------------------------------------------------------------- /6_load_temp_conf.py: -------------------------------------------------------------------------------- 1 | from jnpr.junos import Device 2 | from jnpr.junos.utils.config import Config 3 | import yaml 4 | 5 | dev = Device(host='xxxx', user='demo', password='demo123', gather_facts=False) 6 | dev.open() 7 | 8 | data = yaml.load(open('protocol_data.yml')) 9 | 10 | cu = Config(dev) 11 | 12 | cu.load(template_path='protocol_temp.j2', template_vars=data, format='text') 13 | cu.pdiff() 14 | if cu.commit_check(): 15 | cu.commit() 16 | else: 17 | cu.rollback() 18 | 19 | dev.close() 20 | -------------------------------------------------------------------------------- /7_rollback_config.py: -------------------------------------------------------------------------------- 1 | from jnpr.junos import Device 2 | from jnpr.junos.utils.config import Config 3 | 4 | dev = Device(host='xxxx', user='demo', password='demo123', gather_facts=False) 5 | dev.open() 6 | 7 | cu = Config(dev) 8 | diff = cu.diff() 9 | if diff: 10 | cu.rollback() 11 | dev.close() 12 | -------------------------------------------------------------------------------- /8_table_view.py: -------------------------------------------------------------------------------- 1 | from jnpr.junos import Device 2 | from jnpr.junos.op.routes import RouteTable 3 | 4 | dev = Device(host='xxxx', user='demo', password='demo123', gather_facts=False) 5 | dev.open() 6 | 7 | tbl = RouteTable(dev) 8 | tbl.get() 9 | #tbl.get('10.13.10.0/23', protocol='static') 10 | print tbl 11 | for item in tbl: 12 | print 'protocol:', item.protocol 13 | print 'age:', item.age 14 | print 'via:', item.via 15 | print 16 | 17 | dev.close() 18 | -------------------------------------------------------------------------------- /9_user_defined_table.py: -------------------------------------------------------------------------------- 1 | from jnpr.junos import Device 2 | from jnpr.junos.factory.factory_loader import FactoryLoader 3 | import yaml 4 | 5 | yaml_data=""" 6 | --- 7 | ArpTable: 8 | rpc: get-arp-table-information 9 | item: arp-table-entry 10 | key: mac-address 11 | view: ArpView 12 | 13 | ArpView: 14 | fields: 15 | mac_address: mac-address 16 | ip_address: ip-address 17 | interface_name: interface-name 18 | host: hostname 19 | """ 20 | 21 | dev = Device(host='xxxx', user='demo', password='demo123', gather_facts=False) 22 | dev.open() 23 | 24 | globals().update(FactoryLoader().load(yaml.load(yaml_data))) 25 | arps = ArpTable(dev) 26 | arps.get() 27 | for arp in arps: 28 | print 'mac_address: ', arp.mac_address 29 | print 'ip_address: ', arp.ip_address 30 | print 'interface_name:', arp.interface_name 31 | print 'hostname:', arp.host 32 | print 33 | 34 | dev.close() 35 | -------------------------------------------------------------------------------- /PyEZ_demo_sept.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 106, 6 | "metadata": { 7 | "collapsed": true 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "import logging\n", 12 | "logging.getLogger(\"paramiko\").setLevel(logging.WARNING)" 13 | ] 14 | }, 15 | { 16 | "cell_type": "code", 17 | "execution_count": 35, 18 | "metadata": { 19 | "collapsed": true 20 | }, 21 | "outputs": [], 22 | "source": [ 23 | "from jnpr.junos import Device" 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": 36, 29 | "metadata": { 30 | "collapsed": true 31 | }, 32 | "outputs": [], 33 | "source": [ 34 | "from lxml import etree" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": 40, 40 | "metadata": { 41 | "collapsed": true 42 | }, 43 | "outputs": [], 44 | "source": [ 45 | "#dev = Device(host='xxxx', user='demo', password='demo123', gather_facts=False)\n", 46 | "dev = Device(host='xxxx', user='demo', password='demo123')" 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": null, 52 | "metadata": { 53 | "collapsed": false 54 | }, 55 | "outputs": [], 56 | "source": [ 57 | "dev.open()" 58 | ] 59 | }, 60 | { 61 | "cell_type": "code", 62 | "execution_count": null, 63 | "metadata": { 64 | "collapsed": false, 65 | "scrolled": true 66 | }, 67 | "outputs": [], 68 | "source": [ 69 | "dev.facts" 70 | ] 71 | }, 72 | { 73 | "cell_type": "code", 74 | "execution_count": null, 75 | "metadata": { 76 | "collapsed": true 77 | }, 78 | "outputs": [], 79 | "source": [] 80 | }, 81 | { 82 | "cell_type": "code", 83 | "execution_count": null, 84 | "metadata": { 85 | "collapsed": true 86 | }, 87 | "outputs": [], 88 | "source": [ 89 | "op = dev.rpc.get_interface_information()\n", 90 | "#op = dev.rpc.get_interface_information({'format': 'text'})\n", 91 | "#op = dev.rpc.get_interface_information(interface_name='lo0', terse=True)" 92 | ] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "execution_count": null, 97 | "metadata": { 98 | "collapsed": false 99 | }, 100 | "outputs": [], 101 | "source": [ 102 | "print etree.tostring(op)" 103 | ] 104 | }, 105 | { 106 | "cell_type": "code", 107 | "execution_count": null, 108 | "metadata": { 109 | "collapsed": false 110 | }, 111 | "outputs": [], 112 | "source": [ 113 | "print dev.cli(\"show version\", warning=False)" 114 | ] 115 | }, 116 | { 117 | "cell_type": "code", 118 | "execution_count": null, 119 | "metadata": { 120 | "collapsed": true 121 | }, 122 | "outputs": [], 123 | "source": [ 124 | "cnf = dev.rpc.get_config()" 125 | ] 126 | }, 127 | { 128 | "cell_type": "code", 129 | "execution_count": null, 130 | "metadata": { 131 | "collapsed": false 132 | }, 133 | "outputs": [], 134 | "source": [ 135 | "print etree.tostring(cnf)" 136 | ] 137 | }, 138 | { 139 | "cell_type": "code", 140 | "execution_count": null, 141 | "metadata": { 142 | "collapsed": true 143 | }, 144 | "outputs": [], 145 | "source": [ 146 | "data = dev.rpc.get_config(filter_xml=etree.XML(''))" 147 | ] 148 | }, 149 | { 150 | "cell_type": "code", 151 | "execution_count": null, 152 | "metadata": { 153 | "collapsed": false 154 | }, 155 | "outputs": [], 156 | "source": [ 157 | "print etree.tostring(data)" 158 | ] 159 | }, 160 | { 161 | "cell_type": "code", 162 | "execution_count": null, 163 | "metadata": { 164 | "collapsed": true 165 | }, 166 | "outputs": [], 167 | "source": [ 168 | "from jnpr.junos.utils.fs import FS" 169 | ] 170 | }, 171 | { 172 | "cell_type": "code", 173 | "execution_count": null, 174 | "metadata": { 175 | "collapsed": true 176 | }, 177 | "outputs": [], 178 | "source": [ 179 | "fs = FS(dev)" 180 | ] 181 | }, 182 | { 183 | "cell_type": "code", 184 | "execution_count": null, 185 | "metadata": { 186 | "collapsed": false 187 | }, 188 | "outputs": [], 189 | "source": [ 190 | "fs.ls('/var/tmp')" 191 | ] 192 | }, 193 | { 194 | "cell_type": "code", 195 | "execution_count": null, 196 | "metadata": { 197 | "collapsed": false 198 | }, 199 | "outputs": [], 200 | "source": [ 201 | "print fs.cat('/var/tmp/nitin.log')" 202 | ] 203 | }, 204 | { 205 | "cell_type": "markdown", 206 | "metadata": {}, 207 | "source": [ 208 | "### Playing with table/View\n", 209 | "```\n", 210 | "RouteTable:\n", 211 | " rpc: get-route-information\n", 212 | " args_key: destination\n", 213 | " item: route-table/rt \n", 214 | " key: rt-destination\n", 215 | " view: RouteTableView\n", 216 | "\n", 217 | "RouteTableView:\n", 218 | " groups:\n", 219 | " entry: rt-entry\n", 220 | " fields_entry:\n", 221 | " # fields taken from the group 'entry'\n", 222 | " protocol: protocol-name\n", 223 | " via: nh/via | nh/nh-local-interface\n", 224 | " age: { age/@seconds : int }\n", 225 | " nexthop: nh/to\n", 226 | "```" 227 | ] 228 | }, 229 | { 230 | "cell_type": "code", 231 | "execution_count": null, 232 | "metadata": { 233 | "collapsed": false 234 | }, 235 | "outputs": [], 236 | "source": [ 237 | "from jnpr.junos.op.routes import RouteTable\n", 238 | "tbl = RouteTable(dev)\n", 239 | "tbl.get()" 240 | ] 241 | }, 242 | { 243 | "cell_type": "code", 244 | "execution_count": null, 245 | "metadata": { 246 | "collapsed": false 247 | }, 248 | "outputs": [], 249 | "source": [ 250 | "for item in tbl:\n", 251 | " print 'protocol:', item.protocol\n", 252 | " print 'age:', item.age\n", 253 | " print 'via:', item.via\n", 254 | " print" 255 | ] 256 | }, 257 | { 258 | "cell_type": "code", 259 | "execution_count": null, 260 | "metadata": { 261 | "collapsed": false 262 | }, 263 | "outputs": [], 264 | "source": [ 265 | "from jnpr.junos.factory.factory_loader import FactoryLoader\n", 266 | "import yaml\n", 267 | "\n", 268 | "yaml_data=\"\"\"\n", 269 | "---\n", 270 | "ArpTable:\n", 271 | " rpc: get-arp-table-information\n", 272 | " item: arp-table-entry\n", 273 | " key: mac-address\n", 274 | " view: ArpView\n", 275 | "\n", 276 | "ArpView:\n", 277 | " fields:\n", 278 | " mac_address: mac-address\n", 279 | " ip_address: ip-address\n", 280 | " interface_name: interface-name\n", 281 | "\"\"\"\n", 282 | "globals().update(FactoryLoader().load(yaml.load(yaml_data)))\n", 283 | "arps = ArpTable(dev)\n", 284 | "arps.get()\n", 285 | "for arp in arps:\n", 286 | " print 'mac_address: ', arp.mac_address\n", 287 | " print 'ip_address: ', arp.ip_address\n", 288 | " print 'interface_name:', arp.interface_name\n", 289 | " print" 290 | ] 291 | }, 292 | { 293 | "cell_type": "markdown", 294 | "metadata": {}, 295 | "source": [ 296 | "## Loading Configs" 297 | ] 298 | }, 299 | { 300 | "cell_type": "code", 301 | "execution_count": 11, 302 | "metadata": { 303 | "collapsed": true 304 | }, 305 | "outputs": [], 306 | "source": [ 307 | "from jnpr.junos.utils.config import Config\n", 308 | "cu = Config(dev)" 309 | ] 310 | }, 311 | { 312 | "cell_type": "code", 313 | "execution_count": null, 314 | "metadata": { 315 | "collapsed": true 316 | }, 317 | "outputs": [], 318 | "source": [ 319 | "data = \"\"\"interfaces { \n", 320 | " ge-1/0/1 {\n", 321 | " description \"MPLS interface\";\n", 322 | " unit 0 {\n", 323 | " family mpls;\n", 324 | " } \n", 325 | " } \n", 326 | " ge-1/0/2 {\n", 327 | " description \"MPLS interface\";\n", 328 | " unit 0 {\n", 329 | " family mpls;\n", 330 | " } \n", 331 | " } \n", 332 | "}\n", 333 | "protocols {\n", 334 | " mpls { \n", 335 | " interface ge-1/0/1; \n", 336 | " interface ge-1/0/2; \n", 337 | " }\n", 338 | "}\n", 339 | "\"\"\"" 340 | ] 341 | }, 342 | { 343 | "cell_type": "code", 344 | "execution_count": null, 345 | "metadata": { 346 | "collapsed": false 347 | }, 348 | "outputs": [], 349 | "source": [ 350 | "cu.load(data, format='text')\n", 351 | "cu.commit_check()" 352 | ] 353 | }, 354 | { 355 | "cell_type": "code", 356 | "execution_count": null, 357 | "metadata": { 358 | "collapsed": false 359 | }, 360 | "outputs": [], 361 | "source": [ 362 | "cu.load?" 363 | ] 364 | }, 365 | { 366 | "cell_type": "code", 367 | "execution_count": null, 368 | "metadata": { 369 | "collapsed": false 370 | }, 371 | "outputs": [], 372 | "source": [ 373 | "data = \"\"\"\n", 374 | " \n", 375 | " F5-in\n", 376 | " \n", 377 | " test\n", 378 | " \n", 379 | " \n", 380 | " \n", 381 | " \n", 382 | " \n", 383 | " mpls\n", 384 | " \n", 385 | " \n", 386 | " \"\"\"\n", 387 | "\n", 388 | "\n", 389 | "cu.load(data)\n", 390 | "cu.commit_check()" 391 | ] 392 | }, 393 | { 394 | "cell_type": "code", 395 | "execution_count": 5, 396 | "metadata": { 397 | "collapsed": true 398 | }, 399 | "outputs": [], 400 | "source": [ 401 | "xml_temp=\"\"\"\n", 402 | " \n", 403 | " all-local\n", 404 | " {% for prot in protocols %}\n", 405 | " \n", 406 | " {{ prot['name'] }}\n", 407 | " \n", 408 | " {{ prot.protocol }}\n", 409 | " \n", 410 | " \n", 411 | " \n", 412 | " \n", 413 | " {% endfor %}\n", 414 | " \n", 415 | " \"\"\"\n" 416 | ] 417 | }, 418 | { 419 | "cell_type": "code", 420 | "execution_count": 6, 421 | "metadata": { 422 | "collapsed": false 423 | }, 424 | "outputs": [ 425 | { 426 | "name": "stdout", 427 | "output_type": "stream", 428 | "text": [ 429 | "\n", 430 | " \n", 431 | " all-local\n", 432 | " \n", 433 | " \n", 434 | " 1\n", 435 | " \n", 436 | " direct\n", 437 | " \n", 438 | " \n", 439 | " \n", 440 | " \n", 441 | " \n", 442 | " \n", 443 | " 2\n", 444 | " \n", 445 | " static\n", 446 | " \n", 447 | " \n", 448 | " \n", 449 | " \n", 450 | " \n", 451 | " \n", 452 | " \n" 453 | ] 454 | } 455 | ], 456 | "source": [ 457 | "from jinja2 import Template\n", 458 | "tmpl = Template(xml_temp)\n", 459 | "conf = tmpl.render(protocols=[{'name':'1', 'protocol':'direct'}, {'name':'2', 'protocol':'static'}])\n", 460 | "print conf\n", 461 | "#cu.load(str(conf))" 462 | ] 463 | }, 464 | { 465 | "cell_type": "code", 466 | "execution_count": 31, 467 | "metadata": { 468 | "collapsed": false 469 | }, 470 | "outputs": [ 471 | { 472 | "name": "stdout", 473 | "output_type": "stream", 474 | "text": [ 475 | "interfaces { \r\n", 476 | " {% for item in interfaces %}\r\n", 477 | " {{ item }} {\r\n", 478 | " description \"{{ description }}\";\r\n", 479 | " unit 0 {\r\n", 480 | " family {{ family }};\r\n", 481 | " } \r\n", 482 | " } {% endfor %} \r\n", 483 | "}\r\n", 484 | "protocols {\r\n", 485 | " mpls { \r\n", 486 | " {% for item in interfaces %} \r\n", 487 | " interface {{ item }}; \r\n", 488 | " {% endfor %} \r\n", 489 | " }\r\n", 490 | "}\r\n", 491 | "\r\n" 492 | ] 493 | } 494 | ], 495 | "source": [ 496 | "%cat /Users/nitinkr/Coding/pyezex/protocol.conf" 497 | ] 498 | }, 499 | { 500 | "cell_type": "code", 501 | "execution_count": 32, 502 | "metadata": { 503 | "collapsed": false 504 | }, 505 | "outputs": [ 506 | { 507 | "name": "stdout", 508 | "output_type": "stream", 509 | "text": [ 510 | "---\r\n", 511 | "interfaces:\r\n", 512 | " - ge-1/0/1\r\n", 513 | " - ge-1/0/2\r\n", 514 | "description: 'MPLS interface'\r\n", 515 | "family: mpls\r\n" 516 | ] 517 | } 518 | ], 519 | "source": [ 520 | "%cat /Users/nitinkr/Coding/pyezex/protocol_data.yml" 521 | ] 522 | }, 523 | { 524 | "cell_type": "code", 525 | "execution_count": 33, 526 | "metadata": { 527 | "collapsed": false 528 | }, 529 | "outputs": [ 530 | { 531 | "name": "stdout", 532 | "output_type": "stream", 533 | "text": [ 534 | "{'interfaces': ['ge-1/0/1', 'ge-1/0/2'], 'description': 'MPLS interface', 'family': 'mpls'}\n" 535 | ] 536 | } 537 | ], 538 | "source": [ 539 | "import yaml\n", 540 | "data = yaml.load(open('/Users/nitinkr/Coding/pyezex/protocol_data.yml'))\n", 541 | "print data" 542 | ] 543 | }, 544 | { 545 | "cell_type": "code", 546 | "execution_count": 34, 547 | "metadata": { 548 | "collapsed": false 549 | }, 550 | "outputs": [ 551 | { 552 | "name": "stdout", 553 | "output_type": "stream", 554 | "text": [ 555 | "interfaces { \n", 556 | " \n", 557 | " ge-1/0/1 {\n", 558 | " description \"MPLS interface\";\n", 559 | " unit 0 {\n", 560 | " family mpls;\n", 561 | " } \n", 562 | " } \n", 563 | " ge-1/0/2 {\n", 564 | " description \"MPLS interface\";\n", 565 | " unit 0 {\n", 566 | " family mpls;\n", 567 | " } \n", 568 | " } \n", 569 | "}\n", 570 | "protocols {\n", 571 | " mpls { \n", 572 | " \n", 573 | " interface ge-1/0/1; \n", 574 | " \n", 575 | " interface ge-1/0/2; \n", 576 | " \n", 577 | " }\n", 578 | "}\n", 579 | "\n" 580 | ] 581 | } 582 | ], 583 | "source": [ 584 | "from jinja2 import Template\n", 585 | "tmpl = Template(open('/Users/nitinkr/Coding/pyezex/protocol.conf').read())\n", 586 | "conf = tmpl.render(data)\n", 587 | "print conf" 588 | ] 589 | }, 590 | { 591 | "cell_type": "code", 592 | "execution_count": 13, 593 | "metadata": { 594 | "collapsed": false 595 | }, 596 | "outputs": [ 597 | { 598 | "data": { 599 | "text/plain": [ 600 | "" 601 | ] 602 | }, 603 | "execution_count": 13, 604 | "metadata": {}, 605 | "output_type": "execute_result" 606 | } 607 | ], 608 | "source": [ 609 | "cu.load(template_path='/Users/nitinkr/Coding/pyezex/protocol.conf',\n", 610 | " template_vars=data, format='text')" 611 | ] 612 | }, 613 | { 614 | "cell_type": "code", 615 | "execution_count": 14, 616 | "metadata": { 617 | "collapsed": false 618 | }, 619 | "outputs": [ 620 | { 621 | "name": "stdout", 622 | "output_type": "stream", 623 | "text": [ 624 | "\n", 625 | "[edit interfaces]\n", 626 | "+ ge-1/0/1 {\n", 627 | "+ description \"MPLS interface\";\n", 628 | "+ unit 0 {\n", 629 | "+ family mpls;\n", 630 | "+ }\n", 631 | "+ }\n", 632 | "+ ge-1/0/2 {\n", 633 | "+ description \"MPLS interface\";\n", 634 | "+ unit 0 {\n", 635 | "+ family mpls;\n", 636 | "+ }\n", 637 | "+ }\n", 638 | "[edit]\n", 639 | "+ protocols {\n", 640 | "+ mpls {\n", 641 | "+ interface ge-1/0/1.0;\n", 642 | "+ interface ge-1/0/2.0;\n", 643 | "+ }\n", 644 | "+ }\n", 645 | "\n" 646 | ] 647 | } 648 | ], 649 | "source": [ 650 | "cu.pdiff()" 651 | ] 652 | }, 653 | { 654 | "cell_type": "code", 655 | "execution_count": 15, 656 | "metadata": { 657 | "collapsed": false 658 | }, 659 | "outputs": [ 660 | { 661 | "data": { 662 | "text/plain": [ 663 | "True" 664 | ] 665 | }, 666 | "execution_count": 15, 667 | "metadata": {}, 668 | "output_type": "execute_result" 669 | } 670 | ], 671 | "source": [ 672 | "cu.rollback()" 673 | ] 674 | }, 675 | { 676 | "cell_type": "code", 677 | "execution_count": 16, 678 | "metadata": { 679 | "collapsed": false 680 | }, 681 | "outputs": [ 682 | { 683 | "name": "stdout", 684 | "output_type": "stream", 685 | "text": [ 686 | "None\n" 687 | ] 688 | } 689 | ], 690 | "source": [ 691 | "cu.pdiff()" 692 | ] 693 | }, 694 | { 695 | "cell_type": "markdown", 696 | "metadata": {}, 697 | "source": [ 698 | "## Software\n", 699 | "\n", 700 | "```python\n", 701 | "def update_progress(dev, report):\n", 702 | " print dev.hostname, '> ', report\n", 703 | " \n", 704 | "sw.install('/var/tmp/junos-srxsme-12.1X46-D15.3-domestic.tgz', validate=True, progress=update_progress)\n", 705 | "```" 706 | ] 707 | }, 708 | { 709 | "cell_type": "code", 710 | "execution_count": 19, 711 | "metadata": { 712 | "collapsed": true 713 | }, 714 | "outputs": [], 715 | "source": [ 716 | "from jnpr.junos.utils.sw import SW\n", 717 | "sw = SW(dev)" 718 | ] 719 | }, 720 | { 721 | "cell_type": "code", 722 | "execution_count": 20, 723 | "metadata": { 724 | "collapsed": false 725 | }, 726 | "outputs": [], 727 | "source": [ 728 | "sw.install?" 729 | ] 730 | }, 731 | { 732 | "cell_type": "code", 733 | "execution_count": null, 734 | "metadata": { 735 | "collapsed": false 736 | }, 737 | "outputs": [], 738 | "source": [ 739 | "dev = Device(host='xxxx', user='demo', password='demo123', gather_facts=False)\n", 740 | "dev.open()\n", 741 | "sw = SW(dev)\n", 742 | "ok = sw.install(package=r'/Users/nitinkr/Downloads/jinstall-xxxxx-domestic.tgz', progress=update_progress)\n", 743 | "if ok:\n", 744 | " print 'rebooting'\n", 745 | " sw.reboot()" 746 | ] 747 | }, 748 | { 749 | "cell_type": "code", 750 | "execution_count": 21, 751 | "metadata": { 752 | "collapsed": true 753 | }, 754 | "outputs": [], 755 | "source": [ 756 | "from jnpr.junos.utils.scp import SCP" 757 | ] 758 | }, 759 | { 760 | "cell_type": "code", 761 | "execution_count": 23, 762 | "metadata": { 763 | "collapsed": false 764 | }, 765 | "outputs": [ 766 | { 767 | "name": "stdout", 768 | "output_type": "stream", 769 | "text": [ 770 | "Hello world\r\n" 771 | ] 772 | } 773 | ], 774 | "source": [ 775 | "%cat info.txt" 776 | ] 777 | }, 778 | { 779 | "cell_type": "code", 780 | "execution_count": 24, 781 | "metadata": { 782 | "collapsed": true 783 | }, 784 | "outputs": [], 785 | "source": [ 786 | "%rm info.txt" 787 | ] 788 | }, 789 | { 790 | "cell_type": "code", 791 | "execution_count": null, 792 | "metadata": { 793 | "collapsed": false 794 | }, 795 | "outputs": [], 796 | "source": [ 797 | "import time\n", 798 | "from bokeh.plotting import figure, output_server, cursession, show\n", 799 | "from bokeh.models import NumeralTickFormatter\n", 800 | "\n", 801 | "from jnpr.junos import Device\n", 802 | "\n", 803 | "# prepare output to server\n", 804 | "output_server(\"animated_line\")\n", 805 | "\n", 806 | "p = figure(plot_width=600, plot_height=600)\n", 807 | "dev = Device(host='xxxx', user='demo', password='demo123', gather_facts=False, port=22)\n", 808 | "dev.open()\n", 809 | "\n", 810 | "x_tmp = [0]*5\n", 811 | "x_var = [0]*5\n", 812 | "ct = time.localtime()\n", 813 | "ct = ct.tm_hour*3600+ct.tm_min*60+ct.tm_sec\n", 814 | "op = dev.rpc.get_statistics_information(tcp=True)\n", 815 | "packets_sent_new = op.xpath('.//packets-sent')[0].text.strip()\n", 816 | "packets_recv_new = op.xpath('.//packets-received')[0].text.strip()\n", 817 | "p.line([ct, ct+2, ct+4, ct+6, ct+8], x_tmp, name='ex_line', legend = 'packets-sent')\n", 818 | "p.line([ct, ct+2, ct+4, ct+6, ct+8], x_var, name='ex_line', line_color=\"red\", legend = 'packets-recv')\n", 819 | "p.xaxis[0].formatter = NumeralTickFormatter(format='00:00:00')\n", 820 | "show(p)\n", 821 | "\n", 822 | "# create some simple animation..\n", 823 | "# first get our figure example data source\n", 824 | "renderer = p.select(dict(name=\"ex_line\"))\n", 825 | "ds1 = renderer[0].data_source\n", 826 | "ds2 = renderer[1].data_source\n", 827 | "while True:\n", 828 | " op = dev.rpc.get_statistics_information(tcp=True)\n", 829 | " packets_sent_new, packets_sent_old = op.xpath('.//packets-sent')[0].text.strip(), packets_sent_new\n", 830 | " packets_recv_new, packets_recv_old = op.xpath('.//packets-received')[0].text.strip(), packets_recv_new\n", 831 | " ct = time.localtime()\n", 832 | " ct = ct.tm_hour*3600+ct.tm_min*60+ct.tm_sec\n", 833 | " ds2.data[\"x\"] = ds1.data[\"x\"] = [ct, ct+2, ct+4, ct+6, ct+8]\n", 834 | " ds1.data[\"y\"] = ds1.data[\"y\"][1:]+[int(packets_sent_new)-int(packets_sent_old)]\n", 835 | " ds2.data[\"y\"] = ds2.data[\"y\"][1:]+[int(packets_recv_new)-int(packets_recv_old)]\n", 836 | " cursession().store_objects(ds1, ds2)\n", 837 | " time.sleep(1.5)" 838 | ] 839 | } 840 | ], 841 | "metadata": { 842 | "kernelspec": { 843 | "display_name": "Python 2", 844 | "language": "python", 845 | "name": "python2" 846 | }, 847 | "language_info": { 848 | "codemirror_mode": { 849 | "name": "ipython", 850 | "version": 2 851 | }, 852 | "file_extension": ".py", 853 | "mimetype": "text/x-python", 854 | "name": "python", 855 | "nbconvert_exporter": "python", 856 | "pygments_lexer": "ipython2", 857 | "version": "2.7.8" 858 | } 859 | }, 860 | "nbformat": 4, 861 | "nbformat_minor": 0 862 | } 863 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## BLOGS 2 | 3 | * Junos and Python – Junos PyEZ – [Part 1](http://www.networkers.fi/blog/junos-and-python-junos-pyez-part-1/) 4 | Blogger: Jesse 5 | 6 | * Juniper's PyEZ - [Loading Configuration Changes](https://pynet.twb-tech.com/blog/juniper/juniper-pyez.html) 7 | Blogger: [Kirk Byers](https://twitter.com/kirkbyers) 8 | 9 | * Juniper's PyEZ - [Commit, Confirm, Rollback](https://pynet.twb-tech.com/blog/juniper/juniper-pyez-commit.html) 10 | Blogger: [Kirk Byers](https://twitter.com/kirkbyers) 11 | 12 | * Junos PyEZ [Installation & Initial Testing On Mac OS X](http://ethancbanks.com/2014/12/31/junos-pyez-installation-initial-testing-on-mac-os-x/) 13 | Blogger: [Ethan Banks](https://twitter.com/ecbanks) 14 | 15 | * Junos PyEZ 16 | * [Getting started with Junos PyEZ](https://stebe.info/2016/11/introduction-junos-pyez/) 17 | * [Checking BGP with PyEZ's Table/View](https://stebe.info/2016/11/checking-bgp-with-pyez-table-view/) 18 | * [Sync PREFIX-LISTS via Junos PyEZ on several routers](https://stebe.info/2016/11/sync-prefix-lists-via-junos-pyez/) 19 | * [How to get support information via junos PyEZ](https://stebe.info/2016/12/howto-get-support-information/) 20 | 21 | Blogger: [Stephan Behrens](https://twitter.com/stebe_info) 22 | 23 | ## USE CASES 24 | User's PyEZ examples for reference 25 | 26 | * Python tool to map vCenter Virtual Machines to logical interface on a Juniper Junos device 27 | https://github.com/fredriclinder/vmtrace 28 | 29 | * Deploying underlay and production networks @Riot Games 30 | http://www.ansible.com/ansible-network-infrastructure 31 | Speaker: [Adam Mills](https://twitter.com/riotgeneral) 32 | 33 | -------------------------------------------------------------------------------- /fpc-info.py: -------------------------------------------------------------------------------- 1 | # Python PyEz script to collect the installed FPC hardware and show FPC status 2 | __author__ = "Chris Booker" 3 | import sys 4 | from jnpr.junos import Device 5 | from jnpr.junos.op.fpc import FpcHwTable 6 | from jnpr.junos.op.fpc import FpcInfoTable 7 | from getpass import getpass 8 | from pprint import pprint as pp 9 | from sys import exit 10 | from lxml import etree 11 | 12 | 13 | user = "lab" 14 | 15 | print "\nPlease provide password for user '" + user + "' on device '" + sys.argv[1] + "'." 16 | passwd = getpass() 17 | 18 | dev = Device(sys.argv[1],user=user,password=passwd) 19 | try: 20 | dev.open() 21 | print "Connected to " + sys.argv[1] + " as", (user) 22 | except: 23 | print "Connection failed. :-(" 24 | print "\n** Type exit() to quit **" 25 | 26 | 27 | class style: 28 | BOLD = '\033[1m' 29 | END = '\033[0m' 30 | 31 | 32 | 33 | #print FPC hardware Table 34 | #get-chassis-inventory 35 | print "\n*************************************************************************************" 36 | print style.BOLD + "Chassis Installed FPC Details " + style.END 37 | fpcs = FpcHwTable(dev) 38 | fpcs.get() 39 | print fpcs 40 | 41 | for fpc in fpcs: 42 | print fpc.key," Description:", fpc.desc, "Model:", fpc.model,"Serial:", fpc.sn, "Part-number:", fpc.pn 43 | 44 | 45 | 46 | #invoke get fpc information 47 | print "\n*************************************************************************************" 48 | print style.BOLD + "Device FPC Status Details " + style.END 49 | jfpcs = FpcInfoTable(dev) 50 | jfpcs.get() 51 | print jfpcs 52 | 53 | for item in jfpcs: 54 | print "Slot:", item.key, "State:", item.state, "Memory Util%:", item.memory, "CPU%:", item.cpu 55 | 56 | dev.close() 57 | -------------------------------------------------------------------------------- /generate_conf_from_template.py: -------------------------------------------------------------------------------- 1 | import yaml 2 | from jinja2 import Template 3 | 4 | data = yaml.load(open('protocol_data.yml')) 5 | print data 6 | 7 | tmpl = Template(open('/var/tmp/pyez_demo/examples/protocol_temp.j2').read()) 8 | conf = tmpl.render(data) 9 | print conf 10 | -------------------------------------------------------------------------------- /images/serial_conn.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vnitinv/pyez-examples/c4ca8c7440398495b5917548443cb754bdc10109/images/serial_conn.jpg -------------------------------------------------------------------------------- /plot_tcp.py: -------------------------------------------------------------------------------- 1 | import time 2 | from bokeh.plotting import figure, output_server, cursession, show 3 | from bokeh.models import NumeralTickFormatter 4 | 5 | from jnpr.junos import Device 6 | 7 | # prepare output to server 8 | output_server("animated_line") 9 | 10 | p = figure(plot_width=600, plot_height=600) 11 | dev = Device(host='xxxx', user='demo', password='demo123', gather_facts=False, port=22) 12 | dev.open() 13 | 14 | x_tmp = [0]*5 15 | x_var = [0]*5 16 | ct = time.localtime() 17 | ct = ct.tm_hour*3600+ct.tm_min*60+ct.tm_sec 18 | op = dev.rpc.get_statistics_information(tcp=True) 19 | packets_sent_new = op.xpath('.//packets-sent')[0].text.strip() 20 | packets_recv_new = op.xpath('.//packets-received')[0].text.strip() 21 | p.line([ct, ct+2, ct+4, ct+6, ct+8], x_tmp, name='ex_line', legend = 'packets-sent') 22 | p.line([ct, ct+2, ct+4, ct+6, ct+8], x_var, name='ex_line', line_color="red", legend = 'packets-recv') 23 | p.xaxis[0].formatter = NumeralTickFormatter(format='00:00:00') 24 | show(p) 25 | 26 | # create some simple animation.. 27 | # first get our figure example data source 28 | renderer = p.select(dict(name="ex_line")) 29 | ds1 = renderer[0].data_source 30 | ds2 = renderer[1].data_source 31 | while True: 32 | op = dev.rpc.get_statistics_information(tcp=True) 33 | packets_sent_new, packets_sent_old = op.xpath('.//packets-sent')[0].text.strip(), packets_sent_new 34 | packets_recv_new, packets_recv_old = op.xpath('.//packets-received')[0].text.strip(), packets_recv_new 35 | ct = time.localtime() 36 | ct = ct.tm_hour*3600+ct.tm_min*60+ct.tm_sec 37 | ds2.data["x"] = ds1.data["x"] = [ct, ct+2, ct+4, ct+6, ct+8] 38 | ds1.data["y"] = ds1.data["y"][1:]+[int(packets_sent_new)-int(packets_sent_old)] 39 | ds2.data["y"] = ds2.data["y"][1:]+[int(packets_recv_new)-int(packets_recv_old)] 40 | cursession().store_objects(ds1, ds2) 41 | time.sleep(1.5) 42 | -------------------------------------------------------------------------------- /protocol_data.yml: -------------------------------------------------------------------------------- 1 | --- 2 | interfaces: 3 | - ge-1/0/1 4 | - ge-1/0/2 5 | description: 'MPLS interface' 6 | family: mpls 7 | -------------------------------------------------------------------------------- /protocol_temp.j2: -------------------------------------------------------------------------------- 1 | interfaces { 2 | {% for item in interfaces %} 3 | {{ item }} { 4 | description "{{ description }}"; 5 | unit 0 { 6 | family {{ family }}; 7 | } 8 | } {% endfor %} 9 | } 10 | protocols { 11 | mpls { 12 | {% for item in interfaces %} 13 | interface {{ item }}; 14 | {% endfor %} 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /table_view_from_existing_xml_file.py: -------------------------------------------------------------------------------- 1 | from jnpr.junos.factory.factory_loader import FactoryLoader 2 | import yaml 3 | 4 | # from existing table/view 5 | from jnpr.junos.op.routes import RouteTable 6 | 7 | tbls = RouteTable(path='/var/tmp/get-route-information.xml') 8 | tbls.get() 9 | for item in tbls: 10 | print 'protocol:', item.protocol 11 | print 'age:', item.age 12 | print 'via:', item.via 13 | 14 | 15 | # From user defined table/view 16 | yaml_data=""" 17 | --- 18 | RemoteVxlanTable: 19 | rpc: get-ethernet-switching-vxlan-rvtep-info 20 | item: vxlan-source-vtep-information/vxlan-remote-vtep-information 21 | key: remote-vtep-address 22 | view: RemoteVxlanView 23 | 24 | RemoteVxlanView: 25 | groups: 26 | vnis: vxlan-dynamic-information 27 | fields_vnis: 28 | vni: vxlan-format/vn-id 29 | 30 | """ 31 | 32 | globals().update(FactoryLoader().load(yaml.load(yaml_data))) 33 | rvxlans = RemoteVxlanTable(path='/var/tmp/show_ethernet-switching_vxlan-tunnel-end-point_remote.xml') 34 | rvxlans.get() 35 | for rvxlan in rvxlans: 36 | print rvxlan.vni 37 | -------------------------------------------------------------------------------- /templates/1_temp.j2: -------------------------------------------------------------------------------- 1 | interfaces { 2 | interface {{ iface_name }} { 3 | unit 0 { 4 | family ethernet-switching { 5 | port-mode access; 6 | replace: 7 | vlan { 8 | member {{ vlan_name }}; 9 | } 10 | } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /templates/create_vlans.conf: -------------------------------------------------------------------------------- 1 | vlans { 2 | {% for vlan in vlan_list %} 3 | {{ vlan.vlan_name }} { 4 | vlan-id {{ vlan.vlan_id }}; 5 | } 6 | {% endfor %} 7 | } 8 | -------------------------------------------------------------------------------- /templates/data_vars.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | host_ports: 3 | ports: 4 | - eth115/1/1 5 | - eth115/1/2 6 | host_ports_vlan: 7 | vlan_id: 11,23,44 8 | description: 9 | nome1: only port1 10 | nome2: only port2 11 | nome3: only port3 12 | nome4: only port4 13 | nome5: only port5 14 | mode: 15 | lacp: 11 16 | vpcid: 17 | domain: 14 18 | -------------------------------------------------------------------------------- /templates/filter.j2: -------------------------------------------------------------------------------- 1 | interfaces { 2 | {% for item in iface_pattern | bracket_expansion %} 3 | {{ item }} { 4 | unit 0 { 5 | family ethernet-switching { 6 | port-mode access; 7 | replace: 8 | vlan { 9 | member {{ vlan_name }}; 10 | } 11 | } 12 | } 13 | } {% endfor %} 14 | } 15 | -------------------------------------------------------------------------------- /templates/generate_conf_from_template.py: -------------------------------------------------------------------------------- 1 | import yaml 2 | from jinja2 import Template 3 | 4 | data = yaml.load(open('data_vars.yaml')) 5 | print data 6 | 7 | tmpl = Template(open('template.j2').read()) 8 | conf = tmpl.render(data) 9 | print conf 10 | -------------------------------------------------------------------------------- /templates/main.j2: -------------------------------------------------------------------------------- 1 | ## 2 | ## This is top main file 3 | ## 4 | 5 | interfaces { 6 | {% for item in interfaces %} 7 | {{ item }} { 8 | description "{{ description }}"; 9 | unit 0 { 10 | family {{ family }}; 11 | } 12 | } {% endfor %} 13 | } 14 | ## 15 | ## including another jinja templete 16 | ## 17 | {% include 'users.j2' %} 18 | 19 | ## 20 | ## thats the end 21 | ## 22 | -------------------------------------------------------------------------------- /templates/main_vlans.conf: -------------------------------------------------------------------------------- 1 | {% set state = state | default('present') %} 2 | 3 | {% if state == 'present' %} 4 | {% include 'create_vlans.conf' %} 5 | {% else %} 6 | {% include 'remove_vlans.conf' %} 7 | {% endif %} 8 | -------------------------------------------------------------------------------- /templates/remove_vlans.conf: -------------------------------------------------------------------------------- 1 | vlans { 2 | {% for vlan in vlan_list %} 3 | delete: {{ vlan.vlan_name }} 4 | {% endfor %} 5 | } 6 | -------------------------------------------------------------------------------- /templates/sshkeys/lakhan: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEApdrhjuLJAb99Ftzuv/xNoeMJmoJ6eRdndmQHoxvq6M8vn2wA 3 | /N5w+HDoOT2X6VU5leat1YrXBu60JUYpuEcPuuvUfp9OgRvxWq7CL9sgFfVc99Mu 4 | dbZcwk4ReE0BFbbSoELXZoLXp6EzpyLGR45rOs8ezsnjMLOJ2+pBRNXhb9gPofhQ 5 | EHiKvuW8V1qR++1q/Q6wlUusKsg7uJ4r+lp8bISRSjvAGTpJedanEM5xHvSeyc+E 6 | n4F56hiibCZyThkncSuoMkUS2C0NkuwmSEHugm/e5xhERUseMPVxTFmX/0ZGN6NJ 7 | Vzr9FQudaa+aHCWL2/iKWAIgoxdKaOsTHddXYQIDAQABAoIBAGAtUWd+c3mkBXHg 8 | pEKImKwr8EG9MDBQNhsdXqBjbBGdM8yK4PfCNlibgM7QvOr+FOqsXlnarV7DxYtn 9 | 6IGIE8MdRpg24VtVTNx9QvZlZ3HUWxkLSYHRQnEavF66qMpivjlZCXfUoCIBBOcC 10 | 72BHYj80JHVd9XUkZ+kzKq40KQqlnNoeKLvHvbLPKFYi1Bj3O/o7fgHqSezLaWQ9 11 | hJz6aA0AyZfEf8+rCBLzM52mBPhXM6AgoemRvyE/JGYV3uOXOJd9Yx/hW5rE3WDG 12 | PcterioB6V8nqeu7lA4P+nNLcRfny7U/kzp9lWQ/eSiPsGSOSwVKP0LboQGL7dHG 13 | iwTAHxECgYEA2z8aNCQTzUkEdYon0+zcfzJCEseinlWQQ8lhW2WfpVjzLQz81rd8 14 | NmY2SVHi6qT7Rx8+/bfKSidZaB2Pfy5cnlhhbRUafRKneh38b9dlAEyi8Pt/LgF7 15 | 3No6CvnMyKcTuy+T+wT70o1WE+Sy0g9qa6QrqFDGX4zNsfrrmyXv28sCgYEAwah/ 16 | uuj35rIDsMQECFHCIP9s700UPY7NtiNo1h1fRpOu/HH2TIlb1iRIdLJhOnM1sswU 17 | 8hNeNgTF0W4785J6oMNIGSDawHpRAZhRLkCaJtDkiXbCcIh7KauiT5YPbzX4zbZQ 18 | ncRMJ3kZcCMzM/X/pg3kngoth0h6lblHTCJmzAMCgYEAsg0qE6Qk7LdaxrX/KE2Y 19 | uDexjxzPhPSJ53MY/KeoIhj9y91bTGjQmEEj3yGAPfzkEFtgxZ3Hy7bvFe3Dxo55 20 | KyMtY/Aahe5rUnIduxpa7QZP4ZLtMwiDddVIA/fgBighjwfRjq76b4DWoes+Cff4 21 | /hfiWJvYrmpj9iGHy4TgqUcCgYA3dhtGm0vL7PVznV+ORmPzcVNwYUHHs2skm5V9 22 | pKHRo5/8umKQXtJHTNLXYPLJe49IanwhK/zSOaGxrgFLa4rlGag/UhJ0B1PFwiqV 23 | tXiwXyjkWXesJNoo//eXFWHMNsfPmkQSOtKYh20KmXojinMxyk7MGBwb310EHjDW 24 | FBAeowKBgQDJCJghGnAPl9hSPlkmOOdBWhStZTm00UdHh4KcId0HA62wfX+2tUa9 25 | 6pa+4lf42/0NvnM1asn6HNESmGyd9baFDrSLc5uwW1emLHzzHuhjP6huHWTVXNg3 26 | UUFtyicEUQw9QG+mGkF4p/f0Em9ZYiNdpculBJFLQPVITEOBTh9ZQA== 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /templates/sshkeys/lakhan.pub: -------------------------------------------------------------------------------- 1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCl2uGO4skBv30W3O6//E2h4wmagnp5F2d2ZAejG+rozy+fbAD83nD4cOg5PZfpVTmV5q3VitcG7rQlRim4Rw+669R+n06BG/FarsIv2yAV9Vz30y51tlzCThF4TQEVttKgQtdmgtenoTOnIsZHjms6zx7OyeMws4nb6kFE1eFv2A+h+FAQeIq+5bxXWpH77Wr9DrCVS6wqyDu4niv6WnxshJFKO8AZOkl51qcQznEe9J7Jz4SfgXnqGKJsJnJOGSdxK6gyRRLYLQ2S7CZIQe6Cb97nGERFSx4w9XFMWZf/RkY3o0lXOv0VC51pr5ocJYvb+IpYAiCjF0po6xMd11dh nitinkr@nitinkr-mba13 2 | -------------------------------------------------------------------------------- /templates/sshkeys/ram: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEAwx0pY3PALmNlIJmbgJeYVtfFGScM4+LtULupFieGnnCu9a91 3 | a2q+uUyjYrL/3jjhVR6CPOvdCDjBxtDVMzSR/lrWhRSoSP9sl+kN1CfAobNxTiH0 4 | bzLTkb4KzeSSXykRJkVRFlXc1qhwxrOg8lw4i/IdF7AUJgiXLjEuSQovhoIGK/8r 5 | DDsy11pI4GWrI9AHFWaxpGk1dEdRHO0lfyGRjGQtUXpQ4mk4jD3bCOyxVeo52c6h 6 | vSGZjB8AywKHDvxzdp5xlFhgZ9e9ofGodH0rk5wPFpuQJw/v95PzebRzozH0VPj+ 7 | +eRVpAvk8D7l67alfJIeGQVlq+Qh1LX5czZjJwIDAQABAoIBABUCgd9sqmgUWeJd 8 | yAnbyRKo31drBg9P8z/7RSTWkr9i4OQhxaIQd4MaholtPvId692vkFShDUcCXZNc 9 | D2kZIxNhkrH33Hsnzfi5pryOn0aKPQwtydVjgrax4RX0o/JNSMR3OFkQW9xdfO9Y 10 | jl8qoQgoxQs08aZ6zFS0BQjmaOGx1DANf0ZIXU6Pobml8D/llFp3/XZY5jbYoJUJ 11 | G7vUsG+ze7Jj4p5OkuqSqdLmvAvIsELJ9RTy5b9UizqsZUzdZpz+4t9NVwANWL2i 12 | kd2pYyPIti9t241guyteZWYf0ZrEk+577oEVnBWP8rihKDtd2E/g0lrxKW3WwXmA 13 | lVqHXzECgYEA+RRCdWIWSjoTaz8WKOx51ayTyvHUzYh6mXSAcQ/h1pQrxQyRqocC 14 | W0Tq4mdesC5VZMkgiyLiPo0aOUKW+mdxQyfqRLzGn1a/bY+0L0mkTO0CGnyhjH4I 15 | ue8d57EtSIPT4Knw+uyWWK/cLr0e4FZp5hNzrM7KTu7muRvUuZX2JikCgYEAyIkJ 16 | 5KZru/9elHOBksOWB54jHCf9/DDEJAbTe7N4BWTVboytjkyO1Rx2CScHv7GfD30Q 17 | nmMb0OKRVCrOJg5u8tdo+s+CJP44BopWvVJXsq2SX/kzHQuB4HRKDTcpei7Zyf08 18 | 3tUJT7rCnpAkKYzO9D0TMEFu6e/zdUOrfl0iSM8CgYAqXXrMUmmuKGCjLjDLtyUl 19 | 5duhei6S4vLPZRRvpp7oC33CX1frZFlPQtKcva5KUyctJFSHteA7eW6LbLsXTj7i 20 | iEh9dopmEbAvp3CjVmg+uVVRQf+MUOeVEInKncUw/1MrdFxLobAU15ygyoQU7j3G 21 | 52oWa3nXoSTXOVeeVVZvuQKBgQCGPW44+Mq/w5gtqhDADVu+Z7a7H25fRsnWEBe8 22 | BAzBF5nkchmwW0F2GaJOSClgwmdm9+KLFG9HapO8kxcC1MCioV5uH0DQwLkCb9LW 23 | 02tPee+1fV0hAVYEyfPUWuvSFdDG7VW1GUktbSjg+j6q7c6QIt5YfETiJzWDdzQy 24 | 1+eecwKBgQC0EOQri7Ev/CrOPswhbzC7qikr/IKoqo7CHPdPItIGVLnCbPUerlMw 25 | 8LSSrPCrlqp2ovkS5SOSDcTQIUHaw5Qiv8UnZqKGqjVJPNHYII7NOvsxMq27tTo4 26 | Tm2UgcYwVVwEFj5kiDNKTrE4G6zT0cof7NQOOCOOrqt2vAJrb5ZFrQ== 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /templates/sshkeys/ram.pub: -------------------------------------------------------------------------------- 1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDHSljc8AuY2UgmZuAl5hW18UZJwzj4u1Qu6kWJ4aecK71r3Vrar65TKNisv/eOOFVHoI8690IOMHG0NUzNJH+WtaFFKhI/2yX6Q3UJ8Chs3FOIfRvMtORvgrN5JJfKREmRVEWVdzWqHDGs6DyXDiL8h0XsBQmCJcuMS5JCi+GggYr/ysMOzLXWkjgZasj0AcVZrGkaTV0R1Ec7SV/IZGMZC1RelDiaTiMPdsI7LFV6jnZzqG9IZmMHwDLAocO/HN2nnGUWGBn172h8ah0fSuTnA8Wm5AnD+/3k/N5tHOjMfRU+P755FWkC+TwPuXrtqV8kh4ZBWWr5CHUtflzNmMn nitinkr@nitinkr-mba13 2 | -------------------------------------------------------------------------------- /templates/template.j2: -------------------------------------------------------------------------------- 1 | {% for iface in host_ports.ports %} 2 | interface {{ iface }} 3 | description {{ description.port1 }} 4 | switchport access vlan {{ host_ports_vlan.vlan_id }} 5 | no snmp trap link-status 6 | no cdp ena 7 | no lldp transmit 8 | no lldp receive 9 | spanning-tree bpduguard enable 10 | channel-group {{ mode.lacp }} mode active 11 | {% endfor %} 12 | -------------------------------------------------------------------------------- /templates/users.j2: -------------------------------------------------------------------------------- 1 | system { 2 | login { 3 | {% for ssh_pub in sshkeyfiles %} 4 | user {{ ssh_pub | basefilename }} { 5 | authentication { 6 | ssh-rsa "{% include ssh_pub %}"; 7 | } 8 | } 9 | {% endfor %} 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /templates/vlans.csv: -------------------------------------------------------------------------------- 1 | vlan_name,vlan_id 2 | Blue,100 3 | Green,200 4 | Yellow,300 5 | Purple,400 6 | Red,500 7 | -------------------------------------------------------------------------------- /templates/yaml_jinja_demo.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 2, 6 | "metadata": { 7 | "collapsed": false 8 | }, 9 | "outputs": [ 10 | { 11 | "name": "stdout", 12 | "output_type": "stream", 13 | "text": [ 14 | "ge-0/0/1\n" 15 | ] 16 | } 17 | ], 18 | "source": [ 19 | "interface_name = 'ge-0/0/1'\n", 20 | "print interface_name" 21 | ] 22 | }, 23 | { 24 | "cell_type": "markdown", 25 | "metadata": {}, 26 | "source": [ 27 | "\n", 28 | "### Python List" 29 | ] 30 | }, 31 | { 32 | "cell_type": "code", 33 | "execution_count": 9, 34 | "metadata": { 35 | "collapsed": false 36 | }, 37 | "outputs": [], 38 | "source": [ 39 | "protocols = ['mpls', 'bgp', 'isis', 'ospf']" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": 10, 45 | "metadata": { 46 | "collapsed": false 47 | }, 48 | "outputs": [ 49 | { 50 | "name": "stdout", 51 | "output_type": "stream", 52 | "text": [ 53 | "mpls\n", 54 | "bgp\n", 55 | "isis\n", 56 | "ospf\n" 57 | ] 58 | } 59 | ], 60 | "source": [ 61 | "for prot in protocols:\n", 62 | " print prot" 63 | ] 64 | }, 65 | { 66 | "cell_type": "markdown", 67 | "metadata": {}, 68 | "source": [ 69 | "### Python Dictionary" 70 | ] 71 | }, 72 | { 73 | "cell_type": "code", 74 | "execution_count": 13, 75 | "metadata": { 76 | "collapsed": false 77 | }, 78 | "outputs": [ 79 | { 80 | "name": "stdout", 81 | "output_type": "stream", 82 | "text": [ 83 | "{'ceo': 'Rami Rahim', 'company': 'Juniper', 'domain': 'Networking'}\n" 84 | ] 85 | } 86 | ], 87 | "source": [ 88 | "data = {'company': 'Juniper',\n", 89 | " 'ceo': 'Rami Rahim',\n", 90 | " 'domain': 'Networking'}\n", 91 | "\n", 92 | "print data" 93 | ] 94 | }, 95 | { 96 | "cell_type": "code", 97 | "execution_count": 14, 98 | "metadata": { 99 | "collapsed": false 100 | }, 101 | "outputs": [ 102 | { 103 | "name": "stdout", 104 | "output_type": "stream", 105 | "text": [ 106 | "ceo -> Rami Rahim\n", 107 | "company -> Juniper\n", 108 | "domain -> Networking\n" 109 | ] 110 | } 111 | ], 112 | "source": [ 113 | "for k,v in data.items():\n", 114 | " print k, ' -> ', v" 115 | ] 116 | }, 117 | { 118 | "cell_type": "code", 119 | "execution_count": 15, 120 | "metadata": { 121 | "collapsed": false 122 | }, 123 | "outputs": [ 124 | { 125 | "name": "stdout", 126 | "output_type": "stream", 127 | "text": [ 128 | "{'vlan_name': '200', 'iface_name': 'ge-0/0/1'}\n" 129 | ] 130 | } 131 | ], 132 | "source": [ 133 | "data = {'iface_name':'ge-0/0/1', 'vlan_name':'200'}\n", 134 | "print data" 135 | ] 136 | }, 137 | { 138 | "cell_type": "markdown", 139 | "metadata": {}, 140 | "source": [ 141 | "# YAML\n", 142 | "\n", 143 | "### YAML is a human friendly data serialization standard for all programming languages. It is ideal for storing object tree.\n", 144 | "\n", 145 | "### Python programmers are generally big fans of YAML, because of the use of indentation, rather than bracketed syntax, to indicate levels.\n", 146 | "\n", 147 | "### A markup language is a language that annotates text so that the computer can manipulate the text.\n" 148 | ] 149 | }, 150 | { 151 | "cell_type": "markdown", 152 | "metadata": {}, 153 | "source": [ 154 | "```yaml\n", 155 | "---\n", 156 | "# An employee record\n", 157 | "name: Example Developer \n", 158 | "job: Developer \n", 159 | "skill: Elite \n", 160 | "employed: True \n", 161 | "foods: \n", 162 | " - Apple \n", 163 | " - Orange \n", 164 | " - Strawberry \n", 165 | " - Mango \n", 166 | "languages: \n", 167 | " ruby: Elite \n", 168 | " python: Elite \n", 169 | " dotnet: Lame\n", 170 | "```" 171 | ] 172 | }, 173 | { 174 | "cell_type": "markdown", 175 | "metadata": {}, 176 | "source": [ 177 | "#### Thumb rule to write YAML: Proper indentation. " 178 | ] 179 | }, 180 | { 181 | "cell_type": "markdown", 182 | "metadata": {}, 183 | "source": [ 184 | "So what are the benefits of YAML:\n", 185 | "\n", 186 | "Portable between programming languages:\n", 187 | "\n", 188 | "YAML emitters and parsers for many popular languages written in the pure native language itself exist, making it portable in a self-contained manner. \n", 189 | "YAML representations of application information will be consistent and portable between various programming environments\n", 190 | "\n", 191 | "Well known libraries to play with YAML in programming language:\n", 192 | "C/C++: \n", 193 | "- libyaml \t# \"C\" Fast YAML 1.1 \n", 194 | "Ruby: \n", 195 | "- Psych \t# libyaml wrapper (in Ruby core for 1.9.2) \n", 196 | "- RbYaml \t# YAML 1.1 (PyYaml Port) binding \n", 197 | "Python: \n", 198 | "- PyYaml \t# YAML 1.1, pure python and libyaml binding \n", 199 | "- PySyck \t# YAML 1.0, syck binding \n", 200 | "Java: \n", 201 | "- JvYaml \t# Java port of RbYaml \n", 202 | "Perl Modules: \n", 203 | "- YAML \t# Pure Perl YAML Module \n", 204 | "- YAML::Syck \t# Binding to libsyck \n", 205 | "- PlYaml \t# Perl port of PyYaml implementation\n", 206 | "PHP: \n", 207 | "- php-yaml \t# libyaml bindings (YAML 1.1) \n", 208 | "- syck \t# syck bindings (YAML 1.0) \n" 209 | ] 210 | }, 211 | { 212 | "cell_type": "markdown", 213 | "metadata": {}, 214 | "source": [ 215 | "### Another example" 216 | ] 217 | }, 218 | { 219 | "cell_type": "markdown", 220 | "metadata": {}, 221 | "source": [ 222 | "```yaml\n", 223 | "---\n", 224 | "name: Juniper Networks \n", 225 | "CEO: Rami Rahim\n", 226 | "Headquarter: Sunnyvale\n", 227 | "Development: \n", 228 | " - Sunnyvale\n", 229 | " - Bangalore\n", 230 | " - Beijing\n", 231 | "Sales: \n", 232 | " - Sydeny\n", 233 | " - Mumbai\n", 234 | "```" 235 | ] 236 | }, 237 | { 238 | "cell_type": "code", 239 | "execution_count": 16, 240 | "metadata": { 241 | "collapsed": false 242 | }, 243 | "outputs": [ 244 | { 245 | "data": { 246 | "text/plain": [ 247 | "{'CEO': 'Rami Rahim',\n", 248 | " 'Development': ['Sunnyvale', 'Bangalore', 'Beijing'],\n", 249 | " 'Headquarter': 'Sunnyvale',\n", 250 | " 'Sales': ['Sydeny', 'Mumbai'],\n", 251 | " 'name': 'Juniper Networks'}" 252 | ] 253 | }, 254 | "execution_count": 16, 255 | "metadata": {}, 256 | "output_type": "execute_result" 257 | } 258 | ], 259 | "source": [ 260 | "import yaml\n", 261 | "\n", 262 | "data = \"\"\"\n", 263 | "---\n", 264 | "name: Juniper Networks \n", 265 | "CEO: Rami Rahim\n", 266 | "Headquarter: Sunnyvale\n", 267 | "Development: \n", 268 | " - Sunnyvale\n", 269 | " - Bangalore\n", 270 | " - Beijing\n", 271 | "Sales: \n", 272 | " - Sydeny\n", 273 | " - Mumbai\n", 274 | "\"\"\"\n", 275 | "\n", 276 | "yaml.load(data)" 277 | ] 278 | }, 279 | { 280 | "cell_type": "code", 281 | "execution_count": 20, 282 | "metadata": { 283 | "collapsed": false 284 | }, 285 | "outputs": [ 286 | { 287 | "data": { 288 | "text/plain": [ 289 | "[['pineapple', 'coconut'], ['umbrella', 'raincoat']]" 290 | ] 291 | }, 292 | "execution_count": 20, 293 | "metadata": {}, 294 | "output_type": "execute_result" 295 | } 296 | ], 297 | "source": [ 298 | "data = \"\"\"\n", 299 | "---\n", 300 | "-\n", 301 | " - pineapple \n", 302 | " - coconut \n", 303 | "-\n", 304 | " - umbrella \n", 305 | " - raincoat\n", 306 | "\"\"\"\n", 307 | "yaml.load(data)" 308 | ] 309 | }, 310 | { 311 | "cell_type": "code", 312 | "execution_count": 21, 313 | "metadata": { 314 | "collapsed": false 315 | }, 316 | "outputs": [ 317 | { 318 | "data": { 319 | "text/plain": [ 320 | "{'Joey': {'age': 22, 'sex': 'M'}, 'Laura': {'age': 24, 'sex': 'F'}}" 321 | ] 322 | }, 323 | "execution_count": 21, 324 | "metadata": {}, 325 | "output_type": "execute_result" 326 | } 327 | ], 328 | "source": [ 329 | "\n", 330 | "data = \"\"\"\n", 331 | "---\n", 332 | "Joey: \n", 333 | " age: 22 \n", 334 | " sex: M \n", 335 | "Laura: \n", 336 | " age: 24 \n", 337 | " sex: F\n", 338 | "\"\"\"\n", 339 | "yaml.load(data)" 340 | ] 341 | }, 342 | { 343 | "cell_type": "code", 344 | "execution_count": 23, 345 | "metadata": { 346 | "collapsed": false 347 | }, 348 | "outputs": [ 349 | { 350 | "data": { 351 | "text/plain": [ 352 | "{'bill-to': {'city': 'East Centerville',\n", 353 | " 'state': 'KS',\n", 354 | " 'street': '123 Tornado Alley\\nSuite 16\\n'},\n", 355 | " 'customer': {'family_name': 'Gale', 'first_name': 'Dorothy'},\n", 356 | " 'date': datetime.date(2012, 8, 6),\n", 357 | " 'items': [{'descrip': 'Water Bucket (Filled)',\n", 358 | " 'part_no': 'A4786',\n", 359 | " 'price': 1.47,\n", 360 | " 'quantity': 4},\n", 361 | " {'descrip': 'High Heeled \"Ruby\" Slippers',\n", 362 | " 'part_no': 'E1628',\n", 363 | " 'price': 133.7,\n", 364 | " 'quantity': 1,\n", 365 | " 'size': 8}],\n", 366 | " 'receipt': 'Oz-Ware Purchase Invoice',\n", 367 | " 'ship-to': {'city': 'East Centerville',\n", 368 | " 'state': 'KS',\n", 369 | " 'street': '123 Tornado Alley\\nSuite 16\\n'},\n", 370 | " 'specialDelivery': 'Follow the Yellow Brick\\nRoad to the Emerald City.\\nPay no attention to the\\nman behind the curtain.\\n'}" 371 | ] 372 | }, 373 | "execution_count": 23, 374 | "metadata": {}, 375 | "output_type": "execute_result" 376 | } 377 | ], 378 | "source": [ 379 | "data = \"\"\"\n", 380 | "---\n", 381 | "receipt: Oz-Ware Purchase Invoice\n", 382 | "date: 2012-08-06\n", 383 | "customer:\n", 384 | " first_name: Dorothy\n", 385 | " family_name: Gale\n", 386 | "\n", 387 | "items:\n", 388 | " - part_no: A4786\n", 389 | " descrip: Water Bucket (Filled)\n", 390 | " price: 1.47\n", 391 | " quantity: 4\n", 392 | "\n", 393 | " - part_no: E1628\n", 394 | " descrip: High Heeled \"Ruby\" Slippers\n", 395 | " size: 8\n", 396 | " price: 133.7\n", 397 | " quantity: 1\n", 398 | "\n", 399 | "bill-to: &id001\n", 400 | " street: |\n", 401 | " 123 Tornado Alley\n", 402 | " Suite 16\n", 403 | " city: East Centerville\n", 404 | " state: KS\n", 405 | "\n", 406 | "ship-to: *id001\n", 407 | "\n", 408 | "specialDelivery: >\n", 409 | " Follow the Yellow Brick\n", 410 | " Road to the Emerald City.\n", 411 | " Pay no attention to the\n", 412 | " man behind the curtain.\n", 413 | "...\n", 414 | "\"\"\"\n", 415 | "yaml.load(data)" 416 | ] 417 | }, 418 | { 419 | "cell_type": "code", 420 | "execution_count": 25, 421 | "metadata": { 422 | "collapsed": false 423 | }, 424 | "outputs": [ 425 | { 426 | "data": { 427 | "text/plain": [ 428 | "[{'step': {'instrument': 'Lasik 2000',\n", 429 | " 'pulseDuration': 12,\n", 430 | " 'pulseEnergy': 5.4,\n", 431 | " 'repetition': 1000,\n", 432 | " 'spotSize': '1mm'}},\n", 433 | " {'step': {'instrument': 'Lasik 2000',\n", 434 | " 'pulseDuration': 10,\n", 435 | " 'pulseEnergy': 5.0,\n", 436 | " 'repetition': 500,\n", 437 | " 'spotSize': '2mm'}},\n", 438 | " {'step': {'instrument': 'Lasik 2000',\n", 439 | " 'pulseDuration': 12,\n", 440 | " 'pulseEnergy': 5.4,\n", 441 | " 'repetition': 1000,\n", 442 | " 'spotSize': '1mm'}},\n", 443 | " {'step': {'instrument': 'Lasik 2000',\n", 444 | " 'pulseDuration': 10,\n", 445 | " 'pulseEnergy': 5.0,\n", 446 | " 'repetition': 500,\n", 447 | " 'spotSize': '2mm'}},\n", 448 | " {'step': {'instrument': 'Lasik 2000',\n", 449 | " 'pulseDuration': 12,\n", 450 | " 'pulseEnergy': 5.4,\n", 451 | " 'repetition': 1000,\n", 452 | " 'spotSize': '2mm'}}]" 453 | ] 454 | }, 455 | "execution_count": 25, 456 | "metadata": {}, 457 | "output_type": "execute_result" 458 | } 459 | ], 460 | "source": [ 461 | "data = \"\"\"\n", 462 | "---\n", 463 | "- step: &id001 # defines anchor label &id001\n", 464 | " instrument: Lasik 2000\n", 465 | " pulseEnergy: 5.4\n", 466 | " pulseDuration: 12\n", 467 | " repetition: 1000\n", 468 | " spotSize: 1mm\n", 469 | "\n", 470 | "- step: &id002\n", 471 | " instrument: Lasik 2000\n", 472 | " pulseEnergy: 5.0\n", 473 | " pulseDuration: 10\n", 474 | " repetition: 500\n", 475 | " spotSize: 2mm\n", 476 | "- step: *id001 # refers to the first step (with anchor &id001)\n", 477 | "- step: *id002 # refers to the second step\n", 478 | "- step: \n", 479 | " <<: *id001\n", 480 | " spotSize: 2mm # redefines just this key, refers rest from &id001\n", 481 | "\"\"\"\n", 482 | "yaml.load(data)" 483 | ] 484 | }, 485 | { 486 | "cell_type": "code", 487 | "execution_count": 27, 488 | "metadata": { 489 | "collapsed": false 490 | }, 491 | "outputs": [], 492 | "source": [ 493 | "yaml.parse?" 494 | ] 495 | }, 496 | { 497 | "cell_type": "markdown", 498 | "metadata": {}, 499 | "source": [ 500 | "## Jinja2" 501 | ] 502 | }, 503 | { 504 | "cell_type": "markdown", 505 | "metadata": {}, 506 | "source": [ 507 | "### Junos sample config" 508 | ] 509 | }, 510 | { 511 | "cell_type": "code", 512 | "execution_count": 28, 513 | "metadata": { 514 | "collapsed": false 515 | }, 516 | "outputs": [ 517 | { 518 | "name": "stdout", 519 | "output_type": "stream", 520 | "text": [ 521 | "/Users/nitinkr/Coding/pyez-examples/templates\n" 522 | ] 523 | } 524 | ], 525 | "source": [ 526 | "import os\n", 527 | "cwd = os.getcwd()\n", 528 | "print cwd" 529 | ] 530 | }, 531 | { 532 | "cell_type": "code", 533 | "execution_count": 31, 534 | "metadata": { 535 | "collapsed": false 536 | }, 537 | "outputs": [ 538 | { 539 | "name": "stdout", 540 | "output_type": "stream", 541 | "text": [ 542 | "Hello xyz!!\n" 543 | ] 544 | } 545 | ], 546 | "source": [ 547 | "from jinja2 import Template\n", 548 | "t = Template(\"Hello {{ data }}!!\")\n", 549 | "print t.render(data='xyz')" 550 | ] 551 | }, 552 | { 553 | "cell_type": "markdown", 554 | "metadata": {}, 555 | "source": [ 556 | "```text\n", 557 | "interfaces {\n", 558 | " interface ge-0/0/1 {\n", 559 | " unit 0 {\n", 560 | " family ethernet-switching {\n", 561 | " port-mode access;\n", 562 | " replace:\n", 563 | " vlan {\n", 564 | " member 200;\n", 565 | " }\n", 566 | " }\n", 567 | " }\n", 568 | " } \n", 569 | "}\n", 570 | "```\n" 571 | ] 572 | }, 573 | { 574 | "cell_type": "markdown", 575 | "metadata": {}, 576 | "source": [ 577 | "### jinja2 template" 578 | ] 579 | }, 580 | { 581 | "cell_type": "markdown", 582 | "metadata": {}, 583 | "source": [ 584 | "```jinja2\n", 585 | "interfaces {\n", 586 | " interface {{ iface_name }} {\n", 587 | " unit 0 {\n", 588 | " family ethernet-switching {\n", 589 | " port-mode access;\n", 590 | " replace:\n", 591 | " vlan {\n", 592 | " member {{ vlan_name }};\n", 593 | " }\n", 594 | " }\n", 595 | " }\n", 596 | " } \n", 597 | "}\n", 598 | "```\n" 599 | ] 600 | }, 601 | { 602 | "cell_type": "code", 603 | "execution_count": 33, 604 | "metadata": { 605 | "collapsed": false 606 | }, 607 | "outputs": [ 608 | { 609 | "name": "stdout", 610 | "output_type": "stream", 611 | "text": [ 612 | "interfaces {\n", 613 | " interface ge-0/0/2 {\n", 614 | " unit 0 {\n", 615 | " family ethernet-switching {\n", 616 | " port-mode access;\n", 617 | " replace:\n", 618 | " vlan {\n", 619 | " member 200;\n", 620 | " }\n", 621 | " }\n", 622 | " }\n", 623 | " } \n", 624 | "}\n" 625 | ] 626 | } 627 | ], 628 | "source": [ 629 | "import jinja2\n", 630 | "template = \"\"\"interfaces {\n", 631 | " interface {{ iface_name }} {\n", 632 | " unit 0 {\n", 633 | " family ethernet-switching {\n", 634 | " port-mode access;\n", 635 | " replace:\n", 636 | " vlan {\n", 637 | " member {{ vlan_name }};\n", 638 | " }\n", 639 | " }\n", 640 | " }\n", 641 | " } \n", 642 | "}\"\"\"\n", 643 | "tmpl = jinja2.Template(template)\n", 644 | "conf = tmpl.render(iface_name='ge-0/0/2', vlan_name='200')\n", 645 | "print conf" 646 | ] 647 | }, 648 | { 649 | "cell_type": "code", 650 | "execution_count": 34, 651 | "metadata": { 652 | "collapsed": false 653 | }, 654 | "outputs": [ 655 | { 656 | "name": "stdout", 657 | "output_type": "stream", 658 | "text": [ 659 | "interfaces {\n", 660 | " interface ge-0/0/1 {\n", 661 | " unit 0 {\n", 662 | " family ethernet-switching {\n", 663 | " port-mode access;\n", 664 | " replace:\n", 665 | " vlan {\n", 666 | " member 200;\n", 667 | " }\n", 668 | " }\n", 669 | " }\n", 670 | " } \n", 671 | "}\n" 672 | ] 673 | } 674 | ], 675 | "source": [ 676 | "import jinja2\n", 677 | "template = \"\"\"interfaces {\n", 678 | " interface {{ iface_name }} {\n", 679 | " unit 0 {\n", 680 | " family ethernet-switching {\n", 681 | " port-mode access;\n", 682 | " replace:\n", 683 | " vlan {\n", 684 | " member {{ vlan_name }};\n", 685 | " }\n", 686 | " }\n", 687 | " }\n", 688 | " } \n", 689 | "}\"\"\"\n", 690 | "tmpl = jinja2.Template(template)\n", 691 | "conf = tmpl.render({'iface_name':'ge-0/0/1', 'vlan_name':'200'})\n", 692 | "print conf" 693 | ] 694 | }, 695 | { 696 | "cell_type": "code", 697 | "execution_count": 35, 698 | "metadata": { 699 | "collapsed": false 700 | }, 701 | "outputs": [ 702 | { 703 | "name": "stdout", 704 | "output_type": "stream", 705 | "text": [ 706 | "interfaces {\n", 707 | " interface ge-0/0/5 {\n", 708 | " unit 0 {\n", 709 | " family ethernet-switching {\n", 710 | " port-mode access;\n", 711 | " replace:\n", 712 | " vlan {\n", 713 | " member 300;\n", 714 | " }\n", 715 | " }\n", 716 | " }\n", 717 | " } \n", 718 | "}\n" 719 | ] 720 | } 721 | ], 722 | "source": [ 723 | "import jinja2\n", 724 | "\n", 725 | "# tmpl = jinja2.Template(open('/Users/nitinkr/demos/PyEZ/templates/1_temp.j2').read())\n", 726 | "\n", 727 | "loader = jinja2.FileSystemLoader(cwd)\n", 728 | "jenv = jinja2.Environment(loader=loader, trim_blocks=True, lstrip_blocks=True)\n", 729 | "tmpl = jenv.get_template('1_temp.j2')\n", 730 | "conf = tmpl.render(iface_name='ge-0/0/5', vlan_name='300')\n", 731 | "print conf" 732 | ] 733 | }, 734 | { 735 | "cell_type": "markdown", 736 | "metadata": {}, 737 | "source": [ 738 | "#### To know more about trim_blocks, lstrip_blocks\n", 739 | "\n", 740 | "http://jinja.pocoo.org/docs/dev/templates/#whitespace-control" 741 | ] 742 | }, 743 | { 744 | "cell_type": "code", 745 | "execution_count": null, 746 | "metadata": { 747 | "collapsed": false 748 | }, 749 | "outputs": [], 750 | "source": [ 751 | "jinja2.Environment?" 752 | ] 753 | }, 754 | { 755 | "cell_type": "markdown", 756 | "metadata": {}, 757 | "source": [ 758 | "### Loop inside Jinja Template\n", 759 | "\n", 760 | "```jinja2\n", 761 | "interfaces {\n", 762 | " {% for item in interfaces %}\n", 763 | " {{ item }} {\n", 764 | " unit 0 {\n", 765 | " family ethernet-switching {\n", 766 | " port-mode access;\n", 767 | " replace:\n", 768 | " vlan {\n", 769 | " member {{ vlan_name }};\n", 770 | " }\n", 771 | " }\n", 772 | " } \n", 773 | " } {% endfor %} \n", 774 | "}\n", 775 | "```" 776 | ] 777 | }, 778 | { 779 | "cell_type": "code", 780 | "execution_count": 37, 781 | "metadata": { 782 | "collapsed": false 783 | }, 784 | "outputs": [ 785 | { 786 | "name": "stdout", 787 | "output_type": "stream", 788 | "text": [ 789 | "interfaces {\n", 790 | " \n", 791 | " ge-0/0/1 {\n", 792 | " unit 0 {\n", 793 | " family ethernet-switching {\n", 794 | " port-mode access;\n", 795 | " replace:\n", 796 | " vlan {\n", 797 | " member 300;\n", 798 | " }\n", 799 | " }\n", 800 | " } \n", 801 | " } \n", 802 | " ge-0/0/2 {\n", 803 | " unit 0 {\n", 804 | " family ethernet-switching {\n", 805 | " port-mode access;\n", 806 | " replace:\n", 807 | " vlan {\n", 808 | " member 300;\n", 809 | " }\n", 810 | " }\n", 811 | " } \n", 812 | " } \n", 813 | " ge-0/2/1 {\n", 814 | " unit 0 {\n", 815 | " family ethernet-switching {\n", 816 | " port-mode access;\n", 817 | " replace:\n", 818 | " vlan {\n", 819 | " member 300;\n", 820 | " }\n", 821 | " }\n", 822 | " } \n", 823 | " } \n", 824 | " ge-0/2/2 {\n", 825 | " unit 0 {\n", 826 | " family ethernet-switching {\n", 827 | " port-mode access;\n", 828 | " replace:\n", 829 | " vlan {\n", 830 | " member 300;\n", 831 | " }\n", 832 | " }\n", 833 | " } \n", 834 | " } \n", 835 | "}\n" 836 | ] 837 | } 838 | ], 839 | "source": [ 840 | "import jinja2\n", 841 | "template = \"\"\"interfaces {\n", 842 | " {% for item in interfaces %}\n", 843 | " {{ item }} {\n", 844 | " unit 0 {\n", 845 | " family ethernet-switching {\n", 846 | " port-mode access;\n", 847 | " replace:\n", 848 | " vlan {\n", 849 | " member {{ vlan_name }};\n", 850 | " }\n", 851 | " }\n", 852 | " } \n", 853 | " } {% endfor %} \n", 854 | "}\"\"\"\n", 855 | "tmpl = jinja2.Template(template)\n", 856 | "conf = tmpl.render(interfaces=['ge-0/0/1', 'ge-0/0/2', 'ge-0/2/1', 'ge-0/2/2'], vlan_name='300')\n", 857 | "print conf" 858 | ] 859 | }, 860 | { 861 | "cell_type": "markdown", 862 | "metadata": {}, 863 | "source": [ 864 | "### Filter in Template" 865 | ] 866 | }, 867 | { 868 | "cell_type": "code", 869 | "execution_count": null, 870 | "metadata": { 871 | "collapsed": false 872 | }, 873 | "outputs": [], 874 | "source": [ 875 | "loader = jinja2.FileSystemLoader(cwd)\n", 876 | "jenv = jinja2.Environment(loader=loader, trim_blocks=True, lstrip_blocks=True)" 877 | ] 878 | }, 879 | { 880 | "cell_type": "code", 881 | "execution_count": 44, 882 | "metadata": { 883 | "collapsed": false 884 | }, 885 | "outputs": [ 886 | { 887 | "name": "stdout", 888 | "output_type": "stream", 889 | "text": [ 890 | "interfaces {\n", 891 | " \n", 892 | " ge-0/0/1 {\n", 893 | " unit 0 {\n", 894 | " family ethernet-switching {\n", 895 | " port-mode ACCESS;\n", 896 | " replace:\n", 897 | " vlan {\n", 898 | " member 300;\n", 899 | " }\n", 900 | " }\n", 901 | " } \n", 902 | " } \n", 903 | " ge-0/0/2 {\n", 904 | " unit 0 {\n", 905 | " family ethernet-switching {\n", 906 | " port-mode ACCESS;\n", 907 | " replace:\n", 908 | " vlan {\n", 909 | " member 300;\n", 910 | " }\n", 911 | " }\n", 912 | " } \n", 913 | " } \n", 914 | "}\n" 915 | ] 916 | } 917 | ], 918 | "source": [ 919 | "import jinja2\n", 920 | "template = \"\"\"interfaces {\n", 921 | " {% for item in interfaces %}\n", 922 | " {{ item }} {\n", 923 | " unit 0 {\n", 924 | " family ethernet-switching {\n", 925 | " port-mode {{ mode | upper }};\n", 926 | " replace:\n", 927 | " vlan {\n", 928 | " member {{ vlan_name }};\n", 929 | " }\n", 930 | " }\n", 931 | " } \n", 932 | " } {% endfor %} \n", 933 | "}\"\"\"\n", 934 | "tmpl = jinja2.Template(template)\n", 935 | "conf = tmpl.render(interfaces=['ge-0/0/1', 'ge-0/0/2'], vlan_name='300', mode='access')\n", 936 | "print conf" 937 | ] 938 | }, 939 | { 940 | "cell_type": "code", 941 | "execution_count": null, 942 | "metadata": { 943 | "collapsed": false 944 | }, 945 | "outputs": [], 946 | "source": [ 947 | "jenv.filters" 948 | ] 949 | }, 950 | { 951 | "cell_type": "code", 952 | "execution_count": 45, 953 | "metadata": { 954 | "collapsed": false 955 | }, 956 | "outputs": [ 957 | { 958 | "name": "stdout", 959 | "output_type": "stream", 960 | "text": [ 961 | "ge-0/0/0\n", 962 | "ge-0/0/1\n", 963 | "ge-0/0/2\n", 964 | "ge-0/0/3\n", 965 | "ge-0/0/4\n", 966 | "ge-0/0/5\n" 967 | ] 968 | } 969 | ], 970 | "source": [ 971 | "from bracket_expansion import bracket_expansion\n", 972 | "jenv.filters['bracket_expansion']=bracket_expansion\n", 973 | "for i in bracket_expansion('ge-0/0/[0-5]'):\n", 974 | " print i" 975 | ] 976 | }, 977 | { 978 | "cell_type": "code", 979 | "execution_count": 46, 980 | "metadata": { 981 | "collapsed": false 982 | }, 983 | "outputs": [ 984 | { 985 | "name": "stdout", 986 | "output_type": "stream", 987 | "text": [ 988 | "interfaces {\n", 989 | " ge-0/0/0 {\n", 990 | " unit 0 {\n", 991 | " family ethernet-switching {\n", 992 | " port-mode access;\n", 993 | " replace:\n", 994 | " vlan {\n", 995 | " member 300;\n", 996 | " }\n", 997 | " }\n", 998 | " } \n", 999 | " } ge-0/0/1 {\n", 1000 | " unit 0 {\n", 1001 | " family ethernet-switching {\n", 1002 | " port-mode access;\n", 1003 | " replace:\n", 1004 | " vlan {\n", 1005 | " member 300;\n", 1006 | " }\n", 1007 | " }\n", 1008 | " } \n", 1009 | " } ge-0/0/2 {\n", 1010 | " unit 0 {\n", 1011 | " family ethernet-switching {\n", 1012 | " port-mode access;\n", 1013 | " replace:\n", 1014 | " vlan {\n", 1015 | " member 300;\n", 1016 | " }\n", 1017 | " }\n", 1018 | " } \n", 1019 | " } ge-0/0/3 {\n", 1020 | " unit 0 {\n", 1021 | " family ethernet-switching {\n", 1022 | " port-mode access;\n", 1023 | " replace:\n", 1024 | " vlan {\n", 1025 | " member 300;\n", 1026 | " }\n", 1027 | " }\n", 1028 | " } \n", 1029 | " } ge-0/0/4 {\n", 1030 | " unit 0 {\n", 1031 | " family ethernet-switching {\n", 1032 | " port-mode access;\n", 1033 | " replace:\n", 1034 | " vlan {\n", 1035 | " member 300;\n", 1036 | " }\n", 1037 | " }\n", 1038 | " } \n", 1039 | " } ge-0/0/5 {\n", 1040 | " unit 0 {\n", 1041 | " family ethernet-switching {\n", 1042 | " port-mode access;\n", 1043 | " replace:\n", 1044 | " vlan {\n", 1045 | " member 300;\n", 1046 | " }\n", 1047 | " }\n", 1048 | " } \n", 1049 | " } ge-0/0/6 {\n", 1050 | " unit 0 {\n", 1051 | " family ethernet-switching {\n", 1052 | " port-mode access;\n", 1053 | " replace:\n", 1054 | " vlan {\n", 1055 | " member 300;\n", 1056 | " }\n", 1057 | " }\n", 1058 | " } \n", 1059 | " } ge-0/0/7 {\n", 1060 | " unit 0 {\n", 1061 | " family ethernet-switching {\n", 1062 | " port-mode access;\n", 1063 | " replace:\n", 1064 | " vlan {\n", 1065 | " member 300;\n", 1066 | " }\n", 1067 | " }\n", 1068 | " } \n", 1069 | " } ge-0/0/8 {\n", 1070 | " unit 0 {\n", 1071 | " family ethernet-switching {\n", 1072 | " port-mode access;\n", 1073 | " replace:\n", 1074 | " vlan {\n", 1075 | " member 300;\n", 1076 | " }\n", 1077 | " }\n", 1078 | " } \n", 1079 | " } ge-0/0/9 {\n", 1080 | " unit 0 {\n", 1081 | " family ethernet-switching {\n", 1082 | " port-mode access;\n", 1083 | " replace:\n", 1084 | " vlan {\n", 1085 | " member 300;\n", 1086 | " }\n", 1087 | " }\n", 1088 | " } \n", 1089 | " } ge-0/0/10 {\n", 1090 | " unit 0 {\n", 1091 | " family ethernet-switching {\n", 1092 | " port-mode access;\n", 1093 | " replace:\n", 1094 | " vlan {\n", 1095 | " member 300;\n", 1096 | " }\n", 1097 | " }\n", 1098 | " } \n", 1099 | " } \n", 1100 | "}\n" 1101 | ] 1102 | } 1103 | ], 1104 | "source": [ 1105 | "import jinja2\n", 1106 | "template = \"\"\"interfaces {\n", 1107 | " {% for item in iface_pattern | bracket_expansion %}\n", 1108 | " {{ item }} {\n", 1109 | " unit 0 {\n", 1110 | " family ethernet-switching {\n", 1111 | " port-mode access;\n", 1112 | " replace:\n", 1113 | " vlan {\n", 1114 | " member {{ vlan_name }};\n", 1115 | " }\n", 1116 | " }\n", 1117 | " } \n", 1118 | " } {% endfor %} \n", 1119 | "}\"\"\"\n", 1120 | "loader = jinja2.FileSystemLoader(cwd)\n", 1121 | "jenv = jinja2.Environment(loader=loader, trim_blocks=True, lstrip_blocks=True)\n", 1122 | "jenv.filters['bracket_expansion']=bracket_expansion\n", 1123 | "tmpl = jenv.get_template('filter.j2')\n", 1124 | "conf = tmpl.render(iface_pattern='ge-0/0/[0-10]', vlan_name='300')\n", 1125 | "print conf" 1126 | ] 1127 | }, 1128 | { 1129 | "cell_type": "markdown", 1130 | "metadata": {}, 1131 | "source": [ 1132 | "### Include directive\n", 1133 | "#### To create Modular template" 1134 | ] 1135 | }, 1136 | { 1137 | "cell_type": "code", 1138 | "execution_count": 49, 1139 | "metadata": { 1140 | "collapsed": false 1141 | }, 1142 | "outputs": [ 1143 | { 1144 | "name": "stdout", 1145 | "output_type": "stream", 1146 | "text": [ 1147 | "['/Users/nitinkr/Coding/pyez-examples/templates/sshkeys/lakhan.pub', '/Users/nitinkr/Coding/pyez-examples/templates/sshkeys/ram.pub']\n" 1148 | ] 1149 | } 1150 | ], 1151 | "source": [ 1152 | "from glob import glob\n", 1153 | "print glob(cwd+'/sshkeys/*.pub')" 1154 | ] 1155 | }, 1156 | { 1157 | "cell_type": "code", 1158 | "execution_count": 50, 1159 | "metadata": { 1160 | "collapsed": false 1161 | }, 1162 | "outputs": [ 1163 | { 1164 | "name": "stdout", 1165 | "output_type": "stream", 1166 | "text": [ 1167 | "['lakhan.pub', 'ram.pub']\n", 1168 | "['lakhan', 'ram']\n" 1169 | ] 1170 | } 1171 | ], 1172 | "source": [ 1173 | "from os.path import basename, splitext\n", 1174 | "print [basename(i) for i in glob(cwd+'/sshkeys/*.pub')]\n", 1175 | "print [splitext(basename(i))[0] for i in glob(cwd+'/sshkeys/*.pub')]" 1176 | ] 1177 | }, 1178 | { 1179 | "cell_type": "code", 1180 | "execution_count": 51, 1181 | "metadata": { 1182 | "collapsed": true 1183 | }, 1184 | "outputs": [], 1185 | "source": [ 1186 | "def basefilename(name):\n", 1187 | " return splitext(basename(name))[0]\n", 1188 | "\n", 1189 | "# basefilename = lambda name: splitext(basename(name))[0]" 1190 | ] 1191 | }, 1192 | { 1193 | "cell_type": "markdown", 1194 | "metadata": {}, 1195 | "source": [ 1196 | "```jinja2\n", 1197 | "system {\n", 1198 | " login {\n", 1199 | " {% for ssh_pub in sshkeyfiles %}\n", 1200 | " user {{ ssh_pub | basefilename }} {\n", 1201 | " authentication {\n", 1202 | " ssh-rsa \"{% include ssh_pub %}\";\n", 1203 | " }\n", 1204 | " }\n", 1205 | " {% endfor %}\n", 1206 | " }\n", 1207 | "}\n", 1208 | "```" 1209 | ] 1210 | }, 1211 | { 1212 | "cell_type": "code", 1213 | "execution_count": 52, 1214 | "metadata": { 1215 | "collapsed": false 1216 | }, 1217 | "outputs": [ 1218 | { 1219 | "name": "stdout", 1220 | "output_type": "stream", 1221 | "text": [ 1222 | "system {\n", 1223 | " login {\n", 1224 | " user lakhan {\n", 1225 | " authentication {\n", 1226 | " ssh-rsa \"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCl2uGO4skBv30W3O6//E2h4wmagnp5F2d2ZAejG+rozy+fbAD83nD4cOg5PZfpVTmV5q3VitcG7rQlRim4Rw+669R+n06BG/FarsIv2yAV9Vz30y51tlzCThF4TQEVttKgQtdmgtenoTOnIsZHjms6zx7OyeMws4nb6kFE1eFv2A+h+FAQeIq+5bxXWpH77Wr9DrCVS6wqyDu4niv6WnxshJFKO8AZOkl51qcQznEe9J7Jz4SfgXnqGKJsJnJOGSdxK6gyRRLYLQ2S7CZIQe6Cb97nGERFSx4w9XFMWZf/RkY3o0lXOv0VC51pr5ocJYvb+IpYAiCjF0po6xMd11dh nitinkr@nitinkr-mba13\";\n", 1227 | " }\n", 1228 | " }\n", 1229 | " user ram {\n", 1230 | " authentication {\n", 1231 | " ssh-rsa \"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDHSljc8AuY2UgmZuAl5hW18UZJwzj4u1Qu6kWJ4aecK71r3Vrar65TKNisv/eOOFVHoI8690IOMHG0NUzNJH+WtaFFKhI/2yX6Q3UJ8Chs3FOIfRvMtORvgrN5JJfKREmRVEWVdzWqHDGs6DyXDiL8h0XsBQmCJcuMS5JCi+GggYr/ysMOzLXWkjgZasj0AcVZrGkaTV0R1Ec7SV/IZGMZC1RelDiaTiMPdsI7LFV6jnZzqG9IZmMHwDLAocO/HN2nnGUWGBn172h8ah0fSuTnA8Wm5AnD+/3k/N5tHOjMfRU+P755FWkC+TwPuXrtqV8kh4ZBWWr5CHUtflzNmMn nitinkr@nitinkr-mba13\";\n", 1232 | " }\n", 1233 | " }\n", 1234 | " }\n", 1235 | "}\n" 1236 | ] 1237 | } 1238 | ], 1239 | "source": [ 1240 | "import jinja2\n", 1241 | "\n", 1242 | "loader = jinja2.FileSystemLoader(cwd)\n", 1243 | "jenv = jinja2.Environment(loader=loader, trim_blocks=True, lstrip_blocks=True)\n", 1244 | "jenv.filters['basefilename']=basefilename\n", 1245 | "tmpl = jenv.get_template('users.j2')\n", 1246 | "print tmpl.render(sshkeyfiles=glob('sshkeys/*.pub'))" 1247 | ] 1248 | }, 1249 | { 1250 | "cell_type": "code", 1251 | "execution_count": 53, 1252 | "metadata": { 1253 | "collapsed": false 1254 | }, 1255 | "outputs": [ 1256 | { 1257 | "name": "stdout", 1258 | "output_type": "stream", 1259 | "text": [ 1260 | "##\n", 1261 | "## This is top main file\n", 1262 | "##\n", 1263 | "\n", 1264 | "interfaces { \n", 1265 | " {% for item in interfaces %}\n", 1266 | " {{ item }} {\n", 1267 | " description \"{{ description }}\";\n", 1268 | " unit 0 {\n", 1269 | " family {{ family }};\n", 1270 | " } \n", 1271 | " } {% endfor %} \n", 1272 | "}\n", 1273 | "##\n", 1274 | "## including another jinja templete\n", 1275 | "##\n", 1276 | "{% include 'users.j2' %}\n", 1277 | "\n", 1278 | "##\n", 1279 | "## thats the end\n", 1280 | "##\n", 1281 | "\n" 1282 | ] 1283 | } 1284 | ], 1285 | "source": [ 1286 | "with open(os.path.join(cwd, 'main.j2')) as fp:\n", 1287 | " print fp.read()" 1288 | ] 1289 | }, 1290 | { 1291 | "cell_type": "code", 1292 | "execution_count": 54, 1293 | "metadata": { 1294 | "collapsed": false 1295 | }, 1296 | "outputs": [ 1297 | { 1298 | "name": "stdout", 1299 | "output_type": "stream", 1300 | "text": [ 1301 | "##\n", 1302 | "## This is top main file\n", 1303 | "##\n", 1304 | "\n", 1305 | "interfaces { \n", 1306 | " ge-0/0/1 {\n", 1307 | " description \"MPLS interface\";\n", 1308 | " unit 0 {\n", 1309 | " family mpls;\n", 1310 | " } \n", 1311 | " } ge-0/0/2 {\n", 1312 | " description \"MPLS interface\";\n", 1313 | " unit 0 {\n", 1314 | " family mpls;\n", 1315 | " } \n", 1316 | " } \n", 1317 | "}\n", 1318 | "##\n", 1319 | "## including another jinja templete\n", 1320 | "##\n", 1321 | "system {\n", 1322 | " login {\n", 1323 | " user lakhan {\n", 1324 | " authentication {\n", 1325 | " ssh-rsa \"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCl2uGO4skBv30W3O6//E2h4wmagnp5F2d2ZAejG+rozy+fbAD83nD4cOg5PZfpVTmV5q3VitcG7rQlRim4Rw+669R+n06BG/FarsIv2yAV9Vz30y51tlzCThF4TQEVttKgQtdmgtenoTOnIsZHjms6zx7OyeMws4nb6kFE1eFv2A+h+FAQeIq+5bxXWpH77Wr9DrCVS6wqyDu4niv6WnxshJFKO8AZOkl51qcQznEe9J7Jz4SfgXnqGKJsJnJOGSdxK6gyRRLYLQ2S7CZIQe6Cb97nGERFSx4w9XFMWZf/RkY3o0lXOv0VC51pr5ocJYvb+IpYAiCjF0po6xMd11dh nitinkr@nitinkr-mba13\";\n", 1326 | " }\n", 1327 | " }\n", 1328 | " user ram {\n", 1329 | " authentication {\n", 1330 | " ssh-rsa \"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDHSljc8AuY2UgmZuAl5hW18UZJwzj4u1Qu6kWJ4aecK71r3Vrar65TKNisv/eOOFVHoI8690IOMHG0NUzNJH+WtaFFKhI/2yX6Q3UJ8Chs3FOIfRvMtORvgrN5JJfKREmRVEWVdzWqHDGs6DyXDiL8h0XsBQmCJcuMS5JCi+GggYr/ysMOzLXWkjgZasj0AcVZrGkaTV0R1Ec7SV/IZGMZC1RelDiaTiMPdsI7LFV6jnZzqG9IZmMHwDLAocO/HN2nnGUWGBn172h8ah0fSuTnA8Wm5AnD+/3k/N5tHOjMfRU+P755FWkC+TwPuXrtqV8kh4ZBWWr5CHUtflzNmMn nitinkr@nitinkr-mba13\";\n", 1331 | " }\n", 1332 | " }\n", 1333 | " }\n", 1334 | "}\n", 1335 | "##\n", 1336 | "## thats the end\n", 1337 | "##\n" 1338 | ] 1339 | } 1340 | ], 1341 | "source": [ 1342 | "main = jenv.get_template('main.j2')\n", 1343 | "print main.render(sshkeyfiles=glob('sshkeys/*.pub'), interfaces=['ge-0/0/1', 'ge-0/0/2'], family='mpls', description='MPLS interface')" 1344 | ] 1345 | }, 1346 | { 1347 | "cell_type": "markdown", 1348 | "metadata": {}, 1349 | "source": [ 1350 | "### if/then/else directives" 1351 | ] 1352 | }, 1353 | { 1354 | "cell_type": "code", 1355 | "execution_count": 56, 1356 | "metadata": { 1357 | "collapsed": false 1358 | }, 1359 | "outputs": [ 1360 | { 1361 | "name": "stdout", 1362 | "output_type": "stream", 1363 | "text": [ 1364 | "\n", 1365 | "{'vlan_id': '100', 'vlan_name': 'Blue'} ,\n", 1366 | "{'vlan_id': '200', 'vlan_name': 'Green'} ,\n", 1367 | "{'vlan_id': '300', 'vlan_name': 'Yellow'} ,\n", 1368 | "{'vlan_id': '400', 'vlan_name': 'Purple'} ,\n", 1369 | "{'vlan_id': '500', 'vlan_name': 'Red'} ,\n" 1370 | ] 1371 | } 1372 | ], 1373 | "source": [ 1374 | "import csv\n", 1375 | "vlans = csv.DictReader(open(os.path.join(cwd,'vlans.csv')))\n", 1376 | "print vlans\n", 1377 | "for i in vlans:\n", 1378 | " print i,','" 1379 | ] 1380 | }, 1381 | { 1382 | "cell_type": "code", 1383 | "execution_count": 57, 1384 | "metadata": { 1385 | "collapsed": false 1386 | }, 1387 | "outputs": [ 1388 | { 1389 | "name": "stdout", 1390 | "output_type": "stream", 1391 | "text": [ 1392 | "\n", 1393 | "vlans {\n", 1394 | " Blue {\n", 1395 | " vlan-id 100;\n", 1396 | " }\n", 1397 | " Green {\n", 1398 | " vlan-id 200;\n", 1399 | " }\n", 1400 | " Yellow {\n", 1401 | " vlan-id 300;\n", 1402 | " }\n", 1403 | " Purple {\n", 1404 | " vlan-id 400;\n", 1405 | " }\n", 1406 | " Red {\n", 1407 | " vlan-id 500;\n", 1408 | " }\n", 1409 | "}\n" 1410 | ] 1411 | } 1412 | ], 1413 | "source": [ 1414 | "import jinja2\n", 1415 | "\n", 1416 | "vlans = csv.DictReader(open(os.path.join(cwd,'vlans.csv')))\n", 1417 | "loader = jinja2.FileSystemLoader(cwd)\n", 1418 | "jenv = jinja2.Environment(loader=loader, trim_blocks=True, lstrip_blocks=True)\n", 1419 | "tmpl = jenv.get_template('main_vlans.conf')\n", 1420 | "print tmpl.render(vlan_list=vlans)" 1421 | ] 1422 | }, 1423 | { 1424 | "cell_type": "code", 1425 | "execution_count": 58, 1426 | "metadata": { 1427 | "collapsed": false 1428 | }, 1429 | "outputs": [ 1430 | { 1431 | "name": "stdout", 1432 | "output_type": "stream", 1433 | "text": [ 1434 | "\n", 1435 | "vlans {\n", 1436 | " delete: Blue\n", 1437 | " delete: Green\n", 1438 | " delete: Yellow\n", 1439 | " delete: Purple\n", 1440 | " delete: Red\n", 1441 | "}\n" 1442 | ] 1443 | } 1444 | ], 1445 | "source": [ 1446 | "vlans = csv.DictReader(open(os.path.join(cwd,'vlans.csv')))\n", 1447 | "print tmpl.render(vlan_list=vlans, state='absent')" 1448 | ] 1449 | }, 1450 | { 1451 | "cell_type": "markdown", 1452 | "metadata": {}, 1453 | "source": [ 1454 | "### This presentation from AnsibleFest San Francisco 2015 focused on how Riot Games utilizes Ansible, Config templates and Juniper’s Py-EZ." 1455 | ] 1456 | }, 1457 | { 1458 | "cell_type": "code", 1459 | "execution_count": 59, 1460 | "metadata": { 1461 | "collapsed": false 1462 | }, 1463 | "outputs": [ 1464 | { 1465 | "data": { 1466 | "text/html": [ 1467 | "" 1468 | ], 1469 | "text/plain": [ 1470 | "" 1471 | ] 1472 | }, 1473 | "execution_count": 59, 1474 | "metadata": {}, 1475 | "output_type": "execute_result" 1476 | } 1477 | ], 1478 | "source": [ 1479 | "from IPython.display import HTML\n", 1480 | "HTML('')" 1481 | ] 1482 | }, 1483 | { 1484 | "cell_type": "code", 1485 | "execution_count": 60, 1486 | "metadata": { 1487 | "collapsed": false 1488 | }, 1489 | "outputs": [ 1490 | { 1491 | "data": { 1492 | "text/html": [ 1493 | "\n", 1494 | " \n", 1501 | " " 1502 | ], 1503 | "text/plain": [ 1504 | "" 1505 | ] 1506 | }, 1507 | "execution_count": 60, 1508 | "metadata": {}, 1509 | "output_type": "execute_result" 1510 | } 1511 | ], 1512 | "source": [ 1513 | "from IPython.display import YouTubeVideo\n", 1514 | "YouTubeVideo('PSgSjTeqRX0', start=450, width=900, height=500)" 1515 | ] 1516 | }, 1517 | { 1518 | "cell_type": "code", 1519 | "execution_count": 61, 1520 | "metadata": { 1521 | "collapsed": false 1522 | }, 1523 | "outputs": [ 1524 | { 1525 | "data": { 1526 | "text/html": [ 1527 | "\n", 1528 | " \n", 1535 | " " 1536 | ], 1537 | "text/plain": [ 1538 | "" 1539 | ] 1540 | }, 1541 | "execution_count": 61, 1542 | "metadata": {}, 1543 | "output_type": "execute_result" 1544 | } 1545 | ], 1546 | "source": [ 1547 | "from IPython.display import YouTubeVideo\n", 1548 | "YouTubeVideo('Gk5KKozJmz8', start=156, width=900, height=500)" 1549 | ] 1550 | } 1551 | ], 1552 | "metadata": { 1553 | "kernelspec": { 1554 | "display_name": "Python 2", 1555 | "language": "python", 1556 | "name": "python2" 1557 | }, 1558 | "language_info": { 1559 | "codemirror_mode": { 1560 | "name": "ipython", 1561 | "version": 2 1562 | }, 1563 | "file_extension": ".py", 1564 | "mimetype": "text/x-python", 1565 | "name": "python", 1566 | "nbconvert_exporter": "python", 1567 | "pygments_lexer": "ipython2", 1568 | "version": "2.7.8" 1569 | } 1570 | }, 1571 | "nbformat": 4, 1572 | "nbformat_minor": 0 1573 | } 1574 | -------------------------------------------------------------------------------- /templates/yaml_jinja_demo.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ```python 4 | interface_name = 'ge-0/0/1' 5 | print interface_name 6 | ``` 7 | 8 | ge-0/0/1 9 | 10 | 11 | 12 | ### Python List 13 | 14 | 15 | ```python 16 | protocols = ['mpls', 'bgp', 'isis', 'ospf'] 17 | ``` 18 | 19 | 20 | ```python 21 | for prot in protocols: 22 | print prot 23 | ``` 24 | 25 | mpls 26 | bgp 27 | isis 28 | ospf 29 | 30 | 31 | ### Python Dictionary 32 | 33 | 34 | ```python 35 | data = {'company': 'Juniper', 36 | 'ceo': 'Rami Rahim', 37 | 'domain': 'Networking'} 38 | 39 | print data 40 | ``` 41 | 42 | {'ceo': 'Rami Rahim', 'company': 'Juniper', 'domain': 'Networking'} 43 | 44 | 45 | 46 | ```python 47 | for k,v in data.items(): 48 | print k, ' -> ', v 49 | ``` 50 | 51 | ceo -> Rami Rahim 52 | company -> Juniper 53 | domain -> Networking 54 | 55 | 56 | 57 | ```python 58 | data = {'iface_name':'ge-0/0/1', 'vlan_name':'200'} 59 | print data 60 | ``` 61 | 62 | {'vlan_name': '200', 'iface_name': 'ge-0/0/1'} 63 | 64 | 65 | # YAML 66 | 67 | ### YAML is a human friendly data serialization standard for all programming languages. It is ideal for storing object tree. 68 | 69 | ### Python programmers are generally big fans of YAML, because of the use of indentation, rather than bracketed syntax, to indicate levels. 70 | 71 | ### A markup language is a language that annotates text so that the computer can manipulate the text. 72 | 73 | 74 | ```yaml 75 | --- 76 | # An employee record 77 | name: Example Developer 78 | job: Developer 79 | skill: Elite 80 | employed: True 81 | foods: 82 | - Apple 83 | - Orange 84 | - Strawberry 85 | - Mango 86 | languages: 87 | ruby: Elite 88 | python: Elite 89 | dotnet: Lame 90 | ``` 91 | 92 | #### Thumb rule to write YAML: Proper indentation. 93 | 94 | So what are the benefits of YAML: 95 | 96 | Portable between programming languages: 97 | 98 | YAML emitters and parsers for many popular languages written in the pure native language itself exist, making it portable in a self-contained manner.  99 | YAML representations of application information will be consistent and portable between various programming environments 100 | 101 | Well known libraries to play with YAML in programming language: 102 | C/C++: 103 | - libyaml # "C" Fast YAML 1.1 104 | Ruby: 105 | - Psych # libyaml wrapper (in Ruby core for 1.9.2) 106 | - RbYaml # YAML 1.1 (PyYaml Port) binding 107 | Python: 108 | - PyYaml # YAML 1.1, pure python and libyaml binding 109 | - PySyck # YAML 1.0, syck binding 110 | Java: 111 | - JvYaml # Java port of RbYaml 112 | Perl Modules: 113 | - YAML # Pure Perl YAML Module 114 | - YAML::Syck # Binding to libsyck 115 | - PlYaml # Perl port of PyYaml implementation 116 | PHP: 117 | - php-yaml # libyaml bindings (YAML 1.1) 118 | - syck # syck bindings (YAML 1.0) 119 | 120 | 121 | ### Another example 122 | 123 | ```yaml 124 | --- 125 | name: Juniper Networks 126 | CEO: Rami Rahim 127 | Headquarter: Sunnyvale 128 | Development: 129 | - Sunnyvale 130 | - Bangalore 131 | - Beijing 132 | Sales: 133 | - Sydeny 134 | - Mumbai 135 | ``` 136 | 137 | 138 | ```python 139 | import yaml 140 | 141 | data = """ 142 | --- 143 | name: Juniper Networks 144 | CEO: Rami Rahim 145 | Headquarter: Sunnyvale 146 | Development: 147 | - Sunnyvale 148 | - Bangalore 149 | - Beijing 150 | Sales: 151 | - Sydeny 152 | - Mumbai 153 | """ 154 | 155 | yaml.load(data) 156 | ``` 157 | 158 | 159 | 160 | 161 | {'CEO': 'Rami Rahim', 162 | 'Development': ['Sunnyvale', 'Bangalore', 'Beijing'], 163 | 'Headquarter': 'Sunnyvale', 164 | 'Sales': ['Sydeny', 'Mumbai'], 165 | 'name': 'Juniper Networks'} 166 | 167 | 168 | 169 | 170 | ```python 171 | data = """ 172 | --- 173 | - 174 | - pineapple 175 | - coconut 176 | - 177 | - umbrella 178 | - raincoat 179 | """ 180 | yaml.load(data) 181 | ``` 182 | 183 | 184 | 185 | 186 | [['pineapple', 'coconut'], ['umbrella', 'raincoat']] 187 | 188 | 189 | 190 | 191 | ```python 192 | data = """ 193 | --- 194 | Joey: 195 | age: 22 196 | sex: M 197 | Laura: 198 | age: 24 199 | sex: F 200 | """ 201 | yaml.load(data) 202 | ``` 203 | 204 | 205 | 206 | 207 | {'Joey': {'age': 22, 'sex': 'M'}, 'Laura': {'age': 24, 'sex': 'F'}} 208 | 209 | 210 | 211 | 212 | ```python 213 | data = """ 214 | --- 215 | receipt: Oz-Ware Purchase Invoice 216 | date: 2012-08-06 217 | customer: 218 | first_name: Dorothy 219 | family_name: Gale 220 | 221 | items: 222 | - part_no: A4786 223 | descrip: Water Bucket (Filled) 224 | price: 1.47 225 | quantity: 4 226 | 227 | - part_no: E1628 228 | descrip: High Heeled "Ruby" Slippers 229 | size: 8 230 | price: 133.7 231 | quantity: 1 232 | 233 | bill-to: &id001 234 | street: | 235 | 123 Tornado Alley 236 | Suite 16 237 | city: East Centerville 238 | state: KS 239 | 240 | ship-to: *id001 241 | 242 | specialDelivery: > 243 | Follow the Yellow Brick 244 | Road to the Emerald City. 245 | Pay no attention to the 246 | man behind the curtain. 247 | ... 248 | """ 249 | yaml.load(data) 250 | ``` 251 | 252 | 253 | 254 | 255 | {'bill-to': {'city': 'East Centerville', 256 | 'state': 'KS', 257 | 'street': '123 Tornado Alley\nSuite 16\n'}, 258 | 'customer': {'family_name': 'Gale', 'first_name': 'Dorothy'}, 259 | 'date': datetime.date(2012, 8, 6), 260 | 'items': [{'descrip': 'Water Bucket (Filled)', 261 | 'part_no': 'A4786', 262 | 'price': 1.47, 263 | 'quantity': 4}, 264 | {'descrip': 'High Heeled "Ruby" Slippers', 265 | 'part_no': 'E1628', 266 | 'price': 133.7, 267 | 'quantity': 1, 268 | 'size': 8}], 269 | 'receipt': 'Oz-Ware Purchase Invoice', 270 | 'ship-to': {'city': 'East Centerville', 271 | 'state': 'KS', 272 | 'street': '123 Tornado Alley\nSuite 16\n'}, 273 | 'specialDelivery': 'Follow the Yellow Brick\nRoad to the Emerald City.\nPay no attention to the\nman behind the curtain.\n'} 274 | 275 | 276 | 277 | 278 | ```python 279 | data = """ 280 | --- 281 | - step: &id001 # defines anchor label &id001 282 | instrument: Lasik 2000 283 | pulseEnergy: 5.4 284 | pulseDuration: 12 285 | repetition: 1000 286 | spotSize: 1mm 287 | 288 | - step: &id002 289 | instrument: Lasik 2000 290 | pulseEnergy: 5.0 291 | pulseDuration: 10 292 | repetition: 500 293 | spotSize: 2mm 294 | - step: *id001 # refers to the first step (with anchor &id001) 295 | - step: *id002 # refers to the second step 296 | - step: 297 | <<: *id001 298 | spotSize: 2mm # redefines just this key, refers rest from &id001 299 | """ 300 | yaml.load(data) 301 | ``` 302 | 303 | 304 | 305 | 306 | [{'step': {'instrument': 'Lasik 2000', 307 | 'pulseDuration': 12, 308 | 'pulseEnergy': 5.4, 309 | 'repetition': 1000, 310 | 'spotSize': '1mm'}}, 311 | {'step': {'instrument': 'Lasik 2000', 312 | 'pulseDuration': 10, 313 | 'pulseEnergy': 5.0, 314 | 'repetition': 500, 315 | 'spotSize': '2mm'}}, 316 | {'step': {'instrument': 'Lasik 2000', 317 | 'pulseDuration': 12, 318 | 'pulseEnergy': 5.4, 319 | 'repetition': 1000, 320 | 'spotSize': '1mm'}}, 321 | {'step': {'instrument': 'Lasik 2000', 322 | 'pulseDuration': 10, 323 | 'pulseEnergy': 5.0, 324 | 'repetition': 500, 325 | 'spotSize': '2mm'}}, 326 | {'step': {'instrument': 'Lasik 2000', 327 | 'pulseDuration': 12, 328 | 'pulseEnergy': 5.4, 329 | 'repetition': 1000, 330 | 'spotSize': '2mm'}}] 331 | 332 | 333 | 334 | 335 | ```python 336 | yaml.parse? 337 | ``` 338 | 339 | ## Jinja2 340 | 341 | ### Junos sample config 342 | 343 | 344 | ```python 345 | import os 346 | cwd = os.getcwd() 347 | print cwd 348 | ``` 349 | 350 | /Users/nitinkr/Coding/pyez-examples/templates 351 | 352 | 353 | 354 | ```python 355 | from jinja2 import Template 356 | t = Template("Hello {{ data }}!!") 357 | print t.render(data='xyz') 358 | ``` 359 | 360 | Hello xyz!! 361 | 362 | 363 | ```text 364 | interfaces { 365 | interface ge-0/0/1 { 366 | unit 0 { 367 | family ethernet-switching { 368 | port-mode access; 369 | replace: 370 | vlan { 371 | member 200; 372 | } 373 | } 374 | } 375 | } 376 | } 377 | ``` 378 | 379 | 380 | ### jinja2 template 381 | 382 | ```jinja2 383 | interfaces { 384 | interface {{ iface_name }} { 385 | unit 0 { 386 | family ethernet-switching { 387 | port-mode access; 388 | replace: 389 | vlan { 390 | member {{ vlan_name }}; 391 | } 392 | } 393 | } 394 | } 395 | } 396 | ``` 397 | 398 | 399 | 400 | ```python 401 | import jinja2 402 | template = """interfaces { 403 | interface {{ iface_name }} { 404 | unit 0 { 405 | family ethernet-switching { 406 | port-mode access; 407 | replace: 408 | vlan { 409 | member {{ vlan_name }}; 410 | } 411 | } 412 | } 413 | } 414 | }""" 415 | tmpl = jinja2.Template(template) 416 | conf = tmpl.render(iface_name='ge-0/0/2', vlan_name='200') 417 | print conf 418 | ``` 419 | 420 | interfaces { 421 | interface ge-0/0/2 { 422 | unit 0 { 423 | family ethernet-switching { 424 | port-mode access; 425 | replace: 426 | vlan { 427 | member 200; 428 | } 429 | } 430 | } 431 | } 432 | } 433 | 434 | 435 | 436 | ```python 437 | import jinja2 438 | template = """interfaces { 439 | interface {{ iface_name }} { 440 | unit 0 { 441 | family ethernet-switching { 442 | port-mode access; 443 | replace: 444 | vlan { 445 | member {{ vlan_name }}; 446 | } 447 | } 448 | } 449 | } 450 | }""" 451 | tmpl = jinja2.Template(template) 452 | conf = tmpl.render({'iface_name':'ge-0/0/1', 'vlan_name':'200'}) 453 | print conf 454 | ``` 455 | 456 | interfaces { 457 | interface ge-0/0/1 { 458 | unit 0 { 459 | family ethernet-switching { 460 | port-mode access; 461 | replace: 462 | vlan { 463 | member 200; 464 | } 465 | } 466 | } 467 | } 468 | } 469 | 470 | 471 | 472 | ```python 473 | import jinja2 474 | 475 | # tmpl = jinja2.Template(open('/Users/nitinkr/demos/PyEZ/templates/1_temp.j2').read()) 476 | 477 | loader = jinja2.FileSystemLoader(cwd) 478 | jenv = jinja2.Environment(loader=loader, trim_blocks=True, lstrip_blocks=True) 479 | tmpl = jenv.get_template('1_temp.j2') 480 | conf = tmpl.render(iface_name='ge-0/0/5', vlan_name='300') 481 | print conf 482 | ``` 483 | 484 | interfaces { 485 | interface ge-0/0/5 { 486 | unit 0 { 487 | family ethernet-switching { 488 | port-mode access; 489 | replace: 490 | vlan { 491 | member 300; 492 | } 493 | } 494 | } 495 | } 496 | } 497 | 498 | 499 | #### To know more about trim_blocks, lstrip_blocks 500 | 501 | http://jinja.pocoo.org/docs/dev/templates/#whitespace-control 502 | 503 | 504 | ```python 505 | jinja2.Environment? 506 | ``` 507 | 508 | ### Loop inside Jinja Template 509 | 510 | ```jinja2 511 | interfaces { 512 | {% for item in interfaces %} 513 | {{ item }} { 514 | unit 0 { 515 | family ethernet-switching { 516 | port-mode access; 517 | replace: 518 | vlan { 519 | member {{ vlan_name }}; 520 | } 521 | } 522 | } 523 | } {% endfor %} 524 | } 525 | ``` 526 | 527 | 528 | ```python 529 | import jinja2 530 | template = """interfaces { 531 | {% for item in interfaces %} 532 | {{ item }} { 533 | unit 0 { 534 | family ethernet-switching { 535 | port-mode access; 536 | replace: 537 | vlan { 538 | member {{ vlan_name }}; 539 | } 540 | } 541 | } 542 | } {% endfor %} 543 | }""" 544 | tmpl = jinja2.Template(template) 545 | conf = tmpl.render(interfaces=['ge-0/0/1', 'ge-0/0/2', 'ge-0/2/1', 'ge-0/2/2'], vlan_name='300') 546 | print conf 547 | ``` 548 | 549 | interfaces { 550 | 551 | ge-0/0/1 { 552 | unit 0 { 553 | family ethernet-switching { 554 | port-mode access; 555 | replace: 556 | vlan { 557 | member 300; 558 | } 559 | } 560 | } 561 | } 562 | ge-0/0/2 { 563 | unit 0 { 564 | family ethernet-switching { 565 | port-mode access; 566 | replace: 567 | vlan { 568 | member 300; 569 | } 570 | } 571 | } 572 | } 573 | ge-0/2/1 { 574 | unit 0 { 575 | family ethernet-switching { 576 | port-mode access; 577 | replace: 578 | vlan { 579 | member 300; 580 | } 581 | } 582 | } 583 | } 584 | ge-0/2/2 { 585 | unit 0 { 586 | family ethernet-switching { 587 | port-mode access; 588 | replace: 589 | vlan { 590 | member 300; 591 | } 592 | } 593 | } 594 | } 595 | } 596 | 597 | 598 | ### Filter in Template 599 | 600 | 601 | ```python 602 | loader = jinja2.FileSystemLoader(cwd) 603 | jenv = jinja2.Environment(loader=loader, trim_blocks=True, lstrip_blocks=True) 604 | ``` 605 | 606 | 607 | ```python 608 | import jinja2 609 | template = """interfaces { 610 | {% for item in interfaces %} 611 | {{ item }} { 612 | unit 0 { 613 | family ethernet-switching { 614 | port-mode {{ mode | upper }}; 615 | replace: 616 | vlan { 617 | member {{ vlan_name }}; 618 | } 619 | } 620 | } 621 | } {% endfor %} 622 | }""" 623 | tmpl = jinja2.Template(template) 624 | conf = tmpl.render(interfaces=['ge-0/0/1', 'ge-0/0/2'], vlan_name='300', mode='access') 625 | print conf 626 | ``` 627 | 628 | interfaces { 629 | 630 | ge-0/0/1 { 631 | unit 0 { 632 | family ethernet-switching { 633 | port-mode ACCESS; 634 | replace: 635 | vlan { 636 | member 300; 637 | } 638 | } 639 | } 640 | } 641 | ge-0/0/2 { 642 | unit 0 { 643 | family ethernet-switching { 644 | port-mode ACCESS; 645 | replace: 646 | vlan { 647 | member 300; 648 | } 649 | } 650 | } 651 | } 652 | } 653 | 654 | 655 | 656 | ```python 657 | jenv.filters 658 | ``` 659 | 660 | 661 | ```python 662 | from bracket_expansion import bracket_expansion 663 | jenv.filters['bracket_expansion']=bracket_expansion 664 | for i in bracket_expansion('ge-0/0/[0-5]'): 665 | print i 666 | ``` 667 | 668 | ge-0/0/0 669 | ge-0/0/1 670 | ge-0/0/2 671 | ge-0/0/3 672 | ge-0/0/4 673 | ge-0/0/5 674 | 675 | 676 | 677 | ```python 678 | import jinja2 679 | template = """interfaces { 680 | {% for item in iface_pattern | bracket_expansion %} 681 | {{ item }} { 682 | unit 0 { 683 | family ethernet-switching { 684 | port-mode access; 685 | replace: 686 | vlan { 687 | member {{ vlan_name }}; 688 | } 689 | } 690 | } 691 | } {% endfor %} 692 | }""" 693 | loader = jinja2.FileSystemLoader(cwd) 694 | jenv = jinja2.Environment(loader=loader, trim_blocks=True, lstrip_blocks=True) 695 | jenv.filters['bracket_expansion']=bracket_expansion 696 | tmpl = jenv.get_template('filter.j2') 697 | conf = tmpl.render(iface_pattern='ge-0/0/[0-10]', vlan_name='300') 698 | print conf 699 | ``` 700 | 701 | interfaces { 702 | ge-0/0/0 { 703 | unit 0 { 704 | family ethernet-switching { 705 | port-mode access; 706 | replace: 707 | vlan { 708 | member 300; 709 | } 710 | } 711 | } 712 | } ge-0/0/1 { 713 | unit 0 { 714 | family ethernet-switching { 715 | port-mode access; 716 | replace: 717 | vlan { 718 | member 300; 719 | } 720 | } 721 | } 722 | } ge-0/0/2 { 723 | unit 0 { 724 | family ethernet-switching { 725 | port-mode access; 726 | replace: 727 | vlan { 728 | member 300; 729 | } 730 | } 731 | } 732 | } ge-0/0/3 { 733 | unit 0 { 734 | family ethernet-switching { 735 | port-mode access; 736 | replace: 737 | vlan { 738 | member 300; 739 | } 740 | } 741 | } 742 | } ge-0/0/4 { 743 | unit 0 { 744 | family ethernet-switching { 745 | port-mode access; 746 | replace: 747 | vlan { 748 | member 300; 749 | } 750 | } 751 | } 752 | } ge-0/0/5 { 753 | unit 0 { 754 | family ethernet-switching { 755 | port-mode access; 756 | replace: 757 | vlan { 758 | member 300; 759 | } 760 | } 761 | } 762 | } ge-0/0/6 { 763 | unit 0 { 764 | family ethernet-switching { 765 | port-mode access; 766 | replace: 767 | vlan { 768 | member 300; 769 | } 770 | } 771 | } 772 | } ge-0/0/7 { 773 | unit 0 { 774 | family ethernet-switching { 775 | port-mode access; 776 | replace: 777 | vlan { 778 | member 300; 779 | } 780 | } 781 | } 782 | } ge-0/0/8 { 783 | unit 0 { 784 | family ethernet-switching { 785 | port-mode access; 786 | replace: 787 | vlan { 788 | member 300; 789 | } 790 | } 791 | } 792 | } ge-0/0/9 { 793 | unit 0 { 794 | family ethernet-switching { 795 | port-mode access; 796 | replace: 797 | vlan { 798 | member 300; 799 | } 800 | } 801 | } 802 | } ge-0/0/10 { 803 | unit 0 { 804 | family ethernet-switching { 805 | port-mode access; 806 | replace: 807 | vlan { 808 | member 300; 809 | } 810 | } 811 | } 812 | } 813 | } 814 | 815 | 816 | ### Include directive 817 | #### To create Modular template 818 | 819 | 820 | ```python 821 | from glob import glob 822 | print glob(cwd+'/sshkeys/*.pub') 823 | ``` 824 | 825 | ['/Users/nitinkr/Coding/pyez-examples/templates/sshkeys/lakhan.pub', '/Users/nitinkr/Coding/pyez-examples/templates/sshkeys/ram.pub'] 826 | 827 | 828 | 829 | ```python 830 | from os.path import basename, splitext 831 | print [basename(i) for i in glob(cwd+'/sshkeys/*.pub')] 832 | print [splitext(basename(i))[0] for i in glob(cwd+'/sshkeys/*.pub')] 833 | ``` 834 | 835 | ['lakhan.pub', 'ram.pub'] 836 | ['lakhan', 'ram'] 837 | 838 | 839 | 840 | ```python 841 | def basefilename(name): 842 | return splitext(basename(name))[0] 843 | 844 | # basefilename = lambda name: splitext(basename(name))[0] 845 | ``` 846 | 847 | ```jinja2 848 | system { 849 | login { 850 | {% for ssh_pub in sshkeyfiles %} 851 | user {{ ssh_pub | basefilename }} { 852 | authentication { 853 | ssh-rsa "{% include ssh_pub %}"; 854 | } 855 | } 856 | {% endfor %} 857 | } 858 | } 859 | ``` 860 | 861 | 862 | ```python 863 | import jinja2 864 | 865 | loader = jinja2.FileSystemLoader(cwd) 866 | jenv = jinja2.Environment(loader=loader, trim_blocks=True, lstrip_blocks=True) 867 | jenv.filters['basefilename']=basefilename 868 | tmpl = jenv.get_template('users.j2') 869 | print tmpl.render(sshkeyfiles=glob('sshkeys/*.pub')) 870 | ``` 871 | 872 | system { 873 | login { 874 | user lakhan { 875 | authentication { 876 | ssh-rsa "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCl2uGO4skBv30W3O6//E2h4wmagnp5F2d2ZAejG+rozy+fbAD83nD4cOg5PZfpVTmV5q3VitcG7rQlRim4Rw+669R+n06BG/FarsIv2yAV9Vz30y51tlzCThF4TQEVttKgQtdmgtenoTOnIsZHjms6zx7OyeMws4nb6kFE1eFv2A+h+FAQeIq+5bxXWpH77Wr9DrCVS6wqyDu4niv6WnxshJFKO8AZOkl51qcQznEe9J7Jz4SfgXnqGKJsJnJOGSdxK6gyRRLYLQ2S7CZIQe6Cb97nGERFSx4w9XFMWZf/RkY3o0lXOv0VC51pr5ocJYvb+IpYAiCjF0po6xMd11dh nitinkr@nitinkr-mba13"; 877 | } 878 | } 879 | user ram { 880 | authentication { 881 | ssh-rsa "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDHSljc8AuY2UgmZuAl5hW18UZJwzj4u1Qu6kWJ4aecK71r3Vrar65TKNisv/eOOFVHoI8690IOMHG0NUzNJH+WtaFFKhI/2yX6Q3UJ8Chs3FOIfRvMtORvgrN5JJfKREmRVEWVdzWqHDGs6DyXDiL8h0XsBQmCJcuMS5JCi+GggYr/ysMOzLXWkjgZasj0AcVZrGkaTV0R1Ec7SV/IZGMZC1RelDiaTiMPdsI7LFV6jnZzqG9IZmMHwDLAocO/HN2nnGUWGBn172h8ah0fSuTnA8Wm5AnD+/3k/N5tHOjMfRU+P755FWkC+TwPuXrtqV8kh4ZBWWr5CHUtflzNmMn nitinkr@nitinkr-mba13"; 882 | } 883 | } 884 | } 885 | } 886 | 887 | 888 | 889 | ```python 890 | with open(os.path.join(cwd, 'main.j2')) as fp: 891 | print fp.read() 892 | ``` 893 | 894 | ## 895 | ## This is top main file 896 | ## 897 | 898 | interfaces { 899 | {% for item in interfaces %} 900 | {{ item }} { 901 | description "{{ description }}"; 902 | unit 0 { 903 | family {{ family }}; 904 | } 905 | } {% endfor %} 906 | } 907 | ## 908 | ## including another jinja templete 909 | ## 910 | {% include 'users.j2' %} 911 | 912 | ## 913 | ## thats the end 914 | ## 915 | 916 | 917 | 918 | 919 | ```python 920 | main = jenv.get_template('main.j2') 921 | print main.render(sshkeyfiles=glob('sshkeys/*.pub'), interfaces=['ge-0/0/1', 'ge-0/0/2'], family='mpls', description='MPLS interface') 922 | ``` 923 | 924 | ## 925 | ## This is top main file 926 | ## 927 | 928 | interfaces { 929 | ge-0/0/1 { 930 | description "MPLS interface"; 931 | unit 0 { 932 | family mpls; 933 | } 934 | } ge-0/0/2 { 935 | description "MPLS interface"; 936 | unit 0 { 937 | family mpls; 938 | } 939 | } 940 | } 941 | ## 942 | ## including another jinja templete 943 | ## 944 | system { 945 | login { 946 | user lakhan { 947 | authentication { 948 | ssh-rsa "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCl2uGO4skBv30W3O6//E2h4wmagnp5F2d2ZAejG+rozy+fbAD83nD4cOg5PZfpVTmV5q3VitcG7rQlRim4Rw+669R+n06BG/FarsIv2yAV9Vz30y51tlzCThF4TQEVttKgQtdmgtenoTOnIsZHjms6zx7OyeMws4nb6kFE1eFv2A+h+FAQeIq+5bxXWpH77Wr9DrCVS6wqyDu4niv6WnxshJFKO8AZOkl51qcQznEe9J7Jz4SfgXnqGKJsJnJOGSdxK6gyRRLYLQ2S7CZIQe6Cb97nGERFSx4w9XFMWZf/RkY3o0lXOv0VC51pr5ocJYvb+IpYAiCjF0po6xMd11dh nitinkr@nitinkr-mba13"; 949 | } 950 | } 951 | user ram { 952 | authentication { 953 | ssh-rsa "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDHSljc8AuY2UgmZuAl5hW18UZJwzj4u1Qu6kWJ4aecK71r3Vrar65TKNisv/eOOFVHoI8690IOMHG0NUzNJH+WtaFFKhI/2yX6Q3UJ8Chs3FOIfRvMtORvgrN5JJfKREmRVEWVdzWqHDGs6DyXDiL8h0XsBQmCJcuMS5JCi+GggYr/ysMOzLXWkjgZasj0AcVZrGkaTV0R1Ec7SV/IZGMZC1RelDiaTiMPdsI7LFV6jnZzqG9IZmMHwDLAocO/HN2nnGUWGBn172h8ah0fSuTnA8Wm5AnD+/3k/N5tHOjMfRU+P755FWkC+TwPuXrtqV8kh4ZBWWr5CHUtflzNmMn nitinkr@nitinkr-mba13"; 954 | } 955 | } 956 | } 957 | } 958 | ## 959 | ## thats the end 960 | ## 961 | 962 | 963 | ### if/then/else directives 964 | 965 | 966 | ```python 967 | import csv 968 | vlans = csv.DictReader(open(os.path.join(cwd,'vlans.csv'))) 969 | print vlans 970 | for i in vlans: 971 | print i,',' 972 | ``` 973 | 974 | 975 | {'vlan_id': '100', 'vlan_name': 'Blue'} , 976 | {'vlan_id': '200', 'vlan_name': 'Green'} , 977 | {'vlan_id': '300', 'vlan_name': 'Yellow'} , 978 | {'vlan_id': '400', 'vlan_name': 'Purple'} , 979 | {'vlan_id': '500', 'vlan_name': 'Red'} , 980 | 981 | 982 | 983 | ```python 984 | import jinja2 985 | 986 | vlans = csv.DictReader(open(os.path.join(cwd,'vlans.csv'))) 987 | loader = jinja2.FileSystemLoader(cwd) 988 | jenv = jinja2.Environment(loader=loader, trim_blocks=True, lstrip_blocks=True) 989 | tmpl = jenv.get_template('main_vlans.conf') 990 | print tmpl.render(vlan_list=vlans) 991 | ``` 992 | 993 | 994 | vlans { 995 | Blue { 996 | vlan-id 100; 997 | } 998 | Green { 999 | vlan-id 200; 1000 | } 1001 | Yellow { 1002 | vlan-id 300; 1003 | } 1004 | Purple { 1005 | vlan-id 400; 1006 | } 1007 | Red { 1008 | vlan-id 500; 1009 | } 1010 | } 1011 | 1012 | 1013 | 1014 | ```python 1015 | vlans = csv.DictReader(open(os.path.join(cwd,'vlans.csv'))) 1016 | print tmpl.render(vlan_list=vlans, state='absent') 1017 | ``` 1018 | 1019 | 1020 | vlans { 1021 | delete: Blue 1022 | delete: Green 1023 | delete: Yellow 1024 | delete: Purple 1025 | delete: Red 1026 | } 1027 | 1028 | 1029 | ### This presentation from AnsibleFest San Francisco 2015 focused on how Riot Games utilizes Ansible, Config templates and Juniper’s Py-EZ. 1030 | 1031 | 1032 | ```python 1033 | from IPython.display import HTML 1034 | HTML('') 1035 | ``` 1036 | 1037 | 1038 | 1039 | 1040 | 1041 | 1042 | 1043 | 1044 | 1045 | ```python 1046 | from IPython.display import YouTubeVideo 1047 | YouTubeVideo('PSgSjTeqRX0', start=450, width=900, height=500) 1048 | ``` 1049 | 1050 | 1051 | 1052 | 1053 | 1054 | 1061 | 1062 | 1063 | 1064 | 1065 | 1066 | ```python 1067 | from IPython.display import YouTubeVideo 1068 | YouTubeVideo('Gk5KKozJmz8', start=156, width=900, height=500) 1069 | ``` 1070 | 1071 | 1072 | 1073 | 1074 | 1075 | 1082 | 1083 | 1084 | 1085 | --------------------------------------------------------------------------------