├── .github └── workflows │ └── python-app.yml ├── .gitignore ├── LICENSE ├── README.md ├── application_hosting ├── README.md ├── guestshell │ ├── README.md │ ├── iosxe_guestshell_setup.txt │ └── requirements.txt ├── intro │ └── README.md ├── iox │ ├── README.md │ ├── app_1 │ │ ├── Dockerfile │ │ ├── main.py │ │ └── package.yaml │ └── requirements.txt └── python_onbox │ ├── README.md │ ├── eem_applet_1.conf │ ├── eem_intf_up.py │ ├── hello_world.py │ ├── iosxe_guestshell_setup.txt │ └── requirements.txt ├── course_info.json ├── course_info.yaml ├── intro └── intro │ └── README.md ├── netdevops ├── README.md ├── aci_ansible │ ├── .ansible_env │ ├── README.md │ ├── ansible.cfg │ ├── cleanup.yaml │ ├── example1.yaml │ ├── example2.yaml │ ├── example3.yaml │ ├── hosts │ ├── requirements.txt │ └── vars │ │ └── example3_Tenant3_Policy.yaml ├── ansible_part_1 │ ├── README.md │ ├── ansible.cfg │ ├── example1.yaml │ ├── example2.yaml │ ├── example2_vars.yaml │ ├── example3.j2 │ ├── example3.yaml │ ├── host_vars │ │ ├── 172.16.30.101.yaml │ │ ├── 172.16.30.102.yaml │ │ ├── 172.16.30.103.yaml │ │ └── 172.16.30.104.yaml │ ├── hosts │ └── requirements.txt ├── ansible_part_2 │ ├── .ansible_env │ ├── README.md │ ├── ansible.cfg │ ├── example1.yaml │ ├── example2.yaml │ ├── group_vars │ │ └── switches.yaml │ ├── host_vars │ │ ├── 172.16.30.101.yaml │ │ ├── 172.16.30.102.yaml │ │ ├── 172.16.30.103.yaml │ │ └── 172.16.30.104.yaml │ ├── hosts │ └── requirements.txt ├── ansible_part_3 │ ├── .ansible_env │ ├── README.md │ ├── ansible.cfg │ ├── configs │ │ └── readme.md │ ├── group_vars │ │ ├── access.yaml │ │ ├── all.yaml │ │ ├── core.yaml │ │ ├── distribution.yaml │ │ ├── iosxe.yaml │ │ └── nxos.yaml │ ├── host_vars │ │ ├── 172.16.30.101.yaml │ │ ├── 172.16.30.102.yaml │ │ ├── 172.16.30.103.yaml │ │ ├── 172.16.30.111.yaml │ │ └── 172.16.30.112.yaml │ ├── hosts │ ├── network_deploy.yaml │ ├── other_vars │ │ └── vlans.yaml │ ├── requirements.txt │ ├── roles │ │ ├── iosxe_mdp │ │ │ ├── tasks │ │ │ │ └── main.yaml │ │ │ └── vars │ │ │ │ └── main.yaml │ │ ├── netconf_l3_interfaces │ │ │ ├── files │ │ │ │ └── ietf_interface_template.j2 │ │ │ ├── tasks │ │ │ │ └── main.yaml │ │ │ └── vars │ │ │ │ └── main.yaml │ │ ├── netconf_ospf │ │ │ ├── files │ │ │ │ └── ned_ospf.j2 │ │ │ ├── tasks │ │ │ │ └── main.yaml │ │ │ └── vars │ │ │ │ └── main.yaml │ │ ├── nxos_hsrp │ │ │ ├── tasks │ │ │ │ └── main.yaml │ │ │ └── vars │ │ │ │ └── main.yaml │ │ ├── nxos_l3_interfaces │ │ │ ├── tasks │ │ │ │ └── main.yaml │ │ │ └── vars │ │ │ │ └── main.yaml │ │ ├── nxos_nxapi │ │ │ ├── tasks │ │ │ │ └── main.yaml │ │ │ └── vars │ │ │ │ └── main.yaml │ │ ├── nxos_ospf │ │ │ ├── tasks │ │ │ │ └── main.yaml │ │ │ └── vars │ │ │ │ └── main.yaml │ │ ├── nxos_po_trunks │ │ │ ├── tasks │ │ │ │ └── main.yaml │ │ │ └── vars │ │ │ │ └── main.yaml │ │ ├── nxos_vlans │ │ │ ├── tasks │ │ │ │ └── main.yaml │ │ │ └── vars │ │ │ │ └── main.yaml │ │ ├── nxos_vpc │ │ │ ├── tasks │ │ │ │ └── main.yaml │ │ │ └── vars │ │ │ │ └── main.yaml │ │ └── nxos_vpc_trunks │ │ │ ├── tasks │ │ │ └── main.yaml │ │ │ └── vars │ │ │ └── main.yaml │ └── virl_sbx_mgmt │ │ ├── ansible_part_3.virl │ │ ├── node_console_info.py │ │ ├── restart-sbx.py │ │ ├── status-sbx.py │ │ ├── virl_simulation_setup.py │ │ ├── virlutils.py │ │ ├── vpn_close.sh │ │ └── vpn_setup.sh └── intro │ └── README.md ├── network_controllers ├── README.md ├── aci │ ├── README.md │ ├── device_info.py │ ├── requirements.txt │ ├── toolkit_getting_started.py │ └── toolkit_new_policy.py ├── apicem │ ├── README.md │ ├── device_info.py │ ├── example1.py │ ├── requirements.txt │ ├── troubleshoot_full.py │ ├── troubleshoot_prep.py │ ├── troubleshoot_step1.py │ ├── troubleshoot_step2.py │ ├── troubleshoot_step3.py │ └── troubleshoot_step4.py ├── dnac │ ├── README.md │ ├── device_info.py │ ├── device_list.py │ ├── example1.py │ ├── requirements.txt │ ├── troubleshoot_full.py │ ├── troubleshoot_prep.py │ ├── troubleshoot_step1.py │ ├── troubleshoot_step2.py │ ├── troubleshoot_step3.py │ └── troubleshoot_step4.py └── meraki │ ├── README.md │ └── requirements.txt ├── network_device_apis ├── README.md ├── netconf │ ├── README.md │ ├── config-temp-ietf-interfaces.xml │ ├── device_info.py │ ├── example1.py │ ├── example2.py │ ├── example3.py │ ├── filter-ietf-interfaces.xml │ └── requirements.txt ├── nxapi │ ├── README.md │ ├── example1.py │ ├── ins_api_request_1.json │ ├── ins_api_response_1.json │ ├── json_rpc_request_1.json │ ├── json_rpc_request_2.json │ ├── json_rpc_response_1.json │ ├── json_rpc_response_2.json │ ├── requirements.txt │ └── sbx_setup.py ├── restconf │ ├── README.md │ └── requirements.txt └── yang │ ├── README.md │ ├── device_info.py │ ├── example1.py │ ├── filter-ietf-interfaces.xml │ ├── ietf-interfaces.html │ ├── ietf-interfaces.yang │ ├── ietf-yang-types.yang │ └── requirements.txt ├── postman_config ├── DevNet Cisco DNA Center Always On 1.postman_environment.json ├── DevNet Cisco DNA Center Always On 2.postman_environment.json ├── Network Programmability Basics.postman_collection.json ├── Sandbox ACI APIC Always On.postman_environment.json ├── Sandbox Always On Open NX-OS Programmability.postman_environment.json ├── Sandbox Meraki Always On.postman_environment.json ├── Sandbox NX-OS Standalone.postman_environment.json └── Sandbox RESTCONF Always On.postman_environment.json ├── programming_fundamentals ├── README.md ├── apis │ ├── README.md │ └── requirements.txt ├── data_formats │ ├── GigabitEthernet2.json │ ├── GigabitEthernet2.xml │ ├── GigabitEthernet2.yaml │ ├── README.md │ ├── address_list.json │ ├── address_list.xml │ ├── address_list.yaml │ └── requirements.txt ├── python_part_1 │ ├── README.md │ ├── example1.py │ ├── example2.py │ ├── example3.py │ └── requirements.txt ├── python_part_2 │ ├── README.md │ ├── common_vars.py │ ├── example1.py │ └── requirements.txt ├── python_part_3 │ ├── README.md │ ├── api_ncclient_example.py │ ├── api_netmiko_example.py │ ├── api_pysnmp_example.py │ ├── api_requests_example.py │ ├── csv_example.csv │ ├── data_library_exercises.py │ ├── json_example.json │ ├── requirements.txt │ ├── scratchpad.py │ ├── xml_example.xml │ └── yaml_example.yaml ├── rest_part_1 │ ├── README.md │ ├── curl_examples.sh │ └── requirements.txt └── rest_part_2 │ ├── README.md │ └── requirements.txt └── readme_resources ├── dev-env-centos.jpg ├── dev-env-mac.jpg ├── dev-env-win.jpg ├── dev-env.jpg └── workstation_setup.md /.github/workflows/python-app.yml: -------------------------------------------------------------------------------- 1 | # This workflow will install Python dependencies, run tests and lint with a single version of Python 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions 3 | 4 | name: Python script tests 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | branches: [ master ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Set up Python 3.8 20 | uses: actions/setup-python@v2 21 | with: 22 | python-version: 3.8 23 | - name: Test Programming Fundamentals Python Part 1 - ex1 24 | run: | 25 | cd programming_fundamentals/python_part_1 26 | pip install -r requirements.txt 27 | VALUE=$(echo $((1 + RANDOM % 10))) 28 | python example1.py $VALUE 29 | - name: Test Programming Fundamentals Python Part 2 30 | run: | 31 | cd programming_fundamentals/python_part_2 32 | pip install -r requirements.txt 33 | python example1.py 34 | - name: Test Programming Fundamentals Python Part 3 - ncclient 35 | run: | 36 | cd programming_fundamentals/python_part_3 37 | pip install -r requirements.txt 38 | python api_ncclient_example.py 39 | - name: Test Programming Fundamentals Python Part 3 - netmiko 40 | run: | 41 | cd programming_fundamentals/python_part_3 42 | pip install -r requirements.txt 43 | python api_netmiko_example.py 44 | - name: Test Programming Fundamentals Python Part 3 - pysnmp 45 | run: | 46 | cd programming_fundamentals/python_part_3 47 | pip install -r requirements.txt 48 | python api_pysnmp_example.py 49 | - name: Test Programming Fundamentals Python Part 3 - requests 50 | run: | 51 | cd programming_fundamentals/python_part_3 52 | pip install -r requirements.txt 53 | python api_requests_example.py 54 | - name: Test Programming Fundamentals Python Part 3 - data_library_exercises 55 | run: | 56 | cd programming_fundamentals/python_part_3 57 | pip install -r requirements.txt 58 | python data_library_exercises.py 59 | 60 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | settings.json 3 | *.code-workspace 4 | *acitoolkit/ 5 | .virl/ 6 | 7 | # Byte-compiled / optimized / DLL files 8 | __pycache__/ 9 | *.py[cod] 10 | *$py.class 11 | 12 | # C extensions 13 | *.so 14 | 15 | # Distribution / packaging 16 | .Python 17 | env/ 18 | build/ 19 | develop-eggs/ 20 | dist/ 21 | downloads/ 22 | eggs/ 23 | .eggs/ 24 | lib/ 25 | lib64/ 26 | parts/ 27 | sdist/ 28 | var/ 29 | wheels/ 30 | *.egg-info/ 31 | .installed.cfg 32 | *.egg 33 | 34 | # PyInstaller 35 | # Usually these files are written by a python script from a template 36 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 37 | *.manifest 38 | *.spec 39 | 40 | # Installer logs 41 | pip-log.txt 42 | pip-delete-this-directory.txt 43 | 44 | # Unit test / coverage reports 45 | htmlcov/ 46 | .tox/ 47 | .coverage 48 | .coverage.* 49 | .cache 50 | nosetests.xml 51 | coverage.xml 52 | *.cover 53 | .hypothesis/ 54 | 55 | # Translations 56 | *.mo 57 | *.pot 58 | 59 | # Django stuff: 60 | *.log 61 | local_settings.py 62 | 63 | # Flask stuff: 64 | instance/ 65 | .webassets-cache 66 | 67 | # Scrapy stuff: 68 | .scrapy 69 | 70 | # Sphinx documentation 71 | docs/_build/ 72 | 73 | # PyBuilder 74 | target/ 75 | 76 | # Jupyter Notebook 77 | .ipynb_checkpoints 78 | 79 | # pyenv 80 | .python-version 81 | 82 | # celery beat schedule file 83 | celerybeat-schedule 84 | 85 | # SageMath parsed files 86 | *.sage.py 87 | 88 | # dotenv 89 | .env 90 | 91 | # virtualenv 92 | .venv 93 | venv/ 94 | ENV/ 95 | venv*/ 96 | 97 | # Spyder project settings 98 | .spyderproject 99 | .spyproject 100 | 101 | # Rope project settings 102 | .ropeproject 103 | 104 | # mkdocs documentation 105 | /site 106 | 107 | # mypy 108 | .mypy_cache/ 109 | 110 | # Other Dev Stuff 111 | .vagrant/ 112 | .package.metadata 113 | package.tar 114 | *.retry 115 | ioxclient 116 | netdevops/ansible_part_3/configs 117 | netdevops/ansible_part_1/example3.conf 118 | config_sample.xml 119 | scratch* 120 | to-do* 121 | Vagrantfile 122 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Cisco DevNet 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Network Programmability Basics 2 | 3 | Code, Examples, and Resources for the Network Programmability Basics Video Course 4 | 5 | ## Table of Contents 6 | * [General Workstation Setup](readme_resources/workstation_setup.md) 7 | * [Operating System Considerations](readme_resources/workstation_setup.md#operating-system-considerations) 8 | * [Setting up git](readme_resources/workstation_setup.md#setting-up-git) 9 | * [Setting Up Python](readme_resources/workstation_setup.md#setting-up-python) 10 | * [Postman](readme_resources/workstation_setup.md#postman) 11 | * [DevNet Sandbox VPN Access](readme_resources/workstation_setup.md#devnet-sandbox-vpn-access) 12 | * [Programming Fundamentals](programming_fundamentals/README.md) 13 | * [Data Formats: Understanding and using JSON, XML and YAML](programming_fundamentals/data_formats/README.md) 14 | * [APIs are Everywhere... but what are they?](programming_fundamentals/apis/README.md) 15 | * [REST APIs Part 1: HTTP is for more than Web Browsing](programming_fundamentals/rest_part_1/README.md) 16 | * [REST APIs Part 2: Making REST API Calls with Postman](programming_fundamentals/rest_part_2/README.md) 17 | * [Python Part 1: Python Language and Script Basics](programming_fundamentals/python_part_1/README.md) 18 | * [Python Part 2: Working with Libraries and Virtual Environments](programming_fundamentals/python_part_2/README.md) 19 | * [Python Part 3: Useful Python Libraries for Network Engineers](programming_fundamentals/python_part_3/README.md) 20 | * [Network Device APIs](network_device_apis/README.md) 21 | * [Getting the “YANG” of it with Standard Data Models](network_device_apis/yang/README.md) 22 | * [Goodbye SNMP NETCONF!](network_device_apis/netconf/README.md) 23 | * [Learn to CRUD with GET, POST and DELETE using RESTCONF](network_device_apis/restconf/README.md) 24 | * [NX-API Part 1: Get Started with APIs and Nexus](network_device_apis/nxapi/README.md) 25 | * [NX-API Part 2: Dive into the Nexus Object Model](network_device_apis/nxapi/README.md) 26 | * [Network Controllers](network_controllers/README.md) 27 | * [Program your own DNA with APIC-EM APIs](network_controllers/apicem/README.md) 28 | * [Got SDN? Understanding the ACI Programmability Options](network_controllers/aci/README.md) 29 | * [Network Control in the Cloud - Developing with Cisco Meraki](network_controllers/meraki/README.md) 30 | * [DNA APIs Part 1: Exploring APIC-EM Apps via API](network_controllers/apicem/README.md) 31 | * [DNA APIs Part 2: Troubleshooting with APIC-EM Programmability](network_controllers/apicem/README.md) 32 | * [ACI Programmability Part 1: The ACI Object Model](network_controllers/aci/README.md) 33 | * [ACI Programmability Part 2: Using the ACI Toolkit](network_controllers/aci/README.md) 34 | * [Application Hosting and the Network](application_hosting/README.md) 35 | * [Cloud to Fog… Why Host Apps in the Network](application_hosting/intro/README.md) 36 | * [Linux at the Edge: Introduction to Guest Shell](application_hosting/guestshell/README.md) 37 | * [Python at the Edge: Super Charged Network Event Management](application_hosting/python_onbox/README.md) 38 | * [Package, Deploy and Run Applications in the Network with IOx](application_hosting/iox/README.md) 39 | * [NetDevOps](netdevops/README.md) 40 | * [Configuration Management and the Network](netdevops/intro/README.md) 41 | * [Ansible Part 1: What you need to Get Started](netdevops/ansible_part_1/README.md) 42 | * [Ansible Part 2: Using Ansible for Network Configuration](netdevops/ansible_part_2/README.md) 43 | * [Ansible Part 3: Your Network As Code](netdevops/ansible_part_3/README.md) 44 | -------------------------------------------------------------------------------- /application_hosting/README.md: -------------------------------------------------------------------------------- 1 | # Application Hosting and the Network 2 | In this module you will explore different options available for running code and hosting applications at the edge of the network, directly on switches, routers and other devices. 3 | 4 | ## Lessons 5 | 6 | * [Cloud to Fog… Why Host Apps in the Network](intro/README.md) 7 | * [Linux at the Edge: Introduction to Guest Shell](guestshell/README.md) 8 | * [Python at the Edge: Super Charged Network Event Management](python_onbox/README.md) 9 | * [Package, Deploy and Run Applications in the Network with IOx](iox/README.md) 10 | -------------------------------------------------------------------------------- /application_hosting/guestshell/README.md: -------------------------------------------------------------------------------- 1 | # Linux at the Edge: Introduction to Guest Shell 2 | 3 | ## "Gitting" the Code 4 | All of the code and examples for this lesson is located in the `netprog_basics/application_hosting/guestshell` directory. Clone and access it with the following commands: 5 | 6 | ```bash 7 | git clone https://github.com/CiscoDevNet/netprog_basics 8 | cd netprog_basics/application_hosting/guestshell 9 | ``` 10 | 11 | ## Local Workstation Setup 12 | Be sure to complete the [General Workstation Setup](https://github.com/CiscoDevNet/netprog_basics/blob/master/readme_resources/workstation_setup.md) instructions before beginning this lesson. 13 | 14 | ### Python Environment Setup 15 | It is recommended that this lesson be completed using Python 3.8. Other versions of Python 3 should also work. 16 | 17 | > **Note about Python 2:** Python 2 was [sunset](https://www.python.org/doc/sunset-python-2/) by Python Software Foundation on January 1, 2020. This means that no more updates to Python 2 are being worked on, including security updates. Python 3 is now the recommended version of Python for everyone to use. Most Python developers of software, packages, and scripts have migrated to Python 3 already, however you may find some older scripts and tools that are no longer maintained that only work with Python 2. 18 | > 19 | > You may see/hear references to Python 2 within the videos in this course from before January 2020, however all examples scripts and demos available in the GitHub repo to run have been updated to leverage Python 3. 20 | 21 | It is highly recommended to leverage Python Virtual Environments for completing exercises in this course. 22 | 23 | *There is no need to create independent venv for each lesson, but you can if you choose.* 24 | 25 | Follow these steps to create and activate a venv. 26 | 27 | ***Note: If you are leveraging a shared venv across all lessons simply activate it.*** 28 | 29 | ```bash 30 | # OS X or Linux 31 | python3 -m venv venv 32 | source venv/bin/activate 33 | ``` 34 | 35 | ```bash 36 | # Windows 37 | python -m venv venv 38 | venv/Scripts/activate 39 | ``` 40 | 41 | 42 | #### Install Python Requirements for Lesson 43 | With the Virtual Environment activated, use pip to install the necessary requirements. 44 | 45 | ```bash 46 | # From the code directory for this lesson 47 | pip install -r requirements.txt 48 | ``` 49 | 50 | ## DevNet Sandbox 51 | This lesson leverages the [IOS XE on CSR Recommended Code](https://devnetsandbox.cisco.com/RM/Diagram/Index/cae403c2-27af-4c7d-b1e1-99b7d42f1504?diagramType=Topology) Sandbox. 52 | 53 | You will need to reserve an instance of the sandbox, and establish a VPN connection to your individual Sandbox to complete this lab. 54 | 55 | ***Note: In the video, an older version of IOS XE was used.*** 56 | 57 | The commands to enable GuestShell have changed slightly, be sure to refer to the [sample configuration in the code samples](https://github.com/CiscoDevNet/netprog_basics/blob/master/application_hosting/guestshell/iosxe_guestshell_setup.txt#L40) for the latest command syntax. 58 | 59 | 60 | 61 | ## Download Slides 62 | 63 | You can download the slides for this lesson [here](https://developer.cisco.com/fileMedia/download/587b59b9-6b7b-3b7b-bce4-ce3acf182e16). 64 | 65 | > *Suggestion: Right click, "Open in new tab"* -------------------------------------------------------------------------------- /application_hosting/guestshell/iosxe_guestshell_setup.txt: -------------------------------------------------------------------------------- 1 | ! To be entered onto IOS XE Device 2 | 3 | ! ***** Step 1 ********* 4 | ! Enable IOX 5 | conf t 6 | iox 7 | exit 8 | 9 | ! Verify IOX 10 | sh iox-service 11 | 12 | ! ***** Step 2 ********* 13 | ! Create and Configure Virtual Port Group 14 | conf t 15 | 16 | interface VirtualPortGroup 0 17 | ip add 192.168.35.1 255.255.255.0 18 | no shut 19 | exit 20 | 21 | ! ***** Step 3 ********* 22 | ! Configure NAT 23 | conf t 24 | 25 | interface VirtualPortGroup0 26 | ip nat inside 27 | exit 28 | 29 | ! Interface connected to local network 30 | interface GigabitEthernet1 31 | ip nat outside 32 | exit 33 | 34 | ip access-list standard NAT_ACL 35 | permit 192.168.0.0 0.0.255.255 36 | exit 37 | 38 | ip nat inside source list NAT_ACL interface GigabitEthernet1 overload 39 | 40 | ! ***** Step 4 ********* 41 | ! Configure Guest Shell 42 | conf t 43 | app-hosting appid guestshell 44 | app-vnic gateway1 virtualportgroup 0 guest-interface 0 45 | guest-ipaddress 192.168.35.2 netmask 255.255.255.0 46 | exit 47 | app-default-gateway 192.168.35.1 guest-interface 0 48 | name-server0 208.67.222.222 49 | end 50 | 51 | ! Enable Guest Shell 52 | ! Entered from Enable Mode (not config) 53 | guestshell enable 54 | 55 | ! Verify Guest Shell Running 56 | show app-hosting list 57 | -------------------------------------------------------------------------------- /application_hosting/guestshell/requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/netprog_basics/a8c75a16c30889f723d094e8df0bb5decb06f0f7/application_hosting/guestshell/requirements.txt -------------------------------------------------------------------------------- /application_hosting/intro/README.md: -------------------------------------------------------------------------------- 1 | # Application Hosting and the Network 2 | ## Local Setup 3 | This lesson has no setup requirements. 4 | 5 | ## Download Slides 6 | 7 | You can download the slides for this lesson [here](https://developer.cisco.com/fileMedia/download/a012b8b7-0896-3b61-a06a-5c0e61f58f89). 8 | 9 | > *Suggestion: Right click, "Open in new tab"* -------------------------------------------------------------------------------- /application_hosting/iox/README.md: -------------------------------------------------------------------------------- 1 | # Package, Deploy and Run Applications in the Network with IOx 2 | 3 | ## "Gitting" the Code 4 | All of the code and examples for this lesson is located in the `netprog_basics/application_hosting/iox` directory. Clone and access it with the following commands: 5 | 6 | ```bash 7 | git clone https://github.com/CiscoDevNet/netprog_basics 8 | cd netprog_basics/application_hosting/iox 9 | ``` 10 | 11 | ## Local Workstation Setup 12 | Be sure to complete the [General Workstation Setup](https://github.com/CiscoDevNet/netprog_basics/blob/master/readme_resources/workstation_setup.md) instructions before beginning this lesson. 13 | 14 | ### Python Environment Setup 15 | It is recommended that this lesson be completed using Python 3.8. Other versions of Python 3 should also work. 16 | 17 | > **Note about Python 2:** Python 2 was [sunset](https://www.python.org/doc/sunset-python-2/) by Python Software Foundation on January 1, 2020. This means that no more updates to Python 2 are being worked on, including security updates. Python 3 is now the recommended version of Python for everyone to use. Most Python developers of software, packages, and scripts have migrated to Python 3 already, however you may find some older scripts and tools that are no longer maintained that only work with Python 2. 18 | > 19 | > You may see/hear references to Python 2 within the videos in this course from before January 2020, however all examples scripts and demos available in the GitHub repo to run have been updated to leverage Python 3. 20 | 21 | It is highly recommended to leverage Python Virtual Environments for completing exercises in this course. 22 | 23 | *There is no need to create independent venv for each lesson, but you can if you choose.* 24 | 25 | Follow these steps to create and activate a venv. 26 | 27 | ***Note: If you are leveraging a shared venv across all lessons simply activate it.*** 28 | 29 | ```bash 30 | # OS X or Linux 31 | python3 -m venv venv 32 | source venv/bin/activate 33 | ``` 34 | 35 | ```bash 36 | # Windows 37 | python -m venv venv 38 | venv/Scripts/activate 39 | ``` 40 | 41 | 42 | #### Install Python Requirements for Lesson 43 | With the Virtual Environment activated, use pip to install the necessary requirements. 44 | 45 | ```bash 46 | # From the code directory for this lesson 47 | pip install -r requirements.txt 48 | ``` 49 | 50 | ### Docker Client Installation 51 | In this lab, you will package and deploy a containerized application to IOx using Docker Tooling. To do so, you'll need Docker version 1.11 or higher installed for your workstation. Docker is supported across Linux, OS X, and Windows operating systems. 52 | 53 | Visit [www.docker.com/get-docker](https://www.docker.com/get-docker), download and install the client for your platform. 54 | 55 | ### IOx Client Installation 56 | IOx Client is an application you'll run use to package, deploy and install applications to IOx devices. 57 | 58 | Download and install version 1.4 or higher from [Cisco Downloads](https://software.cisco.com/download/home/286306005/type/286306762/release). 59 | 60 | Save ioxclient into one of the following locations: 61 | 62 | * The `netprog_basics/application_hosting/iox` directory on your workstation 63 | * A directory that exists within your `PATH` environment variable. 64 | * *Example: `/usr/local/bin` on OS X or Linux* 65 | 66 | ## DevNet Sandbox 67 | This lesson leverages the [IOx v1.11](https://devnetsandbox.cisco.com/RM/Diagram/Index/5f411c0e-b387-4ae6-9ee7-ff793d925cff?diagramType=Topology) Sandbox. 68 | 69 | You will need to reserve an instance of the sandbox, and establish a VPN connection to your individual Sandbox to complete this lab. 70 | 71 | 72 | ## Download Slides 73 | 74 | You can download the slides for this lesson [here](https://developer.cisco.com/fileMedia/download/517a487c-4442-3408-a066-fe17c3795e07). 75 | 76 | > *Suggestion: Right click, "Open in new tab"* 77 | -------------------------------------------------------------------------------- /application_hosting/iox/app_1/Dockerfile: -------------------------------------------------------------------------------- 1 | # Learning Series: Network Programmability Basics 2 | # Module: Application Hosting 3 | # Lesson: Package, Deploy and Run Applications in the Network with IOx 4 | # Author: Hank Preston 5 | # 6 | # Dockerfile 7 | # Illustrate the following concepts: 8 | # - Deploy an IOx application using Docker tooling 9 | FROM alpine:3.5 10 | RUN apk add --update \ 11 | python3 12 | 13 | # Install Python application requirement 14 | RUN pip3 install bottle 15 | 16 | # Application runs on port 8000 17 | EXPOSE 8000 18 | 19 | # Add application code to container 20 | COPY main.py /main.py 21 | 22 | # Start application 23 | CMD python3 /main.py 24 | -------------------------------------------------------------------------------- /application_hosting/iox/app_1/main.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Module: Application Hosting 5 | Lesson: Package, Deploy and Run Applications in the Network with IOx 6 | Author: Hank Preston 7 | 8 | main.py 9 | Illustrate the following concepts: 10 | - Deploy an IOx application using Docker tooling 11 | """ 12 | 13 | __author__ = "Hank Preston" 14 | __author_email__ = "hapresto@cisco.com" 15 | __copyright__ = "Copyright (c) 2016 Cisco Systems, Inc." 16 | __license__ = "MIT" 17 | 18 | from bottle import route, run 19 | from datetime import datetime 20 | 21 | @route('/status/') 22 | def status(device_id): 23 | return { "system": 1, "device": str(device_id) } 24 | 25 | @route('/time') 26 | def time(): 27 | current_time = datetime.now().isoformat(' ') 28 | return {"system": 1, "datetime": current_time} 29 | 30 | run(host='0.0.0.0', port=8000) 31 | -------------------------------------------------------------------------------- /application_hosting/iox/app_1/package.yaml: -------------------------------------------------------------------------------- 1 | # Learning Series: Network Programmability Basics 2 | # Module: Application Hosting 3 | # Lesson: Package, Deploy and Run Applications in the Network with IOx 4 | # Author: Hank Preston 5 | # 6 | # package.yaml 7 | # Illustrate the following concepts: 8 | # - Deploy an IOx application using Docker tooling 9 | 10 | descriptor-schema-version: "2.2" 11 | 12 | info: 13 | name: iox_docker_python_ll 14 | description: "IOx Docker Python Web Learning Lab Application" 15 | version: "1.0" 16 | author-link: "http://www.cisco.com" 17 | author-name: "Cisco Systems" 18 | 19 | app: 20 | cpuarch: "x86_64" 21 | type: docker 22 | resources: 23 | profile: c1.small 24 | network: 25 | - 26 | interface-name: eth0 27 | ports: 28 | tcp: 29 | - 8000 30 | 31 | startup: 32 | rootfs: rootfs.tar 33 | target: ["python3 main.py"] 34 | -------------------------------------------------------------------------------- /application_hosting/iox/requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/netprog_basics/a8c75a16c30889f723d094e8df0bb5decb06f0f7/application_hosting/iox/requirements.txt -------------------------------------------------------------------------------- /application_hosting/python_onbox/eem_applet_1.conf: -------------------------------------------------------------------------------- 1 | event manager applet interface_Lo100_Shutdown 2 | event syslog pattern "Interface Loopback100, changed state to administratively down" 3 | action 0.0 cli command "en" 4 | action 1.0 cli command "guestshell run python /flash/netprog_basics/application_hosting/python_onbox/eem_intf_up.py lo100" 5 | exit 6 | -------------------------------------------------------------------------------- /application_hosting/python_onbox/eem_intf_up.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Module: Application Hosting 5 | Lesson: Python at the Edge 6 | Author: Hank Preston 7 | 8 | eem_intf_up.py 9 | Illustrate the following concepts: 10 | - Run a Python script due to EEM event 11 | - Leverage the Python API library "cli" 12 | """ 13 | 14 | __author__ = "Hank Preston" 15 | __author_email__ = "hapresto@cisco.com" 16 | __copyright__ = "Copyright (c) 2016 Cisco Systems, Inc." 17 | __license__ = "MIT" 18 | 19 | from cli import configurep 20 | import argparse 21 | 22 | # Retrieve the interface from command line using argparse 23 | parser = argparse.ArgumentParser() 24 | parser.add_argument("interface", help="Interface to bring up") 25 | args = parser.parse_args() 26 | 27 | # List of commands to run 28 | commands = [ 29 | "interface {}".format(args.interface), 30 | "no shut" 31 | ] 32 | 33 | # Run commands using Python API 34 | # Commands need to be semicolon seperated 35 | configurep(commands) 36 | -------------------------------------------------------------------------------- /application_hosting/python_onbox/hello_world.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Module: Application Hosting 5 | Lesson: Python at the Edge 6 | Author: Hank Preston 7 | 8 | hello_world.py 9 | Illustrate the following concepts: 10 | - Run a Python script on-box on 11 | """ 12 | 13 | __author__ = "Hank Preston" 14 | __author_email__ = "hapresto@cisco.com" 15 | __copyright__ = "Copyright (c) 2016 Cisco Systems, Inc." 16 | __license__ = "MIT" 17 | 18 | print("Hello World!") 19 | -------------------------------------------------------------------------------- /application_hosting/python_onbox/iosxe_guestshell_setup.txt: -------------------------------------------------------------------------------- 1 | ! To be entered onto IOS XE Device 2 | 3 | ! ***** Step 1 ********* 4 | ! Enable IOX 5 | conf t 6 | iox 7 | exit 8 | 9 | ! Verify IOX 10 | sh iox-service 11 | 12 | ! ***** Step 2 ********* 13 | ! Create and Configure Virtual Port Group 14 | conf t 15 | 16 | interface VirtualPortGroup 0 17 | ip add 192.168.35.1 255.255.255.0 18 | no shut 19 | exit 20 | 21 | ! ***** Step 3 ********* 22 | ! Configure NAT 23 | conf t 24 | 25 | interface VirtualPortGroup0 26 | ip nat inside 27 | exit 28 | 29 | ! Interface connected to local network 30 | interface GigabitEthernet1 31 | ip nat outside 32 | exit 33 | 34 | ip access-list standard NAT_ACL 35 | permit 192.168.0.0 0.0.255.255 36 | exit 37 | 38 | ip nat inside source list NAT_ACL interface GigabitEthernet1 overload 39 | 40 | ! ***** Step 4 ********* 41 | ! Configure Guest Shell 42 | conf t 43 | app-hosting appid guestshell 44 | app-vnic gateway1 virtualportgroup 0 guest-interface 0 45 | guest-ipaddress 192.168.35.2 netmask 255.255.255.0 46 | exit 47 | app-default-gateway 192.168.35.1 guest-interface 0 48 | name-server0 208.67.222.222 49 | end 50 | 51 | ! Enable Guest Shell 52 | ! Entered from Enable Mode (not config) 53 | guestshell enable 54 | 55 | ! Verify Guest Shell Running 56 | show app-hosting list 57 | 58 | ! ***** Step 5 ********* 59 | ! Install git within Guest Shell and Clone Code 60 | guestshell run sudo yum install git 61 | guestshell run git clone https://github.com/CiscoDevNet/netprog_basics /flash/netprog_basics 62 | -------------------------------------------------------------------------------- /application_hosting/python_onbox/requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/netprog_basics/a8c75a16c30889f723d094e8df0bb5decb06f0f7/application_hosting/python_onbox/requirements.txt -------------------------------------------------------------------------------- /intro/intro/README.md: -------------------------------------------------------------------------------- 1 | # How to be a Network Engineer in a Programmable Age 2 | ## Local Setup 3 | This lesson has no setup requirements. 4 | 5 | ## Download Slides 6 | 7 | You can download the slides for this lesson [here](https://developer.cisco.com/fileMedia/download/6059a87f-040c-3922-baeb-6d7bc878dab6). 8 | 9 | > *Suggestion: Right click, "Open in new tab"* -------------------------------------------------------------------------------- /netdevops/README.md: -------------------------------------------------------------------------------- 1 | # Application Hosting and the Network 2 | In this module you will explore different options available for running code and hosting applications at the edge of the network, directly on switches, routers and other devices. 3 | 4 | ## Lessons 5 | 6 | * [Configuration Management and the Network](intro/README.md) 7 | * [Ansible Part 1: What you need to Get Started](ansible_part_1/README.md) 8 | * [Ansible Part 2: Using Ansible for Network Configuration](ansible_part_2/README.md) 9 | * [Ansible Part 3: Your Network As Code](ansible_part_3/README.md) 10 | -------------------------------------------------------------------------------- /netdevops/aci_ansible/.ansible_env: -------------------------------------------------------------------------------- 1 | # Setup environment for ansible playbooks 2 | # Credentials for DevNet Always On ACI Sandbox 3 | # https://devnetsandbox.cisco.com/ 4 | 5 | # usage: source .ansible_env 6 | 7 | # Authentication for ansible network modules 8 | export ANSIBLE_NET_USERNAME=admin 9 | export ANSIBLE_NET_PASSWORD=ciscopsdt 10 | -------------------------------------------------------------------------------- /netdevops/aci_ansible/README.md: -------------------------------------------------------------------------------- 1 | # Application Centric Infrastructure and Ansible 2 | 3 | ## "Gitting" the Code 4 | All of the code and examples for this lesson is located in the `netprog_basics/netdevops/aci_ansible` directory. Clone and access it with the following commands: 5 | 6 | ```bash 7 | git clone https://github.com/CiscoDevNet/netprog_basics 8 | cd netprog_basics/netdevops/aci_ansible 9 | ``` 10 | 11 | ## Local Workstation Setup 12 | Be sure to complete the [General Workstation Setup](https://github.com/CiscoDevNet/netprog_basics/blob/master/readme_resources/workstation_setup.md) instructions before beginning this lesson. 13 | 14 | ### Python Environment Setup 15 | It is recommended that this lesson be completed using Python 3.8. Other versions of Python 3 should also work. 16 | 17 | > **Note about Python 2:** Python 2 was [sunset](https://www.python.org/doc/sunset-python-2/) by Python Software Foundation on January 1, 2020. This means that no more updates to Python 2 are being worked on, including security updates. Python 3 is now the recommended version of Python for everyone to use. Most Python developers of software, packages, and scripts have migrated to Python 3 already, however you may find some older scripts and tools that are no longer maintained that only work with Python 2. 18 | > 19 | > You may see/hear references to Python 2 within the videos in this course from before January 2020, however all examples scripts and demos available in the GitHub repo to run have been updated to leverage Python 3. 20 | 21 | It is highly recommended to leverage Python Virtual Environments for completing exercises in this course. 22 | 23 | *There is no need to create independent venv for each lesson, but you can if you choose.* 24 | 25 | Follow these steps to create and activate a venv. 26 | 27 | ***Note: If you are leveraging a shared venv across all lessons simply activate it.*** 28 | 29 | ```bash 30 | # OS X or Linux 31 | python3 -m venv venv 32 | source venv/bin/activate 33 | ``` 34 | 35 | ```bash 36 | # Windows 37 | python -m venv venv 38 | venv/Scripts/activate 39 | ``` 40 | 41 | 42 | #### Install Python Requirements for Lesson 43 | With the Virtual Environment activated, use pip to install the necessary requirements. 44 | 45 | ```bash 46 | # From the code directory for this lesson 47 | pip install -r requirements.txt 48 | ``` 49 | 50 | ## DevNet Sandbox 51 | This lesson leverages the [Always On: ACI APIC](https://devnetsandbox.cisco.com/RM/Diagram/Index/5a229a7c-95d5-4cfd-a651-5ee9bc1b30e2?diagramType=Topology) Sandbox. This sandbox requires no reservation **or** VPN connection. 52 | -------------------------------------------------------------------------------- /netdevops/aci_ansible/ansible.cfg: -------------------------------------------------------------------------------- 1 | # config file for ansible 2 | # override global certain global settings 3 | 4 | [defaults] 5 | # default to inventory file of ./hosts 6 | inventory = ./hosts 7 | # disable host checking to automatically add hosts to known_hosts 8 | host_key_checking = False 9 | # set the roles path to the local directory 10 | roles_path = ./roles/ 11 | -------------------------------------------------------------------------------- /netdevops/aci_ansible/cleanup.yaml: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # Learning Series: Network Programmability Basics 3 | # Module: NetDevOps 4 | # Lesson: Application Centric Infrastructure and Ansible 5 | # Author: Hank Preston 6 | # 7 | # Illustrate the following concepts: 8 | # - Managing Tenants with Ansible 9 | # - aci_tenant module 10 | # - state: "absent" 11 | ############################################################## 12 | --- 13 | - name: Cleanup - Removing Tenants 14 | hosts: apic 15 | connection: local 16 | gather_facts: False 17 | vars_prompt: 18 | - name: "prefix" 19 | prompt: "What are your initials?" 20 | private: no 21 | vars: 22 | tenants: 23 | - "{{ prefix }}_Tenant1" 24 | - "{{ prefix }}_Tenant2" 25 | - "{{ prefix }}_Tenant3" 26 | - "{{ prefix }}_Tenant4" 27 | 28 | tasks: 29 | - name: Delete Tenants 30 | aci_tenant: 31 | host: "{{ ansible_host }}" 32 | username: "{{ username }}" 33 | password: "{{ password }}" 34 | state: "absent" 35 | validate_certs: False 36 | tenant: "{{ item }}" 37 | with_items: "{{ tenants }}" 38 | -------------------------------------------------------------------------------- /netdevops/aci_ansible/example1.yaml: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # Learning Series: Network Programmability Basics 3 | # Module: NetDevOps 4 | # Lesson: Application Centric Infrastructure and Ansible 5 | # Author: Hank Preston 6 | # 7 | # Illustrate the following concepts: 8 | # - Managing Tenants with Ansible 9 | # - aci_tenant module 10 | ############################################################## 11 | --- 12 | - name: Example 1 - Managing Tenants 13 | hosts: apic 14 | connection: local 15 | gather_facts: False 16 | vars_prompt: 17 | - name: "prefix" 18 | prompt: "What are your initials?" 19 | private: no 20 | vars: 21 | tenants: 22 | - "{{ prefix }}_Tenant1" 23 | - "{{ prefix }}_Tenant2" 24 | 25 | tasks: 26 | - name: Create Tenants 27 | aci_tenant: 28 | host: "{{ ansible_host }}" 29 | username: "{{ username }}" 30 | password: "{{ password }}" 31 | state: "present" 32 | validate_certs: False 33 | tenant: "{{ item }}" 34 | description: "Tenant Created Using Ansible" 35 | with_items: "{{ tenants }}" 36 | -------------------------------------------------------------------------------- /netdevops/aci_ansible/example2.yaml: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # Learning Series: Network Programmability Basics 3 | # Module: NetDevOps 4 | # Lesson: Application Centric Infrastructure and Ansible 5 | # Author: Hank Preston 6 | # 7 | # Illustrate the following concepts: 8 | # - Managing Application Policy with Ansible 9 | # - aci_ap module 10 | # - aci_epg module 11 | ############################################################## 12 | --- 13 | - name: Example 2 - Managing Application Profiles and EPGs 14 | hosts: apic 15 | connection: local 16 | gather_facts: False 17 | vars_prompt: 18 | - name: "prefix" 19 | prompt: "What are your initials?" 20 | private: no 21 | vars: 22 | tenant: "{{ prefix }}_Tenant2" 23 | ap: "Supply_Chain" 24 | epgs: 25 | - epg: "web" 26 | - epg: "sql" 27 | 28 | tasks: 29 | - name: Create Application Profile 30 | aci_ap: 31 | host: "{{ inventory_hostname }}" 32 | username: "{{ username }}" 33 | password: "{{ password }}" 34 | state: "present" 35 | validate_certs: False 36 | tenant: "{{ tenant }}" 37 | ap: "{{ ap }}" 38 | descr: "App Profile Created Using Ansible" 39 | 40 | - name: Create EPGs 41 | aci_epg: 42 | host: "{{ inventory_hostname }}" 43 | username: "{{ username }}" 44 | password: "{{ password }}" 45 | state: "present" 46 | validate_certs: False 47 | tenant: "{{ tenant }}" 48 | ap: "{{ ap }}" 49 | epg: "{{ item.epg }}" 50 | description: "EPG Created Using Ansible" 51 | with_items: "{{ epgs }}" 52 | -------------------------------------------------------------------------------- /netdevops/aci_ansible/hosts: -------------------------------------------------------------------------------- 1 | [apic:vars] 2 | username=admin 3 | password=ciscopsdt 4 | ansible_python_interpreter="/usr/bin/env python" 5 | 6 | [apic] 7 | sandboxapicdc.cisco.com 8 | -------------------------------------------------------------------------------- /netdevops/aci_ansible/requirements.txt: -------------------------------------------------------------------------------- 1 | ansible>=2.4.0.0 2 | -------------------------------------------------------------------------------- /netdevops/aci_ansible/vars/example3_Tenant3_Policy.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | tenant: "{{ prefix }}_Tenant3" 3 | vrf: "prod_vrf" 4 | bridge_domains: 5 | - bd: "prod_bd" 6 | gateway: "10.1.100.1" 7 | mask: "24" 8 | scope: "public" 9 | ap: "intranet" 10 | epgs: 11 | - epg: "web" 12 | bd: "prod_bd" 13 | encap: "21" 14 | - epg: "db" 15 | bd: "prod_bd" 16 | encap: "22" 17 | epg_contracts: 18 | - epg: "web" 19 | contract: "web" 20 | contract_type: "provider" 21 | - epg: "web" 22 | contract: "sql" 23 | contract_type: "consumer" 24 | - epg: "db" 25 | contract: "sql" 26 | contract_type: "provider" 27 | contracts: 28 | - contract: "web" 29 | subject: "https" 30 | filter: "https" 31 | - contract: "sql" 32 | subject: "sql" 33 | filter: "sql" 34 | filters: 35 | - filter: "https" 36 | entry: "https" 37 | protocol: "tcp" 38 | port: "443" 39 | - filter: "sql" 40 | entry: "sql" 41 | protocol: "tcp" 42 | port: "1433" 43 | -------------------------------------------------------------------------------- /netdevops/ansible_part_1/ansible.cfg: -------------------------------------------------------------------------------- 1 | # config file for ansible 2 | # override global certain global settings 3 | 4 | [defaults] 5 | # default to inventory file of ./hosts 6 | inventory = ./hosts 7 | # disable host checking to automatically add hosts to known_hosts 8 | host_key_checking = False 9 | # set the roles path to the local directory 10 | roles_path = ./ 11 | -------------------------------------------------------------------------------- /netdevops/ansible_part_1/example1.yaml: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # Learning Series: Network Programmability Basics 3 | # Module: NetDevOps 4 | # Lesson: Ansible Part 1: What you need to Get Started 5 | # Author: Hank Preston 6 | # 7 | # example1.yaml 8 | # Illustrate the following concepts: 9 | # - Basic Playbook Structure 10 | # - Use of Variables 11 | ############################################################## 12 | --- 13 | - name: Report Hostname and Operating System Details 14 | hosts: servers 15 | 16 | tasks: 17 | - name: "Get hostname from server" 18 | debug: 19 | msg: "{{ansible_hostname}}" 20 | 21 | - name: "Operating System" 22 | debug: msg="{{ansible_distribution}}" 23 | 24 | - name: Report Network Details of Servers 25 | hosts: servers 26 | become: yes 27 | 28 | tasks: 29 | - name: "Default IPv4 Interface" 30 | debug: msg="{{ansible_default_ipv4.interface}}" 31 | 32 | - name: "Retrieve network routes" 33 | command: "ip route list" 34 | register: routes 35 | 36 | - name: "Network routes installed" 37 | debug: msg="{{routes}}" 38 | -------------------------------------------------------------------------------- /netdevops/ansible_part_1/example2.yaml: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # Learning Series: Network Programmability Basics 3 | # Module: NetDevOps 4 | # Lesson: Ansible Part 1: What you need to Get Started 5 | # Author: Hank Preston 6 | # 7 | # example2.yaml 8 | # Illustrate the following concepts: 9 | # - Using vars_files in playbooks 10 | ############################################################## 11 | --- 12 | - name: Illustrate Variables 13 | hosts: servers 14 | gather_facts: false 15 | vars_files: 16 | - example2_vars.yaml 17 | 18 | tasks: 19 | - name: "Print Company Name from Variable" 20 | debug: msg="Hello {{company_name}}" 21 | 22 | - name: "Loop over a List" 23 | with_items: "{{quotes}}" 24 | debug: msg="{{item}}" 25 | -------------------------------------------------------------------------------- /netdevops/ansible_part_1/example2_vars.yaml: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # Learning Series: Network Programmability Basics 3 | # Module: NetDevOps 4 | # Lesson: Ansible Part 1: What you need to Get Started 5 | # Author: Hank Preston 6 | # 7 | # example2_vars.yaml 8 | # Illustrate the following concepts: 9 | # - Using vars_files in playbooks 10 | ############################################################## 11 | --- 12 | company_name: "DevNet" 13 | quotes: 14 | - "DevNet Rocks!" 15 | - "Programmability is amazing" 16 | - "Ansible is easy to use" 17 | - "Lists are fun!" 18 | 19 | -------------------------------------------------------------------------------- /netdevops/ansible_part_1/example3.j2: -------------------------------------------------------------------------------- 1 | feature {{feature}} 2 | router bgp {{asn}} 3 | router-id {{router_id}} 4 | -------------------------------------------------------------------------------- /netdevops/ansible_part_1/example3.yaml: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # Learning Series: Network Programmability Basics 3 | # Module: NetDevOps 4 | # Lesson: Ansible Part 1: What you need to Get Started 5 | # Author: Hank Preston 6 | # 7 | # example3.yaml 8 | # Illustrate the following concepts: 9 | # - Using Jinja templates 10 | ############################################################## 11 | --- 12 | - name: Generate Configuration from Template 13 | hosts: localhost 14 | gather_facts: false 15 | vars: 16 | feature: bgp 17 | asn: 65001 18 | router_id: 10.10.10.1 19 | 20 | tasks: 21 | - name: "Generate config" 22 | template: 23 | src: "example3.j2" 24 | dest: "./example3.conf" 25 | 26 | -------------------------------------------------------------------------------- /netdevops/ansible_part_1/host_vars/172.16.30.101.yaml: -------------------------------------------------------------------------------- 1 | l3_fabric: 2 | interfaces: 3 | - name: Ethernet1/1 4 | desc: L3 Link to nx-osv9000-3 5 | ip_address: 172.20.0.1 6 | prefix: 30 7 | - name: Ethernet1/2 8 | desc: L3 Link to nx-osv9000-4 9 | ip_address: 172.20.0.5 10 | prefix: 30 11 | - name: Ethernet1/3 12 | desc: L3 Link to nx-osv9000-2 13 | ip_address: 172.20.0.17 14 | prefix: 30 15 | local_loopbacks: 16 | - name: Loopback11 17 | desc: Sample Network Route Injection 18 | ip_address: 172.21.1.1 19 | prefix: 24 20 | - name: Loopback12 21 | desc: Sample Network Route Injection 22 | ip_address: 172.21.2.1 23 | prefix: 24 24 | - name: Loopback13 25 | desc: Sample Network Route Injection 26 | ip_address: 172.21.3.1 27 | prefix: 24 28 | - name: Loopback14 29 | desc: Sample Network Route Injection 30 | ip_address: 172.21.4.1 31 | prefix: 24 32 | bgp: 33 | asn: 65531 34 | router_id: 192.168.0.1 35 | neighbors: 36 | - neighbor: 172.20.0.18 37 | asn: 65532 38 | description: nx-osv9000-2 39 | update_source: Ethernet1/3 40 | - neighbor: 172.20.0.2 41 | asn: 65533 42 | description: nx-osv9000-3 43 | update_source: Ethernet1/1 44 | - neighbor: 172.20.0.6 45 | asn: 65534 46 | description: nx-osv9000-4 47 | update_source: Ethernet1/2 48 | networks: 49 | - - 172.21.1.0/24 50 | - - 172.21.2.0/24 51 | - - 172.21.3.0/24 52 | - - 172.21.4.0/24 53 | -------------------------------------------------------------------------------- /netdevops/ansible_part_1/host_vars/172.16.30.102.yaml: -------------------------------------------------------------------------------- 1 | l3_fabric: 2 | interfaces: 3 | - name: Ethernet1/1 4 | desc: L3 Link to nx-osv9000-3 5 | ip_address: 172.20.0.9 6 | prefix: 30 7 | - name: Ethernet1/2 8 | desc: L3 Link to nx-osv9000-4 9 | ip_address: 172.20.0.13 10 | prefix: 30 11 | - name: Ethernet1/3 12 | desc: L3 Link to nx-osv9000-1 13 | ip_address: 172.20.0.18 14 | prefix: 30 15 | local_loopbacks: 16 | - name: Loopback11 17 | desc: Sample Network Route Injection 18 | ip_address: 172.22.1.1 19 | prefix: 24 20 | - name: Loopback12 21 | desc: Sample Network Route Injection 22 | ip_address: 172.22.2.1 23 | prefix: 24 24 | - name: Loopback13 25 | desc: Sample Network Route Injection 26 | ip_address: 172.22.3.1 27 | prefix: 24 28 | - name: Loopback14 29 | desc: Sample Network Route Injection 30 | ip_address: 172.22.4.1 31 | prefix: 24 32 | bgp: 33 | asn: 65532 34 | router_id: 192.168.0.2 35 | neighbors: 36 | - neighbor: 172.20.0.17 37 | asn: 65531 38 | description: nx-osv9000-1 39 | update_source: Ethernet1/3 40 | - neighbor: 172.20.0.10 41 | asn: 65533 42 | description: nx-osv9000-3 43 | update_source: Ethernet1/1 44 | - neighbor: 172.20.0.14 45 | asn: 65534 46 | description: nx-osv9000-4 47 | update_source: Ethernet1/2 48 | networks: 49 | - - 172.22.1.0/24 50 | - - 172.22.2.0/24 51 | - - 172.22.3.0/24 52 | - - 172.22.4.0/24 53 | -------------------------------------------------------------------------------- /netdevops/ansible_part_1/host_vars/172.16.30.103.yaml: -------------------------------------------------------------------------------- 1 | l3_fabric: 2 | interfaces: 3 | - name: Ethernet1/1 4 | desc: L3 Link to nx-osv9000-1 5 | ip_address: 172.20.0.2 6 | prefix: 30 7 | - name: Ethernet1/2 8 | desc: L3 Link to nx-osv9000-2 9 | ip_address: 172.20.0.10 10 | prefix: 30 11 | local_loopbacks: 12 | - name: Loopback11 13 | desc: Sample Network Route Injection 14 | ip_address: 172.23.1.1 15 | prefix: 24 16 | - name: Loopback12 17 | desc: Sample Network Route Injection 18 | ip_address: 172.23.2.1 19 | prefix: 24 20 | - name: Loopback13 21 | desc: Sample Network Route Injection 22 | ip_address: 172.23.3.1 23 | prefix: 24 24 | - name: Loopback14 25 | desc: Sample Network Route Injection 26 | ip_address: 172.23.4.1 27 | prefix: 24 28 | bgp: 29 | asn: 65533 30 | router_id: 192.168.0.3 31 | neighbors: 32 | - neighbor: 172.20.0.1 33 | asn: 65531 34 | description: nx-osv9000-1 35 | update_source: Ethernet1/1 36 | - neighbor: 172.20.0.9 37 | asn: 65532 38 | description: nx-osv9000-2 39 | update_source: Ethernet1/2 40 | networks: 41 | - - 172.23.1.0/24 42 | - - 172.23.2.0/24 43 | - - 172.23.3.0/24 44 | - - 172.23.4.0/24 45 | -------------------------------------------------------------------------------- /netdevops/ansible_part_1/host_vars/172.16.30.104.yaml: -------------------------------------------------------------------------------- 1 | l3_fabric: 2 | interfaces: 3 | - name: Ethernet1/1 4 | desc: L3 Link to nx-osv9000-1 5 | ip_address: 172.20.0.6 6 | prefix: 30 7 | - name: Ethernet1/2 8 | desc: L3 Link to nx-osv9000-2 9 | ip_address: 172.20.0.14 10 | prefix: 30 11 | local_loopbacks: 12 | - name: Loopback11 13 | desc: Sample Network Route Injection 14 | ip_address: 172.24.1.1 15 | prefix: 24 16 | - name: Loopback12 17 | desc: Sample Network Route Injection 18 | ip_address: 172.24.2.1 19 | prefix: 24 20 | - name: Loopback13 21 | desc: Sample Network Route Injection 22 | ip_address: 172.24.3.1 23 | prefix: 24 24 | - name: Loopback14 25 | desc: Sample Network Route Injection 26 | ip_address: 172.24.4.1 27 | prefix: 24 28 | bgp: 29 | asn: 65534 30 | router_id: 192.168.0.4 31 | neighbors: 32 | - neighbor: 172.20.0.5 33 | asn: 65531 34 | description: nx-osv9000-1 35 | update_source: Ethernet1/1 36 | - neighbor: 172.20.0.13 37 | asn: 65532 38 | description: nx-osv9000-2 39 | update_source: Ethernet1/2 40 | networks: 41 | - - 172.24.1.0/24 42 | - - 172.24.2.0/24 43 | - - 172.24.3.0/24 44 | - - 172.24.4.0/24 45 | -------------------------------------------------------------------------------- /netdevops/ansible_part_1/hosts: -------------------------------------------------------------------------------- 1 | [servers] 2 | 10.10.20.20 ansible_python_interpreter="/usr/bin/env python" ansible_ssh_user=developer 3 | 4 | [switches] 5 | 172.16.30.101 ansible_python_interpreter="/usr/bin/env python" 6 | 172.16.30.102 ansible_python_interpreter="/usr/bin/env python" 7 | 172.16.30.103 ansible_python_interpreter="/usr/bin/env python" 8 | 172.16.30.104 ansible_python_interpreter="/usr/bin/env python" 9 | -------------------------------------------------------------------------------- /netdevops/ansible_part_1/requirements.txt: -------------------------------------------------------------------------------- 1 | ansible==2.9.16 2 | ncclient>=0.6.9 3 | paramiko==2.7.2 4 | requests>=2.25.1 5 | -------------------------------------------------------------------------------- /netdevops/ansible_part_2/.ansible_env: -------------------------------------------------------------------------------- 1 | # Deprecation Note: 2 | # Ansible no longer suggests using these environment variables for credentails 3 | # now users should use the connection: network_cli method for network devices 4 | # and use the parameters there. 5 | # Info: https://docs.ansible.com/ansible/2.9/network/user_guide/platform_nxos.html 6 | # https://docs.ansible.com/ansible/2.9/plugins/connection/network_cli.html 7 | # 8 | # Though the use of these environment variables may still work. Timing for removing 9 | # their functionality from Ansible is undetermined. 10 | 11 | # Setup environment for ansible playbooks 12 | # Credentials for DevNet Open NX-OS Sandbox 13 | # https://devnetsandbox.cisco.com/ 14 | 15 | # usage: source .ansible_env 16 | 17 | # Authentication for ansible network modules 18 | export ANSIBLE_NET_USERNAME=cisco 19 | export ANSIBLE_NET_PASSWORD=cisco 20 | -------------------------------------------------------------------------------- /netdevops/ansible_part_2/ansible.cfg: -------------------------------------------------------------------------------- 1 | # config file for ansible 2 | # override global certain global settings 3 | 4 | [defaults] 5 | # default to inventory file of ./hosts 6 | inventory = ./hosts 7 | # disable host checking to automatically add hosts to known_hosts 8 | host_key_checking = False 9 | # set the roles path to the local directory 10 | roles_path = ./ 11 | 12 | # Don't display deprecation warnings. There are several modules used 13 | # in examples that are deprecated, but the replacement modules have bugs. 14 | # Notes in Playbooks/Roles have been made. 15 | deprecation_warnings = False 16 | 17 | 18 | [persistent_connection] 19 | # Increase timeout for network devices and slow commands 20 | # https://docs.ansible.com/ansible/latest/network/user_guide/network_debug_troubleshooting.html#command-timeout 21 | command_timeout = 60 -------------------------------------------------------------------------------- /netdevops/ansible_part_2/example1.yaml: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # Learning Series: Network Programmability Basics 3 | # Module: NetDevOps 4 | # Lesson: Ansible Part 2: Using Ansible for Network Configuration 5 | # Author: Hank Preston 6 | # 7 | # example1.yaml 8 | # Illustrate the following concepts: 9 | # - Basic Playbook Structure for NX-OS Modules 10 | ############################################################## 11 | --- 12 | - name: Retrieve facts from Switches 13 | hosts: switches 14 | gather_facts: False 15 | 16 | # Ansible added new connection options for networking devices 17 | # to replace connection: local 18 | # Now connection: network_cli or httpapi are recommended 19 | # Doc: https://docs.ansible.com/ansible/2.9/network/user_guide/platform_nxos.html 20 | connection: network_cli 21 | 22 | tasks: 23 | - name: "Retrieving NX-OS Facts" 24 | nxos_facts: 25 | # See docs for what subset options of facts are available 26 | # https://docs.ansible.com/ansible/2.9/modules/nxos_facts_module.html#nxos-facts-module 27 | gather_subset: all 28 | register: nxos_info 29 | 30 | - name: "Print NX-OS Facts" 31 | debug: msg="{{nxos_info}}" 32 | -------------------------------------------------------------------------------- /netdevops/ansible_part_2/example2.yaml: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # Learning Series: Network Programmability Basics 3 | # Module: NetDevOps 4 | # Lesson: Ansible Part 2: Using Ansible for Network Configuration 5 | # Author: Hank Preston 6 | # 7 | # example2.yaml 8 | # Illustrate the following concepts: 9 | # - Configuring NX-OS network interfaces with Ansible 10 | ############################################################## 11 | --- 12 | - name: Configure Loopback Networks on Each Switch 13 | hosts: switches 14 | gather_facts: False 15 | 16 | # Ansible added new connection options for networking devices 17 | # to replace connection: local 18 | # Now connection: network_cli or httpapi are recommended 19 | # Doc: https://docs.ansible.com/ansible/2.9/network/user_guide/platform_nxos.html 20 | connection: network_cli 21 | 22 | tasks: 23 | - name: Create Loopback Interface 24 | # Note: The "with_items" syntax has been replaced by "loop" 25 | # - https://docs.ansible.com/ansible/2.9/user_guide/playbooks_loops.html#with-items 26 | loop: "{{ local_loopbacks }}" 27 | # with_items: "{{ l3_fabric.interfaces }}" 28 | # Note: the nxos_interface module has been replaced with nxos_interfaces 29 | # and will be deprecated/removed soon. However the new nxos_interfaces 30 | # module has a bug in Ansible 2.9 when trying to create loopbacks. Keeping 31 | # this example using nxos_interface for now. 32 | # Info: 33 | # - https://docs.ansible.com/ansible/2.9/modules/nxos_interfaces_module.html 34 | # - https://docs.ansible.com/ansible/2.9/modules/nxos_interface_module.html 35 | nxos_interface: 36 | interface: "{{ item.name }}" 37 | mode: layer3 38 | description: "{{ item.desc }}" 39 | 40 | 41 | 42 | # Note: The module nxos_ip_interface was obsoleted by Ansible and replaced with 43 | # nxos_l3_interfaces. This module provides the same purpose, but with different 44 | # syntax. See details at: 45 | # - https://docs.ansible.com/ansible/2.9/modules/nxos_l3_interfaces_module.html 46 | - name: Configure IPv4 Address on Interface 47 | # Note: The "with_items" syntax has been replaced by "loop" 48 | # - https://docs.ansible.com/ansible/2.9/user_guide/playbooks_loops.html#with-items 49 | loop: "{{ local_loopbacks }}" 50 | # Note: to stay consistent with the videos for the lesson, this playbook 51 | # uses the loop construct for configuring interfaces. The current module 52 | # does support multiple interfaces in one task execution, and that would 53 | # be a more efficient configuration. 54 | nxos_l3_interfaces: 55 | state: merged 56 | config: 57 | - name: "{{ item.name }}" 58 | ipv4: 59 | - address: "{{ item.ip_address }}/{{ item.prefix }}" 60 | -------------------------------------------------------------------------------- /netdevops/ansible_part_2/group_vars/switches.yaml: -------------------------------------------------------------------------------- 1 | # These variables are used with the connection: network_cli for Ansible 2 | # Info: https://docs.ansible.com/ansible/2.9/network/user_guide/platform_nxos.html 3 | # https://docs.ansible.com/ansible/2.9/plugins/connection/network_cli.html 4 | 5 | --- 6 | # ansible_connection: network_cli 7 | ansible_network_os: nxos 8 | ansible_user: cisco 9 | ansible_password: cisco 10 | ansible_become: yes 11 | ansible_become_method: enable 12 | ansible_become_password: cisco -------------------------------------------------------------------------------- /netdevops/ansible_part_2/host_vars/172.16.30.101.yaml: -------------------------------------------------------------------------------- 1 | l3_fabric: 2 | interfaces: 3 | - name: Ethernet1/1 4 | desc: L3 Link to nx-osv9000-3 5 | ip_address: 172.20.0.1 6 | prefix: 30 7 | - name: Ethernet1/2 8 | desc: L3 Link to nx-osv9000-4 9 | ip_address: 172.20.0.5 10 | prefix: 30 11 | - name: Ethernet1/3 12 | desc: L3 Link to nx-osv9000-2 13 | ip_address: 172.20.0.17 14 | prefix: 30 15 | local_loopbacks: 16 | - name: Loopback11 17 | desc: Sample Network Route Injection 18 | ip_address: 172.21.1.1 19 | prefix: 24 20 | - name: Loopback12 21 | desc: Sample Network Route Injection 22 | ip_address: 172.21.2.1 23 | prefix: 24 24 | - name: Loopback13 25 | desc: Sample Network Route Injection 26 | ip_address: 172.21.3.1 27 | prefix: 24 28 | - name: Loopback14 29 | desc: Sample Network Route Injection 30 | ip_address: 172.21.4.1 31 | prefix: 24 32 | bgp: 33 | asn: 65531 34 | router_id: 192.168.0.1 35 | neighbors: 36 | - neighbor: 172.20.0.18 37 | asn: 65532 38 | description: nx-osv9000-2 39 | update_source: Ethernet1/3 40 | - neighbor: 172.20.0.2 41 | asn: 65533 42 | description: nx-osv9000-3 43 | update_source: Ethernet1/1 44 | - neighbor: 172.20.0.6 45 | asn: 65534 46 | description: nx-osv9000-4 47 | update_source: Ethernet1/2 48 | networks: 49 | - - 172.21.1.0/24 50 | - - 172.21.2.0/24 51 | - - 172.21.3.0/24 52 | - - 172.21.4.0/24 53 | -------------------------------------------------------------------------------- /netdevops/ansible_part_2/host_vars/172.16.30.102.yaml: -------------------------------------------------------------------------------- 1 | l3_fabric: 2 | interfaces: 3 | - name: Ethernet1/1 4 | desc: L3 Link to nx-osv9000-3 5 | ip_address: 172.20.0.9 6 | prefix: 30 7 | - name: Ethernet1/2 8 | desc: L3 Link to nx-osv9000-4 9 | ip_address: 172.20.0.13 10 | prefix: 30 11 | - name: Ethernet1/3 12 | desc: L3 Link to nx-osv9000-1 13 | ip_address: 172.20.0.18 14 | prefix: 30 15 | local_loopbacks: 16 | - name: Loopback11 17 | desc: Sample Network Route Injection 18 | ip_address: 172.22.1.1 19 | prefix: 24 20 | - name: Loopback12 21 | desc: Sample Network Route Injection 22 | ip_address: 172.22.2.1 23 | prefix: 24 24 | - name: Loopback13 25 | desc: Sample Network Route Injection 26 | ip_address: 172.22.3.1 27 | prefix: 24 28 | - name: Loopback14 29 | desc: Sample Network Route Injection 30 | ip_address: 172.22.4.1 31 | prefix: 24 32 | bgp: 33 | asn: 65532 34 | router_id: 192.168.0.2 35 | neighbors: 36 | - neighbor: 172.20.0.17 37 | asn: 65531 38 | description: nx-osv9000-1 39 | update_source: Ethernet1/3 40 | - neighbor: 172.20.0.10 41 | asn: 65533 42 | description: nx-osv9000-3 43 | update_source: Ethernet1/1 44 | - neighbor: 172.20.0.14 45 | asn: 65534 46 | description: nx-osv9000-4 47 | update_source: Ethernet1/2 48 | networks: 49 | - - 172.22.1.0/24 50 | - - 172.22.2.0/24 51 | - - 172.22.3.0/24 52 | - - 172.22.4.0/24 53 | -------------------------------------------------------------------------------- /netdevops/ansible_part_2/host_vars/172.16.30.103.yaml: -------------------------------------------------------------------------------- 1 | l3_fabric: 2 | interfaces: 3 | - name: Ethernet1/1 4 | desc: L3 Link to nx-osv9000-1 5 | ip_address: 172.20.0.2 6 | prefix: 30 7 | - name: Ethernet1/2 8 | desc: L3 Link to nx-osv9000-2 9 | ip_address: 172.20.0.10 10 | prefix: 30 11 | local_loopbacks: 12 | - name: Loopback11 13 | desc: Sample Network Route Injection 14 | ip_address: 172.23.1.1 15 | prefix: 24 16 | - name: Loopback12 17 | desc: Sample Network Route Injection 18 | ip_address: 172.23.2.1 19 | prefix: 24 20 | - name: Loopback13 21 | desc: Sample Network Route Injection 22 | ip_address: 172.23.3.1 23 | prefix: 24 24 | - name: Loopback14 25 | desc: Sample Network Route Injection 26 | ip_address: 172.23.4.1 27 | prefix: 24 28 | bgp: 29 | asn: 65533 30 | router_id: 192.168.0.3 31 | neighbors: 32 | - neighbor: 172.20.0.1 33 | asn: 65531 34 | description: nx-osv9000-1 35 | update_source: Ethernet1/1 36 | - neighbor: 172.20.0.9 37 | asn: 65532 38 | description: nx-osv9000-2 39 | update_source: Ethernet1/2 40 | networks: 41 | - - 172.23.1.0/24 42 | - - 172.23.2.0/24 43 | - - 172.23.3.0/24 44 | - - 172.23.4.0/24 45 | -------------------------------------------------------------------------------- /netdevops/ansible_part_2/host_vars/172.16.30.104.yaml: -------------------------------------------------------------------------------- 1 | l3_fabric: 2 | interfaces: 3 | - name: Ethernet1/1 4 | desc: L3 Link to nx-osv9000-1 5 | ip_address: 172.20.0.6 6 | prefix: 30 7 | - name: Ethernet1/2 8 | desc: L3 Link to nx-osv9000-2 9 | ip_address: 172.20.0.14 10 | prefix: 30 11 | local_loopbacks: 12 | - name: Loopback11 13 | desc: Sample Network Route Injection 14 | ip_address: 172.24.1.1 15 | prefix: 24 16 | - name: Loopback12 17 | desc: Sample Network Route Injection 18 | ip_address: 172.24.2.1 19 | prefix: 24 20 | - name: Loopback13 21 | desc: Sample Network Route Injection 22 | ip_address: 172.24.3.1 23 | prefix: 24 24 | - name: Loopback14 25 | desc: Sample Network Route Injection 26 | ip_address: 172.24.4.1 27 | prefix: 24 28 | bgp: 29 | asn: 65534 30 | router_id: 192.168.0.4 31 | neighbors: 32 | - neighbor: 172.20.0.5 33 | asn: 65531 34 | description: nx-osv9000-1 35 | update_source: Ethernet1/1 36 | - neighbor: 172.20.0.13 37 | asn: 65532 38 | description: nx-osv9000-2 39 | update_source: Ethernet1/2 40 | networks: 41 | - - 172.24.1.0/24 42 | - - 172.24.2.0/24 43 | - - 172.24.3.0/24 44 | - - 172.24.4.0/24 45 | -------------------------------------------------------------------------------- /netdevops/ansible_part_2/hosts: -------------------------------------------------------------------------------- 1 | [servers] 2 | 10.10.20.20 ansible_python_interpreter="/usr/bin/env python" ansible_ssh_user=developer 3 | 4 | [switches] 5 | 172.16.30.101 ansible_python_interpreter="/usr/bin/env python" 6 | 172.16.30.102 ansible_python_interpreter="/usr/bin/env python" 7 | 172.16.30.103 ansible_python_interpreter="/usr/bin/env python" 8 | 172.16.30.104 ansible_python_interpreter="/usr/bin/env python" 9 | -------------------------------------------------------------------------------- /netdevops/ansible_part_2/requirements.txt: -------------------------------------------------------------------------------- 1 | ansible==2.9.16 2 | ncclient>=0.6.9 3 | paramiko==2.7.2 4 | requests>=2.25.1 5 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/.ansible_env: -------------------------------------------------------------------------------- 1 | # Setup environment for ansible playbooks 2 | # Credentials for DevNet Open NX-OS Sandbox 3 | # https://devnetsandbox.cisco.com/ 4 | 5 | # usage: source .ansible_env 6 | 7 | # Authentication for ansible network modules 8 | export ANSIBLE_NET_USERNAME=cisco 9 | export ANSIBLE_NET_PASSWORD=cisco 10 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/ansible.cfg: -------------------------------------------------------------------------------- 1 | # config file for ansible 2 | # override global certain global settings 3 | 4 | [defaults] 5 | # default to inventory file of ./hosts 6 | inventory = ./hosts 7 | # disable host checking to automatically add hosts to known_hosts 8 | host_key_checking = False 9 | # set the roles path to the local directory 10 | roles_path = ./roles/ 11 | 12 | # Don't display deprecation warnings. There are several modules used 13 | # in examples that are deprecated, but the replacement modules have bugs. 14 | # Notes in Playbooks/Roles have been made. 15 | deprecation_warnings = False 16 | 17 | [persistent_connection] 18 | # Increase timeout for network devices and slow commands 19 | # https://docs.ansible.com/ansible/latest/network/user_guide/network_debug_troubleshooting.html#command-timeout 20 | command_timeout = 60 -------------------------------------------------------------------------------- /netdevops/ansible_part_3/configs/readme.md: -------------------------------------------------------------------------------- 1 | This directory will be used to hold Ansible generated configuration files during execution. 2 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/group_vars/access.yaml: -------------------------------------------------------------------------------- 1 | uplinks: 2 | - port_channel_id: 11 3 | members: 4 | - Ethernet1/1 5 | - Ethernet1/2 6 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/group_vars/all.yaml: -------------------------------------------------------------------------------- 1 | vlans: 2 | - id: 100 3 | name: Management 4 | gateway: 172.20.100.1 5 | - id: 101 6 | name: Private 7 | gateway: 172.20.101.1 8 | - id: 102 9 | name: Guest 10 | gateway: 172.20.102.1 11 | - id: 103 12 | name: Security 13 | gateway: 172.20.103.1 14 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/group_vars/core.yaml: -------------------------------------------------------------------------------- 1 | ospf: 2 | process_id: 1 3 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/group_vars/distribution.yaml: -------------------------------------------------------------------------------- 1 | hsrp_interfaces: 2 | - interface: vlan100 3 | group: 10 4 | vip: 172.16.100.1 5 | - interface: vlan101 6 | group: 10 7 | vip: 172.16.101.1 8 | - interface: vlan102 9 | group: 10 10 | vip: 172.16.102.1 11 | - interface: vlan103 12 | group: 10 13 | vip: 172.16.103.1 14 | ospf: 15 | process_id: 1 16 | networks: 17 | - interface: Ethernet1/5 18 | area: 0 19 | - interface: Ethernet1/6 20 | area: 0 21 | - interface: vlan100 22 | area: 0 23 | - interface: vlan101 24 | area: 0 25 | - interface: vlan102 26 | area: 0 27 | - interface: vlan103 28 | area: 0 29 | - interface: loopback0 30 | area: 0 31 | vpc: 32 | domain: 100 33 | pkl_vrf: management 34 | port_channel: 35 | id: "1" 36 | members: 37 | - Ethernet1/3 38 | - Ethernet1/4 39 | trunks: 40 | - port_channel_id: 11 41 | members: 42 | - Ethernet1/1 43 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/group_vars/iosxe.yaml: -------------------------------------------------------------------------------- 1 | # These variables are used with the connection: network_cli for Ansible 2 | # Info: https://docs.ansible.com/ansible/2.9/network/user_guide/platform_ios.html 3 | # https://docs.ansible.com/ansible/2.9/plugins/connection/network_cli.html 4 | 5 | --- 6 | # ansible_connection: network_cli 7 | ansible_network_os: ios 8 | ansible_user: cisco 9 | ansible_password: cisco 10 | ansible_become: yes 11 | ansible_become_method: enable 12 | ansible_become_password: cisco -------------------------------------------------------------------------------- /netdevops/ansible_part_3/group_vars/nxos.yaml: -------------------------------------------------------------------------------- 1 | # These variables are used with the connection: network_cli for Ansible 2 | # Info: https://docs.ansible.com/ansible/2.9/network/user_guide/platform_nxos.html 3 | # https://docs.ansible.com/ansible/2.9/plugins/connection/network_cli.html 4 | 5 | --- 6 | # ansible_connection: network_cli 7 | ansible_network_os: nxos 8 | ansible_user: cisco 9 | ansible_password: cisco 10 | ansible_become: yes 11 | ansible_become_method: enable 12 | ansible_become_password: cisco -------------------------------------------------------------------------------- /netdevops/ansible_part_3/host_vars/172.16.30.101.yaml: -------------------------------------------------------------------------------- 1 | ospf_router_id: 192.168.0.1 2 | vpc_pkl_src: 172.16.30.101 3 | vpc_pkl_dest: 172.16.30.102 4 | l3_interfaces: 5 | - interface_type: Loopback 6 | interface_id: 0 7 | description: Default Loopback 8 | ip_address: 192.168.0.1 9 | subnet_mask: 255.255.255.255 10 | prefix: 32 11 | area: 0 12 | - interface_type: Ethernet 13 | interface_id: 1/5 14 | description: L3 Link to ios-xev-1 15 | ip_address: 172.16.0.2 16 | subnet_mask: 255.255.255.252 17 | prefix: 30 18 | area: 0 19 | - interface_type: Ethernet 20 | interface_id: 1/6 21 | description: L3 Link to ios-xev-2 22 | ip_address: 172.16.0.10 23 | subnet_mask: 255.255.255.252 24 | prefix: 30 25 | area: 0 26 | - interface_type: vlan 27 | interface_id: 100 28 | description: VLAN Interface - Management 29 | ip_address: 172.16.100.2 30 | subnet_mask: 255.255.255.0 31 | prefix: 24 32 | area: 0 33 | - interface_type: vlan 34 | interface_id: 101 35 | description: VLAN Interface - Private 36 | ip_address: 172.16.101.2 37 | subnet_mask: 255.255.255.0 38 | prefix: 24 39 | area: 0 40 | - interface_type: vlan 41 | interface_id: 102 42 | description: VLAN Interface - Guest 43 | ip_address: 172.16.102.2 44 | subnet_mask: 255.255.255.0 45 | prefix: 24 46 | area: 0 47 | - interface_type: vlan 48 | interface_id: 103 49 | description: VLAN Interface - Security 50 | ip_address: 172.16.103.2 51 | subnet_mask: 255.255.255.0 52 | prefix: 24 53 | area: 0 54 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/host_vars/172.16.30.102.yaml: -------------------------------------------------------------------------------- 1 | ospf_router_id: 192.168.0.2 2 | vpc_pkl_src: 172.16.30.102 3 | vpc_pkl_dest: 172.16.30.101 4 | l3_interfaces: 5 | - interface_type: Loopback 6 | interface_id: 0 7 | description: Default Loopback 8 | ip_address: 192.168.0.2 9 | subnet_mask: 255.255.255.255 10 | prefix: 32 11 | area: 0 12 | - interface_type: Ethernet 13 | interface_id: 1/5 14 | description: L3 Link to ios-xev-2 15 | ip_address: 172.16.0.14 16 | subnet_mask: 255.255.255.252 17 | prefix: 30 18 | area: 0 19 | - interface_type: Ethernet 20 | interface_id: 1/6 21 | description: L3 Link to ios-xev-1 22 | ip_address: 172.16.0.6 23 | subnet_mask: 255.255.255.252 24 | prefix: 30 25 | area: 0 26 | - interface_type: vlan 27 | interface_id: 100 28 | description: VLAN Interface - Management 29 | ip_address: 172.16.100.3 30 | subnet_mask: 255.255.255.0 31 | prefix: 24 32 | area: 0 33 | - interface_type: vlan 34 | interface_id: 101 35 | description: VLAN Interface - Private 36 | ip_address: 172.16.101.3 37 | subnet_mask: 255.255.255.0 38 | prefix: 24 39 | area: 0 40 | - interface_type: vlan 41 | interface_id: 102 42 | description: VLAN Interface - Guest 43 | ip_address: 172.16.102.3 44 | subnet_mask: 255.255.255.0 45 | prefix: 24 46 | area: 0 47 | - interface_type: vlan 48 | interface_id: 103 49 | description: VLAN Interface - Security 50 | ip_address: 172.16.103.3 51 | subnet_mask: 255.255.255.0 52 | prefix: 24 53 | area: 0 54 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/host_vars/172.16.30.103.yaml: -------------------------------------------------------------------------------- 1 | l3_interfaces: 2 | - interface_type: Loopback 3 | interface_id: 0 4 | description: Default Loopback 5 | ip_address: 192.168.0.2 6 | subnet_mask: 255.255.255.255 7 | prefix: 32 8 | area: 0 9 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/host_vars/172.16.30.111.yaml: -------------------------------------------------------------------------------- 1 | l3_interfaces: 2 | - interface_type: GigabitEthernet 3 | interface_id: 2 4 | description: L3 Link to nx-osv9000-1 5 | ip_address: 172.16.0.1 6 | subnet_mask: 255.255.255.252 7 | - interface_type: GigabitEthernet 8 | interface_id: 3 9 | description: L3 Link to nx-osv9000-2 10 | ip_address: 172.16.0.5 11 | subnet_mask: 255.255.255.252 12 | - interface_type: GigabitEthernet 13 | interface_id: 4 14 | description: L3 Link to ios-xev-2 15 | ip_address: 172.16.0.17 16 | subnet_mask: 255.255.255.252 17 | - interface_type: Loopback 18 | interface_id: 0 19 | description: Default Loopback 20 | ip_address: 192.168.1.1 21 | subnet_mask: 255.255.255.255 22 | ospf_router_id: 192.168.1.1 23 | ospf_networks: 24 | - network: 172.16.0.0 25 | mask: 0.0.0.3 26 | area: 0 27 | - network: 172.16.0.4 28 | mask: 0.0.0.3 29 | area: 0 30 | - network: 172.16.0.16 31 | mask: 0.0.0.3 32 | area: 0 33 | - network: 192.168.1.1 34 | mask: 0.0.0.0 35 | area: 0 36 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/host_vars/172.16.30.112.yaml: -------------------------------------------------------------------------------- 1 | l3_interfaces: 2 | - interface_type: GigabitEthernet 3 | interface_id: 2 4 | description: L3 Link to nx-osv9000-2 5 | ip_address: 172.16.0.13 6 | subnet_mask: 255.255.255.252 7 | - interface_type: GigabitEthernet 8 | interface_id: 3 9 | description: L3 Link to nx-osv9000-1 10 | ip_address: 172.16.0.9 11 | subnet_mask: 255.255.255.252 12 | - interface_type: GigabitEthernet 13 | interface_id: 4 14 | description: L3 Link to ios-xev-1 15 | ip_address: 172.16.0.18 16 | subnet_mask: 255.255.255.252 17 | - interface_type: Loopback 18 | interface_id: 0 19 | description: Default Loopback 20 | ip_address: 192.168.1.2 21 | subnet_mask: 255.255.255.255 22 | ospf_router_id: 192.168.1.2 23 | ospf_networks: 24 | - network: 172.16.0.12 25 | mask: 0.0.0.3 26 | area: 0 27 | - network: 172.16.0.8 28 | mask: 0.0.0.3 29 | area: 0 30 | - network: 172.16.0.16 31 | mask: 0.0.0.3 32 | area: 0 33 | - network: 192.168.1.2 34 | mask: 0.0.0.0 35 | area: 0 36 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/hosts: -------------------------------------------------------------------------------- 1 | [all:vars] 2 | ansible_python_interpreter="/usr/bin/env python" 3 | 4 | [iosxe:children] 5 | core 6 | 7 | [nxos:children] 8 | distribution 9 | access 10 | 11 | [core] 12 | 172.16.30.111 13 | 172.16.30.112 14 | 15 | [distribution] 16 | 172.16.30.101 17 | 172.16.30.102 18 | 19 | [access] 20 | 172.16.30.103 21 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/network_deploy.yaml: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # Learning Series: Network Programmability Basics 3 | # Module: NetDevOps 4 | # Lesson: Ansible Part 2: Using Ansible for Network Configuration 5 | # Author: Hank Preston 6 | # 7 | # Illustrate the following concepts: 8 | # - 9 | ############################################################## 10 | --- 11 | - name: Enable Model Driven Programmability (NETCONF) on IOS-XE 12 | hosts: iosxe 13 | 14 | # Ansible added new connection options for networking devices 15 | # to replace connection: local 16 | # Now connection: network_cli or httpapi are recommended 17 | # Doc: https://docs.ansible.com/ansible/2.9/network/user_guide/platform_nxos.html 18 | connection: network_cli 19 | gather_facts: false 20 | 21 | roles: 22 | - iosxe_mdp 23 | 24 | - name: Enable NX-API on NX-OS 25 | hosts: nxos 26 | connection: network_cli 27 | gather_facts: false 28 | 29 | roles: 30 | - nxos_nxapi 31 | 32 | - name: Configure Network Core 33 | hosts: core 34 | connection: netconf 35 | gather_facts: false 36 | 37 | roles: 38 | - netconf_l3_interfaces 39 | - netconf_ospf 40 | 41 | - name: Configure Distribution Switches 42 | hosts: distribution 43 | connection: network_cli 44 | gather_facts: false 45 | 46 | roles: 47 | - nxos_vlans 48 | - nxos_vpc 49 | - nxos_vpc_trunks 50 | - nxos_l3_interfaces 51 | - nxos_hsrp 52 | - nxos_ospf 53 | 54 | - name: Configure Access Switches 55 | hosts: access 56 | connection: network_cli 57 | gather_facts: false 58 | 59 | roles: 60 | - nxos_vlans 61 | - nxos_l3_interfaces 62 | - nxos_po_trunks 63 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/other_vars/vlans.yaml: -------------------------------------------------------------------------------- 1 | vlans: 2 | - id: 100 3 | name: Management 4 | gateway: 172.20.100.1 5 | - id: 101 6 | name: Private 7 | gateway: 172.20.101.1 8 | - id: 102 9 | name: Guest 10 | gateway: 172.20.102.1 11 | - id: 103 12 | name: Security 13 | gateway: 172.20.103.1 14 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/requirements.txt: -------------------------------------------------------------------------------- 1 | ansible==2.9.16 2 | ncclient>=0.6.9 3 | paramiko==2.7.2 4 | requests>=2.25.1 5 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/roles/iosxe_mdp/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # Learning Series: Network Programmability Basics 3 | # Module: NetDevOps 4 | # Lesson: Ansible Part 3: Your Network as Code 5 | # Author: Hank Preston 6 | # 7 | # Illustrate the following concepts: 8 | # - 9 | # 10 | # Note: This file has been updated to leverage the network_cli 11 | # connection method. This is an update from the original 12 | # version which is used in videos. 13 | ############################################################## 14 | --- 15 | - name: Configure NETCONF 16 | tags: [api, netconf] 17 | ios_config: 18 | lines: 19 | # Note: Due to problem with older IOS XE Self Signed certs expiring 20 | # on Jan 1, 2020, manually changing time on routers to allow certs 21 | # to remain valid. 22 | # Info: https://www.cisco.com/c/en/us/support/docs/security-vpn/public-key-infrastructure-pki/215118-ios-self-signed-certificate-expiration-o.html#anc9 23 | # This is only needed because Sandbox used has IOS XE 16.8.1a deployed. 24 | # newer CSR images would NOT need this fix. 25 | - do clock set 10:00:00 1 Dec 2019 26 | - netconf-yang 27 | - netconf-yang cisco-odm polling-enable 28 | # - restconf 29 | # - ip http server 30 | # - ip http secure-server 31 | 32 | - name: Pause for NETCONF to start 33 | pause: 34 | seconds: 45 35 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/roles/iosxe_mdp/vars/main.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/netprog_basics/a8c75a16c30889f723d094e8df0bb5decb06f0f7/netdevops/ansible_part_3/roles/iosxe_mdp/vars/main.yaml -------------------------------------------------------------------------------- /netdevops/ansible_part_3/roles/netconf_l3_interfaces/files/ietf_interface_template.j2: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{item.interface_type}}{{item.interface_id}} 5 | {{item.description}} 6 | {% if item.interface_type == "Loopback" %} 7 | ianaift:softwareLoopback 8 | {% else %} 9 | ianaift:ethernetCsmacd 10 | {% endif %} 11 | true 12 | 13 |
14 | {{item.ip_address}} 15 | {{item.subnet_mask}} 16 |
17 |
18 |
19 |
20 |
21 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/roles/netconf_l3_interfaces/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # Learning Series: Network Programmability Basics 3 | # Module: NetDevOps 4 | # Lesson: Ansible Part 3: Your Network as Code 5 | # Author: Hank Preston 6 | # 7 | # Illustrate the following concepts: 8 | # - 9 | ############################################################## 10 | --- 11 | - name: "Generate NETCONF Interface config" 12 | tags: [api, netconf, layer3] 13 | loop: "{{l3_interfaces}}" 14 | template: 15 | src: "files/ietf_interface_template.j2" 16 | dest: "./configs/{{inventory_hostname}}-{{item.interface_type}}{{item.interface_id}}.xml" 17 | 18 | - name: Configure Interfaces with NETCONF 19 | tags: [api, netconf, layer3] 20 | loop: "{{l3_interfaces}}" 21 | loop_control: 22 | pause: 2 23 | netconf_config: 24 | host: "{{inventory_hostname}}" 25 | hostkey_verify: false 26 | src: "./configs/{{inventory_hostname}}-{{item.interface_type}}{{item.interface_id}}.xml" 27 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/roles/netconf_l3_interfaces/vars/main.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/netprog_basics/a8c75a16c30889f723d094e8df0bb5decb06f0f7/netdevops/ansible_part_3/roles/netconf_l3_interfaces/vars/main.yaml -------------------------------------------------------------------------------- /netdevops/ansible_part_3/roles/netconf_ospf/files/ned_ospf.j2: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ ospf.process_id }} 6 | {{ ospf_router_id }} 7 | {% for network in ospf_networks %} 8 | 9 | {{ network.network }} 10 | {{ network.mask }} 11 | {{ network.area }} 12 | 13 | {% endfor %} 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/roles/netconf_ospf/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # Learning Series: Network Programmability Basics 3 | # Module: NetDevOps 4 | # Lesson: Ansible Part 3: Your Network as Code 5 | # Author: Hank Preston 6 | # 7 | # Illustrate the following concepts: 8 | # - 9 | ############################################################## 10 | --- 11 | - name: "Generate NETCONF OSPF config" 12 | tags: [api, netconf, ospf] 13 | template: 14 | src: "files/ned_ospf.j2" 15 | dest: "./configs/{{inventory_hostname}}-ospf.xml" 16 | 17 | - name: Configure OSPF with NETCONF 18 | tags: [api, netconf, ospf] 19 | netconf_config: 20 | host: "{{inventory_hostname}}" 21 | hostkey_verify: false 22 | src: "./configs/{{inventory_hostname}}-ospf.xml" 23 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/roles/netconf_ospf/vars/main.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/netprog_basics/a8c75a16c30889f723d094e8df0bb5decb06f0f7/netdevops/ansible_part_3/roles/netconf_ospf/vars/main.yaml -------------------------------------------------------------------------------- /netdevops/ansible_part_3/roles/nxos_hsrp/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # Learning Series: Network Programmability Basics 3 | # Module: NetDevOps 4 | # Lesson: Ansible Part 3: Your Network as Code 5 | # Author: Hank Preston 6 | # 7 | # Illustrate the following concepts: 8 | # - 9 | ############################################################## 10 | --- 11 | - name: Enable Features 12 | tags: [api, nxapi, hsrp] 13 | loop: 14 | - hsrp 15 | nxos_feature: 16 | feature: "{{ item }}" 17 | state: enabled 18 | 19 | - name: Configure HSRP 20 | tags: [api, nxapi, hsrp] 21 | loop: "{{ hsrp_interfaces }}" 22 | nxos_hsrp: 23 | group: "{{ item.group }}" 24 | vip: "{{ item.vip }}" 25 | interface: "{{ item.interface }}" 26 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/roles/nxos_hsrp/vars/main.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/netprog_basics/a8c75a16c30889f723d094e8df0bb5decb06f0f7/netdevops/ansible_part_3/roles/nxos_hsrp/vars/main.yaml -------------------------------------------------------------------------------- /netdevops/ansible_part_3/roles/nxos_l3_interfaces/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # Learning Series: Network Programmability Basics 3 | # Module: NetDevOps 4 | # Lesson: Ansible Part 3: Your Network as Code 5 | # Author: Hank Preston 6 | # 7 | # Illustrate the following concepts: 8 | # - 9 | ############################################################## 10 | --- 11 | - name: Enable Features 12 | tags: [api, nxapi, layer3] 13 | loop: 14 | - interface-vlan 15 | nxos_feature: 16 | feature: "{{ item }}" 17 | state: enabled 18 | 19 | - name: Configure Layer 3 Interfaces 20 | tags: [api, nxapi, layer3] 21 | loop: "{{ l3_interfaces }}" 22 | # Note: the nxos_interface module has been replaced with nxos_interfaces 23 | # and will be deprecated/removed soon. However the new nxos_interfaces 24 | # module has a bug in Ansible 2.9 when trying to create loopbacks or SVI. 25 | # Keeping this example using nxos_interface for now. 26 | # Info: 27 | # - https://docs.ansible.com/ansible/2.9/modules/nxos_interfaces_module.html 28 | # - https://docs.ansible.com/ansible/2.9/modules/nxos_interface_module.html 29 | nxos_interface: 30 | interface: "{{ item.interface_type }}{{ item.interface_id }}" 31 | mode: layer3 32 | description: "{{ item.description }}" 33 | admin_state: up 34 | 35 | - name: Configure IPv4 Address on Interface 36 | tags: [api, nxapi, layer3] 37 | loop: "{{ l3_interfaces }}" 38 | nxos_l3_interfaces: 39 | config: 40 | - name: "{{ item.interface_type }}{{ item.interface_id }}" 41 | ipv4: 42 | - address: "{{ item.ip_address }}/{{ item.prefix }}" 43 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/roles/nxos_l3_interfaces/vars/main.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/netprog_basics/a8c75a16c30889f723d094e8df0bb5decb06f0f7/netdevops/ansible_part_3/roles/nxos_l3_interfaces/vars/main.yaml -------------------------------------------------------------------------------- /netdevops/ansible_part_3/roles/nxos_nxapi/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # Learning Series: Network Programmability Basics 3 | # Module: NetDevOps 4 | # Lesson: Ansible Part 3: Your Network as Code 5 | # Author: Hank Preston 6 | # 7 | # Illustrate the following concepts: 8 | # - 9 | ############################################################## 10 | --- 11 | - name: Enable NX-API 12 | tags: [api, nxapi] 13 | nxos_feature: 14 | feature: nxapi 15 | state: enabled 16 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/roles/nxos_nxapi/vars/main.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/netprog_basics/a8c75a16c30889f723d094e8df0bb5decb06f0f7/netdevops/ansible_part_3/roles/nxos_nxapi/vars/main.yaml -------------------------------------------------------------------------------- /netdevops/ansible_part_3/roles/nxos_ospf/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # Learning Series: Network Programmability Basics 3 | # Module: NetDevOps 4 | # Lesson: Ansible Part 3: Your Network as Code 5 | # Author: Hank Preston 6 | # 7 | # Illustrate the following concepts: 8 | # - 9 | ############################################################## 10 | --- 11 | - name: Enable Features 12 | tags: [api, nxapi, ospf] 13 | loop: 14 | - ospf 15 | nxos_feature: 16 | feature: "{{ item }}" 17 | state: enabled 18 | 19 | - name: Configure OSPF 20 | tags: [api, nxapi, ospf] 21 | nxos_ospf: 22 | ospf: "{{ ospf.process_id }}" 23 | state: present 24 | 25 | - name: Configure OSPF Interfaces 26 | tags: [api, nxapi, ospf] 27 | loop: "{{ ospf.networks }}" 28 | nxos_interface_ospf: 29 | interface: "{{ item.interface }}" 30 | ospf: "{{ ospf.process_id }}" 31 | area: "{{ item.area }}" 32 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/roles/nxos_ospf/vars/main.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/netprog_basics/a8c75a16c30889f723d094e8df0bb5decb06f0f7/netdevops/ansible_part_3/roles/nxos_ospf/vars/main.yaml -------------------------------------------------------------------------------- /netdevops/ansible_part_3/roles/nxos_po_trunks/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # Learning Series: Network Programmability Basics 3 | # Module: NetDevOps 4 | # Lesson: Ansible Part 3: Your Network as Code 5 | # Author: Hank Preston 6 | # 7 | # Illustrate the following concepts: 8 | # - 9 | ############################################################## 10 | --- 11 | - name: Enable Features 12 | tags: [api, nxapi, trunk, vlan] 13 | loop: 14 | - lacp 15 | nxos_feature: 16 | feature: "{{ item }}" 17 | state: enabled 18 | 19 | - name: Create Uplink Port Channel to Distribution 20 | tags: [api, nxapi, trunk, vlan] 21 | loop: "{{ uplinks }}" 22 | nxos_lag_interfaces: 23 | config: 24 | - name: "port-channel{{ item.port_channel_id }}" 25 | members: 26 | - member: "{{ item.members.0 }}" 27 | mode: active 28 | - member: "{{ item.members.1 }}" 29 | mode: active 30 | 31 | - name: Make Port Channel Layer 2 32 | tags: [api, nxapi, vpc] 33 | loop: "{{ uplinks }}" 34 | nxos_interfaces: 35 | config: 36 | - name: "port-channel{{ item.port_channel_id }}" 37 | enabled: true 38 | mode: layer2 39 | 40 | # BUG: The nxos_l2_interfaces module should be able to configure 41 | # an interface as a trunk. However testing showed it isn't working 42 | # in the current version of Ansible. Therefore the nxos_config module 43 | # is used here to configure correctly. 44 | - name: Configure Port Channel Trunk 45 | tags: [api, nxapi, vpc] 46 | loop: "{{ uplinks }}" 47 | nxos_config: 48 | lines: 49 | - switchport mode trunk 50 | parents: interface port-channel{{ item.port_channel_id }} 51 | 52 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/roles/nxos_po_trunks/vars/main.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/netprog_basics/a8c75a16c30889f723d094e8df0bb5decb06f0f7/netdevops/ansible_part_3/roles/nxos_po_trunks/vars/main.yaml -------------------------------------------------------------------------------- /netdevops/ansible_part_3/roles/nxos_vlans/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # Learning Series: Network Programmability Basics 3 | # Module: NetDevOps 4 | # Lesson: Ansible Part 3: Your Network as Code 5 | # Author: Hank Preston 6 | # 7 | # Illustrate the following concepts: 8 | # - 9 | ############################################################## 10 | --- 11 | # - name: Configure VLANs 12 | # tags: [api, nxapi, vlan] 13 | # loop: "{{ vlans }}" 14 | # nxos_vlan: 15 | # vlan_id: "{{ item.id }}" 16 | # name: "{{ item.name }}" 17 | 18 | - name: Configure VLANs 19 | tags: [api, nxapi, vlan] 20 | # Note: to stay consistent with the videos for the lesson, this playbook 21 | # uses the loop construct for configuring interfaces. The current module 22 | # does support multiple interfaces in one task execution, and that would 23 | # be a more efficient configuration. 24 | loop: "{{ vlans }}" 25 | # Note: the module nxos_vlan has been replaced with nxos_vlans in 26 | # recent versions of Ansible. 27 | nxos_vlans: 28 | config: 29 | - vlan_id: "{{ item.id }}" 30 | name: "{{ item.name }}" 31 | 32 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/roles/nxos_vlans/vars/main.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/netprog_basics/a8c75a16c30889f723d094e8df0bb5decb06f0f7/netdevops/ansible_part_3/roles/nxos_vlans/vars/main.yaml -------------------------------------------------------------------------------- /netdevops/ansible_part_3/roles/nxos_vpc/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # Learning Series: Network Programmability Basics 3 | # Module: NetDevOps 4 | # Lesson: Ansible Part 3: Your Network as Code 5 | # Author: Hank Preston 6 | # 7 | # Illustrate the following concepts: 8 | # - 9 | ############################################################## 10 | --- 11 | - name: Enable Features 12 | tags: [api, nxapi, vpc] 13 | loop: 14 | - vpc 15 | - lacp 16 | nxos_feature: 17 | feature: "{{ item }}" 18 | state: enabled 19 | 20 | - name: Configure VPC 21 | tags: [api, nxapi, vpc] 22 | nxos_vpc: 23 | domain: "{{ vpc.domain }}" 24 | pkl_src: "{{ vpc_pkl_src }}" 25 | pkl_dest: "{{ vpc_pkl_dest }}" 26 | pkl_vrf: "{{ vpc.pkl_vrf }}" 27 | peer_gw: true 28 | auto_recovery: true 29 | 30 | - name: Create Port Channel for VPC 31 | tags: [api, nxapi, vpc] 32 | nxos_lag_interfaces: 33 | config: 34 | - name: "port-channel{{ vpc.port_channel.id }}" 35 | members: 36 | - member: "{{ vpc.port_channel.members.0 }}" 37 | mode: active 38 | - member: "{{ vpc.port_channel.members.1 }}" 39 | mode: active 40 | 41 | - name: Make VPC Port Channel Layer 2 42 | tags: [api, nxapi, vpc] 43 | nxos_interfaces: 44 | config: 45 | - name: "port-channel{{ vpc.port_channel.id }}" 46 | description: "VPC PortChannel" 47 | enabled: true 48 | mode: layer2 49 | 50 | 51 | # BUG: The nxos_l2_interfaces module should be able to configure 52 | # an interface as a trunk. However testing showed it isn't working 53 | # in the current version of Ansible. Therefore the nxos_config module 54 | # is used here to configure correctly. 55 | - name: Configure VPC Port Channel Trunk 56 | tags: [api, nxapi, vpc] 57 | nxos_config: 58 | lines: 59 | - switchport mode trunk 60 | parents: interface port-channel{{ vpc.port_channel.id }} 61 | 62 | 63 | # BUG: This module SHOULD configure the interface as a trunk, 64 | # however it is NOT working. Therefore the above nxos_config 65 | # is used. This is left in the role for reference and possible 66 | # future updates. 67 | # - name: Configure VPC Port Channel Trunk 68 | # tags: [api, nxapi, vpc] 69 | # nxos_l2_interfaces: 70 | # config: 71 | # - name: "portchannel{{ vpc.port_channel.id }}" 72 | # trunk: 73 | # native_vlan: 1 74 | 75 | 76 | - name: Enable VPC Peer Link on port_channel 77 | tags: [api, nxapi, vpc] 78 | nxos_vpc_interface: 79 | portchannel: "{{ vpc.port_channel.id }}" 80 | peer_link: true 81 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/roles/nxos_vpc/vars/main.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/netprog_basics/a8c75a16c30889f723d094e8df0bb5decb06f0f7/netdevops/ansible_part_3/roles/nxos_vpc/vars/main.yaml -------------------------------------------------------------------------------- /netdevops/ansible_part_3/roles/nxos_vpc_trunks/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | ############################################################## 2 | # Learning Series: Network Programmability Basics 3 | # Module: NetDevOps 4 | # Lesson: Ansible Part 3: Your Network as Code 5 | # Author: Hank Preston 6 | # 7 | # Illustrate the following concepts: 8 | # - 9 | ############################################################## 10 | --- 11 | - name: Enable Features 12 | tags: [api, nxapi, vpc, vlan, trunks] 13 | loop: 14 | - vpc 15 | - lacp 16 | nxos_feature: 17 | feature: "{{ item }}" 18 | state: enabled 19 | 20 | - name: Create Port Channels for Access Switches 21 | tags: [api, nxapi, vpc, vlan, trunks] 22 | loop: "{{ trunks }}" 23 | nxos_lag_interfaces: 24 | config: 25 | - name: "port-channel{{ item.port_channel_id }}" 26 | members: 27 | - member: "{{ item.members.0 }}" 28 | mode: active 29 | 30 | - name: Make Port Channel Layer 2 31 | tags: [api, nxapi, vpc] 32 | loop: "{{ trunks }}" 33 | nxos_interfaces: 34 | config: 35 | - name: "port-channel{{ item.port_channel_id }}" 36 | enabled: true 37 | mode: layer2 38 | 39 | # BUG: The nxos_l2_interfaces module should be able to configure 40 | # an interface as a trunk. However testing showed it isn't working 41 | # in the current version of Ansible. Therefore the nxos_config module 42 | # is used here to configure correctly. 43 | - name: Configure Port Channel Trunk 44 | tags: [api, nxapi, vpc] 45 | loop: "{{ trunks }}" 46 | nxos_config: 47 | lines: 48 | - switchport mode trunk 49 | parents: interface port-channel{{ item.port_channel_id }} 50 | 51 | - name: Configure VPC for Trunks 52 | tags: [api, nxapi, vpc, vlan, trunks] 53 | loop: "{{ trunks }}" 54 | nxos_vpc_interface: 55 | portchannel: "{{ item.port_channel_id }}" 56 | vpc: "{{ item.port_channel_id }}" 57 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/roles/nxos_vpc_trunks/vars/main.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/netprog_basics/a8c75a16c30889f723d094e8df0bb5decb06f0f7/netdevops/ansible_part_3/roles/nxos_vpc_trunks/vars/main.yaml -------------------------------------------------------------------------------- /netdevops/ansible_part_3/virl_sbx_mgmt/node_console_info.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ''' 4 | This script returns the telnet console info for all nodes. 5 | ''' 6 | 7 | from time import sleep 8 | from virlutils import * 9 | 10 | 11 | if __name__ == "__main__": 12 | 13 | # Get simulation list 14 | nx_os_simulation = get_simulations() 15 | nx_os_simulation_name = nx_os_simulation.keys()[0] 16 | 17 | print("VIRL Simulation Name: {}\n".format(nx_os_simulation_name)) 18 | 19 | # Get Simulation Node List 20 | print("Retrieving Console Connection Details: ") 21 | nodes = get_nodes(nx_os_simulation_name) 22 | for node in nodes.keys(): 23 | console = get_node_console(nx_os_simulation_name, node) 24 | try: 25 | print(" Console to {} -> `telnet {} {}`".format(node, console["host"], console["console_port"])) 26 | except TypeError: 27 | pass 28 | 29 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/virl_sbx_mgmt/restart-sbx.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ''' 4 | This script stops, and then starts all the nodes in the 5 | sandbox using the VIRL APIs. 6 | ''' 7 | 8 | from time import sleep 9 | from virlutils import * 10 | from builtins import input 11 | import sys 12 | 13 | if __name__ == "__main__": 14 | 15 | # Get simulation list 16 | nx_os_simulation = get_simulations() 17 | nx_os_simulation_name = list(nx_os_simulation.keys())[0] 18 | 19 | print("VIRL Simulation Name: {}\n".format(nx_os_simulation_name)) 20 | 21 | # Get Simulation Node List and determine which to restart 22 | print("Which node would you like to restart?") 23 | nodes = get_nodes(nx_os_simulation_name) 24 | node_key = [] 25 | for i, node in enumerate(nodes.keys()): 26 | node_key.append(node) 27 | print(" {} - {}: Status {}".format(i, node, nodes[node]["state"])) 28 | print(" a - Restart All Nodes ") 29 | print("Enter 0 - {} to choose a node, or a for all".format(len(node_key)-1)) 30 | # Ask user which to start 31 | choice = input() 32 | 33 | # Validate Users Choice. 34 | try: 35 | if int(choice) not in range(0, len(node_key)-1): 36 | print("Invalid Choice") 37 | print(" Enter 0 - {} to choose a node, or a for all").format(len(node_key)-1) 38 | sys.exit(1) 39 | else: 40 | choice = int(choice) 41 | # A single node was picked, update working nodes dictionary 42 | nodes = {node_key[choice]: nodes[node_key[choice]]} 43 | except ValueError: 44 | # A non-Integer was entered, verify it was the letter "a". 45 | if str.lower(choice) != "a": 46 | print("Invalid Choice") 47 | print(" Enter 0 - {} to choose a node, or a for all").format(len(node_key)-1) 48 | sys.exit(1) 49 | 50 | 51 | # Stop Nodes 52 | print("Stopping Nodes") 53 | action = stop_nodes(nx_os_simulation_name, nodes) 54 | print(action["stopped"]) 55 | print("") 56 | 57 | # Wait for nodes to be fully stopped (state = ABSENT) 58 | while not test_node_state(nx_os_simulation_name, "ABSENT", test_nodes=nodes): 59 | print("Nodes not stopped yet") 60 | sleep(10) 61 | 62 | # Start Nodes 63 | print("Starting Nodes") 64 | action = start_nodes(nx_os_simulation_name, nodes) 65 | print(action["started"]) 66 | print("") 67 | 68 | # Wait for nodes to be fully started (state = ACTIVE) 69 | while not test_node_state(nx_os_simulation_name, "ACTIVE", test_nodes=nodes): 70 | print("Nodes not started yet") 71 | sleep(10) 72 | 73 | # Done 74 | print("Nodes have been restarted, however it can take up to 15 minutes for all switches to fully boot and be ready.") 75 | print("You can monitor the startup activity at: ") 76 | for node in nodes.keys(): 77 | console = get_node_console(nx_os_simulation_name, node) 78 | try: 79 | print(" Console to {} -> `telnet {} {}`".format(node, console["host"], console["console_port"])) 80 | except TypeError: 81 | pass 82 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/virl_sbx_mgmt/status-sbx.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ''' 4 | This script checks the status of all nodes 5 | sandbox using the VIRL APIs. 6 | ''' 7 | 8 | from time import sleep 9 | from virlutils import * 10 | 11 | 12 | if __name__ == "__main__": 13 | 14 | # Get simulation list 15 | nx_os_simulation = get_simulations() 16 | nx_os_simulation_name = list(nx_os_simulation.keys())[0] 17 | 18 | print("VIRL Simulation Name: {}\n".format(nx_os_simulation_name)) 19 | 20 | # Get Simulation Node List 21 | nodes = get_nodes(nx_os_simulation_name) 22 | for node in nodes.keys(): 23 | print("{}: Status {}".format(node, nodes[node]["state"])) 24 | print(" ") 25 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/virl_sbx_mgmt/virl_simulation_setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ''' 4 | ''' 5 | 6 | from time import sleep 7 | from virlutils import * 8 | 9 | 10 | if __name__ == "__main__": 11 | 12 | # Get simulation list 13 | nx_os_simulation = get_simulations() 14 | 15 | # See if a simulation is active 16 | if len(nx_os_simulation) > 0: 17 | nx_os_simulation_name = list(nx_os_simulation.keys())[0] 18 | 19 | print("Current VIRL Simulation Name: {}\n".format(nx_os_simulation_name)) 20 | print("Killing VIRL Simulation") 21 | print(kill_simulation(nx_os_simulation_name)) 22 | print("Waiting 20 seconds to clear simulation") 23 | sleep(20) 24 | print("") 25 | 26 | poap_virl_file = open("ansible_part_3.virl", "r") 27 | poap_sim_name = "ansible_part_3" 28 | 29 | print("Launching New Simulation") 30 | print(launch_simulation(poap_sim_name, poap_virl_file.read())) 31 | sleep(5) 32 | 33 | # Wait for nodes to be fully started (state = ACTIVE) 34 | while not test_node_state(poap_sim_name, "ACTIVE"): 35 | print(" Nodes not started yet") 36 | sleep(10) 37 | print("") 38 | 39 | # Print Console Information for Nodes 40 | print("Retrieving Console Connection Details: ") 41 | nodes = get_nodes(poap_sim_name) 42 | for node in nodes.keys(): 43 | console = get_node_console(poap_sim_name, node) 44 | try: 45 | print(" Console to {} -> `telnet {} {}`".format(node, console["host"], console["console_port"])) 46 | except TypeError: 47 | pass 48 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/virl_sbx_mgmt/virlutils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ''' 4 | Basic wrappers for the VIRL API 5 | ''' 6 | 7 | import requests 8 | 9 | simengine_host = "http://10.10.20.160:19399" 10 | virl_user = "guest" 11 | virl_password = "guest" 12 | 13 | 14 | def get_simulations(): 15 | u = simengine_host + "/simengine/rest/list" 16 | r = requests.get(u, auth=(virl_user, virl_password)) 17 | return r.json()["simulations"] 18 | 19 | def get_nodes(simulation): 20 | u = simengine_host + "/simengine/rest/nodes/{}".format(simulation) 21 | r = requests.get(u, auth=(virl_user, virl_password)) 22 | return r.json()[simulation] 23 | 24 | def stop_nodes(simulation, nodes): 25 | u = simengine_host + "/simengine/rest/update/{}/stop?".format(simulation) 26 | node_list = [] 27 | for node in nodes.keys(): 28 | node_list.append("nodes={}".format(node)) 29 | node_list = "&".join(node_list) 30 | u += node_list 31 | r = requests.put(u, auth=(virl_user, virl_password)) 32 | return r.json() 33 | 34 | def start_nodes(simulation, nodes): 35 | u = simengine_host + "/simengine/rest/update/{}/start?".format(simulation) 36 | node_list = [] 37 | for node in nodes.keys(): 38 | node_list.append("nodes={}".format(node)) 39 | node_list = "&".join(node_list) 40 | u += node_list 41 | r = requests.put(u, auth=(virl_user, virl_password)) 42 | return r.json() 43 | 44 | def test_node_state(simulation, target_state, test_nodes=None): 45 | nodes = get_nodes(simulation) 46 | if test_nodes == None: 47 | test_nodes = nodes 48 | for node in test_nodes.keys(): 49 | if not nodes[node]["state"] == target_state: 50 | return False 51 | return True 52 | 53 | def get_node_console(simulation, node): 54 | node_key = "guest|{}|virl|{}".format(simulation, node) 55 | u = simengine_host + "/roster/rest" 56 | r = requests.get(u, auth=(virl_user, virl_password)) 57 | roster = r.json() 58 | for node in roster.keys(): 59 | if node == node_key: 60 | try: 61 | return {"host": roster[node]["SimulationHost"], "console_port": roster[node]["PortConsole"]} 62 | except KeyError: 63 | pass 64 | 65 | def kill_simulation(simulation): 66 | u = simengine_host + "/simengine/rest/stop/{}".format(simulation) 67 | r = requests.get(u, auth=(virl_user, virl_password)) 68 | return "{} {}".format(r.status_code, r.text) 69 | 70 | def launch_simulation(simulation_name, simulation_data): 71 | u = simengine_host + "/simengine/rest/launch?session={}".format(simulation_name) 72 | headers = {"Content-Type": "text/xml;charset=UTF-8"} 73 | r = requests.post(u, auth=(virl_user, virl_password), headers = headers, data = simulation_data) 74 | return "{} {}".format(r.status_code, r.text) 75 | 76 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/virl_sbx_mgmt/vpn_close.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | echo "Step 2: Killing VPN Connection to Pod" 4 | OCPID=$(cat openconnect_pid.txt) 5 | kill ${OCPID} 6 | rm openconnect_pid.txt 7 | -------------------------------------------------------------------------------- /netdevops/ansible_part_3/virl_sbx_mgmt/vpn_setup.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | echo " This script establishes VPN connection to Sandbox " 4 | echo " and must be run with 'sudo'." 5 | echo " " 6 | 7 | echo "What is your assigned Pod Number? (ie 1, 2, 3, etc)" 8 | read DEVNUMBER 9 | 10 | # echo "What is the VPN Password? (Instructor will provide)" 11 | # read VPNPASSWORD 12 | 13 | # VPN User Account 14 | VPNUSER=hapresto-perm 15 | VPNPASSWORD=Cisco1234! 16 | 17 | echo "Setting up for Pod 'rave${DEVNUMBER}'. Is this correct? y/n" 18 | read CONFIRM 19 | 20 | if [${CONFIRM} != "y"] 21 | then 22 | echo "Canceling setup" 23 | exit 1 24 | fi 25 | 26 | echo "Step 2: Establish VPN Connection to Pod" 27 | echo "${VPNPASSWORD}" | \ 28 | openconnect -u ${VPNUSER} \ 29 | -b \ 30 | --pid-file openconnect_pid.txt \ 31 | --passwd-on-stdin \ 32 | --no-dtls \ 33 | --servercert sha256:1795855fced9de6659b8fe18cb293a22ed1f2717da581daa8c9439c126961a80 \ 34 | devnetsandboxlabs.cisco.com/rave${DEVNUMBER} 35 | 36 | echo "Step 3: Verify DevBox Accessible" 37 | ping -c 4 10.10.20.20 38 | if [ $? -ne 0 ] 39 | then 40 | echo "DevBox Unavailable." 41 | echo "Please ensure active and then click anykey to continue" 42 | read CONFIRM 43 | echo "Testing Connectivity to DevBox." 44 | ping -c 4 10.10.20.20 45 | if [ $? -ne 0 ] 46 | then 47 | echo "DevBox Unavailable. Killing VPN connection and stopping setup." 48 | OCPID=$(cat openconnect_pid.txt) 49 | kill ${OCPID} 50 | fi 51 | fi 52 | 53 | echo "Lab VPN Connection Successful." 54 | -------------------------------------------------------------------------------- /netdevops/intro/README.md: -------------------------------------------------------------------------------- 1 | # Configuration Management and the Network 2 | ## Local Setup 3 | This lesson has no setup requirements. 4 | 5 | ## Download Slides 6 | 7 | You can download the slides for this lesson [here](https://developer.cisco.com/fileMedia/download/d7833ac8-be49-379d-b7d6-04d4a39b67be). 8 | 9 | > *Suggestion: Right click, "Open in new tab"* -------------------------------------------------------------------------------- /network_controllers/README.md: -------------------------------------------------------------------------------- 1 | # Network Controllers 2 | In this module you will explore different APIs for interacting with different network controllers. 3 | 4 | ## Lessons 5 | 6 | * [Program your own DNA with APIC-EM APIs](apicem/README.md) 7 | * [Got SDN? Understanding the ACI Programmability Options](aci/README.md) 8 | * [Network Control in the Cloud - Developing with Cisco Meraki](meraki/README.md) 9 | * [DNA APIs Part 1: Exploring APIC-EM Apps via API](apicem/README.md) 10 | * [DNA APIs Part 2: Troubleshooting with APIC-EM Programmability](apicem/README.md) 11 | * [ACI Programmability Part 1: The ACI Object Model](aci/README.md) 12 | * [ACI Programmability Part 2: Using the ACI Toolkit](aci/README.md) 13 | -------------------------------------------------------------------------------- /network_controllers/aci/device_info.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Author: Hank Preston 5 | 6 | device_info.py 7 | Illustrate the following concepts: 8 | - Store device info for Sandbox Infrastructure used 9 | in examples 10 | """ 11 | 12 | __author__ = "Hank Preston" 13 | __author_email__ = "hapresto@cisco.com" 14 | __copyright__ = "Copyright (c) 2016 Cisco Systems, Inc." 15 | __license__ = "MIT" 16 | 17 | # DevNet Always-On NETCONF/YANG & RESTCONF Sandbox Device 18 | # https://devnetsandbox.cisco.com/RM/Diagram/Index/27d9747a-db48-4565-8d44-df318fce37ad?diagramType=Topology 19 | ios_xe1 = { 20 | "address": "ios-xe-mgmt.cisco.com", 21 | "port": 10000, 22 | "username": "root", 23 | "password": "D_Vay!_10&" 24 | } 25 | 26 | # DevNet IOS XE Programmability Sandbox Device 27 | # https://devnetsandbox.cisco.com/RM/Diagram/Index/7fd27b24-7034-477d-9ad2-e2c8096dd1a5?diagramType=Topology 28 | ios_xe2 = { 29 | "address": "10.10.20.21", 30 | "port": 830, 31 | "username": "root", 32 | "password": "cisco123" 33 | } 34 | 35 | 36 | # DevNet Always-On Sandbox APIC-EM 37 | # https://devnetsandbox.cisco.com/RM/Diagram/Index/2e0f9525-5f46-4f46-973e-0f0c1bf934fa?diagramType=Topology 38 | apicem = { 39 | "host": "sandboxapicem.cisco.com", 40 | "username": "devnetuser", 41 | "password": "Cisco123!", 42 | "port": 443 43 | } 44 | 45 | # DevNet Always-On Sandbox ACI APIC 46 | # https://devnetsandbox.cisco.com/RM/Diagram/Index/5a229a7c-95d5-4cfd-a651-5ee9bc1b30e2?diagramType=Topology 47 | apic = { 48 | "host": "https://sandboxapicdc.cisco.com", 49 | "username": "admin", 50 | "password": "ciscopsdt", 51 | "port": 443 52 | } 53 | 54 | -------------------------------------------------------------------------------- /network_controllers/aci/requirements.txt: -------------------------------------------------------------------------------- 1 | acicobra 2 | acitoolkit 3 | graphviz>=0.16 4 | requests>=2.25.1 5 | -------------------------------------------------------------------------------- /network_controllers/aci/toolkit_getting_started.py: -------------------------------------------------------------------------------- 1 | ! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Module: Network Controllers 5 | Lesson: ACI Programmability Part 2 6 | Author: Hank Preston 7 | 8 | toolkit_getting_started.py 9 | Illustrate the following concepts: 10 | - Import ACI Toolkit library 11 | - Connect to APIC Controller 12 | - Print list of tenants 13 | - Intended to be entered into an interactive 14 | interpreter 15 | """ 16 | 17 | from device_info import apic 18 | from acitoolkit.acitoolkit import * 19 | 20 | session = Session(apic['host'], 21 | apic['username'], 22 | apic['password']) 23 | session.login() 24 | session.logged_in() 25 | 26 | tenants = Tenant.get(session) 27 | 28 | for tenant in tenants: 29 | print(tenant.name) 30 | if tenant.name == "Heroes": 31 | heroe_tenant = tenant 32 | -------------------------------------------------------------------------------- /network_controllers/aci/toolkit_new_policy.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Module: Network Controllers 5 | Lesson: ACI Programmability Part 2 6 | Author: Hank Preston 7 | 8 | toolkit_new_policy.py 9 | Illustrate the following concepts: 10 | - Create Complete Application Policy using ACI Toolkit 11 | - Intended to be entered into an interactive 12 | interpreter 13 | """ 14 | 15 | # Import modules 16 | from device_info import apic 17 | from acitoolkit.acitoolkit import * 18 | from pprint import pprint 19 | 20 | # Establish Session Object and Log into APIC 21 | session = Session(apic['host'], 22 | apic['username'], 23 | apic['password']) 24 | session.login() 25 | session.logged_in() 26 | 27 | # Create New Tenant and Main Network Object 28 | my_tenant = Tenant("Hanks_Tenant") 29 | my_tenant.get_json() 30 | my_vrf = Context("Hanks_VRF", my_tenant) 31 | my_bd = BridgeDomain("Hanks_BD", my_tenant) 32 | my_tenant.get_json() 33 | pprint(my_tenant.get_json()) 34 | 35 | # Configure Bridge Domain Properties 36 | my_bd.add_context(my_vrf) 37 | my_subnet = Subnet("Hanks_Subnet", my_bd) 38 | my_subnet.set_scope("public") 39 | my_subnet.set_addr("10.10.10.1/24") 40 | 41 | # Create Application Profile and EPGs 42 | my_app = AppProfile("Hanks_App", my_tenant) 43 | my_epg = EPG("Hanks_EPG", my_app) 44 | my_epg.add_bd(my_bd) 45 | 46 | # Create Security Policy Elements 47 | # Create new Filter 48 | filter_web = Filter("web", my_tenant) 49 | 50 | FilterEntry("tcp-80", filter_web, 51 | etherT="ip", prot="tcp", 52 | dFromPort="http", dToPort="http") 53 | 54 | FilterEntry("tcp-443", filter_web, 55 | etherT="ip", prot="tcp", 56 | dFromPort="https", dToPort="https") 57 | 58 | # Create New Contract 59 | contract_web = Contract("web", my_tenant) 60 | contract_subject_web= ContractSubject("web", contract_web) 61 | 62 | # Add Filter to Contract 63 | contract_subject_web.add_filter(filter_web) 64 | 65 | # Add Contract to EPG 66 | my_epg.provide(contract_web) 67 | 68 | # Review the ACI Object Definition created 69 | pprint(my_tenant.get_json()) 70 | 71 | # Push configuration to APIC 72 | response = session.push_to_apic( 73 | my_tenant.get_url(), 74 | data=my_tenant.get_json() 75 | ) 76 | 77 | # View Status 78 | response.status_code 79 | response.reason 80 | 81 | # Check in APIC GUI 82 | 83 | # Delete Tenant 84 | my_tenant.mark_as_deleted() 85 | pprint(my_tenant.get_json()) 86 | 87 | response = session.push_to_apic( 88 | my_tenant.get_url(), 89 | data=my_tenant.get_json() 90 | ) 91 | 92 | # Check in APIC GUI 93 | -------------------------------------------------------------------------------- /network_controllers/apicem/README.md: -------------------------------------------------------------------------------- 1 | # Programming APIC-EM Lessons 2 | 3 | * **Program your own DNA with APIC-EM APIs** 4 | * **DNA APIs Part 1: Exploring APIC-EM Apps via API** 5 | * **DNA APIs Part 2: Troubleshooting with APIC-EM Programmability** 6 | 7 | ## "Gitting" the Code 8 | All of the code and examples for this lesson is located in the `netprog_basics/network_controllers/apicem` directory. Clone and access it with the following commands: 9 | 10 | ```bash 11 | git clone https://github.com/CiscoDevNet/netprog_basics 12 | cd netprog_basics/network_controllers/apicem 13 | ``` 14 | 15 | ## Local Workstation Setup 16 | Be sure to complete the [General Workstation Setup](https://github.com/CiscoDevNet/netprog_basics/blob/master/readme_resources/workstation_setup.md) instructions before beginning this lesson. 17 | 18 | ### Postman Setup 19 | During this lesson the Postman client for making REST API calls is used. For convenience we have included a `postman_collection.json` file that contains all the REST API calls leveraged in the different lessons, and `postman_environment.json` files for each of the DevNet Sandboxes leveraged across the lessons. These files are all located in the [postman_config](https://github.com/CiscoDevNet/netprog_basics/tree/master/postman_config) directory in the code repository. 20 | 21 | To leverage them, simply `Import` them into your Postman client. 22 | 23 | 1. Collections: Use the **Import** button in the upper left corner of the client. 24 | 2. Environments: Use the **Import** button from the `Manage Environments` interface of the client. 25 | 26 | > Reminder: Many network devices leverage self-signed certificates for `https://` APIs. Don't forget to turn **OFF** SSL certificate checking within Postman settings. 27 | 28 | ### Python Environment Setup 29 | It is recommended that this lesson be completed using Python 3.8. Other versions of Python 3 should also work. 30 | 31 | > **Note about Python 2:** Python 2 was [sunset](https://www.python.org/doc/sunset-python-2/) by Python Software Foundation on January 1, 2020. This means that no more updates to Python 2 are being worked on, including security updates. Python 3 is now the recommended version of Python for everyone to use. Most Python developers of software, packages, and scripts have migrated to Python 3 already, however you may find some older scripts and tools that are no longer maintained that only work with Python 2. 32 | > 33 | > You may see/hear references to Python 2 within the videos in this course from before January 2020, however all examples scripts and demos available in the GitHub repo to run have been updated to leverage Python 3. 34 | 35 | It is highly recommended to leverage Python Virtual Environments for completing exercises in this course. 36 | 37 | *There is no need to create independent venv for each lesson, but you can if you choose.* 38 | 39 | Follow these steps to create and activate a venv. 40 | 41 | ***Note: If you are leveraging a shared venv across all lessons simply activate it.*** 42 | 43 | ```bash 44 | # OS X or Linux 45 | python3 -m venv venv 46 | source venv/bin/activate 47 | ``` 48 | 49 | ```bash 50 | # Windows 51 | python -m venv venv 52 | venv/Scripts/activate 53 | ``` 54 | 55 | #### Install Python Requirements for Lesson 56 | With the Virtual Environment activated, use pip to install the necessary requirements. 57 | 58 | ```bash 59 | # From the code directory for this lesson 60 | pip install -r requirements.txt 61 | ``` 62 | 63 | ## DevNet Sandbox 64 | This lesson leverages the [Always On: APIC-EM](https://devnetsandbox.cisco.com/RM/Diagram/Index/2e0f9525-5f46-4f46-973e-0f0c1bf934fa?diagramType=Topology) Sandbox. This sandbox requires no reservation **or** VPN connection. 65 | -------------------------------------------------------------------------------- /network_controllers/apicem/device_info.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Author: Hank Preston 5 | 6 | device_info.py 7 | Illustrate the following concepts: 8 | - Store device info for Sandbox Infrastructure used 9 | in examples 10 | """ 11 | 12 | __author__ = "Hank Preston" 13 | __author_email__ = "hapresto@cisco.com" 14 | __copyright__ = "Copyright (c) 2016 Cisco Systems, Inc." 15 | __license__ = "MIT" 16 | 17 | # DevNet Always-On NETCONF/YANG & RESTCONF Sandbox Device 18 | # https://devnetsandbox.cisco.com/RM/Diagram/Index/27d9747a-db48-4565-8d44-df318fce37ad?diagramType=Topology 19 | ios_xe1 = { 20 | "address": "ios-xe-mgmt.cisco.com", 21 | "port": 10000, 22 | "username": "root", 23 | "password": "D_Vay!_10&" 24 | } 25 | 26 | # DevNet IOS XE Programmability Sandbox Device 27 | # https://devnetsandbox.cisco.com/RM/Diagram/Index/7fd27b24-7034-477d-9ad2-e2c8096dd1a5?diagramType=Topology 28 | ios_xe2 = { 29 | "address": "10.10.20.21", 30 | "port": 830, 31 | "username": "root", 32 | "password": "cisco123" 33 | } 34 | 35 | 36 | # DevNet Always-On Sandbox APIC-EM 37 | # https://devnetsandbox.cisco.com/RM/Diagram/Index/2e0f9525-5f46-4f46-973e-0f0c1bf934fa?diagramType=Topology 38 | apicem = { 39 | "host": "sandboxapicem.cisco.com", 40 | "username": "devnetuser", 41 | "password": "Cisco123!", 42 | "port": 443 43 | } 44 | 45 | # DevNet Always-On Sandbox ACI APIC 46 | # https://devnetsandbox.cisco.com/RM/Diagram/Index/5a229a7c-95d5-4cfd-a651-5ee9bc1b30e2?diagramType=Topology 47 | apic = { 48 | "host": "https://sandboxapicdc.cisco.com", 49 | "username": "admin", 50 | "password": "ciscopsdt", 51 | "port": 443 52 | } 53 | 54 | -------------------------------------------------------------------------------- /network_controllers/apicem/example1.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Module: Network Controllers 5 | Lesson: Program your own DNA with APIC-EM APIs 6 | Author: Hank Preston 7 | 8 | example1.py 9 | Illustrate the following concepts: 10 | - Building APIC-EM API Code 11 | - Start from Postman Auto-generated code 12 | - Multiple requests in one script 13 | """ 14 | 15 | __author__ = "Hank Preston" 16 | __author_email__ = "hapresto@cisco.com" 17 | __copyright__ = "Copyright (c) 2016 Cisco Systems, Inc." 18 | __license__ = "MIT" 19 | 20 | from device_info import apicem 21 | import requests 22 | import json 23 | 24 | headers = { 25 | 'content-type': "application/json", 26 | 'x-auth-token': "" 27 | } 28 | 29 | def apic_login(host, username, password): 30 | """ 31 | Use the REST API to Log into an APIC-EM and retrieve ticket 32 | """ 33 | url = "https://{}/api/v1/ticket".format(host) 34 | payload = {"username": username, "password": password} 35 | 36 | # Make Login request and return the response body 37 | response = requests.request("POST", url, data=json.dumps(payload), 38 | headers=headers, verify=False) 39 | return response.json()["response"] 40 | 41 | 42 | def network_device_list(host, ticket): 43 | """ 44 | Use the REST API to retrieve the list of network devices 45 | """ 46 | url = "https://{}/api/v1/network-device".format(host) 47 | headers["x-auth-token"] = ticket 48 | 49 | # Make API request and return the response body 50 | response = requests.request("GET", url, headers=headers, verify=False) 51 | return response.json()["response"] 52 | 53 | 54 | # Entry point for program 55 | if __name__ == '__main__': 56 | # Log into the APIC-EM Controller to get Ticket 57 | login = apic_login(apicem["host"], apicem["username"], apicem["password"]) 58 | 59 | # Get the list of devices 60 | devices = network_device_list(apicem["host"], login["serviceTicket"]) 61 | 62 | # Loop through the devices and print details 63 | for device in devices: 64 | print("{} in family {}".format(device["hostname"], device["family"])) 65 | print(" Management IP: {}".format(device["managementIpAddress"])) 66 | print(" Platform Type: {}".format(device["platformId"])) 67 | print(" Software Version: {}".format(device["softwareVersion"])) 68 | print("") 69 | -------------------------------------------------------------------------------- /network_controllers/apicem/requirements.txt: -------------------------------------------------------------------------------- 1 | requests>=2.20.0 2 | -------------------------------------------------------------------------------- /network_controllers/apicem/troubleshoot_prep.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Module: Network Controllers 5 | Lesson: Program your own DNA with APIC-EM APIs 6 | Author: Hank Preston 7 | 8 | troubleshoot_full.py 9 | Illustrate the following concepts: 10 | - Automating common information gathering used in troubleshooting 11 | - Replicating "runbook logic" in code 12 | - Leveraging REST APIs in Python 13 | - Using details from one request in the next 14 | """ 15 | 16 | __author__ = "Hank Preston" 17 | __author_email__ = "hapresto@cisco.com" 18 | __copyright__ = "Copyright (c) 2016 Cisco Systems, Inc." 19 | __license__ = "MIT" 20 | 21 | from device_info import apicem 22 | from time import sleep 23 | import json 24 | import requests 25 | import sys 26 | import urllib3 27 | 28 | # Silence the insecure warning due to SSL Certificate 29 | urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) 30 | 31 | headers = { 32 | 'content-type': "application/json", 33 | 'x-auth-token': "" 34 | } 35 | 36 | 37 | def apic_login(apic, username, password): 38 | """ 39 | Use the REST API to Log into an APIC-EM and retrieve ticket 40 | """ 41 | url = "https://{}/api/v1/ticket".format(apic) 42 | payload = {"username": username, "password": password} 43 | 44 | # Make Login request and return the response body 45 | response = requests.request("POST", url, data=json.dumps(payload), 46 | headers=headers, verify=False) 47 | return response.json()["response"] 48 | 49 | 50 | # Entry point for program 51 | if __name__ == '__main__': 52 | # Setup Arg Parse for Command Line parameters 53 | import argparse 54 | parser = argparse.ArgumentParser() 55 | 56 | # Command Line Parameters for Source and Destination IP 57 | parser.add_argument("source_ip", help = "Source IP Address") 58 | parser.add_argument("destination_ip", help = "Destination IP Address") 59 | args = parser.parse_args() 60 | 61 | # Get Source and Destination IPs from Command Line 62 | source_ip = args.source_ip 63 | destination_ip = args.destination_ip 64 | 65 | # Print Starting message 66 | print("Running Troubleshooting Script for ") 67 | print(" Source IP: {} ".format(source_ip)) 68 | print(" Destination IP: {}".format(destination_ip)) 69 | print("") 70 | 71 | # Log into the APIC-EM Controller to get Ticket 72 | login = apic_login(apicem["host"], apicem["username"], apicem["password"]) 73 | -------------------------------------------------------------------------------- /network_controllers/dnac/device_info.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Author: Hank Preston 5 | 6 | device_info.py 7 | Illustrate the following concepts: 8 | - Store device info for Sandbox Infrastructure used 9 | in examples 10 | """ 11 | 12 | __author__ = "Hank Preston" 13 | __author_email__ = "hapresto@cisco.com" 14 | __copyright__ = "Copyright (c) 2016 Cisco Systems, Inc." 15 | __license__ = "MIT" 16 | 17 | # DevNet Always-On NETCONF/YANG & RESTCONF Sandbox Device 18 | # https://devnetsandbox.cisco.com/RM/Diagram/Index/27d9747a-db48-4565-8d44-df318fce37ad?diagramType=Topology 19 | ios_xe1 = { 20 | "address": "ios-xe-mgmt.cisco.com", 21 | "port": 10000, 22 | "username": "root", 23 | "password": "D_Vay!_10&" 24 | } 25 | 26 | # DevNet IOS XE Programmability Sandbox Device 27 | # https://devnetsandbox.cisco.com/RM/Diagram/Index/7fd27b24-7034-477d-9ad2-e2c8096dd1a5?diagramType=Topology 28 | ios_xe2 = { 29 | "address": "10.10.20.21", 30 | "port": 830, 31 | "username": "root", 32 | "password": "cisco123" 33 | } 34 | 35 | 36 | # DevNet Always-On Sandbox APIC-EM 37 | # https://devnetsandbox.cisco.com/RM/Diagram/Index/2e0f9525-5f46-4f46-973e-0f0c1bf934fa?diagramType=Topology 38 | apicem = { 39 | "host": "sandboxapicem.cisco.com", 40 | "username": "devnetuser", 41 | "password": "Cisco123!", 42 | "port": 443 43 | } 44 | 45 | # DevNet Always-On Sandbox ACI APIC 46 | # https://devnetsandbox.cisco.com/RM/Diagram/Index/5a229a7c-95d5-4cfd-a651-5ee9bc1b30e2?diagramType=Topology 47 | apic = { 48 | "host": "https://sandboxapicdc.cisco.com", 49 | "username": "admin", 50 | "password": "ciscopsdt", 51 | "port": 443 52 | } 53 | 54 | # DevNet Always-On Sandbox DNA Center 55 | # https://devnetsandbox.cisco.com/RM/Diagram/Index/471eb739-323e-4805-b2a6-d0ec813dc8fc?diagramType=Topology 56 | dnac = { 57 | "host": "sandboxdnac2.cisco.com", 58 | "username": "devnetuser", 59 | "password": "Cisco123!", 60 | "port": 443 61 | } 62 | -------------------------------------------------------------------------------- /network_controllers/dnac/device_list.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Module: Network Controllers 5 | Lesson: Program your own DNA with DNA Center APIs 6 | Author: Hank Preston 7 | 8 | example1.py 9 | Illustrate the following concepts: 10 | - Building DNA Center API Code 11 | - Start from Postman Auto-generated code 12 | - Multiple requests in one script 13 | """ 14 | 15 | __author__ = "Hank Preston" 16 | __author_email__ = "hapresto@cisco.com" 17 | __copyright__ = "Copyright (c) 2016 Cisco Systems, Inc." 18 | __license__ = "MIT" 19 | 20 | from device_info import dnac 21 | import requests 22 | import json 23 | import urllib3 24 | 25 | # Silence the insecure warning due to SSL Certificate 26 | urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) 27 | 28 | 29 | headers = { 30 | 'content-type': "application/json", 31 | 'x-auth-token': "" 32 | } 33 | 34 | def dnac_login(host, username, password): 35 | """ 36 | Use the REST API to Log into an DNA Center and retrieve ticket 37 | """ 38 | url = "https://{}/api/system/v1/auth/token".format(host) 39 | 40 | # Make Login request and return the response body 41 | response = requests.request("POST", url, 42 | auth = (username, password), 43 | headers=headers, verify=False) 44 | return response.json()["Token"] 45 | 46 | 47 | def network_device_list(host, token): 48 | """ 49 | Use the REST API to retrieve the list of network devices 50 | """ 51 | url = "https://{}/api/v1/network-device".format(host) 52 | headers["x-auth-token"] = token 53 | 54 | # Make API request and return the response body 55 | response = requests.request("GET", url, headers=headers, verify=False) 56 | return response.json()["response"] 57 | 58 | 59 | # Entry point for program 60 | if __name__ == '__main__': 61 | # Log into the DNA Center Controller to get Ticket 62 | token = dnac_login(dnac["host"], dnac["username"], dnac["password"]) 63 | 64 | # Get the list of devices 65 | devices = network_device_list(dnac["host"], token) 66 | 67 | # Loop through the devices and print details 68 | for device in devices: 69 | print("{} in family {}".format(device["hostname"], device["family"])) 70 | print(" Management IP: {}".format(device["managementIpAddress"])) 71 | print(" Platform Type: {}".format(device["platformId"])) 72 | print(" Software Version: {}".format(device["softwareVersion"])) 73 | print("") 74 | -------------------------------------------------------------------------------- /network_controllers/dnac/example1.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Module: Network Controllers 5 | Lesson: Program your own DNA with DNA Center APIs 6 | Author: Hank Preston 7 | 8 | example1.py 9 | Illustrate the following concepts: 10 | - Building DNA Center API Code 11 | - Start from Postman Auto-generated code 12 | - Multiple requests in one script 13 | """ 14 | 15 | __author__ = "Hank Preston" 16 | __author_email__ = "hapresto@cisco.com" 17 | __copyright__ = "Copyright (c) 2016 Cisco Systems, Inc." 18 | __license__ = "MIT" 19 | 20 | from device_info import dnac 21 | import requests 22 | import json 23 | import urllib3 24 | 25 | # Silence the insecure warning due to SSL Certificate 26 | urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) 27 | 28 | 29 | headers = { 30 | 'content-type': "application/json", 31 | 'x-auth-token': "" 32 | } 33 | 34 | def dnac_login(dnac, port, username, password): 35 | """ 36 | Use the REST API to Log into an DNA Center and retrieve ticket 37 | """ 38 | url = "https://{}:{}/dna/system/api/v1/auth/token".format(dnac, port) 39 | 40 | # Make Login request and return the response body 41 | response = requests.request("POST", url, 42 | auth = (username, password), 43 | headers=headers, verify=False) 44 | return response.json()["Token"] 45 | 46 | 47 | def network_device_list(host, token): 48 | """ 49 | Use the REST API to retrieve the list of network devices 50 | """ 51 | url = "https://{}/dna/intent/api/v1/network-device".format(host) 52 | headers["x-auth-token"] = token 53 | 54 | # Make API request and return the response body 55 | response = requests.request("GET", url, headers=headers, verify=False) 56 | return response.json()["response"] 57 | 58 | 59 | # Entry point for program 60 | if __name__ == '__main__': 61 | # Log into the DNA Center Controller to get Ticket 62 | token = dnac_login(dnac["host"], dnac["port"], dnac["username"], dnac["password"]) 63 | 64 | # Get the list of devices 65 | devices = network_device_list(dnac["host"], token) 66 | 67 | # Loop through the devices and print details 68 | for device in devices: 69 | print("{} in family {}".format(device["hostname"], device["family"])) 70 | print(" Management IP: {}".format(device["managementIpAddress"])) 71 | print(" Platform Type: {}".format(device["platformId"])) 72 | print(" Software Version: {}".format(device["softwareVersion"])) 73 | print("") 74 | -------------------------------------------------------------------------------- /network_controllers/dnac/requirements.txt: -------------------------------------------------------------------------------- 1 | requests>=2.25.1 -------------------------------------------------------------------------------- /network_controllers/dnac/troubleshoot_prep.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Module: Network Controllers 5 | Lesson: Cisco DNA Center Platform APIs Part 2: Network Troubleshooting 6 | Author: Hank Preston 7 | 8 | troubleshoot_full.py 9 | Illustrate the following concepts: 10 | - Automating common information gathering used in troubleshooting 11 | - Replicating "runbook logic" in code 12 | - Leveraging REST APIs in Python 13 | - Using details from one request in the next 14 | """ 15 | 16 | __author__ = "Hank Preston" 17 | __author_email__ = "hapresto@cisco.com" 18 | __copyright__ = "Copyright (c) 2016 Cisco Systems, Inc." 19 | __license__ = "MIT" 20 | 21 | from device_info import dnac as dnac 22 | from time import sleep 23 | import json 24 | import requests 25 | import sys 26 | import urllib3 27 | 28 | # Silence the insecure warning due to SSL Certificate 29 | urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) 30 | 31 | headers = { 32 | 'content-type': "application/json", 33 | 'x-auth-token': "" 34 | } 35 | 36 | 37 | def dnac_login(dnac, port, username, password): 38 | """ 39 | Use the REST API to Log into an DNA Center and retrieve ticket 40 | """ 41 | url = "https://{}:{}/dna/system/api/v1/auth/token".format(dnac, port) 42 | 43 | # Make Login request and return the response body 44 | response = requests.request("POST", url, 45 | auth = (username, password), 46 | headers=headers, verify=False) 47 | return response.json()["Token"] 48 | 49 | 50 | # Entry point for program 51 | if __name__ == '__main__': 52 | # Setup Arg Parse for Command Line parameters 53 | import argparse 54 | parser = argparse.ArgumentParser() 55 | 56 | # Command Line Parameters for Source and Destination IP 57 | parser.add_argument("source_ip", help = "Source IP Address") 58 | parser.add_argument("destination_ip", help = "Destination IP Address") 59 | args = parser.parse_args() 60 | 61 | # Get Source and Destination IPs from Command Line 62 | source_ip = args.source_ip 63 | destination_ip = args.destination_ip 64 | 65 | # Print Starting message 66 | print("Running Troubleshooting Script for ") 67 | print(" Source IP: {} ".format(source_ip)) 68 | print(" Destination IP: {}".format(destination_ip)) 69 | print("") 70 | 71 | # Log into the dnac Controller to get Ticket 72 | token = dnac_login(dnac["host"], dnac["port"], dnac["username"], dnac["password"]) 73 | -------------------------------------------------------------------------------- /network_controllers/meraki/README.md: -------------------------------------------------------------------------------- 1 | # Network Control in the Cloud - Developing with Cisco Meraki 2 | 3 | ## "Gitting" the Code 4 | All of the code and examples for this lesson is located in the `netprog_basics/network_controllers/meraki` directory. Clone and access it with the following commands: 5 | 6 | ```bash 7 | git clone https://github.com/CiscoDevNet/netprog_basics 8 | cd netprog_basics/network_controllers/meraki 9 | ``` 10 | 11 | ## Local Workstation Setup 12 | Be sure to complete the [General Workstation Setup](https://github.com/CiscoDevNet/netprog_basics/blob/master/readme_resources/workstation_setup.md) instructions before beginning this lesson. 13 | 14 | ### Postman Setup 15 | During this lesson the Postman client for making REST API calls is used. For convenience we have included a `postman_collection.json` file that contains all the REST API calls leveraged in the different lessons, and `postman_environment.json` files for each of the DevNet Sandboxes leveraged across the lessons. These files are all located in the [postman_config](https://github.com/CiscoDevNet/netprog_basics/tree/master/postman_config) directory in the code repository. 16 | 17 | To leverage them, simply `Import` them into your Postman client. 18 | 19 | 1. Collections: Use the **Import** button in the upper left corner of the client. 20 | 2. Environments: Use the **Import** button from the `Manage Environments` interface of the client. 21 | 22 | > Reminder: Many network devices leverage self-signed certificates for `https://` APIs. Don't forget to turn **OFF** SSL certificate checking within Postman settings. 23 | 24 | ### Python Environment Setup 25 | It is recommended that this lesson be completed using Python 3.8. Other versions of Python 3 should also work. 26 | 27 | > **Note about Python 2:** Python 2 was [sunset](https://www.python.org/doc/sunset-python-2/) by Python Software Foundation on January 1, 2020. This means that no more updates to Python 2 are being worked on, including security updates. Python 3 is now the recommended version of Python for everyone to use. Most Python developers of software, packages, and scripts have migrated to Python 3 already, however you may find some older scripts and tools that are no longer maintained that only work with Python 2. 28 | > 29 | > You may see/hear references to Python 2 within the videos in this course from before January 2020, however all examples scripts and demos available in the GitHub repo to run have been updated to leverage Python 3. 30 | 31 | It is highly recommended to leverage Python Virtual Environments for completing exercises in this course. 32 | 33 | *There is no need to create independent venv for each lesson, but you can if you choose.* 34 | 35 | Follow these steps to create and activate a venv. 36 | 37 | ***Note: If you are leveraging a shared venv across all lessons simply activate it.*** 38 | 39 | ```bash 40 | # OS X or Linux 41 | python3 -m venv venv 42 | source venv/bin/activate 43 | ``` 44 | 45 | ```bash 46 | # Windows 47 | python -m venv venv 48 | venv/Scripts/activate 49 | ``` 50 | 51 | #### Install Python Requirements for Lesson 52 | With the Virtual Environment activated, use pip to install the necessary requirements. 53 | 54 | ```bash 55 | # From the code directory for this lesson 56 | pip install -r requirements.txt 57 | ``` 58 | 59 | ## DevNet Sandbox 60 | This lesson leverages the [Always On: Meraki](https://devnetsandbox.cisco.com/RM/Diagram/Index/a9487767-deef-4855-b3e3-880e7f39eadc?diagramType=Topology) Sandbox. This sandbox requires no reservation **or** VPN connection. 61 | 62 | 63 | ## Download Slides 64 | 65 | You can download the slides for this lesson [here](https://developer.cisco.com/fileMedia/download/12c50842-e1c3-34aa-9d47-650b6a01502f). 66 | 67 | > *Suggestion: Right click, "Open in new tab"* -------------------------------------------------------------------------------- /network_controllers/meraki/requirements.txt: -------------------------------------------------------------------------------- 1 | requests>=2.25.1 2 | -------------------------------------------------------------------------------- /network_device_apis/README.md: -------------------------------------------------------------------------------- 1 | # Network Device APIs 2 | In this module you will explore different APIs for interacting with individual Network Devices. 3 | 4 | ## Lessons 5 | 6 | * [Getting the “YANG” of it with Standard Data Models](yang/README.md) 7 | * [Goodbye SNMP NETCONF!](netconf/README.md) 8 | * [Learn to CRUD with GET, POST and DELETE using RESTCONF](restconf/README.md) 9 | * [NX-API Part 1: Get Started with APIs and Nexus](nxapi/README.md) 10 | * [NX-API Part 2: Dive into the Nexus Object Model](nxapi/README.md) -------------------------------------------------------------------------------- /network_device_apis/netconf/README.md: -------------------------------------------------------------------------------- 1 | # Goodbye SNMP, hello NETCONF! 2 | 3 | ## "Gitting" the Code 4 | All of the code and examples for this lesson is located in the `netprog_basics/network_device_apis/netconf` directory. Clone and access it with the following commands: 5 | 6 | ```bash 7 | git clone https://github.com/CiscoDevNet/netprog_basics 8 | cd netprog_basics/network_device_apis/netconf 9 | ``` 10 | 11 | ## Local Workstation Setup 12 | Be sure to complete the [General Workstation Setup](https://github.com/CiscoDevNet/netprog_basics/blob/master/readme_resources/workstation_setup.md) instructions before beginning this lesson. 13 | 14 | ### Python Environment Setup 15 | It is recommended that this lesson be completed using Python 3.8. Other versions of Python 3 should also work. 16 | 17 | > **Note about Python 2:** Python 2 was [sunset](https://www.python.org/doc/sunset-python-2/) by Python Software Foundation on January 1, 2020. This means that no more updates to Python 2 are being worked on, including security updates. Python 3 is now the recommended version of Python for everyone to use. Most Python developers of software, packages, and scripts have migrated to Python 3 already, however you may find some older scripts and tools that are no longer maintained that only work with Python 2. 18 | > 19 | > You may see/hear references to Python 2 within the videos in this course from before January 2020, however all examples scripts and demos available in the GitHub repo to run have been updated to leverage Python 3. 20 | 21 | It is highly recommended to leverage Python Virtual Environments for completing exercises in this course. 22 | 23 | *There is no need to create independent venv for each lesson, but you can if you choose.* 24 | 25 | Follow these steps to create and activate a venv. 26 | 27 | ***Note: If you are leveraging a shared venv across all lessons simply activate it.*** 28 | 29 | ```bash 30 | # OS X or Linux 31 | python3 -m venv venv 32 | source venv/bin/activate 33 | ``` 34 | 35 | ```bash 36 | # Windows 37 | python -m venv venv 38 | venv/Scripts/activate 39 | ``` 40 | 41 | #### Install Python Requirements for Lesson 42 | With the Virtual Environment activated, use pip to install the necessary requirements. 43 | 44 | ```bash 45 | # From the code directory for this lesson 46 | pip install -r requirements.txt 47 | ``` 48 | 49 | ## DevNet Sandbox 50 | This lesson leverages the [IOS XE on CSR Recommended Code AlwaysOn](https://devnetsandbox.cisco.com/RM/Diagram/Index/27d9747a-db48-4565-8d44-df318fce37ad?diagramType=Topology) Sandbox. This sandbox requires no reservation **or** VPN connection. 51 | 52 | ## Download Slides 53 | 54 | You can download the slides for this lesson [here](https://developer.cisco.com/fileMedia/download/cf107e01-e285-394d-8592-0cecff480133). 55 | 56 | > *Suggestion: Right click, "Open in new tab"* -------------------------------------------------------------------------------- /network_device_apis/netconf/config-temp-ietf-interfaces.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {int_name} 5 | {int_desc} 6 | ianaift:ethernetCsmacd 7 | true 8 | 9 |
10 | {ip_address} 11 | {subnet_mask} 12 |
13 |
14 |
15 |
16 |
17 | -------------------------------------------------------------------------------- /network_device_apis/netconf/device_info.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Author: Hank Preston 5 | 6 | device_info.py 7 | Illustrate the following concepts: 8 | - Store device info for Sandbox Infrastructure used 9 | in examples 10 | """ 11 | 12 | __author__ = "Hank Preston" 13 | __author_email__ = "hapresto@cisco.com" 14 | __copyright__ = "Copyright (c) 2016 Cisco Systems, Inc." 15 | __license__ = "MIT" 16 | 17 | # DevNet Always-On IOS XE on CSR Recommended Code Sandbox Device 18 | # https://devnetsandbox.cisco.com/RM/Diagram/Index/27d9747a-db48-4565-8d44-df318fce37ad?diagramType=Topology 19 | ios_xe1 = { 20 | "address": "sandbox-iosxe-recomm-1.cisco.com", 21 | "port": 830, 22 | "username": "developer", 23 | "password": "lastorangerestoreball8876" 24 | } 25 | 26 | # DevNet Always-On IOS XE on CSR Latest Code Sandbox Device 27 | # https://devnetsandbox.cisco.com/RM/Diagram/Index/38ded1f0-16ce-43f2-8df5-43a40ebf752e?diagramType=Topology 28 | ios_xe_latest = { 29 | "address": "sandbox-iosxe-latest-1.cisco.com", 30 | "port": 830, 31 | "username": "admin", 32 | "password": "C1sco12345" 33 | } 34 | 35 | # DevNet IOS XE Programmability Sandbox Device 36 | # https://devnetsandbox.cisco.com/RM/Diagram/Index/cae403c2-27af-4c7d-b1e1-99b7d42f1504?diagramType=Topology 37 | ios_xe2 = { 38 | "address": "10.10.20.48", 39 | "port": 830, 40 | "username": "developer", 41 | "password": "C1sco12345" 42 | } 43 | 44 | 45 | # DevNet Always-On Sandbox APIC-EM 46 | # https://devnetsandbox.cisco.com/RM/Diagram/Index/2e0f9525-5f46-4f46-973e-0f0c1bf934fa?diagramType=Topology 47 | apicem = { 48 | "host": "sandboxapicem.cisco.com", 49 | "username": "devnetuser", 50 | "password": "Cisco123!", 51 | "port": 443 52 | } 53 | 54 | # DevNet Always-On Sandbox ACI APIC 55 | # https://devnetsandbox.cisco.com/RM/Diagram/Index/5a229a7c-95d5-4cfd-a651-5ee9bc1b30e2?diagramType=Topology 56 | apic = { 57 | "host": "https://sandboxapicdc.cisco.com", 58 | "username": "admin", 59 | "password": "ciscopsdt", 60 | "port": 443 61 | } 62 | 63 | -------------------------------------------------------------------------------- /network_device_apis/netconf/example1.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Module: Network Device APIs 5 | Lesson: Goodbye SNMP hello NETCONF 6 | Author: Hank Preston 7 | 8 | example1.py 9 | Illustrate the following concepts: 10 | - Opening a NETCONF connection with ncclient 11 | - Saying and review capabilities 12 | """ 13 | 14 | __author__ = "Hank Preston" 15 | __author_email__ = "hapresto@cisco.com" 16 | __copyright__ = "Copyright (c) 2016 Cisco Systems, Inc." 17 | __license__ = "MIT" 18 | 19 | from device_info import ios_xe1 20 | from ncclient import manager 21 | 22 | if __name__ == '__main__': 23 | with manager.connect(host=ios_xe1["address"], port=ios_xe1["port"], 24 | username=ios_xe1["username"], 25 | password=ios_xe1["password"], 26 | hostkey_verify=False) as m: 27 | 28 | print("Here are the NETCONF Capabilities") 29 | for capability in m.server_capabilities: 30 | print(capability) 31 | -------------------------------------------------------------------------------- /network_device_apis/netconf/example2.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Module: Network Device APIs 5 | Lesson: Goodbye SNMP hello NETCONF 6 | Author: Hank Preston 7 | 8 | example2.py 9 | Illustrate the following concepts: 10 | - Send to retrieve config and state data 11 | - Process and leverage XML within Python 12 | - Report back current state of interface 13 | """ 14 | 15 | __author__ = "Hank Preston" 16 | __author_email__ = "hapresto@cisco.com" 17 | __copyright__ = "Copyright (c) 2016 Cisco Systems, Inc." 18 | __license__ = "MIT" 19 | 20 | from device_info import ios_xe1 21 | from ncclient import manager 22 | import xmltodict 23 | 24 | # NETCONF filter to use 25 | netconf_filter = open("filter-ietf-interfaces.xml").read() 26 | 27 | if __name__ == '__main__': 28 | with manager.connect(host=ios_xe1["address"], port=ios_xe1["port"], 29 | username=ios_xe1["username"], 30 | password=ios_xe1["password"], 31 | hostkey_verify=False) as m: 32 | 33 | # Get Configuration and State Info for Interface 34 | netconf_reply = m.get(netconf_filter) 35 | 36 | # Process the XML and store in useful dictionaries 37 | intf_details = xmltodict.parse(netconf_reply.xml)["rpc-reply"]["data"] 38 | intf_config = intf_details["interfaces"]["interface"] 39 | intf_info = intf_details["interfaces-state"]["interface"] 40 | 41 | print("") 42 | print("Interface Details:") 43 | print(" Name: {}".format(intf_config["name"])) 44 | print(" Description: {}".format(intf_config["description"])) 45 | print(" Type: {}".format(intf_config["type"]["#text"])) 46 | print(" MAC Address: {}".format(intf_info["phys-address"])) 47 | print(" Packets Input: {}".format(intf_info["statistics"]["in-unicast-pkts"])) 48 | print(" Packets Output: {}".format(intf_info["statistics"]["out-unicast-pkts"])) 49 | -------------------------------------------------------------------------------- /network_device_apis/netconf/example3.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Module: Network Device APIs 5 | Lesson: Goodbye SNMP hello NETCONF 6 | Author: Hank Preston 7 | 8 | example3.py 9 | Illustrate the following concepts: 10 | - Constructing XML Config Payload for NETCONF 11 | - Sending operation with ncclient 12 | - Verify result 13 | """ 14 | 15 | __author__ = "Hank Preston" 16 | __author_email__ = "hapresto@cisco.com" 17 | __copyright__ = "Copyright (c) 2016 Cisco Systems, Inc." 18 | __license__ = "MIT" 19 | 20 | from device_info import ios_xe1 21 | from ncclient import manager 22 | 23 | # NETCONF Config Template to use 24 | netconf_template = open("config-temp-ietf-interfaces.xml").read() 25 | 26 | if __name__ == '__main__': 27 | # Build the XML Configuration to Send 28 | netconf_payload = netconf_template.format(int_name="GigabitEthernet2", 29 | int_desc="Configured by NETCONF", 30 | ip_address="10.255.255.1", 31 | subnet_mask="255.255.255.0" 32 | ) 33 | print("Configuration Payload:") 34 | print("----------------------") 35 | print(netconf_payload) 36 | 37 | with manager.connect(host=ios_xe1["address"], port=ios_xe1["port"], 38 | username=ios_xe1["username"], 39 | password=ios_xe1["password"], 40 | hostkey_verify=False) as m: 41 | 42 | # Send NETCONF 43 | netconf_reply = m.edit_config(netconf_payload, target="running") 44 | 45 | # Print the NETCONF Reply 46 | print(netconf_reply) 47 | -------------------------------------------------------------------------------- /network_device_apis/netconf/filter-ietf-interfaces.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | GigabitEthernet2 5 | 6 | 7 | 8 | 9 | GigabitEthernet2 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /network_device_apis/netconf/requirements.txt: -------------------------------------------------------------------------------- 1 | ncclient>=0.6.9 2 | pyang>=2.4.0 3 | xmltodict>=0.12.0 4 | -------------------------------------------------------------------------------- /network_device_apis/nxapi/README.md: -------------------------------------------------------------------------------- 1 | # Programming with NX-API Lessons 2 | * **NX-API Part 1: Get Started with APIs and Nexus** 3 | * **NX-API Part 2: Dive into the Nexus Object Model** 4 | 5 | ## "Gitting" the Code 6 | All of the code and examples for this lesson is located in the `netprog_basics/network_device_apis/nxapi` directory. Clone and access it with the following commands: 7 | 8 | ```bash 9 | git clone https://github.com/CiscoDevNet/netprog_basics 10 | cd netprog_basics/network_device_apis/nxapi 11 | ``` 12 | 13 | ## Local Workstation Setup 14 | Be sure to complete the [General Workstation Setup](https://github.com/CiscoDevNet/netprog_basics/blob/master/readme_resources/workstation_setup.md) instructions before beginning this lesson. 15 | 16 | ### Postman Setup 17 | During this lesson the Postman client for making REST API calls is used. For convenience we have included a `postman_collection.json` file that contains all the REST API calls leveraged in the different lessons, and `postman_environment.json` files for each of the DevNet Sandboxes leveraged across the lessons. These files are all located in the [postman_config](https://github.com/CiscoDevNet/netprog_basics/tree/master/postman_config) directory in the code repository. 18 | 19 | To leverage them, simply `Import` them into your Postman client. 20 | 21 | 1. Collections: Use the **Import** button in the upper left corner of the client. 22 | 2. Environments: Use the **Import** button from the `Manage Environments` interface of the client. 23 | 24 | > Reminder: Many network devices leverage self-signed certificates for `https://` APIs. Don't forget to turn **OFF** SSL certificate checking within Postman settings. 25 | 26 | ### Python Environment Setup 27 | It is recommended that this lesson be completed using Python 3.8. Other versions of Python 3 should also work. 28 | 29 | > **Note about Python 2:** Python 2 was [sunset](https://www.python.org/doc/sunset-python-2/) by Python Software Foundation on January 1, 2020. This means that no more updates to Python 2 are being worked on, including security updates. Python 3 is now the recommended version of Python for everyone to use. Most Python developers of software, packages, and scripts have migrated to Python 3 already, however you may find some older scripts and tools that are no longer maintained that only work with Python 2. 30 | > 31 | > You may see/hear references to Python 2 within the videos in this course from before January 2020, however all examples scripts and demos available in the GitHub repo to run have been updated to leverage Python 3. 32 | 33 | It is highly recommended to leverage Python Virtual Environments for completing exercises in this course. 34 | 35 | *There is no need to create independent venv for each lesson, but you can if you choose.* 36 | 37 | Follow these steps to create and activate a venv. 38 | 39 | ***Note: If you are leveraging a shared venv across all lessons simply activate it.*** 40 | 41 | ```bash 42 | # OS X or Linux 43 | python3 -m venv venv 44 | source venv/bin/activate 45 | ``` 46 | 47 | ```bash 48 | # Windows 49 | python -m venv venv 50 | venv/Scripts/activate 51 | ``` 52 | 53 | #### Install Python Requirements for Lesson 54 | With the Virtual Environment activated, use pip to install the necessary requirements. 55 | 56 | ```bash 57 | # From the code directory for this lesson 58 | pip install -r requirements.txt 59 | ``` 60 | 61 | ## DevNet Sandbox 62 | This lesson leverages the [Always On: Open NX-OS Programmability](https://devnetsandbox.cisco.com/RM/Diagram/Index/dae38dd8-e8ee-4d7c-a21c-6036bed7a804?diagramType=Topology) Sandbox. This sandbox requires no reservation **or** VPN connection. 63 | 64 | 65 | ## Download Slides 66 | 67 | You can download the slides for this lesson here. 68 | 69 | * [**NX-API Part 1: Get Started with APIs and Nexus**](https://developer.cisco.com/fileMedia/download/de3355ca-aa6e-398a-9c09-5eedb28a957e) 70 | * [**NX-API Part 2: Dive into the Nexus Object Model**](https://developer.cisco.com/fileMedia/download/baf5bda7-1337-330e-bcf6-a2b72cc6e65d) 71 | 72 | > *Suggestion: Right click, "Open in new tab"* -------------------------------------------------------------------------------- /network_device_apis/nxapi/example1.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Module: Network Device APIs 5 | Lesson: NX-API Part 1 6 | Author: Hank Preston 7 | 8 | example1.py 9 | Illustrate the following concepts: 10 | - NX-API CLI code generation from Developer Sandbox 11 | - INS-API JSON 12 | - Execute command, print output 13 | """ 14 | 15 | __author__ = "Hank Preston" 16 | __author_email__ = "hapresto@cisco.com" 17 | __copyright__ = "Copyright (c) 2016 Cisco Systems, Inc." 18 | __license__ = "MIT" 19 | 20 | import requests 21 | import json 22 | 23 | requests.packages.urllib3.disable_warnings( 24 | requests.packages.urllib3.exceptions.InsecureRequestWarning 25 | ) 26 | 27 | """ 28 | Modify these please 29 | """ 30 | url = "https://sbx-nxos-mgmt.cisco.com/ins" 31 | switchuser = "admin" 32 | switchpassword = "Admin_1234!" 33 | 34 | myheaders = {"content-type": "application/json"} 35 | payload = { 36 | "ins_api": { 37 | "version": "1.0", 38 | "type": "cli_show", 39 | "chunk": "0", 40 | "sid": "1", 41 | "input": "show vlan bri", 42 | "output_format": "json", 43 | } 44 | } 45 | response = requests.post( 46 | url, 47 | data=json.dumps(payload), 48 | headers=myheaders, 49 | auth=(switchuser, switchpassword), 50 | verify=False, 51 | ).json() 52 | 53 | # Extract interesting info from Response 54 | vlan_list = response["ins_api"]["outputs"]["output"]["body"][ 55 | "TABLE_vlanbriefxbrief" 56 | ]["ROW_vlanbriefxbrief"] 57 | 58 | # Print out the vlan details 59 | for vlan in vlan_list: 60 | print("VLAN Name: {}".format(vlan["vlanshowbr-vlanname"])) 61 | -------------------------------------------------------------------------------- /network_device_apis/nxapi/ins_api_request_1.json: -------------------------------------------------------------------------------- 1 | { 2 | "ins_api": { 3 | "version": "1.0", 4 | "type": "cli_show", 5 | "chunk": "0", 6 | "sid": "1", 7 | "input": "show ip int bri vrf management", 8 | "output_format": "json" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /network_device_apis/nxapi/ins_api_response_1.json: -------------------------------------------------------------------------------- 1 | { 2 | "ins_api": { 3 | "type": "cli_show", 4 | "version": "1.0", 5 | "sid": "eoc", 6 | "outputs": { 7 | "output": { 8 | "input": "show ip int bri vrf management", 9 | "msg": "Success", 10 | "code": "200", 11 | "body": { 12 | "TABLE_intf": { 13 | "ROW_intf": { 14 | "intf-name": "mgmt0", 15 | "prefix": "10.10.20.58", 16 | "ip-disabled": "FALSE", 17 | "iod": 2, 18 | "proto-state": "up", 19 | "link-state": "up", 20 | "admin-state": "up" 21 | } 22 | }, 23 | "TABLE_vrf": { 24 | "ROW_vrf": { 25 | "vrf-name-out": "management" 26 | } 27 | } 28 | } 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /network_device_apis/nxapi/json_rpc_request_1.json: -------------------------------------------------------------------------------- 1 | { 2 | "jsonrpc": "2.0", 3 | "method": "colormix", 4 | "params": { 5 | "basecolor": "red", 6 | "addcolor": "yellow" 7 | }, 8 | "id": 1 9 | } 10 | -------------------------------------------------------------------------------- /network_device_apis/nxapi/json_rpc_request_2.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "jsonrpc": "2.0", 4 | "method": "cli", 5 | "params": { 6 | "cmd": "show ip int bri vrf management", 7 | "version": 1 8 | }, 9 | "id": 1 10 | } 11 | ] 12 | -------------------------------------------------------------------------------- /network_device_apis/nxapi/json_rpc_response_1.json: -------------------------------------------------------------------------------- 1 | { 2 | "jsonrpc": "2.0", 3 | "result": "orange", 4 | "id": 1 5 | } 6 | -------------------------------------------------------------------------------- /network_device_apis/nxapi/json_rpc_response_2.json: -------------------------------------------------------------------------------- 1 | { 2 | "jsonrpc": "2.0", 3 | "result": { 4 | "body": { 5 | "TABLE_intf": { 6 | "ROW_intf": { 7 | "intf-name": "mgmt0", 8 | "prefix": "10.10.20.58", 9 | "ip-disabled": "FALSE", 10 | "iod": 2, 11 | "proto-state": "up", 12 | "link-state": "up", 13 | "admin-state": "up" 14 | } 15 | }, 16 | "TABLE_vrf": { 17 | "ROW_vrf": { 18 | "vrf-name-out": "management" 19 | } 20 | } 21 | } 22 | }, 23 | "id": 1 24 | } 25 | -------------------------------------------------------------------------------- /network_device_apis/nxapi/requirements.txt: -------------------------------------------------------------------------------- 1 | requests>=2.25.1 2 | -------------------------------------------------------------------------------- /network_device_apis/nxapi/sbx_setup.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Module: Network Device APIs 5 | Lesson: NX-API Part 2 6 | Author: Hank Preston 7 | 8 | sbx_setup.py 9 | Deploy baseline configuration for the lesson: 10 | - Add 3 VLANs to the Switch Configuration 11 | """ 12 | 13 | __author__ = "Hank Preston" 14 | __author_email__ = "hapresto@cisco.com" 15 | __copyright__ = "Copyright (c) 2016 Cisco Systems, Inc." 16 | __license__ = "MIT" 17 | 18 | import requests 19 | import json 20 | 21 | requests.packages.urllib3.disable_warnings( 22 | requests.packages.urllib3.exceptions.InsecureRequestWarning 23 | ) 24 | 25 | # Switch Connection Info 26 | url = "https://sbx-nxos-mgmt.cisco.com/ins" 27 | switchuser = "admin" 28 | switchpassword = "Admin_1234!" 29 | myheaders = {'content-type': 'application/json'} 30 | 31 | # Configuration Payload 32 | payload = { 33 | "ins_api": { 34 | "version": "1.0", 35 | "type": "cli_conf", 36 | "chunk": "0", 37 | "sid": "1", 38 | "input": "vlan 201 ;name Web_VLAN ;vlan 202 ;name App_VLAN ;vlan 203 ;name Data_VLAN", # noqa 39 | "output_format": "json" 40 | } 41 | } 42 | 43 | # Send Configuration 44 | response = requests.post( 45 | url, 46 | data=json.dumps(payload), 47 | headers=myheaders, 48 | auth=(switchuser, switchpassword), 49 | verify=False 50 | ).json() 51 | -------------------------------------------------------------------------------- /network_device_apis/restconf/requirements.txt: -------------------------------------------------------------------------------- 1 | pyang>=2.4.0 2 | requests>=2.25.1 3 | -------------------------------------------------------------------------------- /network_device_apis/yang/README.md: -------------------------------------------------------------------------------- 1 | # Getting the “YANG” of it with Standard Data Models 2 | 3 | ## "Gitting" the Code 4 | All of the code and examples for this lesson is located in the `netprog_basics/network_device_apis/yang` directory. Clone and access it with the following commands: 5 | 6 | ```bash 7 | git clone https://github.com/CiscoDevNet/netprog_basics 8 | cd netprog_basics/network_device_apis/yang 9 | ``` 10 | 11 | ## Local Workstation Setup 12 | Be sure to complete the [General Workstation Setup](https://github.com/CiscoDevNet/netprog_basics/blob/master/readme_resources/workstation_setup.md) instructions before beginning this lesson. 13 | 14 | ### Python Environment Setup 15 | It is recommended that this lesson be completed using Python 3.8. Other versions of Python 3 should also work. 16 | 17 | > **Note about Python 2:** Python 2 was [sunset](https://www.python.org/doc/sunset-python-2/) by Python Software Foundation on January 1, 2020. This means that no more updates to Python 2 are being worked on, including security updates. Python 3 is now the recommended version of Python for everyone to use. Most Python developers of software, packages, and scripts have migrated to Python 3 already, however you may find some older scripts and tools that are no longer maintained that only work with Python 2. 18 | > 19 | > You may see/hear references to Python 2 within the videos in this course from before January 2020, however all examples scripts and demos available in the GitHub repo to run have been updated to leverage Python 3. 20 | 21 | It is highly recommended to leverage Python Virtual Environments for completing exercises in this course. 22 | 23 | *There is no need to create independent venv for each lesson, but you can if you choose.* 24 | 25 | Follow these steps to create and activate a venv. 26 | 27 | ***Note: If you are leveraging a shared venv across all lessons simply activate it.*** 28 | 29 | ```bash 30 | # OS X or Linux 31 | python3 -m venv venv 32 | source venv/bin/activate 33 | ``` 34 | 35 | ```bash 36 | # Windows 37 | python -m venv venv 38 | venv/Scripts/activate 39 | ``` 40 | 41 | #### Install Python Requirements for Lesson 42 | With the Virtual Environment activated, use pip to install the necessary requirements. 43 | 44 | ```bash 45 | # From the code directory for this lesson 46 | pip install -r requirements.txt 47 | ``` 48 | 49 | ## DevNet Sandbox 50 | This lesson leverages the [IOS XE on CSR Recommended Code AlwaysOn](https://devnetsandbox.cisco.com/RM/Diagram/Index/27d9747a-db48-4565-8d44-df318fce37ad?diagramType=Topology) Sandbox. This sandbox requires no reservation **or** VPN connection. 51 | 52 | ## Download Slides 53 | 54 | You can download the slides for this lesson [here](https://developer.cisco.com/fileMedia/download/65078461-ac9c-33ee-841e-f1c37c68e81d). 55 | 56 | > *Suggestion: Right click, "Open in new tab"* -------------------------------------------------------------------------------- /network_device_apis/yang/device_info.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Author: Hank Preston 5 | 6 | device_info.py 7 | Illustrate the following concepts: 8 | - Store device info for Sandbox Infrastructure used 9 | in examples 10 | """ 11 | 12 | __author__ = "Hank Preston" 13 | __author_email__ = "hapresto@cisco.com" 14 | __copyright__ = "Copyright (c) 2016 Cisco Systems, Inc." 15 | __license__ = "MIT" 16 | 17 | # DevNet Always-On IOS XE on CSR Recommended Code Sandbox Device 18 | # https://devnetsandbox.cisco.com/RM/Diagram/Index/27d9747a-db48-4565-8d44-df318fce37ad?diagramType=Topology 19 | ios_xe1 = { 20 | "address": "ios-xe-mgmt.cisco.com", 21 | "port": 10000, 22 | "username": "developer", 23 | "password": "C1sco12345" 24 | } 25 | 26 | # DevNet Always-On IOS XE on CSR Latest Code Sandbox Device 27 | # https://devnetsandbox.cisco.com/RM/Diagram/Index/38ded1f0-16ce-43f2-8df5-43a40ebf752e?diagramType=Topology 28 | ios_xe_latest = { 29 | "address": "ios-xe-mgmt-latest.cisco.com", 30 | "port": 10000, 31 | "username": "developer", 32 | "password": "C1sco12345" 33 | } 34 | 35 | # DevNet IOS XE Programmability Sandbox Device 36 | # https://devnetsandbox.cisco.com/RM/Diagram/Index/cae403c2-27af-4c7d-b1e1-99b7d42f1504?diagramType=Topology 37 | ios_xe2 = { 38 | "address": "10.10.20.48", 39 | "port": 830, 40 | "username": "developer", 41 | "password": "C1sco12345" 42 | } 43 | 44 | 45 | # DevNet Always-On Sandbox APIC-EM 46 | # https://devnetsandbox.cisco.com/RM/Diagram/Index/2e0f9525-5f46-4f46-973e-0f0c1bf934fa?diagramType=Topology 47 | apicem = { 48 | "host": "sandboxapicem.cisco.com", 49 | "username": "devnetuser", 50 | "password": "Cisco123!", 51 | "port": 443 52 | } 53 | 54 | # DevNet Always-On Sandbox ACI APIC 55 | # https://devnetsandbox.cisco.com/RM/Diagram/Index/5a229a7c-95d5-4cfd-a651-5ee9bc1b30e2?diagramType=Topology 56 | apic = { 57 | "host": "https://sandboxapicdc.cisco.com", 58 | "username": "admin", 59 | "password": "ciscopsdt", 60 | "port": 443 61 | } 62 | 63 | -------------------------------------------------------------------------------- /network_device_apis/yang/example1.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Module: Network Device APIs 5 | Lesson: Getting the YANG of it 6 | Author: Hank Preston 7 | 8 | example1.py 9 | Illustrate the following concepts: 10 | - Connect with NETCONF 11 | - Print to screen the 12 | - Used to compare to data model 13 | """ 14 | 15 | __author__ = "Hank Preston" 16 | __author_email__ = "hapresto@cisco.com" 17 | __copyright__ = "Copyright (c) 2016 Cisco Systems, Inc." 18 | __license__ = "MIT" 19 | 20 | from device_info import ios_xe1 21 | from ncclient import manager 22 | import xml.dom.minidom 23 | 24 | # NETCONF filter to use 25 | netconf_filter = open("filter-ietf-interfaces.xml").read() 26 | 27 | 28 | if __name__ == '__main__': 29 | with manager.connect(host=ios_xe1["address"], port=ios_xe1["port"], 30 | username=ios_xe1["username"], 31 | password=ios_xe1["password"], 32 | hostkey_verify=False) as m: 33 | 34 | netconf_reply = m.get_config("running", netconf_filter) 35 | interfaces = xml.dom.minidom.parseString(netconf_reply.xml) 36 | interfaces = interfaces.getElementsByTagName("interfaces") 37 | print(interfaces[0].toprettyxml()) 38 | -------------------------------------------------------------------------------- /network_device_apis/yang/filter-ietf-interfaces.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /network_device_apis/yang/requirements.txt: -------------------------------------------------------------------------------- 1 | ncclient>=0.6.9 2 | pyang>=2.4 3 | xmltodict>=0.12.0 -------------------------------------------------------------------------------- /postman_config/DevNet Cisco DNA Center Always On 1.postman_environment.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "ab176a78-ca93-0f80-cae4-960682ddf1a9", 3 | "name": "DevNet Cisco DNA Center Always On 1", 4 | "values": [ 5 | { 6 | "key": "dnac", 7 | "value": "sandboxdnac.cisco.com", 8 | "enabled": true 9 | }, 10 | { 11 | "key": "username", 12 | "value": "devnetuser", 13 | "enabled": true 14 | }, 15 | { 16 | "key": "password", 17 | "value": "Cisco123!", 18 | "enabled": true 19 | }, 20 | { 21 | "key": "token", 22 | "value": "", 23 | "enabled": true 24 | }, 25 | { 26 | "key": "port", 27 | "value": "443", 28 | "enabled": true 29 | }, 30 | { 31 | "key": "deviceId", 32 | "value": "", 33 | "enabled": true 34 | }, 35 | { 36 | "key": "tagId", 37 | "value": "", 38 | "enabled": true 39 | }, 40 | { 41 | "key": "taskId", 42 | "value": "", 43 | "enabled": true 44 | }, 45 | { 46 | "key": "pathId", 47 | "value": "", 48 | "enabled": true 49 | }, 50 | { 51 | "key": "GLOBALtime", 52 | "value": "", 53 | "enabled": true 54 | }, 55 | { 56 | "key": "CLIENTtime", 57 | "value": "", 58 | "enabled": true 59 | }, 60 | { 61 | "key": "host_id", 62 | "value": "", 63 | "enabled": true 64 | }, 65 | { 66 | "key": "network_device_id", 67 | "value": "", 68 | "enabled": true 69 | }, 70 | { 71 | "key": "network_device_hostname", 72 | "value": "cat_9k_1", 73 | "enabled": true 74 | }, 75 | { 76 | "key": "network_device_ip_address", 77 | "value": "10.10.22.66", 78 | "enabled": true 79 | }, 80 | { 81 | "key": "network_device_serial", 82 | "value": "FCW2136L0AK", 83 | "enabled": true 84 | }, 85 | { 86 | "key": "network_device_interface_name", 87 | "value": "TenGigabitEthernet1/0/3", 88 | "enabled": true 89 | }, 90 | { 91 | "key": "host_ip_address", 92 | "value": "10.10.22.114", 93 | "enabled": true 94 | }, 95 | { 96 | "key": "client_mac_address", 97 | "value": "00:1e:13:a5:b9:40", 98 | "enabled": true 99 | } 100 | ], 101 | "_postman_variable_scope": "environment", 102 | "_postman_exported_at": "2021-01-07T15:46:21.957Z", 103 | "_postman_exported_using": "Postman/7.36.1" 104 | } -------------------------------------------------------------------------------- /postman_config/DevNet Cisco DNA Center Always On 2.postman_environment.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "e04b4d61-d124-436f-8b30-e9e68e53bb06", 3 | "name": "DevNet Cisco DNA Center Always On 2", 4 | "values": [ 5 | { 6 | "key": "dnac", 7 | "value": "sandboxdnac2.cisco.com", 8 | "enabled": true 9 | }, 10 | { 11 | "key": "username", 12 | "value": "devnetuser", 13 | "enabled": true 14 | }, 15 | { 16 | "key": "password", 17 | "value": "Cisco123!", 18 | "enabled": true 19 | }, 20 | { 21 | "key": "token", 22 | "value": "", 23 | "enabled": true 24 | }, 25 | { 26 | "key": "port", 27 | "value": "443", 28 | "enabled": true 29 | }, 30 | { 31 | "key": "deviceId", 32 | "value": "", 33 | "enabled": true 34 | }, 35 | { 36 | "key": "tagId", 37 | "value": "", 38 | "enabled": true 39 | }, 40 | { 41 | "key": "taskId", 42 | "value": "", 43 | "enabled": true 44 | }, 45 | { 46 | "key": "pathId", 47 | "value": "", 48 | "enabled": true 49 | }, 50 | { 51 | "key": "GLOBALtime", 52 | "value": "", 53 | "enabled": true 54 | }, 55 | { 56 | "key": "CLIENTtime", 57 | "value": "", 58 | "enabled": true 59 | }, 60 | { 61 | "key": "host_id", 62 | "value": "", 63 | "enabled": true 64 | }, 65 | { 66 | "key": "network_device_id", 67 | "value": "", 68 | "enabled": true 69 | }, 70 | { 71 | "key": "network_device_hostname", 72 | "value": "leaf2.abc.inc", 73 | "enabled": true 74 | }, 75 | { 76 | "key": "network_device_ip_address", 77 | "value": "10.10.20.82", 78 | "enabled": true 79 | }, 80 | { 81 | "key": "network_device_serial", 82 | "value": "FCW2214L0UZ", 83 | "enabled": true 84 | }, 85 | { 86 | "key": "network_device_interface_name", 87 | "value": "GigabitEthernet1/0/1", 88 | "enabled": true 89 | }, 90 | { 91 | "key": "host_ip_address", 92 | "value": "10.10.20.83", 93 | "enabled": true 94 | }, 95 | { 96 | "key": "client_mac_address", 97 | "value": "f0:25:72:2a:d2:41", 98 | "enabled": true 99 | } 100 | ], 101 | "_postman_variable_scope": "environment", 102 | "_postman_exported_at": "2021-01-07T15:45:47.189Z", 103 | "_postman_exported_using": "Postman/7.36.1" 104 | } -------------------------------------------------------------------------------- /postman_config/Sandbox ACI APIC Always On.postman_environment.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "49cb0574-0c4f-4cf7-8ce1-8208a785890e", 3 | "name": "DevNet ACI APIC Sandbox Always On", 4 | "values": [ 5 | { 6 | "enabled": true, 7 | "key": "apic", 8 | "value": "sandboxapicdc.cisco.com", 9 | "type": "text" 10 | }, 11 | { 12 | "enabled": true, 13 | "key": "username", 14 | "value": "admin", 15 | "type": "text" 16 | }, 17 | { 18 | "enabled": true, 19 | "key": "password", 20 | "value": "ciscopsdt", 21 | "type": "text" 22 | }, 23 | { 24 | "enabled": true, 25 | "key": "port", 26 | "value": "443", 27 | "type": "text" 28 | } 29 | ], 30 | "timestamp": 1506371182617, 31 | "_postman_variable_scope": "environment", 32 | "_postman_exported_at": "2017-11-20T23:16:54.897Z", 33 | "_postman_exported_using": "Postman/5.3.2" 34 | } -------------------------------------------------------------------------------- /postman_config/Sandbox Always On Open NX-OS Programmability.postman_environment.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "3c1e00f8-b9ba-8b45-9827-34d568ab0f98", 3 | "name": "Sandbox Always On Open NX-OS Programmability", 4 | "values": [ 5 | { 6 | "key": "host", 7 | "value": "sbx-nxos-mgmt.cisco.com", 8 | "enabled": true 9 | }, 10 | { 11 | "key": "username", 12 | "value": "admin", 13 | "enabled": true 14 | }, 15 | { 16 | "key": "password", 17 | "value": "Admin_1234!", 18 | "enabled": true 19 | }, 20 | { 21 | "key": "port", 22 | "value": "443", 23 | "enabled": true 24 | } 25 | ], 26 | "_postman_variable_scope": "environment", 27 | "_postman_exported_at": "2019-03-26T23:47:32.576Z", 28 | "_postman_exported_using": "Postman/6.7.4" 29 | } 30 | -------------------------------------------------------------------------------- /postman_config/Sandbox Meraki Always On.postman_environment.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "0f2c6521-c8a9-51cc-c0b0-2e8520ca8130", 3 | "name": "Sandbox Meraki", 4 | "values": [ 5 | { 6 | "key": "X-Cisco-Meraki-API-Key", 7 | "value": "6bec40cf957de430a6f1f2baa056b99a4fac9ea0", 8 | "enabled": true 9 | }, 10 | { 11 | "key": "Organization Name", 12 | "value": "DevNet Sandbox", 13 | "enabled": true 14 | }, 15 | { 16 | "key": "Network Name", 17 | "value": "Sandbox 1 - Galway Ireland", 18 | "enabled": true 19 | }, 20 | { 21 | "key": "organizationId", 22 | "value": "", 23 | "enabled": true 24 | }, 25 | { 26 | "key": "networkId", 27 | "value": "", 28 | "enabled": true 29 | }, 30 | { 31 | "key": "serial", 32 | "value": "", 33 | "enabled": true 34 | } 35 | ], 36 | "_postman_variable_scope": "environment", 37 | "_postman_exported_at": "2021-01-07T18:27:41.248Z", 38 | "_postman_exported_using": "Postman/7.36.1" 39 | } -------------------------------------------------------------------------------- /postman_config/Sandbox NX-OS Standalone.postman_environment.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "73cbbfdd-93f6-a8b4-a468-b50ec4c08c38", 3 | "name": "Sandbox NX-OS Standalone", 4 | "values": [ 5 | { 6 | "enabled": true, 7 | "key": "host", 8 | "value": "10.10.20.58", 9 | "type": "text" 10 | }, 11 | { 12 | "enabled": true, 13 | "key": "username", 14 | "value": "admin", 15 | "type": "text" 16 | }, 17 | { 18 | "enabled": true, 19 | "key": "password", 20 | "value": "Cisco123", 21 | "type": "text" 22 | } 23 | ], 24 | "timestamp": 1506371182627, 25 | "_postman_variable_scope": "environment", 26 | "_postman_exported_at": "2017-11-20T23:33:47.194Z", 27 | "_postman_exported_using": "Postman/5.3.2" 28 | } -------------------------------------------------------------------------------- /postman_config/Sandbox RESTCONF Always On.postman_environment.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "154579bc-c45e-516a-6a0c-815699215142", 3 | "name": "Sandbox RESTCONF Always On", 4 | "values": [ 5 | { 6 | "key": "host", 7 | "value": "ios-xe-mgmt.cisco.com", 8 | "type": "text", 9 | "enabled": true 10 | }, 11 | { 12 | "key": "port", 13 | "value": "9443", 14 | "type": "text", 15 | "enabled": true 16 | }, 17 | { 18 | "key": "username", 19 | "value": "developer", 20 | "type": "text", 21 | "enabled": true 22 | }, 23 | { 24 | "key": "password", 25 | "value": "C1sco12345", 26 | "type": "text", 27 | "enabled": true 28 | } 29 | ], 30 | "_postman_variable_scope": "environment", 31 | "_postman_exported_at": "2021-01-06T19:10:23.447Z", 32 | "_postman_exported_using": "Postman/7.36.1" 33 | } -------------------------------------------------------------------------------- /programming_fundamentals/README.md: -------------------------------------------------------------------------------- 1 | # Programming Fundamentals 2 | In this module you will explore different options available for running code and hosting applications at the edge of the network, directly on switches, routers and other devices. 3 | 4 | ## Lessons 5 | 6 | * [Data Formats: Understanding and using JSON, XML and YAML](data_formats/README.md) 7 | * [APIs are Everywhere... but what are they?](apis/README.md) 8 | * [REST APIs Part 1: HTTP is for more than Web Browsing](rest_part_1/README.md) 9 | * [REST APIs Part 2: Making REST API Calls with Postman](rest_part_2/README.md) 10 | * [Python Part 1: Python Language and Script Basics](python_part_1/README.md) 11 | * [Python Part 2: Working with Libraries and Virtual Environments](python_part_2/README.md) 12 | * [Python Part 3: Useful Python Libraries for Network Engineers](python_part_3/README.md) 13 | -------------------------------------------------------------------------------- /programming_fundamentals/apis/README.md: -------------------------------------------------------------------------------- 1 | # APIs are Everywhere... but what are they? 2 | ## Local Setup 3 | This lesson has no setup requirements. 4 | 5 | ## Download Slides 6 | 7 | You can download the slides for this lesson [here](https://developer.cisco.com/fileMedia/download/67578642-b07f-3007-97f9-3c222842237c). 8 | 9 | > *Suggestion: Right click, "Open in new tab"* -------------------------------------------------------------------------------- /programming_fundamentals/apis/requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/netprog_basics/a8c75a16c30889f723d094e8df0bb5decb06f0f7/programming_fundamentals/apis/requirements.txt -------------------------------------------------------------------------------- /programming_fundamentals/data_formats/GigabitEthernet2.json: -------------------------------------------------------------------------------- 1 | { 2 | "ietf-interfaces:interface": { 3 | "name": "GigabitEthernet2", 4 | "description": "Wide Area Network", 5 | "enabled": true, 6 | "ietf-ip:ipv4": { 7 | "address": [ 8 | { 9 | "ip": "172.16.0.2", 10 | "netmask": "255.255.255.0" 11 | } 12 | ] 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /programming_fundamentals/data_formats/GigabitEthernet2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | GigabitEthernet2 4 | Wide Area Network 5 | true 6 | 7 |
8 | 172.16.0.2 9 | 255.255.255.0 10 |
11 |
12 |
13 | -------------------------------------------------------------------------------- /programming_fundamentals/data_formats/GigabitEthernet2.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | ietf-interfaces:interface: 3 | name: GigabitEthernet2 4 | description: Wide Area Network 5 | enabled: true 6 | ietf-ip:ipv4: 7 | address: 8 | - ip: 172.16.0.2 9 | netmask: 255.255.255.0 10 | -------------------------------------------------------------------------------- /programming_fundamentals/data_formats/README.md: -------------------------------------------------------------------------------- 1 | # Data Formats: Understanding and using JSON, XML and YAML 2 | 3 | ## "Gitting" the Code 4 | All of the code and examples for this lesson is located in the `netprog_basics/programming_fundamentals/data_formats` directory. Clone and access it with the following commands: 5 | 6 | ```bash 7 | git clone https://github.com/CiscoDevNet/netprog_basics 8 | cd netprog_basics/programming_fundamentals/data_formats 9 | ``` 10 | 11 | ## Local Workstation Setup 12 | Be sure to complete the [General Workstation Setup](https://github.com/CiscoDevNet/netprog_basics/blob/master/readme_resources/workstation_setup.md) instructions before beginning this lesson. 13 | 14 | ## DevNet Sandbox 15 | No Sandbox is required for this lesson. 16 | 17 | ## Download Slides 18 | 19 | You can download the slides for this lesson [here](https://developer.cisco.com/fileMedia/download/2681d7c1-4cc3-3bc4-a1c8-a5881eb8dd58). 20 | 21 | > *Suggestion: Right click, "Open in new tab"* 22 | -------------------------------------------------------------------------------- /programming_fundamentals/data_formats/address_list.json: -------------------------------------------------------------------------------- 1 | { 2 | "addresses": [ 3 | { 4 | "ip": "172.16.0.2", 5 | "netmask": "255.255.255.0" 6 | }, 7 | { 8 | "ip": "172.16.0.3", 9 | "netmask": "255.255.255.0" 10 | }, 11 | { 12 | "ip": "172.16.0.4", 13 | "netmask": "255.255.255.0" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /programming_fundamentals/data_formats/address_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 172.16.0.2 4 | 255.255.255.0 5 | 6 | 7 | 172.16.0.3 8 | 255.255.255.0 9 | 10 | 11 | 172.16.0.4 12 | 255.255.255.0 13 | 14 | -------------------------------------------------------------------------------- /programming_fundamentals/data_formats/address_list.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | addresses: 3 | - ip: 172.16.0.2 4 | netmask: 255.255.255.0 5 | - ip: 172.16.0.3 6 | netmask: 255.255.255.0 7 | - ip: 172.16.0.4 8 | netmask: 255.255.255.0 9 | -------------------------------------------------------------------------------- /programming_fundamentals/data_formats/requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/netprog_basics/a8c75a16c30889f723d094e8df0bb5decb06f0f7/programming_fundamentals/data_formats/requirements.txt -------------------------------------------------------------------------------- /programming_fundamentals/python_part_1/README.md: -------------------------------------------------------------------------------- 1 | # Python Part 1: Python Language and Script Basics 2 | 3 | ## "Gitting" the Code 4 | All of the code and examples for this lesson is located in the `netprog_basics/programming_fundamentals/python_part_1` directory. Clone and access it with the following commands: 5 | 6 | ```bash 7 | git clone https://github.com/CiscoDevNet/netprog_basics 8 | cd netprog_basics/programming_fundamentals/python_part_1 9 | ``` 10 | 11 | ## Local Workstation Setup 12 | Be sure to complete the [General Workstation Setup](https://github.com/CiscoDevNet/netprog_basics/blob/master/readme_resources/workstation_setup.md) instructions before beginning this lesson. 13 | 14 | ### Python Environment Setup 15 | It is recommended that this lesson be completed using Python 3.8. Other versions of Python 3 should also work. 16 | 17 | > **Note about Python 2:** Python 2 was [sunset](https://www.python.org/doc/sunset-python-2/) by Python Software Foundation on January 1, 2020. This means that no more updates to Python 2 are being worked on, including security updates. Python 3 is now the recommended version of Python for everyone to use. Most Python developers of software, packages, and scripts have migrated to Python 3 already, however you may find some older scripts and tools that are no longer maintained that only work with Python 2. 18 | > 19 | > You may see/hear references to Python 2 within the videos in this course from before January 2020, however all examples scripts and demos available in the GitHub repo to run have been updated to leverage Python 3. 20 | 21 | ***Note: During this lesson you will explore the basics of Python.*** 22 | 23 | ## DevNet Sandbox 24 | No Sandbox is required for this lesson. 25 | 26 | ## Download Slides 27 | 28 | You can download the slides for this lesson [here](https://developer.cisco.com/fileMedia/download/f41c131a-d809-3b9c-95eb-6f625ce3aa64). 29 | 30 | > *Suggestion: Right click, "Open in new tab"* -------------------------------------------------------------------------------- /programming_fundamentals/python_part_1/example1.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Module: Programming Fundamentals 5 | Lesson: Python Part 1 6 | Author: Hank Preston 7 | 8 | example1.py 9 | Illustrate the following concepts: 10 | - Script Structure and Format 11 | - Importing and using packages 12 | - Variable declaration and usage 13 | - Function creations and usage 14 | - Basic Error Handling 15 | """ 16 | 17 | __author__ = "Hank Preston" 18 | __author_email__ = "hapresto@cisco.com" 19 | __copyright__ = "Copyright (c) 2016 Cisco Systems, Inc." 20 | __license__ = "MIT" 21 | 22 | import sys 23 | 24 | 25 | def doubler(number): 26 | """ 27 | Given a number, double it and return the value 28 | """ 29 | result = number * 2 30 | return result 31 | 32 | 33 | # Entry point for program 34 | if __name__ == '__main__': 35 | # Retrieve command line input 36 | try: 37 | input = float(sys.argv[1]) 38 | except (IndexError, ValueError) as e: 39 | # Indicates no command line parameter was provided 40 | print("You must provide a number as a parameter to this script") 41 | print("Example: ") 42 | print(" python example1.py 12") 43 | sys.exit(1) 44 | 45 | # Double the provided number and print output 46 | answer = doubler(input) 47 | print(answer) 48 | -------------------------------------------------------------------------------- /programming_fundamentals/python_part_1/example2.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Module: Programming Fundamentals 5 | Lesson: Python Part 1 6 | Author: Hank Preston 7 | 8 | example2.py 9 | Illustrate the following concepts: 10 | - Reading from and writing to files 11 | - The "with" statement 12 | - Writing to command line 13 | - Requesting interactive user input 14 | """ 15 | 16 | __author__ = "Hank Preston" 17 | __author_email__ = "hapresto@cisco.com" 18 | __copyright__ = "Copyright (c) 2016 Cisco Systems, Inc." 19 | __license__ = "MIT" 20 | 21 | from datetime import datetime 22 | 23 | log_file = "example2.log" 24 | 25 | 26 | def read_log(log): 27 | """ 28 | Open the logfile and print contents to the terminal 29 | """ 30 | with open(log, "r") as f: 31 | print(f.read()) 32 | 33 | 34 | def write_log(log, name): 35 | """ 36 | Add new logfile entry with datestamp 37 | """ 38 | # Get current date and time 39 | log_time = str(datetime.now()) 40 | with open(log, "a") as f: 41 | f.writelines("Entry logged at: {} by {}\n".format(log_time, name)) 42 | 43 | 44 | # Entry point for program 45 | if __name__ == '__main__': 46 | # Get users name 47 | name = input("What is your name? ") 48 | 49 | # Add entry to log file 50 | print("Adding new log entry") 51 | write_log(log_file, name) 52 | print("") 53 | 54 | # Access Starting Log File 55 | print("Log File Contents") 56 | print("-----------------") 57 | read_log(log_file) 58 | -------------------------------------------------------------------------------- /programming_fundamentals/python_part_1/example3.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Module: Programming Fundamentals 5 | Lesson: Python Part 1 6 | Author: Hank Preston 7 | 8 | example3.py 9 | Illustrate the following concepts: 10 | - Creating and using dictionaries 11 | - Creating and using lists 12 | - Working with for loops 13 | - Conditional statements 14 | """ 15 | 16 | __author__ = "Hank Preston" 17 | __author_email__ = "hapresto@cisco.com" 18 | __copyright__ = "Copyright (c) 2016 Cisco Systems, Inc." 19 | __license__ = "MIT" 20 | 21 | # Example Dictionary 22 | author = {"name": "Hank", "color": "green", "shape": "circle"} 23 | 24 | # A list of colors 25 | colors = ["blue", "green", "red"] 26 | 27 | # A list of dictionaries 28 | favorite_colors = [ 29 | { 30 | "student": "Mary", 31 | "color": "red" 32 | }, 33 | { 34 | "student": "John", 35 | "color": "blue" 36 | } 37 | ] 38 | 39 | # Entry point for program 40 | if __name__ == '__main__': 41 | print("The author's name is {}.".format(author["name"])) 42 | print("His favorite color is {}.".format(author["color"])) 43 | print("") 44 | 45 | print("The current colors are:") 46 | for color in colors: 47 | print(color) 48 | print("") 49 | 50 | # Ask user for favorite color and compare to author's color 51 | new_color = input("What is your favorite color? ") 52 | if new_color == author["color"]: 53 | print("You have the same favorite as {}.".format(author["name"])) 54 | print("") 55 | 56 | # See if this is a new color for the list 57 | if new_color not in colors: 58 | print("That's a new color, adding it to the list!") 59 | colors.append(new_color) 60 | # Print update message about the new colors list 61 | message = ("There are now {} colors in the list. ".format(len(colors))) 62 | message += "The color you added was {}.".format(colors[3]) 63 | print(message) 64 | else: 65 | pass 66 | -------------------------------------------------------------------------------- /programming_fundamentals/python_part_1/requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/netprog_basics/a8c75a16c30889f723d094e8df0bb5decb06f0f7/programming_fundamentals/python_part_1/requirements.txt -------------------------------------------------------------------------------- /programming_fundamentals/python_part_2/README.md: -------------------------------------------------------------------------------- 1 | # Python Part 2: Working with Libraries and Virtual Environments 2 | 3 | ## "Gitting" the Code 4 | All of the code and examples for this lesson is located in the `netprog_basics/programming_fundamentals/python_part_2` directory. Clone and access it with the following commands: 5 | 6 | ```bash 7 | git clone https://github.com/CiscoDevNet/netprog_basics 8 | cd netprog_basics/programming_fundamentals/python_part_2 9 | ``` 10 | 11 | ## Local Workstation Setup 12 | Be sure to complete the [General Workstation Setup](https://github.com/CiscoDevNet/netprog_basics/blob/master/readme_resources/workstation_setup.md) instructions before beginning this lesson. 13 | 14 | ### Python Environment Setup 15 | It is recommended that this lesson be completed using Python 3.8. Other versions of Python 3 should also work. 16 | 17 | > **Note about Python 2:** Python 2 was [sunset](https://www.python.org/doc/sunset-python-2/) by Python Software Foundation on January 1, 2020. This means that no more updates to Python 2 are being worked on, including security updates. Python 3 is now the recommended version of Python for everyone to use. Most Python developers of software, packages, and scripts have migrated to Python 3 already, however you may find some older scripts and tools that are no longer maintained that only work with Python 2. 18 | > 19 | > You may see/hear references to Python 2 within the videos in this course from before January 2020, however all examples scripts and demos available in the GitHub repo to run have been updated to leverage Python 3. 20 | 21 | ***Note: During this lesson you will learn about Python Virtual Environments and Libraries and practice using these tools.*** 22 | 23 | ### Creating Virtual Environments 24 | Python 3 includes a library called `venv` for creating virtual environments. This replaces the `virtualenv` library that was used with Python 2 and shown in the video and slides. The recommended way to create virtual environments in Python 3 is: 25 | 26 | ```python 27 | python3 -m venv venv 28 | ``` 29 | 30 | The `-m` argument to the Python command is used to run a library module. In this case the `venv` library. The second `venv` in the command above is the name of the virtual environment to create. While any name could be used, `venv` is a common practice for naming the virtual enviornment with Python. 31 | 32 | Once created, the virtual environment is activated the same way: 33 | 34 | ``` 35 | source venv/bin/activate 36 | ``` 37 | 38 | ## DevNet Sandbox 39 | No Sandbox is required for this lesson. 40 | 41 | ## Download Slides 42 | 43 | You can download the slides for this lesson [here](https://developer.cisco.com/fileMedia/download/c4e972fd-ce42-3ea6-b957-316472c37c5e). 44 | 45 | > *Suggestion: Right click, "Open in new tab"* -------------------------------------------------------------------------------- /programming_fundamentals/python_part_2/common_vars.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Module: Programming Fundamentals 5 | Lesson: Python Part 2 6 | Author: Hank Preston 7 | 8 | common_vars.py 9 | Illustrate the following concepts: 10 | - Code reuse 11 | 12 | imported into other examples 13 | """ 14 | 15 | shapes = ["square", "triangle", "circle"] 16 | books = [ 17 | { 18 | "title": "War and Peace", 19 | "shelf": 3, 20 | "available": True 21 | }, 22 | { 23 | "title": "Hamlet", 24 | "shelf": 1, 25 | "available": False 26 | }, 27 | { 28 | "title": "Harold and the Purple Crayon", 29 | "shelf": 2, 30 | "available": True 31 | } 32 | ] 33 | colors = ["blue", "green", "red"] 34 | -------------------------------------------------------------------------------- /programming_fundamentals/python_part_2/example1.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Module: Programming Fundamentals 5 | Lesson: Python Part 2 6 | Author: Hank Preston 7 | 8 | example1.py 9 | Illustrate the following concepts: 10 | - importing and using libraries 11 | """ 12 | 13 | __author__ = "Hank Preston" 14 | __author_email__ = "hapresto@cisco.com" 15 | __copyright__ = "Copyright (c) 2016 Cisco Systems, Inc." 16 | __license__ = "MIT" 17 | 18 | # Import data from another script 19 | from common_vars import shapes 20 | # Import a library that offers date-time capabilities 21 | import datetime 22 | 23 | print("The shapes are:") 24 | for shape in shapes: 25 | print(shape) 26 | print("") 27 | 28 | # Get Current Date and Time 29 | date_now = datetime.datetime.now() 30 | print("It is currently {}.".format(str(date_now))) 31 | 32 | # Add 1000 minutes to Current Date and Time 33 | new_date = date_now + datetime.timedelta(minutes=1000) 34 | print("In 1000 minutes it will be {}.".format(str(new_date))) 35 | -------------------------------------------------------------------------------- /programming_fundamentals/python_part_2/requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/netprog_basics/a8c75a16c30889f723d094e8df0bb5decb06f0f7/programming_fundamentals/python_part_2/requirements.txt -------------------------------------------------------------------------------- /programming_fundamentals/python_part_3/README.md: -------------------------------------------------------------------------------- 1 | # Python Part 3: Useful Python Libraries for Network Engineers 2 | 3 | ## "Gitting" the Code 4 | All of the code and examples for this lesson is located in the `netprog_basics/programming_fundamentals/python_part_3` directory. Clone and access it with the following commands: 5 | 6 | ```bash 7 | git clone https://github.com/CiscoDevNet/netprog_basics 8 | cd netprog_basics/programming_fundamentals/python_part_3 9 | ``` 10 | 11 | ## Local Workstation Setup 12 | Be sure to complete the [General Workstation Setup](https://github.com/CiscoDevNet/netprog_basics/blob/master/readme_resources/workstation_setup.md) instructions before beginning this lesson. 13 | 14 | ### Python YAML Loading Note 15 | In the video and slides you'll see the use of `yaml.load()` to process YAML data. The `load` function of the pyyaml library is/was an unsafe method that could be exploited. You can read about this at [https://msg.pyyaml.org/load](https://msg.pyyaml.org/load). 16 | 17 | The `load()` method is now deprecated and will result in the following error message when used. 18 | 19 | ```python 20 | :1: YAMLLoadWarning: calling yaml.load() without Loader=... is deprecated, as the default Loader is unsafe. Please read https://msg.pyyaml.org/load for full details 21 | ``` 22 | 23 | The function `yaml.safe_load()` is the recommended alternative to leverage. 24 | 25 | 26 | ### Python Environment Setup 27 | It is recommended that this lesson be completed using Python 3.8. Other versions of Python 3 should also work. 28 | 29 | > **Note about Python 2:** Python 2 was [sunset](https://www.python.org/doc/sunset-python-2/) by Python Software Foundation on January 1, 2020. This means that no more updates to Python 2 are being worked on, including security updates. Python 3 is now the recommended version of Python for everyone to use. Most Python developers of software, packages, and scripts have migrated to Python 3 already, however you may find some older scripts and tools that are no longer maintained that only work with Python 2. 30 | > 31 | > You may see/hear references to Python 2 within the videos in this course from before January 2020, however all examples scripts and demos available in the GitHub repo to run have been updated to leverage Python 3. 32 | 33 | It is highly recommended to leverage Python Virtual Environments for completing exercises in this course. 34 | 35 | *There is no need to create independent venv for each lesson, but you can if you choose.* 36 | 37 | Follow these steps to create and activate a venv. 38 | 39 | ***Note: If you are leveraging a shared venv across all lessons simply activate it.*** 40 | 41 | ```bash 42 | # OS X or Linux 43 | python3 -m venv venv 44 | source venv/bin/activate 45 | ``` 46 | 47 | ```bash 48 | # Windows 49 | python -m venv venv 50 | venv/Scripts/activate 51 | ``` 52 | 53 | #### Install Python Requirements for Lesson 54 | With the Virtual Environment activated, use pip to install the necessary requirements. 55 | 56 | ```bash 57 | # From the code directory for this lesson 58 | pip install -r requirements.txt 59 | ``` 60 | 61 | ***Note: During the lesson, there are instructions to `pip install` different libraries. If you follow this setup, you will already have the libraries installed, but still run the commands to become familiar with using them*** 62 | 63 | ## DevNet Sandbox 64 | This lesson leverages the [IOS XE on CSR Recommended Code Always On](https://devnetsandbox.cisco.com/RM/Diagram/Index/27d9747a-db48-4565-8d44-df318fce37ad?diagramType=Topology) Sandbox. This sandbox requires no reservation **or** VPN connection. 65 | 66 | ***Note: In the video, a different DevNet Sandbox is used*** 67 | 68 | In the Python API Examples, the `router` dictionary will use `ios-xe-mgmt.cisco.com` for the address, and different ports than in the video. The Python example files in the code repository have been updated to use the Always On Sandbox already. 69 | 70 | 71 | ## Download Slides 72 | 73 | You can download the slides for this lesson [here](https://developer.cisco.com/fileMedia/download/39d29167-4b3d-3086-b777-3dcfeaeb6a1e). 74 | 75 | > *Suggestion: Right click, "Open in new tab"* -------------------------------------------------------------------------------- /programming_fundamentals/python_part_3/api_ncclient_example.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Module: Programming Fundamentals 5 | Lesson: Python Part 3 6 | Author: Hank Preston 7 | 8 | api_ncclient_example.py 9 | Illustrate the following concepts: 10 | - Making NETCONF calls using ncclient library 11 | - Intended to be entered into an interactive 12 | interpreter 13 | """ 14 | 15 | from ncclient import manager 16 | from pprint import pprint 17 | import xmltodict 18 | 19 | router = {"ip": "ios-xe-mgmt.cisco.com", 20 | "port": 10000, 21 | "user": "developer", 22 | "pass": "C1sco12345"} 23 | 24 | netconf_filter = """ 25 | 26 | 27 | 28 | GigabitEthernet1 29 | 30 | 31 | 32 | """ 33 | 34 | m = manager.connect(host=router["ip"], 35 | port=router["port"], 36 | username=router["user"], 37 | password=router["pass"], 38 | hostkey_verify=False) 39 | 40 | interface_netconf = m.get_config("running", netconf_filter) 41 | interface_python = xmltodict.parse(interface_netconf.xml)["rpc-reply"]["data"] 42 | pprint(interface_python["interfaces"]["interface"]["name"]["#text"]) 43 | -------------------------------------------------------------------------------- /programming_fundamentals/python_part_3/api_netmiko_example.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Module: Programming Fundamentals 5 | Lesson: Python Part 3 6 | Author: Hank Preston 7 | 8 | api_netmiko_example.py 9 | Illustrate the following concepts: 10 | - Making CLI calls using netmiko library 11 | - Intended to be entered into an interactive 12 | interpreter 13 | """ 14 | 15 | from netmiko import ConnectHandler 16 | from pprint import pprint 17 | 18 | router = {"device_type": "cisco_ios", 19 | "host": "ios-xe-mgmt.cisco.com", 20 | "port": 8181, 21 | "user": "developer", 22 | "pass": "C1sco12345"} 23 | 24 | net_connect = ConnectHandler(ip=router["host"], 25 | port=router["port"], 26 | username=router["user"], 27 | password=router["pass"], 28 | device_type=router["device_type"]) 29 | 30 | interface_cli = net_connect.send_command("show run int Gig1") 31 | 32 | pprint(interface_cli) 33 | -------------------------------------------------------------------------------- /programming_fundamentals/python_part_3/api_pysnmp_example.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Module: Programming Fundamentals 5 | Lesson: Python Part 3 6 | Author: Hank Preston 7 | 8 | api_snmp_example.py 9 | Illustrate the following concepts: 10 | - How to make an SNMP GET with PySNMP 11 | - Intended to be entered into an interactive 12 | interpreter 13 | 14 | Sandbox Usage: The DevNet Always On IOS XE Sandbox does NOT 15 | have SNMP available. If you'd like to try this example, you 16 | can reserve the "IOS XE on CSR Recommended Code" Sandbox 17 | """ 18 | 19 | from pysnmp.hlapi import * 20 | from pprint import pprint 21 | 22 | router = {"ip": "10.10.20.48", 23 | "port": 161, 24 | "user": "developer", 25 | "pass": "C1sco12345"} 26 | 27 | iterator = getCmd(SnmpEngine(), 28 | CommunityData('public'), 29 | UdpTransportTarget((router["ip"], router["port"])), 30 | ContextData(), 31 | ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0))) 32 | 33 | errorIndication, errorStatus, errorIndex, varBinds = next(iterator) 34 | 35 | if errorIndication: # SNMP engine errors 36 | print(errorIndication) 37 | print("Check to be sure you're connected to the VPN for the DevNet Sandbox.") 38 | else: 39 | if errorStatus: # SNMP agent errors 40 | print('%s at %s' % (errorStatus.prettyPrint(), 41 | varBinds[int(errorIndex)-1] if errorIndex else '?')) 42 | else: 43 | for varBind in varBinds: # SNMP response contents 44 | print(' = '.join([x.prettyPrint() for x in varBind])) 45 | -------------------------------------------------------------------------------- /programming_fundamentals/python_part_3/api_requests_example.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Module: Programming Fundamentals 5 | Lesson: Python Part 3 6 | Author: Hank Preston 7 | 8 | api_requests_example.py 9 | Illustrate the following concepts: 10 | - Making REST API calls using requests library 11 | - Intended to be entered into an interactive 12 | interpreter 13 | """ 14 | 15 | 16 | import requests 17 | from pprint import pprint 18 | import urllib3 19 | 20 | # Disable SSL Warnings 21 | urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) 22 | 23 | router = {"ip": "ios-xe-mgmt.cisco.com", 24 | "port": "443", 25 | "user": "developer", 26 | "pass": "lastorangerestoreball8876"} 27 | 28 | headers = {"Accept": "application/yang-data+json"} 29 | 30 | u = "https://{}:{}/restconf/data/interfaces/interface=GigabitEthernet1" 31 | 32 | u = u.format(router["ip"], router["port"]) 33 | 34 | r = requests.get(u, 35 | headers = headers, 36 | auth=(router["user"], router["pass"]), 37 | verify=False) 38 | 39 | pprint(r.text) 40 | 41 | api_data = r.json() 42 | interface_name = api_data["Cisco-IOS-XE-interfaces-oper:interface"]["name"] 43 | interface_name 44 | -------------------------------------------------------------------------------- /programming_fundamentals/python_part_3/csv_example.csv: -------------------------------------------------------------------------------- 1 | "router1","10.1.0.1","New York" 2 | "router2","10.2.0.1","Denver" 3 | "router3","10.3.0.1","Austin" 4 | -------------------------------------------------------------------------------- /programming_fundamentals/python_part_3/data_library_exercises.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | """ 3 | Learning Series: Network Programmability Basics 4 | Module: Programming Fundamentals 5 | Lesson: Python Part 3 6 | Author: Hank Preston 7 | 8 | data_library_exercises.py 9 | Illustrate the following concepts: 10 | - Commands from slides exploring data interactions 11 | """ 12 | 13 | # XML 14 | print("Treat XML like Python Dictionaries with xmltodict\n\n") 15 | import xmltodict 16 | from pprint import pprint 17 | 18 | xml_example = open("xml_example.xml").read() 19 | pprint(xml_example) 20 | 21 | xml_dict = xmltodict.parse(xml_example) 22 | int_name = xml_dict["interface"]["name"] 23 | print(int_name) 24 | 25 | print(xmltodict.unparse(xml_dict)) 26 | 27 | print("\n\n") 28 | 29 | # JSON 30 | print("To JSON and back again with json\n\n") 31 | import json 32 | from pprint import pprint 33 | 34 | json_example = open("json_example.json").read() 35 | pprint(json_example) 36 | 37 | json_python = json.loads(json_example) 38 | int_name = json_python["ietf-interfaces:interface"]["name"] 39 | print(int_name) 40 | 41 | print(json.dumps(json_python)) 42 | 43 | print("\n\n") 44 | 45 | # YAML 46 | print("YAML? Yep, Python Can Do That Too!\n\n") 47 | import yaml 48 | from pprint import pprint 49 | 50 | yml_example = open("yaml_example.yaml").read() 51 | pprint(yml_example) 52 | 53 | # Note: The video used the yaml.load() method. This method 54 | # has security vulnerabilities and has been deprecated. The 55 | # yaml.safe_load() method is the suggested way to load YAML 56 | # data now. 57 | # You can read about this at https://msg.pyyaml.org/load 58 | yaml_python = yaml.safe_load(yml_example) 59 | int_name = yaml_python["ietf-interfaces:interface"]["name"] 60 | print(int_name) 61 | 62 | print(yaml.dump(yaml_python)) 63 | 64 | print("\n\n") 65 | 66 | # CSV 67 | print("Import Spreadsheets and Data with csv\n\n") 68 | import csv 69 | from pprint import pprint 70 | 71 | csv_example = open("csv_example.csv").read() 72 | pprint(csv_example) 73 | 74 | csv_example = open("csv_example.csv") 75 | csv_python = csv.reader(csv_example) 76 | 77 | for row in csv_python: 78 | print("{} is in {} and has IP {}.".format(row[0], row[2], row[1])) 79 | 80 | print("\n\n") -------------------------------------------------------------------------------- /programming_fundamentals/python_part_3/json_example.json: -------------------------------------------------------------------------------- 1 | { 2 | "ietf-interfaces:interface": { 3 | "name": "GigabitEthernet2", 4 | "description": "Wide Area Network", 5 | "enabled": true, 6 | "ietf-ip:ipv4": { 7 | "address": [ 8 | { 9 | "ip": "172.16.0.2", 10 | "netmask": "255.255.255.0" 11 | } 12 | ] 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /programming_fundamentals/python_part_3/requirements.txt: -------------------------------------------------------------------------------- 1 | ncclient>=0.6.9 2 | netmiko>=3.3.2 3 | pyyaml>=5.3.1 4 | requests>=2.25.1 5 | xmltodict>=0.12.0 6 | pysnmp>=4.4.12 -------------------------------------------------------------------------------- /programming_fundamentals/python_part_3/scratchpad.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from pprint import pprint 3 | 4 | router = {"ip": "127.0.0.1", 5 | "port": "2225", 6 | "user": "vagrant", 7 | "pass": "vagrant"} 8 | 9 | headers = {"Accept": "application/yang-data+json"} 10 | 11 | u = 'https://{}:{}/restconf/data/ietf-interfaces:interfaces/"interface=GigabitEthernet2' 12 | u = u.format(router["ip"], router["port"]) 13 | 14 | 15 | r = requests.get(u, 16 | headers = headers, 17 | auth=(router["user"], router["pass"]), 18 | verify=False) 19 | pprint(r.text) 20 | 21 | api_data = r.json() 22 | interface_name = api_data["ietf-interfaces:interface"]["name"] 23 | interface_name 24 | 25 | 26 | from ncclient import manager 27 | from pprint import pprint 28 | import xmltodict 29 | 30 | router = {"ip": "127.0.0.1", "port": 2223, 31 | "user": "vagrant", "pass": "vagrant"} 32 | 33 | netconf_filter = """ 34 | 35 | 36 | 37 | GigabitEthernet2 38 | 39 | 40 | 41 | """ 42 | 43 | m = manager.connect(host=router["ip"], 44 | port=router["port"], 45 | username=router["user"], 46 | password=router["pass"], 47 | hostkey_verify=False) 48 | 49 | interface_netconf = m.get_config("running", netconf_filter) 50 | interface_python = xmltodict.parse(interface_netconf.xml)["rpc-reply"]["data"]["interfaces"]["interface"] 51 | 52 | pprint(interface_python["name"]["#text"]) 53 | 54 | 55 | interface_python=xmltodict.parse(interface_netconf.xml)["rpc-reply"]["data"] 56 | 57 | pprint(interface_python["interfaces"]["interface"]["name"]["#text"]) 58 | 59 | 60 | 61 | from netmiko import ConnectHandler 62 | from pprint import pprint 63 | 64 | router = { 65 | 'device_type': 'cisco_ios', 66 | 'host': '127.0.0.1', 67 | 'user': 'vagrant', 68 | 'pass': 'vagrant', 69 | 'port' : 2222 70 | } 71 | 72 | net_connect = ConnectHandler(ip=router["host"], 73 | port=router["port"], 74 | username=router["user"], 75 | password=router["pass"], 76 | device_type=router["device_type"] 77 | ) 78 | 79 | interface_cli = net_connect.send_command("show run int Gig2") 80 | 81 | pprint(interface_cli) 82 | -------------------------------------------------------------------------------- /programming_fundamentals/python_part_3/xml_example.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | GigabitEthernet2 4 | Wide Area Network 5 | true 6 | 7 |
8 | 172.16.0.2 9 | 255.255.255.0 10 |
11 |
12 |
13 | -------------------------------------------------------------------------------- /programming_fundamentals/python_part_3/yaml_example.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | ietf-interfaces:interface: 3 | name: GigabitEthernet2 4 | description: Wide Area Network 5 | enabled: true 6 | ietf-ip:ipv4: 7 | address: 8 | - ip: 172.16.0.2 9 | netmask: 255.255.255.0 10 | -------------------------------------------------------------------------------- /programming_fundamentals/rest_part_1/README.md: -------------------------------------------------------------------------------- 1 | # REST APIs Part 1: HTTP is for more than Web Browsing 2 | 3 | ## "Gitting" the Code 4 | All of the code and examples for this lesson is located in the `netprog_basics/programming_fundamentals/rest_part_1 ` directory. Clone and access it with the following commands: 5 | 6 | ```bash 7 | git clone https://github.com/CiscoDevNet/netprog_basics 8 | cd netprog_basics/programming_fundamentals/rest_part_1 9 | ``` 10 | 11 | ## Local Workstation Setup 12 | Be sure to complete the [General Workstation Setup](https://github.com/CiscoDevNet/netprog_basics/blob/master/readme_resources/workstation_setup.md) instructions before beginning this lesson. 13 | 14 | ### curl on Windows 15 | In this lesson the Linux utility `curl` is used to send basic REST API requests. On Linux and OS X, `curl` is available and installed by default. 16 | 17 | Windows does **not** come with `curl` by default, but today there are several options for running Linux utilities like `curl` on Windows with ease. Here are two options to use. 18 | 19 | 1. `git bash`: When you install git for Windows, it includes `git bash` which is a bash shell option for Windows that includes common Linux tools such as `curl`. Just start `git bash` and work as if you are within bash on Linux. 20 | 2. `Ubuntu Bash`: If you are on Windows 10 you can install Ubuntu Bash using the Linux Subsystem for Windows. Once installed you can run the Ubuntu Bash Shell and work within Linux from Windows. 21 | 22 | ## DevNet Sandbox 23 | This lesson leverages the [IOS XE on CSR Recommended Code Always On](https://devnetsandbox.cisco.com/RM/Diagram/Index/27d9747a-db48-4565-8d44-df318fce37ad?diagramType=Topology) Sandbox. This sandbox requires no reservation **or** VPN connection. 24 | 25 | ***Note: In the video, a different DevNet Sandbox is used*** 26 | 27 | When running the `curl` for the RESTCONF example, leverage `https://ios-xe-mgmt.cisco.com:443` as the URL instead of `https://10.10.20.21`. 28 | 29 | ## Download Slides 30 | 31 | You can download the slides for this lesson [here](https://developer.cisco.com/fileMedia/download/c5942bff-3499-3e11-829a-fa90ebeb5fd1). 32 | 33 | > *Suggestion: Right click, "Open in new tab"* 34 | -------------------------------------------------------------------------------- /programming_fundamentals/rest_part_1/curl_examples.sh: -------------------------------------------------------------------------------- 1 | # Learning Series: Network Programmability Basics 2 | # Module: Programming Fundamentals 3 | # Lesson: REST Part 1 4 | # Author: Hank Preston 5 | # 6 | # curl_examples.sh 7 | # Illustrate the following concepts: 8 | # - REST API Basics 9 | # - Leveraging curl utility 10 | 11 | # Example 1: Random Chuck Norris Joke 12 | curl https://api.icndb.com/jokes/random 13 | 14 | # Example 2: Nerdy Chuck Norris Joke 15 | curl https://api.icndb.com/jokes/random?limitTo=nerdy 16 | 17 | # Example 3: Network Programmability with RESTCONF 18 | curl -vk \ 19 | -u developer:lastorangerestoreball8876 \ 20 | -H 'accept: application/yang-data+json' \ 21 | https://ios-xe-mgmt.cisco.com:443/restconf/data/ietf-interfaces:interfaces/interface=GigabitEthernet2 22 | -------------------------------------------------------------------------------- /programming_fundamentals/rest_part_1/requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/netprog_basics/a8c75a16c30889f723d094e8df0bb5decb06f0f7/programming_fundamentals/rest_part_1/requirements.txt -------------------------------------------------------------------------------- /programming_fundamentals/rest_part_2/requirements.txt: -------------------------------------------------------------------------------- 1 | requests==2.18.2 2 | -------------------------------------------------------------------------------- /readme_resources/dev-env-centos.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/netprog_basics/a8c75a16c30889f723d094e8df0bb5decb06f0f7/readme_resources/dev-env-centos.jpg -------------------------------------------------------------------------------- /readme_resources/dev-env-mac.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/netprog_basics/a8c75a16c30889f723d094e8df0bb5decb06f0f7/readme_resources/dev-env-mac.jpg -------------------------------------------------------------------------------- /readme_resources/dev-env-win.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/netprog_basics/a8c75a16c30889f723d094e8df0bb5decb06f0f7/readme_resources/dev-env-win.jpg -------------------------------------------------------------------------------- /readme_resources/dev-env.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CiscoDevNet/netprog_basics/a8c75a16c30889f723d094e8df0bb5decb06f0f7/readme_resources/dev-env.jpg --------------------------------------------------------------------------------