Instructor DevNet Associate Lab

Lab 1.1.2 Lab - Install the Virtual Machine Lab Environment (Instructor Version) Instructor Note: Red font color or gray

Views 496 Downloads 110 File size 4MB

Report DMCA / Copyright

DOWNLOAD FILE

Recommend stories

  • Author / Uploaded
  • indry
Citation preview

Lab 1.1.2 Lab - Install the Virtual Machine Lab Environment (Instructor Version) Instructor Note: Red font color or gray highlights indicate text that appears in the instructor copy only.

Objectives Part 1: Prepare a Computer for Virtualization Part 2: Explore the DEVASC VM GUI Part 3: Create Lab Environment Accounts Part 4: Install Webex Teams on your Device

Background / Scenario In this lab, you will install the DEVASC virtual machine (DEVASC VM) in Oracle VirtualBox. After completing the installation, you will explore the GUI interface. You will then create the necessary accounts for the services that you will use throughout the labs. Finally, you will install Webex Teams in the lab environment for communication with the other students in your class, and for use in later labs.

Required Resources •

Host computer with at least 4 GB of RAM and 15 GB of free disk space



High-speed internet access to download Oracle VirtualBox and the DEVASC VM

Instructions Part 1: Prepare a Computer for Virtualization In this Part, you will download and install desktop virtualization software and the DEVASC VM. Your instructor may provide you with the DEVASC VM file. Note: The following instructions are for Windows 10 using VirtualBox v6.1.4. Your steps may differ slightly. Regardless of the operating system or VirtualBox version, be sure you locate and select the options specified in the following steps. Note: If you have previously installed VirtualBox, you can proceed to Step 2.

Step 1: Download and install VirtualBox. VMware Player and Oracle VirtualBox are two virtualization programs that you can download and install to support the VM images. In this lab, you will use the VirtualBox application. a. Navigate to https://www.virtualbox.org/. Click the download link on this page. b. Choose and download the appropriate VirtualBox installation file based on your operating system. c.

Run the installer for VirtualBox and accept the default installation settings.

d. VirtualBox is open and ready for the next step.

Step 2: Import the DEVASC VM. a. Navigate to the Cisco Networking Academy DEVASC VM and download it. Note the location of the downloaded VM. b. In VirtualBox, select File > Import Appliance.

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 1 of 3

www.netacad.com

Lab - Install the Virtual Machine Lab Environment

c.

The source of the appliance is Local File System. Browse to the location of the downloaded DEVASC VM, and click Open.

d. Click Import to continue. The import process will take several minutes.

Part 2: Explore the DEVASC VM GUI a. Start the DEVASC VM. This will take a few minutes as the Ubuntu image boots. b. The DEVASC VM contains Packet Tracer. You must agree to the Cisco Packet Tracer EULA to continue starting the VM. When you see the license agreement, use the arrow keys to scroll the text. Press the Right Arrow key to select when you are finished. Press the Space Bar to move to the Agreement screen. Press the Left Arrow key to select when you are finished. c.

The Ubuntu image will continue to load. Close any popup messages.

d. In the later labs, you will use the terminal, VS Code, Packet Tracer, Chromium Browser, and Postman. Open these applications and explore them. e. Click the Menu button and explore the Places, System, and All applications. Remember that this is a virtual machine and is completely separate from the computer on which it is installed. You can make any changes you like. If you make a mistake, or break something, you can simply remove the VM from VirtualBox, and import a fresh copy from the file you downloaded. This is a great way to experiment with programs without affecting your real computer. Don't be afraid to explore and have fun!

Part 3: Create Lab Environment Accounts There are many tools that you will need to use to complete the labs in this course. Some of these require you to have your own account. These are easy to set up and can be done for free. In this Part, you will create the accounts you will need for the rest of the course.

Step 1: Create a DevNet account. a. Open the Chromium browser and navigate to developer.cisco.com. b. Click SIGN UP FREE. c.

You can choose any of the Login types for which you already have an account. This allows for easy association with other accounts. If you do not wish to associate your DevNet account with any other apps, Choose Login with a Cisco ID.

d. Follow the instructions to complete the account creation.

Step 2: Create a GitHub account. a. Navigate to github.com. b. Fill in the fields for Username, Email, and Password, and then click Sign up for GitHub. c.

Perform any verification to ensure you are human.

d. Click Join a free plan. e. On the next page, click Complete Setup.

Step 3: Create a Webex account. a. Navigate to webex.com. b. Click Start for Free or Sign up now, it's free. c.

Enter the Email address you wish to use.

d. Click Sign Up. e. Follow the instructions to complete the account creation. © 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 2 of 3

www.netacad.com

Lab - Install the Virtual Machine Lab Environment

Step 4: Shut down the VM. When you are done with the VM, you can save the machine state of the VM for future use or shut down the VM. Close the VM using the GUI: a. From the Virtual Box File menu, choose Close... b. Click the Save the machine state radio button and click OK. The next time you start the virtual machine, you will be able to resume working in the operating system in its current state. The other two options are: •

Send the shutdown signal: This simulates pressing the power button on a physical computer.



Power off the machine: This simulates pulling the plug on a physical computer.

Close the VM using the CLI: To shut down the VM using the command line, you can use the menu options inside the VM or enter sudo shutdown -h now command in a terminal window. Rebooting the VM: If you want to reboot the VM, you can use the menu options inside the VM or enter the sudo reboot command in a terminal.

Part 4: Install Webex Teams on your Device In this Part, you will install Webex Teams

Step 1: Download the installation file. a. Navigate to www.webex.com/downloads.html b. Under Webex Teams, click Download for Windows, or you can choose to install Teams on your mobile device. Note: For MacOS, you will download the Mac version. At the time of this lab was written, there is no Linux desktop application. However, you can run Webex Teams in a browser. Click Sign in at the top and choose Webex Teams. Then sign in with your new Webex account credentials. c.

Open the installation file and follow the instructions to finish the installation.

Step 2: Launch Webex Teams. Open Webex Teams. If your instructor already created a Team, you should see that you are now a member. If not, then you can do one of the following: •

Give your instructor your email address so that you can be added to the class Team.



Create your own Team. In the left panel, click the Teams button. Then click the plus button to Create a team. A Team is required for the next step.

Step 3: Add a user to Webex Teams. a. In Webex Teams, search for a user in the Search field. You may search by username or email. The user must be a member of your team. b. Click the user in the list of search results to open a space. c.

Type a message to the user. They will be notified of your message and can now return a message to you.

End of document

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 3 of 3

www.netacad.com

LAB 1.2.2 Lab - Linux Review (Instructor Version) Instructor Note: Red font color or gray highlights indicate text that appears in the instructor copy only.

Objectives Part 1: Launch the DEVASC VM Part 2: Review Command Syntax Navigation Part 3: Review File Management Part 4: Review Regular Expressions Part 5: Review System Administration

Background / Scenario In this lab, you review basic Linux skills including command navigation, file management, regular expressions, and system administration. This lab is not meant as a substitute for prior Linux experience and does not necessarily cover all the Linux skills you need for this course. However, this lab should serve as a good measure of your Linux skills and help direct you to where you may need more review.

Required Resources •

1 PC with operating system of your choice



Virtual Box or VMWare



DEVASC Virtual Machine

Instructions Part 1: Launch the DEVASC VM If you have not already completed the Lab - Install the Virtual Machine Lab Environment, do so now. If you have already completed that lab, launch the DEVASC VM now.

Part 2: Review Command Syntax Navigation In this part, you will use the ls, pwd, cd, and sudo commands to review basic command syntax navigation.

Step 1: Open a terminal in the DEVASC-LABVM. a. Double-click the Terminal Emulator icon on the desktop to open a terminal window.

Step 2: Navigate directories. a. Use the ls command to display a listing of the current directory. Remember that commands are casesensitive. devasc@labvm:~$ ls Desktop Documents

Downloads labs

Music Pictures

Public snap

Templates Videos

devasc@labvm:~$ b. Use the ls command with the labs argument to display the contents of the labs folder.

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 1 of 15

www.netacad.com

Lab - Linux Review

devasc@labvm:~$ ls labs devnet-src

devasc@labvm:~$ c.

Use the ls command with the -l option to display a "long display" of the contents of the current directory. devasc@labvm:~$ ls -l total 40 drwxr-xr-x drwxr-xr-x drwxr-xr-x drwxr-xr-x drwxr-xr-x drwxr-xr-x drwxr-xr-x drwxr-xr-x drwxr-xr-x drwxr-xr-x

2 2 2 5 2 2 2 5 2 2

devasc devasc devasc devasc devasc devasc devasc devasc devasc devasc

devasc devasc devasc devasc devasc devasc devasc devasc devasc devasc

4096 4096 4096 4096 4096 4096 4096 4096 4096 4096

Mar Apr Apr Mar Apr Apr Apr Mar Apr Apr

30 15 15 30 15 15 15 30 15 15

21:25 19:09 19:09 21:21 19:09 19:09 19:09 21:24 19:09 19:09

Desktop Documents Downloads labs Music Pictures Public snap Templates Videos

devasc@labvm:~$ d. Use the ls command with the -r option to display the contents of the current directory in reverse alphabetical order. devasc@labvm:~$ ls -r Videos Templates

snap Public

Pictures Music

labs Downloads

Documents Desktop

devasc@labvm:~$ e. Multiple options can be used at the same time. Use the ls command with both the -l and -r options to display the contents of the current directory both in long and reverse order. devasc@labvm:~$ ls -lr total 40 drwxr-xr-x drwxr-xr-x drwxr-xr-x drwxr-xr-x drwxr-xr-x drwxr-xr-x drwxr-xr-x drwxr-xr-x drwxr-xr-x drwxr-xr-x

2 2 5 2 2 2 5 2 2 2

devasc devasc devasc devasc devasc devasc devasc devasc devasc devasc

devasc devasc devasc devasc devasc devasc devasc devasc devasc devasc

4096 4096 4096 4096 4096 4096 4096 4096 4096 4096

Apr Apr Mar Apr Apr Apr Mar Apr Apr Mar

15 15 30 15 15 15 30 15 15 30

19:09 19:09 21:24 19:09 19:09 19:09 21:21 19:09 19:09 21:25

Videos Templates snap Public Pictures Music labs Downloads Documents Desktop

devasc@labvm:~$ f.

There are many more options that can be used with the ls command. Use the man command with the argument ls to see all of the possibilities in the manual. The man command can be used to look up any command within the system. Use the space bar to advance to subsequent screens. Press q to quit. devasc@labvm:~$ man ls (The command line disappears and the manual page for ls opens.) LS(1) User Commands

LS(1)

NAME ls - list directory contents © 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 2 of 15

www.netacad.com

Lab - Linux Review

SYNOPSIS ls [OPTION]... [FILE]... DESCRIPTION List

information

about

the FILEs (the current directory by default).

Sort entries alphabetically if none of -cftuvSUX nor --sort fied. Mandatory too.

arguments

to

long

is

speci‐

options are mandatory for short options

-a, --all do not ignore entries starting with . -A, --almost-all do not list implied . and .. --author Manual page ls(1) line 1 (press h for help or q to quit)

g. You can also use --help argument after most commands to see a shorter summary of all the available command options. devasc@labvm:~$ ls --help Usage: ls [OPTION]... [FILE]... List information about the FILEs (the current directory by default). Sort entries alphabetically if none of -cftuvSUX nor --sort is specified. Mandatory arguments to long options are mandatory for short options too. -a, --all do not ignore entries starting with . -A, --almost-all do not list implied . and .. (Output Omitted)

devasc@labvm:~$ h. Use the pwd command to display the current working directory. devasc@labvm:~$ pwd /home/devasc

devasc@labvm:~$ i.

Use the cd command to change the directory to /home/devasc/Documents. devasc@labvm:~$ cd Documents devasc@labvm:~/Documents$

j.

Use the cd command with the / symbol to change directories to the root directory. Use pwd again to see that you are now in the root directory. devasc@labvm:~/Documents$ cd / devasc@labvm:/$ pwd /

devasc@labvm:/$

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 3 of 15

www.netacad.com

Lab - Linux Review

k.

Return to the /home/devasc/Documents directory. Tip: You can move one directory at a time or all the way to a destination. To quickly enter the command, type the first few letters of the directory name and press Tab for the system to automatically enter the rest of the name. Remember that names are casesensitive. devasc@labvm:/$ cd /home/devasc/Documents/ devasc@labvm:~/Documents$

l.

Use the .. characters to move up a single directory. Use pwd again to see you are back in the user’s home directory. devasc@labvm:~/Documents$ cd .. devasc@labvm:~$ pwd /home/devasc

devasc@labvm:~$

Step 3: Use super user commands for administrative access. a. Use the sudo command to issue a single command as the root user. A new terminal will not be created. Use the sudo apt-get update command to update to refresh the list of available packages installed on the VM. This command will not work without using the sudo command. Note: Your output will most likely be different. devasc@labvm:~$ sudo apt-get update Get:1 http://security.ubuntu.com/ubuntu focal-security InRelease [97.9 kB] Get:2 http://us.archive.ubuntu.com/ubuntu focal InRelease [265 kB] Get:3 http://us.archive.ubuntu.com/ubuntu focal-updates InRelease [89.1 kB] Get:4 http://us.archive.ubuntu.com/ubuntu focal-backports InRelease [89.2 kB] Get:5 http://us.archive.ubuntu.com/ubuntu focal/main i386 Packages [723 kB] Get:6 http://us.archive.ubuntu.com/ubuntu focal/main amd64 Packages [981 kB] (Output Omitted) Fetched 677 kB in 2s (346 kB/s) Reading package lists... Done

devasc@labvm:~$

Part 3: Review File Management In this part, you will review file permissions, change file permissions and ownership, move files, copy files, remove files, and view files.

Step 1: Review file permissions. a. Use the ls Desktop -l to display the contents of the Desktop folder. devasc@labvm:~$ ls Desktop -l total 28 -rwxr-xr-x 1 devasc -rwxr-xr-x 1 devasc tracer.desktop -rwxr-xr-x 1 devasc -rwxr-xr-x 1 devasc -rwxr-xr-x 1 devasc -rwxr-xr-x 1 devasc -rwxr-xr-x 1 devasc

devasc 1095 Mar 30 21:24 chromium_chromium.desktop devasc 401 Mar 30 21:25 cisco-packet-tracer_cisco-pacetdevasc devasc devasc devasc devasc

776 373 250 99 334

Mar Mar Mar Mar Mar

30 30 30 30 30

21:23 21:25 21:21 21:21 21:24

code.desktop drawio_drawio.desktop exo-terminal-emulator.desktop labs.desktop postman_postman.desktop

devasc@labvm:~$

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 4 of 15

www.netacad.com

Lab - Linux Review

b. Answer the following questions about the output above. If necessary, search the internet for information of Linux file permission shown in the output of the ls command. Questions

What does the initial dash represent in the permission information? Type your answers here. This is the file type field. The dash represents a regular file. What would be in the place of the dash if the item was a directory? Type your answers here. It would be a "d" for "directory". What do the next three letters or dashes represent in the permission information? Type your answers here. These represent the permissions of the file owner over the file. What do the middle three letters or dashes represent in the permission information? Type your answers here. These represent the permissions of the group over the file. What do the last three letters or dashes represent in the permission information? Type your answers here. These represent the permissions others over the file. What does the first instance of "devasc" in the permission information indicate? Type your answers here. This indicates the user owner field and is the owner of the file. What does the second instance of "devasc" in the permission information indicate? Type your answers here. This indicates the group owner field and is the group of the file. What does a permission type of "r" mean? Type your answers here. This means a permission of "read". This allows for file contents to be read or copied. What does a permission type of "w" mean? Type your answers here. This means a permission of "write". This allows for contents to be modified or overwritten. It allows for files to be added or removed from a directory. What does a permission type of "x" mean? Type your answers here. This means a permission of "execute". This allows for a file to be run as a process, although script files require read permission, as well.

Step 2: Change file permissions and ownership. a. Use the command cd to change to the Documents directory. devasc@labvm:~$ cd Documents/ devasc@labvm:~/Documents$ © 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 5 of 15

www.netacad.com

Lab - Linux Review

b. Use the command echo to create a shell script file, that will have the command ls ../Desktop inside the file. Remember that the greater than (>) character redirects command output to a file. devasc@labvm:~/Documents$ echo "ls ../Desktop" > myfile.sh devasc@labvm:~/Documents$ c.

The myfile.sh script is stored in the /Documents directory. Use the cat command to view the only command in the script. This file will be used as an example to modify permissions and ownership. devasc@labvm:~/Documents$ cat myfile.sh ls ../Desktop

devasc@labvm:~/Documents$ d. Use the command ./myfile.sh to run the script. Access is denied because you must set the permission of executable on the file. devasc@labvm:~/Documents$ ./myfile.sh bash: ./myfile.sh: Permission denied

e. Use the command ls -l myfile.sh to view the current file permissions. devasc@labvm:~/Documents$ ls -l myfile.sh -rw-rw-r-- 1 devasc devasc 14 Apr 16 12:46 myfile.sh

f.

Use the command chmod +x myfile.sh to allow you to execute the file. devasc@labvm:~/Documents$ chmod +x myfile.sh devasc@labvm:~/Documents$

g. Use the command ./myfile.sh to run the script. devasc@labvm:~/Documents$ ./myfile.sh chromium_chromium.desktop exo-terminal-emulator.desktop cisco-packet-tracer_cisco-pacet-tracer.desktop labs.desktop code.desktop postman_postman.desktop drawio_drawio.desktop

devasc@labvm:~/Documents$ h. Use the command sudo chown root myfile.sh to change the ownership of the file to "root". devasc@labvm:~/Documents$ sudo chown root myfile.sh devasc@labvm:~/Documents$ i.

Display the permissions of the myfile.sh file. devasc@labvm:~/Documents$ ls -l total 4 -rwxrwxr-x 1 root devasc 14 Apr 16 21:28 myfile.sh

devasc@labvm:~/Documents$

Step 3: Use the move files command. a. Use the command mv to move the myfile.sh file to the desktop. devasc@labvm:~/Documents$ mv myfile.sh /home/devasc/Desktop/ devasc@labvm:~/Documents$ b. Display the contents of the Desktop folder. devasc@labvm:~/Documents$ ls ../Desktop/ chromium_chromium.desktop cisco-packet-tracer_cisco-pacet-tracer.desktop

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

exo-terminal-emulator.desktop labs.desktop

Page 6 of 15

www.netacad.com

Lab - Linux Review

code.desktop drawio_drawio.desktop

myfile.sh postman_postman.desktop

devasc@labvm:~/Documents$ c.

Return the file to the Documents folder. devasc@labvm:~/Documents$ mv ../Desktop/myfile.sh myfile.sh devasc@labvm:~/Documents$

d. Use the command mv to rename myfile.sh to myfile_renamed.sh. devasc@labvm:~/Documents$ mv myfile.sh myfile_renamed.sh devasc@labvm:~/Documents$ ls myfile_renamed.sh

devasc@labvm:~/Documents$

Step 4: Use the copy files command. a. Use the command cp to make a copy of the myfile_renamed.sh file. devasc@labvm:~/Documents$ cp myfile_renamed.sh myfile_renamed_and_copied.sh devasc@labvm:~/Documents$ ls myfile_renamed_and_copied.sh

myfile_renamed.sh

devasc@labvm:~/Documents$

Step 5: Use the remove files command. Use the rm command to remove the myfile_renamed_and_copied.sh file. devasc@labvm:~/Documents$ rm myfile_renamed_and_copied.sh devasc@labvm:~/Documents$ ls mbr.img

myfile_renamed.sh

devasc@labvm:~/Documents$

Step 6: Use the standard output redirect. a. Use the redirect (>) to place text into a new file called linux.txt. devasc@labvm:~$ echo "Linux is AWESOME!" > linux.txt devasc@labvm:~$ b. Use the command cat to redirect the contents of linux.txt to another file. devasc@labvm:~$ cat linux.txt > linux2.txt devasc@labvm:~$ c. Use the command cat to view the contents of linux2.txt. devasc@labvm:~$ cat linux2.txt Linux is AWESOME!

devasc@labvm:~$ d. Use the echo command to append text to the linux2.txt file. devasc@labvm:~$ echo "I LOVE Linux!" >> linux2.txt devasc@labvm:~$ e. Use the cat command to view the contents of the linux2.txt file. devasc@labvm:~$ cat linux2.txt Linux is AWESOME! © 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 7 of 15

www.netacad.com

Lab - Linux Review

I LOVE Linux!

devasc@labvm:~$ f.

Use the echo command to overwrite the contents of a file using the single angle bracket. devasc@labvm:~$ echo "Linux is POWERFUL!" > linux.txt devasc@labvm:~$

g. Use the cat command to view the contents of the linux.txt file. Notice that the previous state “Linux is AWESOME!” was overwritten. devasc@labvm:~$ cat linux.txt Linux is POWERFUL!

devasc@labvm:~$

Step 7: Use the vi text editor. a. Use the following command to start the vi text editor and open a text file. devasc@labvm:~$ vi linux2.txt The following content is shown in the editor window: Linux is AWESOME! I LOVE Linux!

b. Use the text editor to change the content to the following: Linux is Linux I am AWESOME!

The a key will allow you to enter edit mode, appending after the cursor’s position, while the i key will allow you to enter edit mode, inserting at the cursor’s position. You will need to use the Esc key to enter command mode to move around. Remember that d will delete (cut), y will yank (copy), and p will put (paste) the current line with the cursor. c.

Save the text to a new file called "linux3.txt". Remember that you will need to be in the command mode and type a colon ( : ) to enter ex mode so that you can write (save) the document ( :w linux3.txt). You can then use the quit (exit) command ( :q) to exit the vi editor.

d. Use the cat command to view the contents of the linux3.txt file. devasc@labvm:~$ cat linux3.txt Linux is Linux I am AWESOME! devasc@labvm:~$

Part 4: Review Regular Expressions In this part, you use the grep command to review how you can use regular expressions for filtering. Note: Your output may differ than the output shown below as the state of the VM is based on the most recent iteration that you downloaded as well as any changes you may have made. However, you should get some output from the passwd file but your highlighted output will differ. a. Use the grep command to filter the contents of the passwd file to display the line from the passwd file containing devasc. Notice that the two instances of devasc are highlighted. Also notice that the grep command is case-sensitive. The instance of DEVASC is not highlighted. devasc@labvm:~$ grep devasc /etc/passwd devasc:x:900:900:DEVASC,,,:/home/devasc:/bin/bash

devasc@labvm:~$

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 8 of 15

www.netacad.com

Lab - Linux Review

b. Use the grep command to show how many times root appears in the passwd file. Notice that all three instances of root are highlighted. devasc@labvm:~$ grep root /etc/passwd root:x:0:0:root:/root:/bin/bash

devasc@labvm:~$ c.

Use the grep command with the anchor character ^ to find the word, but only at the beginning of the line. Notice that only the word at the beginning of the line is highlighted. devasc@labvm:~$ grep '^root' /etc/passwd root:x:0:0:root:/root:/bin/bash

devasc@labvm:~$ d. Use the grep command with the anchor character $ to find a word at the end of a line. devasc@labvm:~$ grep 'false$' /etc/passwd tss:x:106:114:TPM software stack,,,:/var/lib/tpm:/bin/false lightdm:x:107:117:Light Display Manager:/var/lib/lightdm:/bin/false hplip:x:115:7:HPLIP system user,,,:/run/hplip:/bin/false

devasc@labvm:~$ e. Use the grep command with the anchor character . to match specific length words with different letters in them. Notice that not only is daem highlighted, but also dnsm is highlighted. devasc@labvm:~$ grep 'd..m' /etc/passwd daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin dnsmasq:x:109:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin avahi-autoipd:x:110:121:Avahi autoip daemon,,,:/var/lib/avahiautoipd:/usr/sbin/nologin usbmux:x:111:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin avahi:x:113:122:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/usr/sbin/nologin colord:x:116:125:colord colour management daemon,,,:/var/lib/colord:/usr/sbin/nologin pulse:x:117:126:PulseAudio daemon,,,:/var/run/pulse:/usr/sbin/nologin

devasc@labvm:~$ f.

Use the grep command to find lines where only the numbers 8 or 9 are present. Notice that only the lines containing an 8, a 9, or both are returned. devasc@labvm:~$ grep '[8-9]' /etc/passwd mail:x:8:8:mail:/var/mail:/usr/sbin/nologin news:x:9:9:news:/var/spool/news:/usr/sbin/nologin list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin uuidd:x:103:109::/run/uuidd:/usr/sbin/nologin devasc:x:900:900:DEVASC,,,:/home/devasc:/bin/bash systemd-network:x:999:999:systemd Network Management:/:/usr/sbin/nologin systemd-resolve:x:998:998:systemd Resolver:/:/usr/sbin/nologin systemd-timesync:x:997:997:systemd Time Synchronization:/:/usr/sbin/nologin systemd-coredump:x:996:996:systemd Core Dumper:/:/usr/sbin/nologin rtkit:x:108:119:RealtimeKit,,,:/proc:/usr/sbin/nologin dnsmasq:x:109:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin

devasc@labvm:~$ g. Use the grep command to find literal characters. Notice that only the lines containing a comma are returned.

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 9 of 15

www.netacad.com

Lab - Linux Review

devasc@labvm:~$ grep '[,]' /etc/passwd devasc:x:900:900:DEVASC,,,:/home/devasc:/bin/bash tss:x:106:114:TPM software stack,,,:/var/lib/tpm:/bin/false rtkit:x:108:119:RealtimeKit,,,:/proc:/usr/sbin/nologin dnsmasq:x:109:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin avahi-autoipd:x:110:121:Avahi autoip daemon,,,:/var/lib/avahiautoipd:/usr/sbin/nologin usbmux:x:111:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin kernoops:x:112:65534:Kernel Oops Tracking Daemon,,,:/:/usr/sbin/nologin avahi:x:113:122:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/usr/sbin/nologin hplip:x:115:7:HPLIP system user,,,:/run/hplip:/bin/false colord:x:116:125:colord colour management daemon,,,:/var/lib/colord:/usr/sbin/nologin pulse:x:117:126:PulseAudio daemon,,,:/var/run/pulse:/usr/sbin/nologin

devasc@labvm:~$ h. Use the grep command to find occurrences of zero or more of the pattern preceding it. Notice that only the lines with either new and ne are returned. devasc@labvm:~$ grep 'new*' /etc/passwd news:x:9:9:news:/var/spool/news:/usr/sbin/nologin nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin messagebus:x:100:103::/nonexistent:/usr/sbin/nologin _apt:x:102:65534::/nonexistent:/usr/sbin/nologin tcpdump:x:104:110::/nonexistent:/usr/sbin/nologin systemd-network:x:999:999:systemd Network Management:/:/usr/sbin/nologin kernoops:x:112:65534:Kernel Oops Tracking Daemon,,,:/:/usr/sbin/nologin saned:x:114:124::/var/lib/saned:/usr/sbin/nologin

devasc@labvm:~$

Part 5: Review System Administration In this part, you will review basic Linux system administration tasks including shutting down the computer, viewing and testing the network configuration, viewing processes, managing installation packages, updating user passwords, adding content to files, and using text editors.

Step 1: Shut down the computer. a. Use the command shutdown now to initiate a shutdown of the OS (and the VM) immediately. You do not have to perform this action as the VM will shut down and you will need to restart it manually. Formats of this time argument can be the word now, a time of day in the format hh:mm or the number of minutes to delay in the format +minutes. devasc@labvm:~$ shutdown now b. Use the command date to check set date of the OS. devasc@labvm:~$ date Fri 17 Apr 2020 08:53:20 PM UTC

devasc@labvm:~$ c.

Use the command shutdown +1 "Come back soon!" to shut down the OS in 1 minute and display the message "Come back soon!". Be sure to cancel or your VM will shut down. devasc@labvm:~$ shutdown +1 "Come back soon!" Shutdown scheduled for Fri 2020-04-17 20:57:13 UTC, use 'shutdown -c' to cancel.

devasc@labvm:~$ shutdown -c

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 10 of 15

www.netacad.com

Lab - Linux Review

devasc@labvm:~$

Step 2: View and test the network configuration. a. Use the ip address command to display the network configuration. The output is a bit more detailed. For example, notice that five IPv4 addresses are shown for the dummy0 interface. devasc@labvm:~$ ip address 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: enp0s3: mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 08:00:27:ce:2b:8b brd ff:ff:ff:ff:ff:ff inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic enp0s3 valid_lft 75746sec preferred_lft 75746sec inet6 fe80::a00:27ff:fece:2b8b/64 scope link valid_lft forever preferred_lft forever 3: dummy0: mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000 link/ether 46:8b:41:b5:de:aa brd ff:ff:ff:ff:ff:ff inet 192.0.2.1/32 scope global dummy0 valid_lft forever preferred_lft forever inet 192.0.2.2/32 scope global dummy0 valid_lft forever preferred_lft forever inet 192.0.2.3/32 scope global dummy0 valid_lft forever preferred_lft forever inet 192.0.2.4/32 scope global dummy0 valid_lft forever preferred_lft forever inet 192.0.2.5/32 scope global dummy0 valid_lft forever preferred_lft forever inet6 fe80::448b:41ff:feb5:deaa/64 scope link valid_lft forever preferred_lft forever

devasc@labvm:~$ b. Use the command ping with the options -c 4 to ping a computer on your local network four times. You must use a valid IP address of a device on your local network. The following example is using 192.168.1.1, but your network will most likely have different IPv4 addresses. devasc@labvm:~$ ping -c 4 192.168.1.1 PING 192.168.1.1 (192.168.1.1) 56(84) 64 bytes from 192.168.1.1: icmp_seq=1 64 bytes from 192.168.1.1: icmp_seq=2 64 bytes from 192.168.1.1: icmp_seq=3 64 bytes from 192.168.1.1: icmp_seq=4

bytes of data. ttl=63 time=1.13 ttl=63 time=2.30 ttl=63 time=1.31 ttl=63 time=2.49

ms ms ms ms

--- 192.168.1.1 ping statistics --4 packets transmitted, 4 received, 0% packet loss, time 3005ms rtt min/avg/max/mdev = 1.130/1.809/2.492/0.594 ms

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 11 of 15

www.netacad.com

Lab - Linux Review

devasc@labvm:~$ c.

You can also ping a name and Domain Name System (DNS) will resolve the name to an IP address. For example, ping Cisco’s website. Your VM will send out a DNS request first to get the IP address and then send the ping packets. The DNS process is not shown in the ping output. devasc@labvm:~$ ping -c 4 www.cisco.com PING e2867.dsca.akamaiedge.net (23.204.11.200) 56(84) bytes of data. 64 bytes from a23-204-11-200.deploy.static.akamaitechnologies.com (23.204.11.200): icmp_seq=1 ttl=58 time=185 ms 64 bytes from a23-204-11-200.deploy.static.akamaitechnologies.com (23.204.11.200): icmp_seq=2 ttl=58 time=28.8 ms 64 bytes from a23-204-11-200.deploy.static.akamaitechnologies.com (23.204.11.200): icmp_seq=3 ttl=58 time=28.8 ms 64 bytes from a23-204-11-200.deploy.static.akamaitechnologies.com (23.204.11.200): icmp_seq=4 ttl=58 time=26.4 ms --- e2867.dsca.akamaiedge.net ping statistics --4 packets transmitted, 4 received, 0% packet loss, time 3007ms rtt min/avg/max/mdev = 26.443/67.339/185.363/68.147 ms

devasc@labvm:~$

Step 3: View Processes a. Use the ps command to display the processes that are running in the current terminal. devasc@labvm:~$ ps PID TTY 1416 pts/0 1453 pts/0

TIME CMD 00:00:00 bash 00:00:00 ps

devasc@labvm:~$ b. Use the ps with the -e option to display all the processes that are running on the computer. devasc@labvm:~$ ps -e PID TTY TIME 1 ? 00:00:01 2 ? 00:00:00 3 ? 00:00:00 4 ? 00:00:00 6 ? 00:00:00 7 ? 00:00:00 9 ? 00:00:00 (output omitted)

c.

CMD systemd kthreadd rcu_gp rcu_par_gp kworker/0:0H-kblockd kworker/0:1-events mm_percpu_wq

You can pipe any command output to one screen at a time by adding | more. One screen of output displays with the --more-- shown at the bottom. You can now use the Enter key to display one line at a time, the space bar to display one screen at a time, or Ctrl+C to exit and return to the command prompt. devasc@labvm:~$ ps -e | more PID 1 2 3 4 6

TTY ? ? ? ? ?

TIME 00:00:01 00:00:00 00:00:00 00:00:00 00:00:00

CMD systemd kthreadd rcu_gp rcu_par_gp kworker/0:0H-kblockd

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 12 of 15

www.netacad.com

Lab - Linux Review

9 ? 10 ? --More--

00:00:00 mm_percpu_wq 00:00:00 ksoftirqd/0

d. Use the ps with the -ef option to display all the processes that are running on the computer with more detail. devasc@labvm:~$ ps -ef UID PID root 1 root 2 root 3 root 4 root 6 root 9 root 10 root 11 (output omitted)

PPID 0 0 2 2 2 2 2 2

C 0 0 0 0 0 0 0 0

STIME 20:57 20:57 20:57 20:57 20:57 20:57 20:57 20:57

TTY ? ? ? ? ? ? ? ?

TIME 00:00:01 00:00:00 00:00:00 00:00:00 00:00:00 00:00:00 00:00:00 00:00:01

CMD /sbin/init [kthreadd] [rcu_gp] [rcu_par_gp] [kworker/0:0H-kblockd] [mm_percpu_wq] [ksoftirqd/0] [rcu_sched]

Step 4: Manage packages. a. Use the command apt-get update to refresh the list of available packages in the OS, as shown previously in Part 1 of this lab. You must use administrative level permissions to use this command. devasc@labvm:~$ sudo apt-get update Hit:1 http://security.ubuntu.com/ubuntu focal-security InRelease Get:2 http://us.archive.ubuntu.com/ubuntu focal InRelease [265 kB] Hit:3 http://us.archive.ubuntu.com/ubuntu focal-updates InRelease Hit:4 http://us.archive.ubuntu.com/ubuntu focal-backports InRelease Get:5 http://us.archive.ubuntu.com/ubuntu focal/main i386 Packages [721 kB] Get:6 http://us.archive.ubuntu.com/ubuntu focal/main amd64 Packages [974 kB] Get:7 http://us.archive.ubuntu.com/ubuntu focal/main Translation-en [506 kB] (output omitted)

b. Use the command apt-cache search to find a specific package. devasc@labvm:~$ apt-cache search speed test (output omitted) smalt-examples - Sequence Mapping and Alignment Tool (examples) speedtest-cli - Command line interface for testing internet bandwidth using speedtest.net sup - Software Upgrade Protocol implementation sysbench - multi-threaded benchmark tool for database systems tcpreplay - Tool to replay saved tcpdump files at arbitrary speeds (output omitted)

c.

Use the command apt-get install to install a package. devasc@labvm:~$ sudo apt-get install speedtest-cli Reading package lists... Done Building dependency tree Reading state information... Done The following NEW packages will be installed: speedtest-cli 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. Need to get 23.9 kB of archives.

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 13 of 15

www.netacad.com

Lab - Linux Review

After this operation, 106 kB of additional disk space will be used. Get:1 http://archive.ubuntu.com/ubuntu focal/universe amd64 speedtest-cli all 2.1.2-2 [23.9 kB] Fetched 23.9 kB in 1s (43.9 kB/s) Selecting previously unselected package speedtest-cli. (output omitted)

d. Now you can use the speedtest-cli command to test your current Internet connection speed. devasc@labvm:~$ speedtest-cli Retrieving speedtest.net configuration... Testing from Cable Company (192.168.100.21)... Retrieving speedtest.net server list... Selecting best server based on ping... Hosted by Comcast (Albuquerque, NM) [494.76 km]: 48.636 ms Testing download speed................................................................................ Download: 90.87 Mbit/s Testing upload speed................................................................................. ..................... Upload: 17.87 Mbit/s

devasc@labvm:~$ e. Use the command apt-get upgrade to update all packages and dependencies on the computer. devasc@labvm:~$ sudo apt-get upgrade Reading package lists... Done Building dependency tree Reading state information... Done Calculating upgrade... Done The following packages have been kept back: libnss-systemd libpam-systemd libsystemd0 libyelp0 linux-generic linux-headersgeneric (output omitted)

f.

Use the command apt-get purge to completely remove a package from the computer. devasc@labvm:~$ sudo apt-get purge speedtest-cli Reading package lists... Done Building dependency tree Reading state information... Done The following packages will be REMOVED: speedtest-cli* 0 upgraded, 0 newly installed, 1 to remove and 0 not upgraded. After this operation, 106 kB disk space will be freed. Do you want to continue? [Y/n] (Reading database ... 211937 files and directories currently installed.) Removing speedtest-cli (2.1.2-2) ... (output omitted)

Step 5: Update Passwords a. Use the command passwd to update your password. Note: If you actually change the password for your devasc user, make sure you remember it. © 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 14 of 15

www.netacad.com

Lab - Linux Review

devasc@labvm:~$ passwd Changing password for devasc. Current password: New password: Retype new password: passwd: password updated successfully

devasc@labvm:~$ b. Use the command passwd with the option -S to view the status of your password. devasc@labvm:~$ passwd -S devasc P 04/17/2020 0 99999 7 -1

devasc@labvm:~$ c.

Use the manual pages for the passwd command (man passwd) to research the -S option and find the answer the following questions. Questions

What is the current status of the password? Type your answers here. P indicates a usable password. What is the minimum number of days that must pass before the password can be changed? Type your answers here. 0 What is the number of days after password expiration that the account remains active? Type your answers here. -1 indicates the password never expires due to inactivity. End of document

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 15 of 15

www.netacad.com

LAB 1.3.3

Lab - Python Programming Review (Instructor Version) Instructor Note: Red font color or gray highlights indicate text that appears in the instructor copy only.

Objectives Part 1: Launch the DEVASC VM Part 2: Start Python and VS Code Part 3: Review Data Types and Variables Part 4: Review Lists and Dictionaries Part 5: Review the Input Function Part 6: Review If, For, and While Functions Part 7: Review Methods for File Access

Background / Scenario In this lab, you review basic Python programming skills including data types, variables, lists, dictionaries, user input, if statements, for and while loops, and file access. This lab is not meant as a substitute for prior programming experience and does not necessarily cover all the Python skills you will need for this course. However, this lab should serve as a good measure of your Python programming skills and help direct you to where you may need more review. Note: This is a reminder. Be sure you observe correct Python indention conventions when writing your scripts. If you need a tutorial, search the internet for “Python indention rules”.

Required Resources •

1 PC with operating system of your choice



Virtual Box or VMWare



DEVASC Virtual Machine

Instructions Part 1: Launch the DEVASC VM If you have not already completed the Lab - Install the Virtual Machine Lab Environment, do so now. If you have already completed that lab, launch the DEVASC VM.

Part 2: Starting Python and VS Code In this part, you will review starting Python’s interactive interpreter and using Visual Studio Code to write and run a “Hello World” script.

Step 1: Start Python. a. To check the Python version running in the VM, open a terminal window and enter the command python3 -V. This is a good command to run if you were to install Python on a different computer or needed to check what version is installed. devasc@labvm:~$ python3 -V

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 1 of 15

www.netacad.com

Lab - Python Programming Review

Python 3.8.2

Note: You would need to change it to python2 -V if a different device you are using is running version 2. However, as of January 1, 2020, Python 2 is no longer supported. Therefore, Python 2 is not supported in this lab or this course. Note: At the time this lab was written, Python 3.8.2 was the latest version. Although you can update your Python install with the sudo apt-get install python3 command, this lab and the rest of the labs in this course are based on Python 3.8.2. b. To start Python, type python3. The three angle brackets (>>>) indicate that you are in Python's interactive interpreter. devasc@labvm~$ python3 Python 3.8.2 (default, Mar 13 2020, 10:14:16) [GCC 9.3.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>>

Step 2: Use the Interpreter as a calculator. a. From here, you can do a variety of basic programming tasks including math operations. The table shows the Python syntax to use for the most common math operations. Operation

Math

Syntax

Addition

a+b

a+b

Subtraction

a-b

a-b

Multiplication

axb

a*b

Division

a÷b

a/b

Exponents

a^b

a**b

Enter a few math operations using the Python syntax, as shown in the examples. >>> 5 >>> 6 >>> 8 >>> 4.0 >>> 9

2+3 10-4 2*4 20/5 3**2

b. Recall that Python uses the standard order of operations commonly known as PEMDAS. Mathematical expressions are evaluated in the following order. Parentheses Exponents Multiplication and Division Addition and Subtraction Try entering an expression with a complex order of operations in the interactive interpreter.

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 2 of 15

www.netacad.com

Lab - Python Programming Review

Step 3: Use the interactive interpreter to print a string. A string is any sequence of characters such as letters, numbers, symbols, or punctuation marks. The interactive interpreter will directly output text that you enter as a string as long as you enclose the string in either single quotes (') or double quotes ("). a. Type “Hello World!” or ‘Hello World!’ in the interactive interpreter. >>> "Hello World!" 'Hello World!' >>> 'Hello World!' 'Hello World!' b. The print command can be also be used directly in the interactive interpreter. >>> print("Hello World!") Hello World!

c.

To exit the interactive interpreter, enter quit(). >>> quit() devasc@labvm:~$

Step 4: Open VS Code and create a script for Hello World. There are many development environments available for programmers to manage their coding projects. In this course, the labs will use the VM’s installation of Microsoft’s Visual Studio Code (VS Code). a. Open VS Code. If this is your first time, you will most likely be presented with a Welcome window. b. Feel free to explore the VS Code menus and options on your own time. For now, click File > New File to open a new file. c.

In your new file, type the print command from the previous step.

d. Save the script as hello-world.py in the labs/devnet-src/python folder. Be sure you add the extension .py for Python file. e. To run the script, click Run > Run Without Debugging. A terminal window opens inside VS Code, runs the code to launch an instance of Python, runs your script, then exits out of Python back to your Linux command line. devasc@labvm:~/labs/devnet-src/python$ env DEBUGPY_LAUNCHER_PORT=36095 /usr/bin/python3 /home/devasc/.vscode/extensions/ms-python.python2020.4.76186/pythonFiles/lib/python/debugpy/no_wheels/debugpy/launcher /home/devasc/labs/devnet-src/python/hello-world.py Hello World! devasc@labvm:~/labs/devnet-src/python$ f.

Now that you have a command line open inside VS Code, you can manually launch Python and quickly run your script with the following command. devasc@labvm:~/labs/devnet-src/python$ python3 hello-world.py Hello World!

devasc@labvm:~/labs/devnet-src/python$ g. You can also open a terminal window outside of VS Code and enter the same command making sure to provide path information. devasc@labvm:~$ python3 ~/labs/devnet-src/python/hello-world.py Hello World!

devasc@labvm:~$

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 3 of 15

www.netacad.com

Lab - Python Programming Review

In this course you will typically run your scripts directly inside VS Code.

Part 3: Review Data Types and Variables In this part, you will use the interactive interpreter to review data types, create variables, concatenate strings, and cast between data types.

Step 1: Use the interactive interpreter to review basic data types. In programming, data types are a classification which tells the interpreter how the programmer intends to use the data. For example, the interpreter needs to know if the data the programmer entered is a number or a string. Although there are several different data types, we will focus only on the following: •

Integer - used to specify whole numbers (no decimals), such as 1, 2, 3, and so on. If an integer is entered with a decimal, the interpreter ignores the decimal. For example, 3.75 is interpreted as 3.



Float - used to specify numbers that need a decimal value, such as 3.14159.



String - any sequence of characters such as letters, numbers, symbols, or punctuation marks.



Boolean - any data type that has a value of either True or False.

Use the type() command to determine the basic data types: int, float, string, Boolean devasc@labvm:~/labs/devnet-src$ python3 Python 3.8.2 (default, Mar 13 2020, 10:14:16) [GCC 9.3.0] on linux Type "help", "copyright", "credits" or "license" for more information.

>>> type(98)

>>> type(98.6)

>>> type("Hi!")

>>> type(True)

Step 2: Review different Boolean operators. The Boolean data type makes use of the operators shown in the table. Operator

Meaning

>

Greater than


=

Greater than or equal to

>> 1>> 1>> 1==1 True

>>> 1>=1 True

>>> 1>> x=3 >>> x*5 15

>>> "Cisco"*x 'CiscoCiscoCisco'

Step 4: Use the interpreter to concatenate multiple string variables. Concatenation is the process of combining multiple strings into one string. For example, the concatenation of "foot" and "ball" is "football". a. Enter the following four variables and then concatenate them together in a print() statement with the plus sign (+). Notice that the space variable was defined for use as white space between the words. >>> >>> >>> >>> >>>

str1="Cisco" str2="Networking" str3="Academy" space=" " print(str1+space+str2+space+str3)

Cisco Networking Academy

b. To print the variables without using a variable to create the space, separate the variables with a comma. >>> print(str1,str2,str3) Cisco Networking Academy

Step 5: Reviewing casting and printing different data types. a. Converting between data types is called type casting. Type casting often needs to be done in order to work with different data types. For example, concatenation does not work when joining different data types. >>> x=3 >>> print("The value of x is " + x) Traceback (most recent call last): File "", line 1, in TypeError: can only concatenate str (not "int") to str >>>

b. Use the str() function to convert the integer data type to a string data type. >>> print("The value of x is " + str(x)) © 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 5 of 15

www.netacad.com

Lab - Python Programming Review

The value of x is 3

>>> type(x)

c.

Notice that the data type for the variable x is still an integer. To convert the data type, reassign the variable to the new data type. >>> x=str(x) >>> type(x)

d. You may want to display a float to a specific number of decimal places instead of the full number. To do this, you can use f-strings and the "{:.2f}".format function. Note: Search the internet to learn more about f-strings and the format function. >>> num = 22/7 >>> f"The value of num is {num}" 'The value of num is 3.142857142857143' >>> pi = "{:.2f}".format(num) >>> f"The value of pi is {pi}." 'The value of pi is 3.14.' >>>

Part 4: Review Lists and Dictionaries In this part, you will review the methods for creating and manipulating lists and dictionaries.

Step 1: Create and manipulate a list. a. In programming, a list variable is used to store multiple pieces of ordered information. Lists are also called arrays in some programming environments. o

Create a list using brackets [ ] and enclosing each item in the list with quotes.

o

Separate the items with a comma.

o

Use the type() command to verify the data type.

o

Use the len() command to return the number of items in a list.

o

Call the list variable name to display its content.

The following example shows how to create a list variable called hostnames. >>> hostnames=["R1","R2","R3","S1","S2"] >>> type(hostnames)

>>> len(hostnames) 5

>>> hostnames ['R1', 'R2', 'R3', 'S1', 'S2']

b. An item in a list can be referenced and manipulated using its index. o

The first item in a list is indexed as zero, the second is indexed as one, and so on.

o

The last item can be referenced with index [-1].

o

Replace an item by assigning a new value to the index.

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 6 of 15

www.netacad.com

Lab - Python Programming Review

o

Use the del command to remove an item from a list.

>>> hostnames[0] 'R1'

>>> hostnames[-1] 'S2'

>>> hostnames[0]="RTR1" >>> hostnames ['RTR1', 'R2', 'R3', 'S1', 'S2']

>>> del hostnames[3] >>> hostnames ['RTR1', 'R2', 'R3', 'S2'] >>>

Step 2: Create and manipulate a dictionary. a. Dictionaries are unordered lists of objects. Each object contains a key/value pair. o

Create a dictionary using the braces { }.

o

Each dictionary entry includes a key and a value.

o

Separate a key and its value with a colon.

o

Use quotes for keys and values that are strings.

Create the following dictionary called ipAddress with three key/value pairs to specify the IP address values for three routers. >>> ipAddress={"R1":"10.1.1.1","R2":"10.2.2.1","R3":"10.3.3.1"} >>> type(ipAddress)

b. Unlike lists, objectives inside a dictionary cannot be referenced by their sequence number. Instead, you reference a dictionary object using its key. o

The key is enclosed with brackets [ ].

o

Keys that are strings can be referenced using single or double quotes.

o

Use a key in the dictionary statement to verify if a key exists in the dictionary.

o

Add a key/value pair by setting the new key equal to a value.

>>> ipAddress {'R1': '10.1.1.1', 'R2': '10.2.2.1', 'R3': '10.3.3.1'}

>>> ipAddress['R1'] '10.1.1.1'

>>> ipAddress["S1"]="10.1.1.10" >>> ipAddress {'R1': '10.1.1.1', 'R2': '10.2.2.1', 'R3': '10.3.3.1', 'S1': '10.1.1.10'} >>>

c.

Values in a key/value pair can be any other data type including lists and dictionaries. For example, if R3 has more than one IP address, how would you represent that inside the ipAddress dictionary? Create a list for the value of the R3 key. >>> ipAddress["R3"]=["10.3.3.1","10.3.3.2","10.3.3.3"] >>> ipAddress

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 7 of 15

www.netacad.com

Lab - Python Programming Review

{'S1': '10.1.1.10', 'R2': '10.2.2.1', 'R1': '10.1.1.1', 'R3': ['10.3.3.1', '10.3.3.2', '10.3.3.3']} >>>

Part 5: Review the Input Function In this part, you will review how to use the input function to store and display user-supplied data.

Step 1: Create a variable to store user input and then display the value. Most programs require some type of input either from a database, another computer, mouse clicks, or keyboard input. For keyboard input, use the input() function which includes an optional parameter to provide a prompt string. If the input function is called, the program will stop until the user provides input and hits the Enter key. Assign the input() function to a variable that asks the user for input and then print the value of the user’s input. >>> firstName = input("What is your first name? ") What is your first name? User_Name

>>> print("Hello " + firstName +"!") Hello User_Name!

>>>

Step 2: Create a script to collect personal information. Create and run a script to collect personal information. a. Open a blank script file and save it as personal-info.py in the ~/labs/devnet-src/python folder. b. Create a script that asks for four pieces of information such as: first name, last name, location, and age. c.

Add a print statement that combines all the information in one sentence.

d. Your script should run without any errors, as shown in the following output. devasc@labvm:~/labs/devnet-src$ python3 person-info.py What is your first name? Bob What is your last name? Smith What is your location? London What is your age? 36 Hi Bob Smith! Your location is London and you are 36 years old.

devasc@labvm:~/labs/devnet-src$ ^C personal-info.py firstName = input("What is your first name? ") lastName = input("What is your last name? ") location = input("What is your location? ") age = input("What is your age? ") print("Hi " + firstName, lastName + "! Your location is " + location + " and you are " + age + " years old.")

Part 6: Review If, For, and While Functions In this part, you review how to create if statements as well as for and while loops.

Step 1: Create an if/else function. In programming, conditional statements check if something is true and then carry out instructions based on the evaluation. If the evaluation is false, different instructions are carried out. © 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 8 of 15

www.netacad.com

Lab - Python Programming Review

a. Open a blank script and save it as if-vlan.py. Type the following script into the file. nativeVLAN = 1 dataVLAN = 100 if nativeVLAN == dataVLAN: print("The native VLAN and the data VLAN are the same.") else: print("The native VLAN and the data VLAN are different.") Note: In Python, use four spaces to indent. If you save your file in VS Code, this four space indention will be automatic. When beginning the else statement, make sure to backspace to the left margin. b. Save the script and run it. Your output should look like the following example. The native VLAN and the data VLAN are different.

c.

Modify the variables so that nativeVLAN and dataVLAN have the same value. Save and run the script again. Your output should look like the following example. The native VLAN and the data VLAN are the same.

Step 2: Create an if/elif/else function. What if we have more than two conditional statements to consider? In this case, we can use elif statements in the middle of the if/else function. An elif statement is evaluated if the if statement is false and before the else statement. You can have as many elif statements as you would like. However, the first one matched will be executed and none of the remaining elif statements will be checked. Nor will the else statement. The script in the following example asks the user to input the number of an IPv4 ACL and then checks whether that number is a standard IPv4 ACL, extended IPv4 ACL, or neither standard or extended IPv4 ACL. a. Create this script for your files. Open a blank script and save it as if-acl.py. Copy the script into the file. aclNum = int(input("What is the IPv4 ACL number? ")) if aclNum >= 1 and aclNum =100 and aclNum >> devices=["R1","R2","R3","S1","S2"]

>>> for item in devices: ... print(item) ... R1 R2 R3 S1 S2

>>> b. What if you only want to list the items that begin with the letter R? An if statement can be embedded in a for loop to achieve this. Continuing with the same Python instance, enter the following in the interactive interpreter. Note: Be sure you enter four spaces to indent the if function and the eight spaces to indent the print() function. Press the Enter key twice to exit and execute the for loop. >>> for item in devices: ... if "R" in item: ... print(item) ... R1 R2 R3

>>> c.

You can also use a combination of the for loop and if statement to create a new list. Enter the following example to see how to use the append() method to create a new list called switches. Be sure to follow the indention requirements. >>> switches=[] >>> for item in devices: ... if "S" in item: ... switches.append(item) ... >>> switches ['S1', 'S2']

>>>

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 10 of 15

www.netacad.com

Lab - Python Programming Review

Step 4: While Loop Instead of running a block of code once, as in an if statement, you can use a while loop. A while loop keeps executing a code block as long as a Boolean expression remains true. This can cause a program to run endlessly if you do not make sure your script includes a condition for the while loop to stop. While loops will not stop until the Boolean expression evaluates as false. a. Open a blank script and save it as while-loop.py. Use a while loop to create the following program that counts from a programmed value up to a user-supplied number. The program does the following: o

Asks the user for a number.

o

Casts inputted string value to an integer: x = int(x).

o

Sets a variable to start the count: y = 1.

o

While y DEVASC.txt devasc@labvm:~/labs/devnet-src/git-intro$ b. Use the ls -la command terify the file, as well as the .git directory, are in the git intro directory. Then use cat to display the contents of DEVASC.txt. devasc@labvm:~/labs/devnet-src/git-intro$ ls -la total 16 drwxrwxr-x 3 devasc devasc 4096 Apr 17 20:38 . drwxrwxr-x 5 devasc devasc 4096 Apr 17 19:50 .. -rw-rw-r-- 1 devasc devasc 48 Apr 17 20:38 DEVASC.txt drwxrwxr-x 7 devasc devasc 4096 Apr 17 19:57 .git evasc@labvm:~/src/git-intro$ cat DEVASC.txt I am on my way to passing the Cisco DEVASC exam

devasc@labvm:~/labs/devnet-src/git-intro$

Step 2: Examine the Repository Status. Examine the repository status using git status. Notice that Git found the new file in the directory, and knows that it's not tracked. devasc@labvm:~/labs/devnet-src/git-intro$ git status On branch master No commits yet Untracked files: (use "git add ..." to include in what will be committed) DEVASC.txt nothing added to commit but untracked files present (use "git add" to track)

devasc@labvm:~/labs/devnet-src/git-intro$

Step 3: Staging the File. a. Next, use the git add command to "stage" the DEVASC.txt file. Staging is an intermediate phase prior to committing a file to the repository with the git commit command. This command creates a snapshot of the contents of the file at the time this command is entered. Any changes to the file require another git add command prior to committing the file. devasc@labvm:~/labs/devnet-src/git-intro$ git add DEVASC.txt b. Using the git status command again, notice the staged changes displayed as "new file: DEVASC.txt". devasc@labvm:~/labs/devnet-src/git-intro$ git status On branch master

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 3 of 15

www.netacad.com

Lab - Software Version Control with Git

No commits yet Changes to be committed: (use "git rm --cached ..." to unstage) new file: DEVASC.txt

devasc@labvm:~/labs/devnet-src/git-intro$

Step 4: Committing a File. Now that you have staged your changes, you will need to commit them in order to let Git know you want to start tracking those changes. Commit your staged content as a new commit snapshot by using the git commit command. The -m message switch enables you to add a message explaining the changes you've made. Note the number and letter combination highlighted in the output. This is the commit ID. Every commit is identified by a unique SHA1 hash. The commit ID is the first 7 characters of the full commit hash. Your commit ID will be different than the one displayed. devasc@labvm:~/labs/devnet-src/git-intro$ git commit -m "Committing DEVASC.txt to begin tracking changes" [master (root-commit) b510f8e] Committing DEVASC.txt to begin tracking changes 1 file changed, 1 insertion(+) create mode 100644 DEVASC.txt

devasc@labvm:~/labs/devnet-src/git-intro$

Step 5: Viewing the Commit History. Use the git log command to show all commits in the current branch's history. By default, all commits are made to the master branch. (Branches will be discussed later.) The first line is the commit hash with the commit ID as first 7 characters. The file is committed to the master branch. This is followed by your name and email address, the date of the commit and the message you included with the commit. devasc@labvm:~/labs/devnet-src/git-intro$ git log commit b510f8e5f9f63c97432d108a0413567552c07356 (HEAD -> master) Author: Sample User Date: Sat Apr 18 18:03:28 2020 +0000 Committing DEVASC.txt to begin tracking changes

devasc@labvm:~/labs/devnet-src/git-intro$

Part 4: Modifying the File and Tracking the Changes In this part, you will modify a file, stage the file, commit the file, and verify changes in the repository.

Step 1: Modify the file. a. Make a change to DEVASC.txt using the echo command. Be sure to use ">>" to append the existing file. The ">" will overwrite the existing file. Use the cat command to view the modified file. devasc@labvm:~/labs/devnet-src/git-intro$ echo "I am beginning to understand Git!" >> DEVASC.txt b. Use the cat command to view the modified file. devasc@labvm:~/labs/devnet-src/git-intro$ cat DEVASC.txt I am on my way to passing the Cisco DEVASC exam I am beginning to understand Git!

devasc@labvm:~/labs/devnet-src/git-intro$ © 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 4 of 15

www.netacad.com

Lab - Software Version Control with Git

Step 2: Verify the change to the repository. Verify the change in the repository using the git status command. devasc@labvm:~/labs/devnet-src/git-intro$ git status On branch master Changes not staged for commit: (use "git add ..." to update what will be committed) (use "git restore ..." to discard changes in working directory) modified: DEVASC.txt no changes added to commit (use "git add" and/or "git commit -a")

devasc@labvm:~/labs/devnet-src/git-intro$

Step 3: Stage the modified file. The modified file will need to be staged again before it can be committed using the git add command again. devasc@labvm:~/labs/devnet-src/git-intro$ git add DEVASC.txt

Step 4: Commit the staged file. Commit the staged file using the git commit command. Notice the new commit ID. devasc@labvm:~/labs/devnet-src/git-intro$ git commit -m "Added additional line to file" [master 9f5c4c5] Added additional line to file 1 file changed, 1 insertion(+)

devasc@labvm:~/labs/devnet-src/git-intro$

Step 5: Verify the changes in the repository. a. Use the git log command again to show all commits. Notice that the log contains the original commit entry along with the entry for the commit you just performed. The latest commit is shown first. The output highlights the commit ID (first 7 characters of the SHA1 hash), the date/time of the commit, and the message of the commit for each entry. devasc@labvm:~/labs/devnet-src/git-intro$ git log commit 9f5c4c5d630e88abe2a873fe48144e25ebe7bd6a (HEAD -> master) Author: Sample User Date: Sat Apr 18 19:17:50 2020 +0000 Added additional line to file commit b510f8e5f9f63c97432d108a0413567552c07356 Author: Sample User Date: Sat Apr 18 18:03:28 2020 +0000 Committing DEVASC.txt to begin tracking changes

devasc@labvm:~/labs/devnet-src/git-intro$ b. When you have multiple entries in the log, you can compare the two commits using the git diff command adding original commit ID first and the latest commit second: git diff . You will need to use your commit IDs. The "+" sign at the end, followed by the text indicates the content that was appended to the file. devasc@labvm:~/labs/devnet-src/git-intro$ git diff b510f8e 9f5c4c5 © 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 5 of 15

www.netacad.com

Lab - Software Version Control with Git

diff --git a/DEVASC.txt b/DEVASC.txt index 93cd3fb..085273f 100644 --- a/DEVASC.txt +++ b/DEVASC.txt @@ -1 +1,2 @@ I am on my way to passing the Cisco DEVASC exam +I am beginning to understand Git!

devasc@labvm:~/labs/devnet-src/git-intro$

Part 5: Branches and Merging When a repository is created, the files are automatically put in a branch called master. Whenever possible it is recommended to use branches rather than directly updating the master branch. Branching is used so that you can make changes in another area without affecting the master branch. This is done to help prevent accidental updates that might overwrite existing code. In this part, you will create a new branch, checkout the branch, make changes in the branch, stage and commit the branch, merge the branch changes to the master branch, and then delete the branch.

Step 1: Create a new branch Create a new branch called feature using the git branch command. devasc@labvm:~/labs/devnet-src/git-intro$ git branch feature

Step 2: Verify current branch Use the git branch command without a branch-name to display all the branches for this repository. The "*" next to the master branch indicates that this is the current branch – the branch that is currently "checked out". devasc@labvm:~/labs/devnet-src/git-intro$ git branch feature * master

devasc@labvm:~/labs/devnet-src/git-intro$

Step 3: Checkout the new branch Use the git checkout command to switch to the feature branch. devasc@labvm:~/labs/devnet-src/git-intro$ git checkout feature

Step 4: Verify current branch a. Verify you have switched to the feature branch using the git branch command. Note the "*" next to the feature branch. This is now the working branch. devasc@labvm:~/labs/devnet-src/git-intro$ git branch * feature master

devasc@labvm:~/labs/devnet-src/git-intro$ b. Append a new line of text to the DEVASC.txt file, again using the echo command with the ">>" signs. devasc@labvm:~/labs/devnet-src/git-intro$ echo "This text was added originally while in the feature branch" >> DEVASC.txt c.

Verify the line was appended to the file using the cat command. devasc@labvm:~/labs/devnet-src/git-intro$ cat DEVASC.txt I am on my way to passing the Cisco DEVASC exam

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 6 of 15

www.netacad.com

Lab - Software Version Control with Git

I am beginning to understand Git! This text was added originally while in the feature branch

devasc@labvm:~/labs/devnet-src/git-intro$

Step 5: Stage the modified file in the feature branch. a. Stage the updated file to the current feature branch. devasc@labvm:~/labs/devnet-src/git-intro$ git add DEVASC.txt b. Use the git status command and notice the modified file DEVASC.txt is staged in the feature branch. devasc@labvm:~/labs/devnet-src/git-intro$ git status On branch feature Changes to be committed: (use "git restore --staged ..." to unstage) modified: DEVASC.txt

devasc@labvm:~/labs/devnet-src/git-intro$

Step 6: Commit the staged file in the feature branch. a. Commit the staged file using the git commit command. Notice the new commit ID and your message. devasc@labvm:~/labs/devnet-src/git-intro$ git commit -m "Added a third line in feature branch" [feature cd828a7] Added a third line in feature branch 1 file changed, 1 insertion(+)

devasc@labvm:~/labs/devnet-src/git-intro$ b. Use the git log command to show all commits including the commit you just did to the feature branch. The prior commit was done within the master branch. devasc@labvm:~/labs/devnet-src/git-intro$ git log commit cd828a73102cf308981d6290113c358cbd387620 (HEAD -> feature) Author: Sample User Date: Sat Apr 18 22:59:48 2020 +0000 Added a third line in feature branch commit 9f5c4c5d630e88abe2a873fe48144e25ebe7bd6a (master) Author: Sample User Date: Sat Apr 18 19:17:50 2020 +0000 Added additional line to file commit b510f8e5f9f63c97432d108a0413567552c07356 Author: Sample User Date: Sat Apr 18 18:03:28 2020 +0000 Committing DEVASC.txt to begin tracking changes

devasc@labvm:~/labs/devnet-src/git-intro$

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 7 of 15

www.netacad.com

Lab - Software Version Control with Git

Step 7: Checkout the master branch. Switch to the master branch using the git checkout master command and verify the current working branch using the git branch command. devasc@labvm:~/labs/devnet-src/git-intro$ git checkout master Switched to branch 'master'

devasc@labvm:~/labs/devnet-src/git-intro$ git branch feature * master

devasc@labvm:~/labs/devnet-src/git-intro$

Step 8: Merge file contents from feature to master branch. a. Branches are often used when implementing new features or fixes. They can be submitted for review by team members, and then once verified, can be pulled into the main codebase – the master branch. Merge the contents (known as the history) from the feature branch into the master branch using the git merge command. The branch-name is the branch that histories are pulled from into the current branch. The output displays that one file was changed with one line inserted. devasc@labvm:~/labs/devnet-src/git-intro$ git merge feature Updating 9f5c4c5..cd828a7 Fast-forward DEVASC.txt | 1 + 1 file changed, 1 insertion(+)

devasc@labvm:~/labs/devnet-src/git-intro$ b. Verify the appended content to the DEVASC.txt file in the master branch using the cat command. devasc@labvm:~/labs/devnet-src/git-intro$ cat DEVASC.txt I am on my way to passing the Cisco DEVASC exam I am beginning to understand Git! This text was added originally while in the feature branch

devasc@labvm:~/labs/devnet-src/git-intro$

Step 9: Deleting a branch. a. Verify the feature branch is still available using the git branch command. devasc@labvm:~/labs/devnet-src/git-intro$ git branch feature * master

devasc@labvm:~/labs/devnet-src/git-intro$ b. Delete the feature branch using the git branch -d command. . devasc@labvm:~/labs/devnet-src/git-intro$ git branch -d feature Deleted branch feature (was cd828a7).

devasc@labvm:~/labs/devnet-src/git-intro$ c.

Verify the feature branch is no longer available using the git branch command. devasc@labvm:~/labs/devnet-src/git-intro$ git branch * master

devasc@labvm:~/labs/devnet-src/git-intro$

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 8 of 15

www.netacad.com

Lab - Software Version Control with Git

Part 6: Handling Merge Conflicts At times, you may experience a merge conflict. This is when you may have made overlapping changes to a file, and Git cannot automatically merge the changes. In this Part, you will create a test branch, modify its content, stage and commit the test branch, switch to the master branch, modify the content again, stage and commit the master branch, attempt to merge branches, locate and resolve the conflict, stage and commit the master branch again, and verify your commit.

Step 1: Create a new branch test. Create a new branch test. devasc@labvm:~/labs/devnet-src/git-intro$ git branch test

Step 2: Checkout the branch test. a. Checkout (switch to) the branch test. devasc@labvm:~/labs/devnet-src/git-intro$ git checkout test Switched to branch 'test'

devasc@labvm:~/labs/devnet-src/git-intro$ b. Verify the working branch is the test branch. devasc@labvm:~/labs/devnet-src/git-intro$ git branch master * test

devasc@labvm:~/labs/devnet-src/git-intro$

Step 3: Verify the current contents of DEVASC.txt. Verify the current contents of the DEVASC.txt file. Notice the first line includes the word "Cisco". devasc@labvm:~/labs/devnet-src/git-intro$ cat DEVASC.txt I am on my way to passing the Cisco DEVASC exam I am beginning to understand Git! This text was added originally while in the feature branch

devasc@labvm:~/labs/devnet-src/git-intro$

Step 4: Modify the contents of DEVASC.txt in the test branch. Use the sed command to change the word "Cisco" to "NetAcad" in the DEVASC.txt file. devasc@labvm:~/labs/devnet-src/git-intro$ sed -i 's/Cisco/NetAcad/' DEVASC.txt

Step 5: Verify the contents of the modified DEVASC.txt in the test branch. Verify the change to the DEVASC.txt file. devasc@labvm:~/labs/devnet-src/git-intro$ cat DEVASC.txt I am on my way to passing the NetAcad DEVASC exam I am beginning to understand Git! This text was added originally while in the feature branch

devasc@labvm:~/labs/devnet-src/git-intro$

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 9 of 15

www.netacad.com

Lab - Software Version Control with Git

Step 6: Stage and commit the test branch. Stage and commit the file with a single git commit -a command. The -a option only affects files that have been modified and deleted. It does not affect new files. devasc@labvm:~/labs/devnet-src/git-intro$ git commit -a -m "Change Cisco to NetAcad" [test b6130a6] Change Cisco to NetAcad 1 file changed, 1 insertion(+), 1 deletion(-)

devasc@labvm:~/labs/devnet-src/git-intro$

Step 7: Checkout the master branch. a. Checkout (switch to) the master branch. devasc@labvm:~/labs/devnet-src/git-intro$ git checkout master Switched to branch 'master'

devasc@labvm:~/labs/devnet-src/git-intro$ b. Verify that the master branch is your current working branch. devasc@labvm:~/labs/devnet-src/git-intro$ git branch * master test

devasc@labvm:~/labs/devnet-src/git-intro$

Step 8: Modify the contents of DEVASC.txt in the master branch. Use the sed command to change the word "Cisco" to "DevNet" in the DEVASC.txt file. devasc@labvm:~/labs/devnet-src/git-intro$ sed -i 's/Cisco/DevNet/' DEVASC.txt

Step 9: Verify the contents of the modified DEVASC.txt in the master branch. Verify the change to the file. devasc@labvm:~/labs/devnet-src/git-intro$ cat DEVASC.txt I am on my way to passing the DevNet DEVASC exam I am beginning to understand Git! This text was added originally while in the feature branch

devasc@labvm:~/labs/devnet-src/git-intro$

Step 10: Stage and commit the master branch. Stage and commit the file using the git commit -a command. devasc@labvm:~/labs/devnet-src/git-intro$ git commit -a -m "Changed Cisco to DevNet" [master 72996c0] Changed Cisco to DevNet 1 file changed, 1 insertion(+), 1 deletion(-)

devasc@labvm:~/labs/devnet-src/git-intro$

Step 11: Attempt to merge the test branch into the master branch. Attempt to merge the test branch history into the master branch. devasc@labvm:~/labs/devnet-src/git-intro$ git merge test Auto-merging DEVASC.txt CONFLICT (content): Merge conflict in DEVASC.txt

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 10 of 15

www.netacad.com

Lab - Software Version Control with Git

Automatic merge failed; fix conflicts and then commit the result.

devasc@labvm:~/labs/devnet-src/git-intro$

Step 12: Find the conflict. a. Use the git log command to view the commits. Notice that the HEAD version is the master branch. This will be helpful in the next step. devasc@labvm:~/labs/devnet-src/git-intro$ git log commit 72996c09fa0ac5dd0b8ab9ec9f8530ae2c5c4eb6 (HEAD -> master) Author: Sample User Date: Sun Apr 19 00:36:05 2020 +0000 Changed Cisco to DevNet

b. Use the cat command to view the contents of the DEVASC.txt file. The file now contains information to help you find the conflict. The HEAD version (master branch) containing the word "DevNet" is conflicting with the test branch version and the word "NetAcad". devasc@labvm:~/labs/devnet-src/git-intro$ cat DEVASC.txt > test I am beginning to understand Git! This text was added originally while in the feature branch

devasc@labvm:~/labs/devnet-src/git-intro$

Step 13: Manually edit the DEVASC.txt file to remove the conflicting text. a. Use the vim command to edit the file. devasc@labvm:~/labs/devnet-src/git-intro$ vim DEVASC.txt b. Use the up and down arrow to select the proper line of text. Press dd (delete) on the following lines that are highlighted. dd will delete the line the cursor is on. > test I am beginning to understand Git! This text was added originally while in the feature branch

c.

Save your changes in vim by pressing ESC (the escape key) and then typing : (colon) followed by wq and press enter. ESC : wq

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 11 of 15

www.netacad.com

Lab - Software Version Control with Git

Step 14: Verify your edits of DEVASC.txt in the master branch. Verify you changes using the cat command. devasc@labvm:~/labs/devnet-src/git-intro$ cat DEVASC.txt I am on my way to passing the DevNet DEVASC exam I am beginning to understand Git! This text was added originally while in the feature branch

devasc@labvm:~/labs/devnet-src/git-intro$

Step 15: Stage and commit the master branch. Stage and commit DEVASC.txt to the master branch using the git commit -a command. devasc@labvm:~/labs/devnet-src/git-intro$ git add DEVASC.txt devasc@labvm:~/labs/devnet-src/git-intro$ git commit -a -m "Manually merged from test branch" [master 22d3da4] Manually merged from test branch

devasc@labvm:~/labs/devnet-src/git-intro$

Step 16: Verify the commit. Use the git log command to verify the commit. If necessary, you can use q to quit out of the git log display. devasc@labvm:~/labs/devnet-src/git-intro$ git log commit 22d3da41e00549ce69dc145a84884af6a1697734 (HEAD -> master) Merge: 72996c0 b6130a6 Author: Sample User Date: Sun Apr 19 01:09:53 2020 +0000 manually merged from branch test

Part 7: Integrating Git with GitHub So far, all the changes you have made to your file have been stored on your local machine. Git runs locally and does not require any central file server or cloud-based hosting service. Git allows a user to locally store and manage files. Although Git is useful for a single user, integrating the local Git repository with a cloud-based server like GitHub is helpful when working within a team. Each team member keeps a copy on the repository on their local machine and updates the central cloud-based repository to share any changes. There are quite a few popular Git services, including GitHub, Stash from Atlassian, and GitLab. Because it is readily accessible, you will use GitHub in these examples.

Step 1: Create a GitHub Account. If you have not so previously, go to github.com and create a GitHub account. If you have a GitHub account go to step 2.

Step 2: Log into your GitHub Account Create a Repository. Log into your GitHub account.

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 12 of 15

www.netacad.com

Lab - Software Version Control with Git

Step 3: Create a Repository. a. Select the "New repository" button or click on the "+" icon in the upper right corner and select "New repository". b. Create a repository using the following information: Repository name: devasc-study-team Description: Working together to pass the DEVASC exam Public/Private: Private c.

Select: Create repository

Step 4: Create a new directory devasc-study-team. a. If you are not already in the git-intro directory, change to it now. devasc@labvm:~$ cd ~/labs/devnet-src/git-intro b. Make a new directory called devasc-study-team. The directory does not have to match the name as the repository. devasc@labvm:~/labs/devnet-src/git-intro$ mkdir devasc-study-team

Step 5: Change directory to devasc-study-team. Use the cd command to change directories to devasc-study-team. devasc@labvm:~/labs/devnet-src/git-intro$ cd devasc-study-team devasc@labvm:~/labs/devnet-src/git-intro/devasc-study-team$

Step 6: Copy the DEVASC file. a. Use the cp command to copy the DEVASC.txt from git-intro parent directory to the devasc-study-team sub-directory. The two periods and a slash prior the file name indicates the parent directory. The space and period following the file name indicates to copy file in the current directory with the same file name. devasc@labvm:~/labs/devnet-src/git-intro/devasc-study-team$ cp ../DEVASC.txt . b. Verify the file was copied with the ls command and the contents of the file with the cat command. devasc@labvm:~/labs/devnet-src/git-intro/devasc-study-team$ ls DEVASC.txt devasc@labvm:~/labs/devnet-src/git-intro/devasc-study-team$ cat DEVASC.txt I am on my way to passing the DevNet DEVASC exam I am beginning to understand Git! This text was added originally while in the feature branch

devasc@labvm:~/labs/devnet-src/git-intro/devasc-study-team$

Step 7: Initialize a new Git repository. a. Use the git init command to initialize the current directory (devasc-study-team) as a Git repository. The message displayed indicates that you have created a local repository within your project contained in the hidden directory .git. This is where all of your change history is located. devasc@labvm:~/labs/devnet-src/git-intro/devasc-study-team$ git init Initialized empty Git repository in /home/devasc/src/git-intro/devasc-study-team/.git/

devasc@labvm:~/labs/devnet-src/git-intro/devasc-study-team$ b. Next, check your global git variables with the git config --list command. © 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 13 of 15

www.netacad.com

Lab - Software Version Control with Git

devasc@labvm:~/labs/devnet-src/git-intro/devasc-study-team$ git config --list user.name=SampleUser [email protected] core.repositoryformatversion=0 core.filemode=true core.bare=false core.logallrefupdates=true

devasc@labvm:~/labs/devnet-src/git-intro/devasc-study-team$ c.

If the user.name and user.email variables do not match your GitHub credentials, change them now. devasc@labvm:~$ git config --global user.name "GitHub username" devasc@labvm:~$ git config --global user.email GitHub-email-address

Step 8: Point Git repository to GitHub repository. a. Use the git remote add command to add a Git URL as a remote alias. The value "origin" points to the newly created repository on GitHub. Use your GitHub username in the URL path for github-username. Note: Your username is case-sensitive. devasc@labvm:~/labs/devnet-src/git-intro/devasc-study-team$ git remote add origin https://github.com/github-username/devasc-study-team.git b. Verify the remote is running on github.com. devasc@labvm:~/labs/devnet-src/git-intro/devasc-study-team$ git remote -verbose origin https://github.com/username/devasc-study-team.git (fetch) origin https://github.com/username/devasc-study-team.git (push)

devasc@labvm:~/labs/devnet-src/git-intro/devasc-study-team$ c.

View the git log. The error indicates that there are no commits. devasc@labvm:~/labs/devnet-src/git-intro/devasc-study-team$ git log fatal: your current branch 'master' does not have any commits yet

Step 9: Stage and Commit the DEVASC.txt file. a. Use the git add command to stage the DEVASC.txt file. devasc@labvm:~/labs/devnet-src/git-intro/devasc-study-team$ git add DEVASC.txt b. Use git commit command to commit the DEVASC.txt file. devasc@labvm:~/labs/devnet-src/git-intro/devasc-study-team$ git commit -m "Add DEVASC.txt file to devasc-study-team" [master (root-commit) c60635f] Add DEVASC.txt file to devasc-study-team 1 file changed, 3 insertions(+) create mode 100644 DEVASC.txt

devasc@labvm:~/labs/devnet-src/git-intro/devasc-study-team$

Step 10: Verify the commit. a. Use the git log command to verify the commit. devasc@labvm:~/labs/devnet-src/git-intro/devasc-study-team$ git log commit c60635fe4a1f85667641afb9373e7f49a287bdd6 (HEAD -> master) Author: username

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 14 of 15

www.netacad.com

Lab - Software Version Control with Git

Date:

Mon Apr 20 02:48:21 2020 +0000

Add DEVASC.txt file to devasc-study-team

devasc@labvm:~/labs/devnet-src/git-intro/devasc-study-team$ b. Use the git status command to view status information. The phrase "working tree clean" means that Git has compared your file listing to what you've told Git, and it's a clean slate with nothing new to report. devasc@labvm:~/labs/devnet-src/git-intro/devasc-study-team$ git status On branch master nothing to commit, working tree clean

devasc@labvm:~/labs/devnet-src/git-intro/devasc-study-team$

Step 11: Send (push) the file from Git to GitHub. Use the git push origin master command to send (push) the file to your GitHub repository. You will be prompted for a username and password, which will be the one you used to create your GitHub account. devasc@labvm:~/labs/devnet-src/git-intro/devasc-study-team$ git push origin master Username for 'https://github.com': username Password for 'https://[email protected]': password Enumerating objects: 3, done. Counting objects: 100% (3/3), done. Delta compression using up to 2 threads Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 347 bytes | 347.00 KiB/s, done. Total 3 (delta 0), reused 0 (delta 0) To https://github.com/username/devasc-study-team.git * [new branch] master -> master

devasc@labvm:~/labs/devnet-src/git-intro/devasc-study-team$ Note: If, after entering your username and password, you get a fatal error stating repository is not found, you most likely submitted an incorrect URL. You will need to reverse your git add command with the git remote rm origin command.

Step 12: Verify file on GitHub. a. Go to your GitHub account and under "Repositories" select username/devasc-study-team. b. You should see that the DEVASC.txt file has been added to this GitHub repository. Click on the file to view the contents. End of document

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 15 of 15

www.netacad.com

LAB 3.4.6 Lab - Python Classes Review (Instructor Version) Instructor Note: Red font color or gray highlights indicate text that appears in the instructor copy only.

Objectives Part 1: Launch the DEVASC VM Part 2: Review Functions, Methods, and Classes Part 3: Define a Function Part 4: Define a Class with Methods Part 5: Review the circleClass.py Script

Background / Scenario In this lab, you review Python methods, functions, and classes. You then create a class and instantiate it several times with different values. Finally, you review the Circle class example used in the course.

Required Resources •

1 PC with operating system of your choice



Virtual Box or VMWare



DEVASC Virtual Machine

Instructions Part 1: Launch the DEVASC VM If you have not already completed the Lab - Install the Virtual Machine Lab Environment, do so now. If you have already completed that lab, launch the DEVASC VM now.

Part 2: Review Functions, Methods, and Classes In this part, you review the difference between functions and methods. You also review the basic structure of a class.

Step 1: What is a function? As a quick review, recall that a function is an independently defined block of code that is called by name. In the following example, the function called functionName is defined and then called. Notice that it is an independent block of code. It is not encapsulated in any other code. # Define the function def functionName: ...blocks of code... # Call the function functionName()

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 1 of 6

www.netacad.com

Lab - Python Classes Review

Step 2: What is a method? A method, however, cannot be called by itself. It is dependent on the object in which it is defined. In the following example, the class className is declared and three methods are defined. The class is instantiated and then each method of the class is called. Note: This pseudo-code does not explicitly show the class constructor __init__ method with the self variable. This special method is reviewed below. # Define the class class className # Define a method def method1Name ...blocks of code # Define another method def method2Name ...blocks of code # Define yet another method def method3Name ...blocks of code # Instantiate the class myClass = className() # Call the instantiation and associated methods myClass.method1Name() myClass.method2Name() myClass.method3Name()

Part 3: Define a Function In this part, you will define a function with arguments and then call the function. a. Open a new text file and save it as myCity.py in your ~/labs/devnet-src/python directory. b. Define the function myCity with the argument city for city name. When the function is called with a specified city name, it prints a statement that includes the city name. def myCity(city): print("I live in " + city + ".") c.

Call the function myCity passing it different values for city, as shown in the following examples. myCity("Austin") myCity("Tokyo") myCity("Salzburg")

d. Save and run the myCity.py file. You should get the following output. devasc@labvm:~/labs/devnet-src/python$ python3 myCity.py I live in Austin. © 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 2 of 6

www.netacad.com

Lab - Python Classes Review

I live in Tokyo. I live in Salzburg.

devasc@labvm:~/labs/devnet-src/python$

Part 4: Define a Class with Methods In this part, you will define a class, use the __init__() function to define a method for the class, and then create instances of the class.

Step 1: Define and then instantiate a class with the __init__() method. A Python class is used to create objects that have properties and methods. All Python classes typically include an explicitly defined __init__() function, although you can create a class without defining one. The __init__() function is always initiated when a class is instantiated. Instantiating a class creates a copy of the class which inherits all the class variables and methods. Note: Although it is sometimes called the __init__() function, it is dependent on the class. Therefore, it is technically a method. a. Open a new text file and save it as myLocation.py. b. Define a class with the name Location and press Enter. If you are working is VS Code, then the text editor should automatically indent four spaces. class Location: | Open Folder..., navigate to the labs/devnet-src/school-library folder, and click OK.

Step 2: Investigate the libraries used by add100RandomBooks.py program. a. In VS Code EXPLORER pane on the left, click add100RandomBooks.py to open it, if necessary.

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 13 of 17

www.netacad.com

Lab - Explore Rest APIs with API Simulator and Postman

b. At the top, notice the “shebang” that sets the interpreter to Python 3 and then the three libraries that are imported. #!/usr/bin/env python3 import requests import json from faker import Faker c.

You will use the Python requests library throughout this course. The requests library is required if you want to use Python to make API requests using GET, POST, DELETE and other HTTP methods.

d. Faker is a Python library that generates 'fake' data for you. This program uses the Python faker library to generate random book titles, authors, and ISBNs. You can search the internet for more information on faker library. However, complete the following steps to see all the 252 methods for the faker library. 1) Open a terminal window and start Python 3. 2) From faker import the Faker() module. 3) Assign the Faker() module to fake. 4) To see all the methods, enter fake. and then press the tab key twice. Notice the method fake.name(), which you will use in the next step. In the next step and later in this lab, you will also use the three highlighted methods (prefaced with fake.).: catch_phrase(), isbn13(), and name(). devasc@labvm:~/labs/devnet-src/school-library$ python3 Python 3.8.2 (default, Apr 27 2020, 15:53:34) [GCC 9.3.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> from faker import Faker >>> fake = Faker() >>> fake. Display all 252 possibilities? (y or n) fake.add_provider( fake.future_datetime( fake.address( fake.generator_attrs fake.am_pm( fake.get_formatter(

fake.catch_phrase( fake.ipv4_public( fake.chrome( fake.isbn10( fake.city( fake.isbn13(

fake.date_time_ad( fake.msisdn( fake.date_time_between( fake.name(

fake.future_date( fake.pydict(

fake.pyfloat( fake.pyint( fake.pyiterable( fake.random_element( fake.random_int( fake.random_letter( fake.texts( fake.time( fake.zipcode_plus4(

>>>

Step 3: Practice generating random data using the faker library. a. Enter the following to generate a fake name. Your output will be a different fake name each time you execute the command. >>> print('My name is {}.'.format(fake.name())) My name is Katherine Ross.

>>> © 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 14 of 17

www.netacad.com

Lab - Explore Rest APIs with API Simulator and Postman

Question:

b. Using the three highlighted messages in Step 2d above, enter the command that would print the following fake output. Type your answers here. >>> print('My name is {} and I wrote "{}" (ISBN {}).'.format(fake.name(),fake.catch_phrase(),fake.isbn13())) My name is Gary Castaneda and I wrote "Organic incremental neural-net" (ISBN 978-0669-01935-3).

>>> c.

Later in the program, a loop is used to iterate through these three methods to create entries for the School Library. Enter the following to generate 10 random names. After the "…" you will need to press return a second time. >>> for i in range(10): ... print(fake.name()) ... Kevin Moyer Mr. Christopher Green MD Spencer Jensen Whitney Guzman Nicole Scott Tammy Lewis Craig Edwards Michael Diaz Ryan Mccoy Terry Rocha

>>> d. Quit the Python interpreter when done investigating the faker library. >>> quit() devasc@labvm:~/labs/devnet-src/school-library$

Step 4: Review the function variables. The two functions in the program use three variables to get an authorization token from the School Library API service. APIHOST = "http://library.demo.local" LOGIN = "cisco" PASSWORD = "Cisco123!"

Step 5: Review the getAuthToken function. a. The getAuthToken function uses three variables to build a request. The r variable invokes the POST method for the loginViaBasic API and stores the token value if the call is successful. Notice the use of an f-string to build the request URL. def getAuthToken(): authCreds = (LOGIN, PASSWORD) r = requests.post( f"{APIHOST}/api/v1/loginViaBasic", auth = authCreds )

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 15 of 17

www.netacad.com

Lab - Explore Rest APIs with API Simulator and Postman

b. If the call is unsuccessful (HTTP status code is not equal to 200), an exception is raised and printed to the terminal window. Again, notice the use of an f-string to build the exception message. You can test the exception code by changing the one of the variables in Step 4. if r.status_code == 200: return r.json()["token"] else: raise Exception(f"Status code {r.status_code} and text {r.text}, while trying to Auth.")

Step 6: Review the addBook function. a. Similar to the addAuthToken function, the addBook function uses the three variables shown in Step 4 to build a request. The r variable invokes the POST method for the books API. The data comes from a variable called book, which is specified in the final part of the program. def addBook(book, apiKey): r = requests.post( f"{APIHOST}/api/v1/books", headers = { "Content-type": "application/json", "X-API-Key": apiKey }, data = json.dumps(book) )

b. If the call is unsuccessful, an exception is raised and printed to the terminal window. You can test it by changing the one of the variables in Step 4. if r.status_code == 200: print(f"Book {book} added.") else: raise Exception(f"Error code {r.status_code} and text {r.text}, while trying to add book {book}.")

Step 7: Review the code that invokes the two functions. a. The addAuthToken function is invoked and the results are stored in the variable apiKey. apiKey = getAuthToken()

b. The Faker() module is set to a variable named fake. A for loop then iterates 100 times. The i variable is used later in the loop to set the value for the id key for each new book from 4 up to and not including 104. Note: If you want to keep the two previous books added previously in this lab, change range to (6, 106). Instructor Note for LA reviewers: Your version of the script may have the range from 4 to 105, which will add 101 books. Change the range and save the script to only add 100 books. This will be updated in the GA release of the DEVASC VM. fake = Faker() for i in range(4, 104):

c.

Next, three variables hold the value of methods invoked from the Faker() module: catch_phrase(), name(), and isbn13(). fakeTitle = fake.catch_phrase() fakeAuthor = fake.name() fakeISBN = fake.isbn13()

d. Recall that the payload parameter for the books API requires JSON in the following format: © 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 16 of 17

www.netacad.com

Lab - Explore Rest APIs with API Simulator and Postman

{ "id": 0, "title": "string", "author": "string" }

The book variable is built using the three required keys for the payload parameter and values from the three fake variables. book = {"id":i, "title": fakeTitle, "author": fakeAuthor, "isbn": fakeISBN}

e. Finally, the addBook function is called passing the book and apiKey variables. Because addBook is part of the loop, it will be called 101 times, one time each for book ID 4 through 105.

Step 8: Run and verify the add100RandomBooks.py program. a. Enter the Python 3 command to run the add100RandomBooks.py program. You should get output similar to the following although your book titles and ISBN numbers will be different fake values. devasc@labvm:~/labs/devnet-src/school-library$ python3 add100RandomBooks.py Book {'id': 4, 'title': 'Assimilated client-server frame', 'author': 'Chelsea Mitchell', 'isbn': '978-0-411-83123-3'} added. Book {'id': 5, 'title': 'Adaptive tangible conglomeration', 'author': 'Edward Ryan', 'isbn': '978-1-64406-014-8'} added.

Book {'id': 103, 'title': 'Fundamental uniform data-warehouse', 'author': 'Dennis David', 'isbn': '978-1-68465-896-1'} added. Book {'id': 104, 'title': 'Organic 4thgeneration functionalities', 'author': 'Nicole Gilbert', 'isbn': '978-0-13-176202-2'} added.

devasc@labvm:~/labs/devnet-src/school-library$ b. Return to the Chromium browser and refresh the http://library.demo.local/ webpage. You should now see your 100 new books added. Note: If you got to the API documentation page instead of the main page (http://library.demo.local/api/v1/docs) and use Try It out, you will only get a list of the first 10 books. You can enter a value from 2 to 10 the page parameter to see the other books. Question:

How would you add another 100 books? Type your answers here. Change the for loop to have a range of 104 to 204. End of document

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 17 of 17

www.netacad.com

LAB 4.9.2 Lab - Integrate a REST API in a Python Application (Instructor Version) Instructor Note: Red font color or gray highlights indicate text that appears in the instructor copy only.

Objectives Part 1: Launch the DEVASC VM Part 2: Demonstrate the MapQuest Directions Application Part 3: Get a MapQuest API Key Part 4: Build the Basic MapQuest Direction Application Part 5: Upgrade the MapQuest Directions Application with More Features Part 6: Test Full Application Functionality

Background / Scenario In this lab, you will create an application in Visual Studio Code (VS Code) that retrieves JSON data from the MapQuest Directions API, parses the data, and formats it for output to the user. You will use the GET Route request from the MapQuest Directions API. Review the GET Route Directions API documentation here: https://developer.mapquest.com/documentation/directions-api/route/get/ Note: If the above link no longer works, search for “MapQuest API Documentation”.

Required Resources •

1 PC with operating system of your choice



Virtual Box or VMWare



DEVASC Virtual Machine

Instructions Part 1: Launch the DEVASC VM If you have not already completed the Lab - Install the Virtual Machine Lab Environment, do so now. If you have already completed that lab, launch the DEVASC VM now.

Part 2: Demonstrate the MapQuest Directions Application Your instructor may demonstrate the MapQuest Directions Application and show you the script used to create it. However, you will create this script step by step in this lab. The application asks for a starting location and a destination. It then requests JSON data from the MapQuest Directions API, parses it, and displays useful information. >>> Starting Location: Washington Destination: Baltimore URL: https://www.mapquestapi.com/directions/v2/route?key=your_api_key&from=Washington&to=Ba ltimore

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 1 of 17

www.netacad.com

Lab - Integrate a REST API in a Python Application

API Status: 0 = A successful route call. Directions from Washington to Baltimore Trip Duration: 00:49:19 Kilometers: 61.32 Fuel Used (Ltr): 6.24 ============================================= Start out going north on 6th St/US-50 E/US-1 N toward Pennsylvania Ave/US-1 Alt N. (1.28 km) Turn right onto New York Ave/US-50 E. Continue to follow US-50 E (Crossing into Maryland). (7.51 km) Take the Balt-Wash Parkway exit on the left toward Baltimore. (0.88 km) Merge onto MD-295 N. (50.38 km) Turn right onto W Pratt St. (0.86 km) Turn left onto S Calvert St/MD-2. (0.43 km) Welcome to BALTIMORE, MD. (0.00 km) ============================================= Starting Location: quit >>>

Note: To see the JSON for the above output, you can copy the URL in a browser tab. However, you will need to replace your_api_key with the MapQuest API key you obtain in Part 3. Instructor Note: The following is the answer script for the MapQuest Directions Application. You may want to show the script to the students and demonstrate its operation. However, we recommend that you do not give students the script. They will build it over the course of this lab. #Replace "your_api_key" with your MapQuest API key import urllib.parse import requests main_api = "https://www.mapquestapi.com/directions/v2/route?" key = "your_api_key"

while True: orig = input("Starting Location: ") if orig == "quit" or orig == "q": break dest = input("Destination: ") if dest == "quit" or dest == "q": break url = main_api + urllib.parse.urlencode({"key":key, "from":orig, "to":dest}) json_data = requests.get(url).json() print("URL: " + (url)) json_data = requests.get(url).json() json_status = json_data["info"]["statuscode"] if json_status == 0: print("API Status: " + str(json_status) + " = A successful route call.\n") print("=============================================")

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 2 of 17

www.netacad.com

Lab - Integrate a REST API in a Python Application

print("Directions from " + (orig) + " to " + (dest)) print("Trip Duration: " + (json_data["route"]["formattedTime"])) print("Kilometers: " + str("{:.2f}".format((json_data["route"]["distance"])*1.61))) print("Fuel Used (Ltr): " + str("{:.2f}".format((json_data["route"]["fuelUsed"])*3.78))) print("=============================================") for each in json_data["route"]["legs"][0]["maneuvers"]: print((each["narrative"]) + " (" + str("{:.2f}".format((each["distance"])*1.61) + " km)")) print("=============================================\n") elif json_status == 402: print("**********************************************") print("Status Code: " + str(json_status) + "; Invalid user inputs for one or both locations.") print("**********************************************\n") elif json_status == 611: print("**********************************************") print("Status Code: " + str(json_status) + "; Missing an entry for one or both locations.") print("**********************************************\n") else: print("************************************************************************") print("For Staus Code: " + str(json_status) + "; Refer to:") print("https://developer.mapquest.com/documentation/directions-api/statuscodes") print("************************************************************************\n")

Part 3: Get a MapQuest API Key Before building the application, you need to complete the following steps to get a MapQuest API key. a. Go to: https://developer.mapquest.com/. b. Click Sign Up at the top of the page. c.

Fill out the form to create a new account. For Company, enter Cisco Networking Academy Student.

d. After clicking Sign Me Up, you are redirected to the Manage Keys page. If you are redirected elsewhere, click Manage Keys from the list of options on the left. e. Click Approve All Keys. f.

Expand My Application.

g. Copy your Consumer Key to a text file for future use. This will be the key you use for the rest of this lab. Note: MapQuest may change the process for obtaining a key. If the steps above are no longer valid, search the internet for “steps to generate mapquest api key”.

Part 4: Build the Basic MapQuest Direction Application In this Part, you will create a Python script to send a URL request to the MapQuest directions API. You will then test your API call. Throughout the rest of this lab, you will build your script in parts, saving the file with a new name each time. This will help with learning the pieces of the application as well as provide you a series of scripts that you can return to if you run into any problems in the current version of your application.

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 3 of 17

www.netacad.com

Lab - Integrate a REST API in a Python Application

Step 1: Create a New File in VS Code. You can use any tools you want to enter in Python commands and execute the Python code. However, this lab will demonstrate building the application in VS Code. a. Open VS Code. There is a shortcut on the Desktop, for your convenience. b. Select File > Open Folder... c.

Navigate to the /labs/devnet-src/mapquest directory and click OK. This directory is currently empty and is where you will store each iteration of your application.

d. Select File > New File. e. Select File > Save as… and name the file mapquest_parse-json_1.py and click Save.

Step 2: Importing modules for the application. To begin your script for parsing JSON data, you will need to import two modules from the Python library: requests and urllib.parse. The requests module provides functions for retrieving JSON data from a URL. The urllib.parse module provides a variety of functions that will enable you to parse and manipulate the JSON data you receive from a request to a URL. a. Add the following import statements at the top of your script. import urllib.parse import requests

b. Select Terminal > New Terminal to open a Terminal inside VS Code. c.

Save and run your script. You should get no errors. You should save and run your scripts often to test code functionality. devasc@labvm:~/labs/devnet-src/mapquest$ python3 mapquest_parse-json_1.py devasc@labvm:~/labs/devnet-src/mapquest$

Step 3: Build the URL for the request to the MapQuest directions API. The first step in creating your API request is to construct the URL that your application will use to make the call. Initially, the URL will be the combination of the following variables: • • • •

main_api - the main URL that you are accessing orig - the parameter to specify your point of origin dest - the parameter to specify your destination key - the MapQuest API key you retrieved from the developer website

a. Create variables to build the URL that will be sent in the request. In the following code, replace your_api_key with the Consumer Key you copied from your MapQuest developer account. main_api = "https://www.mapquestapi.com/directions/v2/route?" orig = "Washington, D.C." dest = "Baltimore, Md" key = "your_api_key"

b. Combine the four variables main_api, orig, dest, and key to format the requested URL. Use the urlencode method to properly format the address value. This function builds the parameters part of the URL and converts possible special characters in the address value into acceptable characters (e.g. space into “+” and a comma into “%2C”). url = main_api + urllib.parse.urlencode({"key":key, "from":orig, "to":dest})

c.

Create a variable to hold the reply of the requested URL and print the returned JSON data. The json_data variable holds a Python’s Dictionary representation of the json reply of the get method of the requests module. The requests.get will make the API call to the MapQuest API. The print statement will

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 4 of 17

www.netacad.com

Lab - Integrate a REST API in a Python Application

be used temporarily to check the returned data. You will replace this print statement with more sophisticated display options later in the lab. json_data = requests.get(url).json() print(json_data)

d. Your final code should look like this, but with a different value for the key. import urllib.parse import requests main_api = "https://www.mapquestapi.com/directions/v2/route?" orig = "Washington, D.C." dest = "Baltimore, Md" key = "fZadaFOY22VIEEemZcBFfxl5vjSXIPpZ" #Replace with your MapQuest key url = main_api + urllib.parse.urlencode({"key":key, "from":orig, "to":dest}) json_data = requests.get(url).json() print(json_data)

Step 4: Test the URL request. a. Save and run your mapquest_parse-json_1.py script and verify it works. b. Troubleshoot your code, if necessary. Although your output might be slightly different, you should get a JSON response similar to the following. Notice that the output is a dictionary with two key/value pairs. The value for the key route is another dictionary that includes additional dictionaries and lists. The key info includes the statuscode key/value pair that you will use later in the lab. devasc@labvm:~/labs/devnet-src/mapquest$ python3 mapquest_parse-json_1.py {'route': {'hasTollRoad': False, 'hasBridge': True, 'boundingBox': {'lr': {'lng': 76.612137, 'lat': 38.892063}, 'ul': {'lng': -77.019913, 'lat': 39.290443}}, 'distance': 38.089, 'hasTimedRestriction': False, 'hasTunnel': False, 'hasHighway': True, 'computedWaypoints': [], 'routeError': {'errorCode': -400, 'message': ''}, 'formattedTime': '00:49:29', 'sessionId': '5eadfc17-00ee-5f21-02b4-1a24-0647e6e69816', 'hasAccessRestriction': False, 'realTime': 2915, 'hasSeasonalClosure': False, 'hasCountryCross': False, 'fuelUsed': 1.65, 'legs': [{'hasTollRoad': False, 'hasBridge': True, 'destNarrative': 'Proceed to BALTIMORE, MD.', 'distance': 38.089, 'hasTimedRestriction': False, 'hasTunnel': False, 'hasHighway': True, 'index': 0, 'formattedTime': '00:49:29', 'origIndex': -1, 'hasAccessRestriction': False, 'hasSeasonalClosure': False, 'hasCountryCross': False, 'roadGradeStrategy': [[]], 'destIndex': 3, 'time': 2969, 'hasUnpaved': False, 'origNarrative': '', 'maneuvers': [{'distance': 0.792, 'streets': ['6th St', 'US-50 E', 'US-1 N'], 'narrative': 'Start out going north on 6th St/US-50 E/US-1 N toward Pennsylvania Ave/US-1 Alt N.', 'turnType': 0, 'startPoint': {'lng': -77.019913, 'lat': 38.892063}, 'index': 0, 'formattedTime': '00:02:06', 'directionName': 'North', 'maneuverNotes': [], 'linkIds': [], 'signs': [{'extraText': '', 'text': '50', 'type': 2, 'url': 'http://icons.mqcdn.com/icons/rs2.png?n=50&d=EAST', 'direction': 8}, {'extraText': '', 'text': '1', 'type': 2, 'url': 'http://icons.mqcdn.com/icons/rs2.png?n=1&d=NORTH', > output omitted > 'geocodeQuality': 'CITY', 'adminArea1Type': 'Country', 'adminArea3Type': 'State', 'latLng': {'lng': -76.61233, 'lat': 39.29044}}], 'time': 2969, 'hasUnpaved': False, 'locationSequence': [0, 1], 'hasFerry': False}, 'info': {'statuscode': 0, 'copyright': {'imageAltText': '© 2019 MapQuest, Inc.', 'imageUrl': 'http://api.mqcdn.com/res/mqlogo.gif', 'text': '© 2019 MapQuest, Inc.'}, 'messages': []}}

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 5 of 17

www.netacad.com

Lab - Integrate a REST API in a Python Application

devasc@labvm:~/labs/devnet-src/mapquest$

c.

Change the orig and dest variables. Rerun the script to get different results. To ensure the results you want, it is best to include both the city and the state for cities in the USA. When referring to cities in other countries, you can usually use either the English name for the city and country or the native name. For example: orig = "Rome, Italy" dest = "Frascati, Italy"

or orig = "Roma, Italia" dest = "Frascati, Italia"

Step 5: Print the URL and check the status of the JSON request. Now that you know the JSON request is working, you can add some more functionality to the application. a. Save your script as mapquest_parse-json_2.py. b. Delete the print(json_data) statement as you no longer need to test that the request is properly formatted. c.

Add the statements below, which will do the following: o o o

Print the constructed URL so that the user can see the exact request made by the application. Parse the JSON data to obtain the statuscode value. Start an if loop that checks for a successful call, which is indicated by a returned value of 0. Add a print statement to display the statuscode value and its meaning. The \n adds a blank line below the output.

Later in this lab, you will add elif and else statements for different statuscode values. print("URL: " + (url)) json_data = requests.get(url).json() json_status = json_data["info"]["statuscode"] if json_status == 0: print("API Status: " + str(json_status) + " = A successful route call.\n")

Step 6: Test status and URL print commands. a. The example here uses the following parameters. orig = "Washington, D.C." dest = "Baltimore, Md"

b. Save and run your mapquest_parse-json_2.py script and verify it works. Troubleshoot your code, if necessary. You should get output similar to the following. Notice your key is embedded in the URL request. devasc@labvm:~/labs/devnet-src/mapquest$ python3 mapquest_parse-json_2.py URL: https://www.mapquestapi.com/directions/v2/route?key=fZadaFOY22VIEEemZcBFfxl5vjSXIPpZ&f rom=Washington%2C+D.C.&to=Baltimore%2C+Md API Status: 0 = A successful route call. devasc@labvm:~/labs/devnet-src/mapquest$

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 6 of 17

www.netacad.com

Lab - Integrate a REST API in a Python Application

Step 7: Add User input for starting location and destination. You have used static values for the location variables. However, the application requires that the user input these. Complete the following steps to update your application: a. Save your script as mapquest_parse-json_3.py. b. Delete the current orig and dest variables. c.

Rewrite the orig and dest to be within a while loop in which it requests user input for the starting location and destination. The while loop allows the user to continue to make requests for different directions. Add the following code, highlighted below, after the key parameter. Be sure all the remaining code is correctly indented within the while loop. import urllib.parse import requests main_api = "https://www.mapquestapi.com/directions/v2/route?" key = "fZadaFOY22VIEEemZcBFfxl5vjSXIPpZ" while True: orig = input("Starting Location: ") dest = input("Destination: ") url = main_api + urllib.parse.urlencode({"key": key, "from":orig, "to":dest}) print("URL: " + (url)) json_data = requests.get(url).json() json_status = json_data["info"]["statuscode"] if json_status == 0: print("API Status: " + str(json_status) + " = A successful route call.\n")

Step 8: Test user input functionality. Run your mapquest_parse-json_3.py script and verify it works. Troubleshoot your code, if necessary. You should get output similar to what is shown below. To end the program, enter Ctrl+C. You will get a KeyboardInterrupt error as shown in the output below. To stop the application more gracefully, you will add quit functionality in the next step. devasc@labvm:~/labs/devnet-src/mapquest$ python3 mapquest_parse-json_3.py Starting Location: Washington, D.C. Destination: Baltimore, Md URL: https://www.mapquestapi.com/directions/v2/route?key=fZadaFOY22VIEEemZcBFfxl5vjSXIPpZ&f rom=Washington%2C+D.C.&to=Baltimore%2C+Md API Status: 0 = A successful route call. Starting Location: ^CTraceback (most recent call last): File "mapquest_parse-json_3.py", line 9, in orig = input("Starting Location: ") KeyboardInterrupt

devasc@labvm:~/labs/devnet-src/mapquest$

Step 9: Add quit functionality to the application. Instead of forcing the application to quit with a keyboard interrupt, you will add the ability for the user to enter q or quit as keywords to quit the application. Complete the following steps to update your application:

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 7 of 17

www.netacad.com

Lab - Integrate a REST API in a Python Application

a. Save your script as mapquest_parse-json_4.py. b. Add an if statement after each location variable to check if the user enters q or quit, as shown below. while True: orig = input("Starting Location: ") if orig == "quit" or orig == "q": break dest = input("Destination: ") if dest == "quit" or dest == "q": break

Step 10: Test the quit functionality. Run your mapquest_parse-json_4.py script four times to test each location variable. Verify that both quit and q will end the application. Troubleshoot your code, if necessary. You should get output similar to the following. devasc@labvm:~/labs/devnet-src/mapquest$ Starting Location: q devasc@labvm:~/labs/devnet-src/mapquest$ Starting Location: quit devasc@labvm:~/labs/devnet-src/mapquest$ Starting Location: Washington, D.C Destination: q devasc@labvm:~/labs/devnet-src/mapquest$ Starting Location: Washington, D.C. Destination: quit devasc@labvm:~/labs/devnet-src/mapquest$

python3 mapquest_parse-json_4.py python3 mapquest_parse-json_4.py python3 mapquest_parse-json_4.py

python3 mapquest_parse-json_4.py

Step 11: Display the JSON data in JSONView. The Chromium browser in the DEVASC VM includes the JSONView extension. You can use this to view a JSON object in a readable, colored, and collapsible format. a. Run your mapquest_parse-json_4.py again and copy the code returned for the URL. Do not use the code below. Your result will include your API key. devasc@labvm:~/labs/devnet-src/mapquest$ python3 mapquest_parse-json_4.py Starting Location: Washington, D.C. Destination: Baltimore, Md URL: https://www.mapquestapi.com/directions/v2/route?key=fZadaFOY22VIEEemZcBFfxl5vjSXIPpZ&f rom=Washington%2C+D.C.&to=Baltimore%2C+Md API Status: 0 = A successful route call.

Starting Location: quit devasc@labvm:~/labs/devnet-src/mapquest$ b. Paste the URL in the Chromium browser address field. c.

Collapse the JSONView data by selecting the dash "-" before route, you will see that there are two root dictionaries: route and info. { - route:{

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 8 of 17

www.netacad.com

Lab - Integrate a REST API in a Python Application

hasTollRoad: false, hasBridge: true,

You will see that there are two root dictionaries: route and info. Notice that info has the statuscode key/value paired used in your code. { + route: {}, - info: { statuscode: 0, - copyright: { imageAltText: "© 2019 MapQuest, Inc.", imageUrl: "http://api.mqcdn.com/res/mqlogo.gif", text: "© 2019 MapQuest, Inc." }, messages: [ ] } } d. Expand the route dictionary (click on the plus sign "+" before route) and investigate the rich data. There are values to indicate whether the route has toll roads, bridges, tunnels, highways, closures, or crosses into other countries. You should also see values for distance, the total time the trip will take, and fuel usage. To parse and display this data in your application, you would specify the route dictionary and then select key/value pair you want to print. You will do some parsing of the route dictionary in the next part of the lab.

Part 5: Upgrade the MapQuest Directions Application with More Features In this Part, you will add additional features to your MapQuest Directions Application to provide more information to the user. You will include some trip summary information and then a list of the directions parsed from the legs dictionary. As a final step, you will add some basic error checking to validate user input.

Step 1: Display trip summary information to include duration, distance, and fuel used. a. Save your script as mapquest_parse-json_5.py. b. Below the API status print command, add several print statements that display the from and to locations, as well as the formattedTime, distance, and fuelUsed keys. The additional statements also include print statements that will display a double line before the next request for a starting location. Make sure these statements are embedded in the while True function. if json_status == 0: print("API Status: " + str(json_status) + " = A successful route call.\n") print("=============================================") print("Directions from " + (orig) + " to " + (dest)) print("Trip Duration: " + (json_data["route"]["formattedTime"])) print("Miles: " + str(json_data["route"]["distance"])) print("Fuel Used (Gal): " + str(json_data["route"]["fuelUsed"])) print("=============================================")

c.

Save and run mapquest_parse-json_5.py to see the following output. devasc@labvm:~/labs/devnet-src/mapquest$ python3 mapquest_parse-json_5.py

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 9 of 17

www.netacad.com

Lab - Integrate a REST API in a Python Application

Starting Location: Washington, D.C. Destination: Baltimore, Md URL: https://www.mapquestapi.com/directions/v2/route?key=fZadaFOY22VIEEemZcBFfxl5vjSXIPpZ&f rom=Washington%2C+D.C.&to=Baltimore%2C+Md API Status: 0 = A successful route call. ============================================= Directions from Washington, D.C. to Baltimore, Md Trip Duration: 00:49:29 Miles: 38.089 Fuel Used (Gal): 1.65 ============================================= Starting Location: q

devasc@labvm:~/labs/devnet-src/mapquest$ d. By defauilt, MapQuest uses the imperial system and there is not a request parameter to change data to the metric system. Therefore, you should probably convert your application to display metric values, as shown below. print("Kilometers: " + str((json_data["route"]["distance"])*1.61)) print("Fuel Used (Ltr): " + str((json_data["route"]["fuelUsed"])*3.78))

e. Run the modified mapquest_parse-json_5.py script to see the following output: devasc@labvm:~/labs/devnet-src/mapquest$ python3 mapquest_parse-json_5.py Starting Location: Washington, D.C. Destination: Baltimore, Md URL: https://www.mapquestapi.com/directions/v2/route?key=fZadaFOY22VIEEemZcBFfxl5vjSXIPpZ&f rom=Washington%2C+D.C.&to=Baltimore%2C+Md API Status: 0 = A successful route call. ============================================= Directions from Washington, D.C. to Baltimore, Md Trip Duration: 00:49:29 Kilometers: 61.32329 Fuel Used (Ltr): 6.236999999999999 =============================================

Starting Location: q devasc@labvm:~/labs/devnet-src/mapquest$ f.

The extra decimal places for Kilometers and Fuel Used are not helpful. Use the "{:.2f}".format argument to format the float values to 2 decimal places before converting them to string values, as shown below. Each statement should be on one line. print("Kilometers: " + str("{:.2f}".format((json_data["route"]["distance"])*1.61))) print("Fuel Used (Ltr): " + str("{:.2f}".format((json_data["route"]["fuelUsed"])*3.78)))

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 10 of 17

www.netacad.com

Lab - Integrate a REST API in a Python Application

Step 2: Test the parsing and formatting functionality. Save and run your mapquest_parse-json_5.py script to verify it works. Troubleshoot your code, if necessary. Make sure you have all the proper opening and closing parentheses. You should get output similar to the following. devasc@labvm:~/labs/devnet-src/mapquest$ python3 mapquest_parse-json_5.py Starting Location: Washington, D.C. Destination: Baltimore, Md URL: https://www.mapquestapi.com/directions/v2/route?key=fZadaFOY22VIEEemZcBFfxl5vjSXIPpZ&f rom=Washington%2C+D.C.&to=Baltimore%2C+Md API Status: 0 = A successful route call. ============================================= Directions from Washington, D.C. to Baltimore, Md Trip Duration: 00:49:29 Kilometers: 61.32 Fuel Used (Ltr): 6.24 =============================================

Starting Location: q devasc@labvm:~/labs/devnet-src/mapquest$

Step 3: Inspect the maneuvers list in the JSON data. a. Now you are ready to display the step-by-step directions from the starting location to the destination. Return to the Chromium browser where earlier you viewed the output in JSONView. If you closed the browser, copy the URL from last time you ran the program and paste it into the browser address bar. b. Inside the route dictionary, locate the legs list. The legs list includes one big dictionary with most of the JSON data. Find the maneuvers list and collapse each of the seven dictionaries inside, as shown below (click the "-" minus sign to toggle it to a "+" plus sign). If you are using different locations, you will probably have a different number of maneuver dictionaries. - legs: [ - { hasTollRoad: false, hasBridge: true, destNarrative: "Proceed to BALTIMORE, MD.", distance: 38.089, hasTimedRestriction: false, hasTunnel: false, hasHighway: true, index: 0, formattedTime: "00:49:29", origIndex: -1, hasAccessRestriction: false, hasSeasonalClosure: false, hasCountryCross: false, - roadGradeStrategy: [ [ ] ], destIndex: 3,

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 11 of 17

www.netacad.com

Lab - Integrate a REST API in a Python Application

time: 2969, hasUnpaved: false, origNarrative: "", - maneuvers: [ + {…}, + {…}, + {…}, + {…}, + {…}, + {…}, + {…} ], hasFerry: false } ], - options: {

c.

Expand the first dictionary in the maneuvers list. Each dictionary contains a narrative key with a value, such as “Start out going north...”, as shown below. You need to parse the JSON data to extract the value for the narrative key to display inside your application. - legs: [ - { hasTollRoad: false, hasBridge: true, destNarrative: "Proceed to BALTIMORE, MD.", distance: 38.089, hasTimedRestriction: false, hasTunnel: false, hasHighway: true, index: 0, formattedTime: "00:49:29", origIndex: -1, hasAccessRestriction: false, hasSeasonalClosure: false, hasCountryCross: false, - roadGradeStrategy: [ [ ] ], destIndex: 3, time: 2969, hasUnpaved: false, origNarrative: "", - maneuvers: [ - { distance: 0.792, - streets: [ "6th St", "US-50 E", "US-1 N" ],

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 12 of 17

www.netacad.com

Lab - Integrate a REST API in a Python Application

narrative: "Start out going north on 6th St/US-50E/US-1 N toward Pennsylvania Ave/US-1 Alt N.", turnType: 0, - startPoint: { lng: -77.019913, lat: 38.892063 }, index: 0, formattedTime: "00:02:06", directionName: "North", maneuverNotes: [ ], linkIds: [ ], - signs: [ - { extraText: "", ext: "50", type: 2,

Note: Word wrap was added for the value in the narrative for display purposes.

Step 4: Add a for loop to iterate through the maneuvers JSON data. Complete the following steps to upgrade the application to display the value for the narrative key. You will do this by creating a for loop to iterate through the maneuvers list, displaying the narrative value for each maneuver from starting location to destination. a. Save your script as mapquest_parse-json_6.py. b. Add a for loop, highlighted below, after the second double line print statement. The for loop iterates through each maneuvers list and does the following: 1) Prints the narrative value. 2) Converts miles to kilometers with *1.61. 3) Formats the kilometer value to print only two decimal places with the "{:.2f}".format function. c.

Add a print statement that will display a double line before the application asks for another starting location, as shown below. Note: The double line print statement is not indented within the for loop. It therefore is part of the previous if statement that checks the statuscode parameter. print("Fuel Used (Ltr): " + str("{:.2f}".format((json_data["route"]["fuelUsed"])*3.78))) print("=============================================") for each in json_data["route"]["legs"][0]["maneuvers"]: print((each["narrative"]) + " (" + str("{:.2f}".format((each["distance"])*1.61) + " km)")) print("=============================================\n")

Step 5: Activity - Test the JSON iteration. Save and run your mapquest_parse-json_6.py script to verify it works. Troubleshoot your code, if necessary. You should get an output similar to the following: devasc@labvm:~/labs/devnet-src/mapquest$ python3 mapquest_parse-json_6.py Starting Location: Washington, D.C. Destination: Baltimore, Md

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 13 of 17

www.netacad.com

Lab - Integrate a REST API in a Python Application

URL: https://www.mapquestapi.com/directions/v2/route?key=fZadaFOY22VIEEemZcBFfxl5vjSXIPpZ&f rom=Washington%2C+D.C.&to=Baltimore%2C+Md API Status: 0 = A successful route call. ============================================= Directions from Washington, D.C. to Baltimore, Md Trip Duration: 00:49:29 Kilometers: 61.32 Fuel Used (Ltr): 6.24 ============================================= Start out going north on 6th St/US-50 E/US-1 N toward Pennsylvania Ave/US-1 Alt N. (1.28 km) Turn right onto New York Ave/US-50 E. Continue to follow US-50 E (Crossing into Maryland). (7.51 km) Take the Balt-Wash Parkway exit on the left toward Baltimore. (0.88 km) Merge onto MD-295 N. (50.38 km) Turn right onto W Pratt St. (0.86 km) Turn left onto S Calvert St/MD-2. (0.43 km) Welcome to BALTIMORE, MD. (0.00 km) =============================================

Starting Location: q devasc@labvm:~/labs/devnet-src/mapquest$

Step 6: Check for invalid user input. Now you are ready to add one final feature to your application to report an error when the user enters invalid data. Recall that you started an if loop to make sure the returned statuscode equals 0 before parsing the JSON data: json_status = json_data["info"]["statuscode"] if json_status == 0: print("API Status: " + str(json_status) + " = A successful route call.\n")

But what happens if the statuscode is not equal to 0? For example, the user might enter an invalid location or might not enter one or more locations. If so, then the application displays the URL and asks for a new starting location. The user has no idea what happened. a. To cause your application to fail without user notification, try the following values in your application. You should see similar results. devasc@labvm:~/labs/devnet-src/mapquest$ python3 mapquest_parse-json_6.py Starting Location: Washington, D.C. Destination: Beijing, China URL: https://www.mapquestapi.com/directions/v2/route?key=fZadaFOY22VIEEemZcBFfxl5vjSXIPpZ&f rom=Washington%2C+D.C.&to=Beijing%2C+China

Starting Location: Washington, D.C. Destination: Bal URL: https://www.mapquestapi.com/directions/v2/route?key=fZadaFOY22VIEEemZcBFfxl5vjSXIPpZ&f rom=Washington%2C+D.C.&to=Bal

Starting Location: q © 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 14 of 17

www.netacad.com

Lab - Integrate a REST API in a Python Application

devasc@labvm:~/labs/devnet-src/mapquest$ b. Copy one of the URLs to a Chromium browser tab. Notice that the only entry in route dictionary is a routeError dictionary with the errorCode 2. In the info dictionary, the statuscode is 402. Therefore, your if loop never executed the code for when the statuscode is 0. c.

Save your script as mapquest_parse-json_7.py.

d. To provide error information when statuscode is equal to 402, 611, or another value, add two elif statements and an else statement to your if loop. Your elif and else statements must align with the previous if statement. After the last double line print statement under the if json_status == 0, add the following elif and else statements: if json_status == 0:

for each in json_data["route"]["legs"][0]["maneuvers"]: print((each["narrative"]) + " (" + str("{:.2f}".format((each["distance"])*1.61) + " km)")) print("=============================================\n") elif json_status == 402: print("**********************************************") print("Status Code: " + str(json_status) + "; Invalid user inputs for one or both locations.") print("**********************************************\n") elif json_status == 611: print("**********************************************") print("Status Code: " + str(json_status) + "; Missing an entry for one or both locations.") print("**********************************************\n") else: print("************************************************************************") print("For Staus Code: " + str(json_status) + "; Refer to:") print("https://developer.mapquest.com/documentation/directions-api/status-codes") print("************************************************************************\n")

The first elif statement prints if the statuscode value is 402 for an invalid location. The second elif statement prints if the statuscode value is 611 because the user did not provide an entry for one or both locations. The else statement prints for all other statuscode values, such as when the MapQuest site returns an error. The else statement ends the if/else loop and returns the application to the while loop.

Part 6: Test Full Application Functionality Run your mapquest_parse-json_7.py script and verify it works. Troubleshoot your code, if necessary. Test all the features of the application. You should get output similar to the following. devasc@labvm:~/labs/devnet-src/mapquest$ python3 mapquest_parse-json_7.py Starting Location: Washington, D.C. Destination: Baltimore, Md URL: https://www.mapquestapi.com/directions/v2/route?key=fZadaFOY22VIEEemZcBFfxl5vjSXIPpZ&f rom=Washington%2C+D.C.&to=Baltimore%2C+Md API Status: 0 = A successful route call. ============================================= Directions from Washington, D.C. to Baltimore, Md Trip Duration: 00:49:29

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 15 of 17

www.netacad.com

Lab - Integrate a REST API in a Python Application

Kilometers: 61.32 Fuel Used (Ltr): 6.24 ============================================= Start out going north on 6th St/US-50 E/US-1 N toward Pennsylvania Ave/US-1 Alt N. (1.28 km) Turn right onto New York Ave/US-50 E. Continue to follow US-50 E (Crossing into Maryland). (7.51 km) Take the Balt-Wash Parkway exit on the left toward Baltimore. (0.88 km) Merge onto MD-295 N. (50.38 km) Turn right onto W Pratt St. (0.86 km) Turn left onto S Calvert St/MD-2. (0.43 km) Welcome to BALTIMORE, MD. (0.00 km) =============================================

Starting Location: Moscow, Russia Destination: Beijing, China URL: https://www.mapquestapi.com/directions/v2/route?key=fZadaFOY22VIEEemZcBFfxl5vjSXIPpZ&f rom=Moscow%2C+Russia&to=Beijing%2C+China API Status: 0 = A successful route call. ============================================= Directions from Moscow, Russia to Beijing, China Trip Duration: 84:31:10 Kilometers: 7826.83 Fuel Used (Ltr): 793.20 ============================================= Start out going west on Кремлёвская набережная/Kremlin Embankment. (0.37 km) Turn slight right onto ramp. (0.15 km) Turn slight right onto Боровицкая площадь. (0.23 km)

Turn slight left onto 前门东大街/Qianmen East Street. (0.31 km) Turn left onto 广场东侧路/E. Guangchang Rd. (0.82 km) 广场东侧路/E. Guangchang Rd becomes 东长安街/E. Chang'an Str. (0.19 km) Welcome to BEIJING. (0.00 km) =============================================

Starting Location: Washington, D.C. Destination: Beijing, China URL: https://www.mapquestapi.com/directions/v2/route?key=fZadaFOY22VIEEemZcBFfxl5vjSXIPpZ&f rom=Washington%2C+D.C.&to=Beijing%2C+China ********************************************** Status Code: 402; Invalid user inputs for one or both locations. **********************************************

Starting Location: Washington, D.C. Destination: Bal

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 16 of 17

www.netacad.com

Lab - Integrate a REST API in a Python Application

URL: https://www.mapquestapi.com/directions/v2/route?key=fZadaFOY22VIEEemZcBFfxl5vjSXIPpZ&f rom=Washington%2C+D.C.&to=Bal ********************************************** Status Code: 402; Invalid user inputs for one or both locations. **********************************************

Starting Location: Washington, D.C. Destination: URL: https://www.mapquestapi.com/directions/v2/route?key=ANUqwkHlgDv1vlsyBPtVrFeX8 uu6agjA&from=Washington%2C+D.C.&to= ********************************************** Status Code: 611; Missing an entry for one or both locations. ********************************************** Starting Location: quit devasc@labvm:~/labs/devnet-src/mapquest$ End of document

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 17 of 17

www.netacad.com

LAB 5.6.7 Lab - Network Troubleshooting Tools (Instructor Version) Instructor Note: Red font color or gray highlights indicate text that appears in the instructor copy only.

Objectives Part 1: Launch the DEVASC VM Part 2: Explore the ifconfig Troubleshooting Tool Part 3: Explore the ping Troubleshooting Tool Part 4: Explore the traceroute Troubleshooting Tool Part 5: Explore the nslookup Troubleshooting Tool

Background / Scenario In the effort to fix network connection issues, it is important for a developer to understand how to use basic network troubleshooting tools. These tools are used to determine what the connection problem might be.

Required Resources •

1 PC with operating system of your choice



Virtual Box or VMWare



DEVASC Virtual Machine

Instructions Part 1: Launch the DEVASC VM If you have not already completed the Lab - Install the Virtual Machine Lab Environment, do so now. If you have already completed that lab, launch the DEVASC VM.

Part 2: Explore the ifconfig Troubleshooting Tool The ifconfig tool is an application for use with UNIX-based operating systems such as Linux. A similar utility is available in Windows called ipconfig. These applications are used to manage network interfaces from the command line. You can use ifconfig to accomplish the following: •

Configure the IP address and subnet mask for an interface.



Retrieve the status of network interfaces.



Enable or disable network interfaces.



Change the MAC address of a network interface.

Step 1: View the ifconfig options. The ifconfig tool has many different options that can be added to the command to perform specific tasks. a. Open a terminal window either directly from the desktop, or within VS Code. b. Type ifconfig --help to see all of the available options for the command. devasc@labvm:~$ ifconfig --help Usage: © 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 1 of 8

www.netacad.com

Lab - Network Troubleshooting Tools

ifconfig [-a] [-v] [-s] [[] ] [add [/]] [del [/]] [[-]broadcast []] [[-]pointopoint []] [netmask ] [dstaddr ] [tunnel ] [outfill ] [keepalive ] [hw ] [mtu ] [[-]trailers] [[-]arp] [[-]allmulti] [multicast] [[-]promisc] [mem_start ] [io_addr ] [irq ] [media ] [txqueuelen ] [[-]dynamic] [up|down] ...

This is an overview of some of the more widely used options; •

add or del - This option allows you to add or delete IP addresses and their subnet mask (prefix length).



hw ether - This is used to change the physical MAC address. This might be useful to, for example, change it to an easily recognizable name so that it stands out in logs for troubleshooting.



up and down - These options are used to enable and disable interfaces. Be sure of which interface you are disabling. If it is the one you are using to remotely connect to a device, you will be disconnected!

Step 2: See the status of all interfaces. a. Display the status of all the network interfaces in use by issuing the ip addr command by itself. devasc@labvm:~$ ip addr 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: enp0s3: mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 08:00:27:e9:3d:e6 brd ff:ff:ff:ff:ff:ff inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic enp0s3 valid_lft 85901sec preferred_lft 85901sec inet6 fe80::a00:27ff:fee9:3de6/64 scope link valid_lft forever preferred_lft forever 3: dummy0: mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000 link/ether e2:2b:24:96:98:b8 brd ff:ff:ff:ff:ff:ff inet 192.0.2.1/32 scope global dummy0 valid_lft forever preferred_lft forever inet 192.0.2.2/32 scope global dummy0 valid_lft forever preferred_lft forever inet 192.0.2.3/32 scope global dummy0 valid_lft forever preferred_lft forever

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 2 of 8

www.netacad.com

Lab - Network Troubleshooting Tools

inet 192.0.2.4/32 scope global dummy0 valid_lft forever preferred_lft forever inet 192.0.2.5/32 scope global dummy0 valid_lft forever preferred_lft forever inet6 fe80::e02b:24ff:fe96:98b8/64 scope link valid_lft forever preferred_lft forever

devasc@labvm:~$ From this output, we can tell a lot about the VM interfaces: •

There are 3 interfaces, the loopback interface (lo), enp0s3, and dummy0.



ether shows the MAC address and that Ethernet is the link encapsulation.



inet is the IP address, the subnet mask is shown in slash notation, and brd is the broadcast address.



UP indicates that the interface is enabled.



mtu is the Maximum Transmission Unit specifying the maximum number of bytes that the frame can be transmitted on this medium before being fragmented.

Part 3: Explore the ping Troubleshooting Tool The ping tool is an application that is used to test network connectivity between devices. ping uses Internet Control Message Protocol (ICMP) to send packets to a device on the network and waits for the device to reply. ping reports network errors, packet loss, and the time to live (TTL), among other statistics.

Step 1: View the ping options. Ping is only available in a terminal window or a command prompt. a. Type ping -help to see all of the available options for the command. devasc@labvm:~$ ping -help Usage ping [options] Options:

-a -A -B -c -D -d -f -h -I -i -L -l -m -M -n -O

dns name or ip address use audible ping use adaptive ping sticky source address stop after replies print timestamps use SO_DEBUG socket option flood ping print help and exit either interface name or address seconds between sending each packet suppress loopback of multicast packets send number of packages while waiting replies tag the packets going out define mtu discovery, can be one of no dns name resolution report outstanding replies

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 3 of 8

www.netacad.com

Lab - Network Troubleshooting Tools

-p -q -Q -s -S -t -U -v -V -w -W







contents of padding byte quiet output use quality of service bits use as number of data bytes to be sent use as SO_SNDBUF socket option value define time to live print user-to-user latency verbose output print version and exit reply wait in seconds time to wait for response

IPv4 options: -4 -b -R -T

use IPv4 allow pinging broadcast record route define timestamp, can be one of

IPv6 options: -6 -F -N

use IPv6 define flow label, default is random use icmp6 node info query, try as argument

For more details see ping(8).

devasc@labvm:~$

Step 2: Ping a host. The ping tool has many different options that can be selected to customize how the communication should take place. Some of the options you can specify include: •

Specify how many ICMP echo requests you want to send.



Identify the source IP address if there are multiple interfaces on the device.



Indicate the amount of time to wait for a reply.



Packet size, if you want to send larger packet sizes than the default 64 bytes. This can help to determine what is the maximum transmission unit (MTU) is.

a. ping www.cisco.com to see if it is reachable. devasc@labvm:~$ ping -c 5 www.cisco.com PING e2867.dsca.akamaiedge.net (23.66.161.25) 56(84) bytes of data. 64 bytes from a23-66-161-25.deploy.static.akamaitechnologies.com (23.66.161.25): icmp_seq=1 ttl=49 time=58.4 ms 64 bytes from a23-66-161-25.deploy.static.akamaitechnologies.com (23.66.161.25): icmp_seq=2 ttl=49 time=63.1 ms 64 bytes from a23-66-161-25.deploy.static.akamaitechnologies.com (23.66.161.25): icmp_seq=3 ttl=49 time=61.2 ms 64 bytes from a23-66-161-25.deploy.static.akamaitechnologies.com (23.66.161.25): icmp_seq=4 ttl=49 time=57.7 ms 64 bytes from a23-66-161-25.deploy.static.akamaitechnologies.com (23.66.161.25): icmp_seq=5 ttl=49 time=57.6 ms

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 4 of 8

www.netacad.com

Lab - Network Troubleshooting Tools

--- e2867.dsca.akamaiedge.net ping statistics --5 packets transmitted, 5 received, 0% packet loss, time 8153ms rtt min/avg/max/mdev = 57.597/59.605/63.145/2.205 ms

devasc@labvm:~$ This ping specified a count of 5 packets. The ping tool automatically does DNS resolution, returning 23.66.161.25 (your returned IP address may be different). Time to Live (TTL) for the received echo replies and round-trip times are also displayed. The final statistics confirm that 5 ICMP echo-request packets have been transmitted and 5 ICMP echo-reply packets have been received, achieving a 0% packet loss. Statistics about the minimum, average, maximum and standard deviation of the time it took for the packets to get to the destination and back are also displayed. If you do not receive any replies from the destination doesn't necessarily mean that the host is offline or not reachable. It could mean that ICMP packets are being blocked by a firewall. It is a best practice to expose only the services needed to be available on the hosts in the network. For IPv6 there exists a similar utility that is called ping6 and is also available on most operating systems.

Part 4: Explore the traceroute Troubleshooting Tool The traceroute tool displays the route that the packets take on their way to a destination. The Microsoft Windows alternative is called tracert. Observing the path network traffic takes from source to the destination is important for troubleshooting because routing loops and non-optimal paths can be detected and corrected. traceroute uses ICMP packets to determine the path to the destination. The Time to Live (TTL) field in the IP packet header is used to avoid infinite loops on the network. For each hop or router that an IP packet goes through, the TTL field is decremented by one. When the TTL field value reaches 0, the packet is discarded avoiding infinite loops. Usually, the TTL field is set to its maximum value, 255, at the source of the traffic, because the host is trying to maximize the chances of that packet getting to its destination. traceroute reverses this logic, and gradually increments the TTL value, from 1 and keeps adding 1 to the TTL field on the next packet and so on. Setting a TTL value of 1 for the first packet, means the packet will be discarded on the first router. By default, most routers, send back to the source of the traffic an ICMP Time Exceeded packet informing it that the packet has reached a TTL value of 0 and had to be discarded. traceroute uses the information received from the router to figure out its IP address and hostname and also round-trip times. For IPv6 there is an alternative called traceroute6 for UNIX-based operating systems and tracert6 for Microsoft Windows-based ones.

Step 1: View the traceroute options. a. Type traceroute --help to see all of the available options for the command. devasc@labvm:~$ traceroute --help Usage: traceroute [OPTION...] HOST Print the route packets trace to network host. -f, -g, -I, -m, -M,

--first-hop=NUM --gateways=GATES --icmp --max-hop=NUM --type=METHOD

-p, --port=PORT -q, --tries=NUM --resolve-hostnames -t, --tos=NUM

set initial hop distance, i.e., time-to-live list of gateways for loose source routing use ICMP ECHO as probe set maximal hop count (default: 64) use METHOD (`icmp' or `udp') for traceroute operations, defaulting to `udp' use destination PORT port (default: 33434) send NUM probe packets per hop (default: 3) resolve hostnames set type of service (TOS) to NUM

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 5 of 8

www.netacad.com

Lab - Network Troubleshooting Tools

-w, --wait=NUM -?, --help --usage -V, --version

wait NUM seconds for response (default: 3) give this help list give a short usage message print program version

Mandatory or optional arguments to long options are also mandatory or optional for any corresponding short options. Report bugs to .

devasc@labvm:~$ Several options are available with traceroute including: •

Specify the TTL value of the first packet sent, 1 by default.



Specify the maximum TTL value. By default, it will increase the TTL value up to 64 or until the destination is reached.



Specify the source address in case there are multiple interfaces on the device.



Specify Quality of Service (QoS) value in the IP header.



Specify the packet length.

Step 2: Use traceroute to find the path to a web server. Because of the way Virtual Box implements a NAT network, you cannot trace outside of your VM. You would need to change your VM to Bridged. But then, you would not be able to communicate with the CSR1000v in other labs. Therefore, we recommend leaving your VM in NAT mode. However, you should be able to use the traceroute command on your local host. For Mac and Linux hosts, use the traceroute command. For Windows hosts, use the tracert command, as shown below. Open a command prompt on your local host and trace the route to www.netacad.com to see how many hops and how much time it takes to reach it. Your output will be different. C:\> tracert www.netacad.com Tracing route to e7792.dsca.akamaiedge.net [2600:1406:22:183::1e70] over a maximum of 30 hops: 1 43 ms 38 ms 36 ms hsrp-2001-420-c0c8-1.cisco.com [2001:420:c0c8::1] 2 48 ms 54 ms 40 ms sjc05-sbb-gw1-twe1-0-13.cisco.com [2001:420:280:1aa::] 3 39 ms 37 ms 38 ms sjc05-rbb-gw1-por20.cisco.com [2001:420:41:116::] 4 37 ms 38 ms 38 ms sjc12-corp-gw1-ten1-3-0.cisco.com [2001:420:41:11c::1] 5 39 ms 39 ms 45 ms sjc12-dmzbb-gw1-vla777.cisco.com [2001:420:82:2::d] 6 51 ms 39 ms 37 ms sjc5-cbb-gw1-be92.cisco.com [2001:420:82:4e::] 7 39 ms 39 ms 38 ms sjc12-isp-gw2-ten0-0-0.cisco.com [2001:420:82:f::] 8 78 ms 57 ms 65 ms 2001:1890:c00:6c01::eee7:a12 9 44 ms 42 ms 47 ms sj2ca81crs.ipv6.att.net [2001:1890:ff:ffff:12:122:110:62] 10 46 ms 46 ms 47 ms 2001:1890:ff:ffff:12:122:149:225 11 43 ms 41 ms 43 ms scaca401cts.ipv6.att.net [2001:1890:ff:ffff:12:122:137:245] 12 43 ms 43 ms 44 ms 2001:1890:fff:2180:12:120:13:178 13 53 ms 54 ms 45 ms 2001:1890:1ff:2a80:12:120:183:64

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 6 of 8

www.netacad.com

Lab - Network Troubleshooting Tools

14 52 ms 42 ms 42 ms g2600-1406-0022-0183-0000-0000-00001e70.deploy.static.akamaitechnologies.com [2600:1406:22:183::1e70] Trace complete.

devasc@labvm:~$ The output shows that there are 14 hops along the path. Round trip times are also displayed.

Part 5: Explore the nslookup Troubleshooting Tool The nslookup tool used for querying Domain Name System (DNS) to obtain domain name to IP address mapping. This tool is useful to determine if the DNS server configured on a specific host is resolving hostnames to IP addresses.

Step 1: Query a domain. To use nslookup, you need to type the hostname you are trying to resolve to an IP address. This will use the configured DNS server to find the IP address. You can also specify a DNS server to use. Usage: nslookup [HOST] [SERVER] a. Type nslookup www.cisco.com to determine the IP address of the domain. devasc@labvm:~$ nslookup www.cisco.com Server: Address:

127.0.0.53 127.0.0.53#53

Non-authoritative answer: www.cisco.com canonical name = origin-www.cisco.com. Name: origin-www.cisco.com Address: 173.37.145.84 Name: origin-www.cisco.com Address: 2001:420:1101:1::a

devasc@labvm:~$ The command returns the non-authoritative answer, and both the IPv4 and IPv6 name and address. The non-authoritative answer means that the server does not contain the original records of the domain's zone, rather, it is created from previous DNS lookups. Note: Your output will most likely be different. However, you should see an IPv4 and IPv6 address.

Step 2: Query an IP address. You can also look up IP addresses to discover the domain associated with it. a. Query the DNS server for the IP address 8.8.8.8. devasc@labvm:~$ nslookup 8.8.8.8 8.8.8.8.in-addr.arpa

name = dns.google.

Authoritative answers can be found from:

devasc@labvm:~$

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 7 of 8

www.netacad.com

Lab - Network Troubleshooting Tools

Step 3: Query a domain using a specific DNS server. a. Type nslookup www.cisco.com 8.8.8.8 to determine the IP address of the domain according to Google's DNS. devasc@labvm:~$ nslookup www.cisco.com 8.8.8.8 Server: Address:

8.8.8.8 8.8.8.8#53

Non-authoritative answer: www.cisco.com canonical name = www.cisco.com.akadns.net. www.cisco.com.akadns.net canonical name = wwwds.cisco.com.edgekey.net. wwwds.cisco.com.edgekey.net canonical name = wwwds.cisco.com.edgekey.net.globalredir.akadns.net. wwwds.cisco.com.edgekey.net.globalredir.akadns.net canonical name = e2867.dsca.akamaiedge.net. Name: e2867.dsca.akamaiedge.net Address: 23.205.37.210 Name: e2867.dsca.akamaiedge.net Address: 2600:1406:22:182::b33 Name: e2867.dsca.akamaiedge.net Address: 2600:1406:22:19c::b33

devasc@labvm:~$ Notice that by using this method, the server resolved the address to three different IP addresses, all different from the previous DNS query. These servers have a different cache of DNS queries to www.cisco.com. End of document

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 8 of 8

www.netacad.com

LAB 6.2.7 Lab - Build a Sample Web App in a Docker Container (Instructor Version) Instructor Note: Red font color or gray highlights indicate text that appears in the instructor copy only.

Objectives Part 1: Launch the DEVASC VM Part 2: Create a Simple Bash Script Part 3: Create a Sample Web App Part 4: Configure the Web App to Use Website Files Part 5: Create a Bash Script to Build and Run a Docker Container Part 6: Build, Run, and Verify the Docker Container

Background / Scenario In this lab, you will review basic bash scripting techniques because bash scripting is a prerequisite for the rest of the lab. You will then build and modify a Python script for a simple web application. Next, you will create a bash script to automate the process for creating a Dockerfile, building the Docker container, and running the Docker container. Finally, you will use docker commands to investigate the intricacies of the Docker container instance.

Required Resources •

1 PC with operating system of your choice



Virtual Box or VMWare



DEVASC Virtual Machine

Instructions Part 1: Launch the DEVASC VM If you have not already completed the Lab - Install the Virtual Machine Lab Environment, do so now. If you have already completed that lab, launch the DEVASC VM now.

Part 2: Create a Simple Bash Script Bash knowledge is crucial for working with continuous integration, continuous deployment, containers, and with your development environment. Bash scripts help programmers automate a variety of tasks in one script file. In this part, you will briefly review how to create a bash script. Later in the lab, you will use a bash script to automate the creation of a web app inside of a Docker container.

Step 1: Create an empty bash script file. Change your working directory to ~/labs/devnet-src/sample-app and add a new file called user-input.sh. devasc@labvm:~$ cd labs/devnet-src/sample-app/ devasc@labvm:~/labs/devnet-src/sample-app$ touch user-input.sh

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 1 of 12

www.netacad.com

Lab - Build a Sample Web App in a Docker Container

Step 2: Open the file in the nano text editor. Use the nano command to open the nano text editor. devasc@labvm:~/labs/devnet-src/sample-app$ nano user-input.sh

Step 3: Add the ‘she-bang’ to the top of the script. From here you can enter commands for your bash script. Use the arrow keys to navigate in nano. Notice the commands at the bottom (not shown here) for managing the file. The carat symbol (^) indicates that you use the CTRL or Command key on your keyboard. For example, to exit nano, type CTRL+X. Add the ‘she-bang’ which tells the system that this file includes commands that need to be run in the bash shell. #!/bin/bash Note: You can use a graphical text editor or open the file with VS Code. However, you should be familiar with command-line text editors like nano and vim. Search the internet for tutorials to refresh your skill or learn more about them.

Step 4: Add simple bash commands to the script. Enter some simple bash commands for your script. The following commands will ask the user for a name, set the name to a variable called userName, and display a string of text with the user’s name. echo -n "Enter Your Name: " read userName echo "Your name is $userName."

Step 5: Exit nano and save your script. Press CTRL+X, then Y, then ENTER to exit nano and save your script.

Step 6: Run your script from the command line. You can run it directly from the command line using the source command. devasc@labvm:~/labs/devnet-src/sample-app$ source user-input.sh Enter Your Name: Bob Your name is Bob.

devasc@labvm:~/labs/devnet-src/sample-app$

Step 7: Change the mode of the script to an executable file for all users. Change the mode of the script to an executable using the chmod command. Set the options to a+x to make the script executable (x) by all users (a). After using chmod, notice permissions have been modified for users, groups, and others to include the "x" (executable). devasc@labvm:~/labs/devnet-src/sample-app$ ls -l user-input.sh -rw-rw-r-- 1 devasc devasc 84 Jun

7 16:43 user-input.sh

devasc@labvm:~/labs/devnet-src/sample-app$ chmod a+x user-input.sh devasc@labvm:~/labs/devnet-src/sample-app$ ls -l user-input.sh -rwxrwxr-x 1 devasc devasc 84 Jun

7 16:43 user-input.sh

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 2 of 12

www.netacad.com

Lab - Build a Sample Web App in a Docker Container

Step 8: Rename the file to remove the .sh extension. You can rename the file to remove the extension so that users do not have to add .sh to the command to execute the script. devasc@labvm:~/labs/devnet-src/sample-app$ mv user-input.sh user-input

Step 9: Execute the script from the command line. Now the script can be run from the command line without the source command or an extension. To run a bash script without the source command, you must preface the script with "./". devasc@labvm:~/labs/devnet-src/sample-app$ ./user-input Enter Your Name: Bob Your name is Bob.

devasc@labvm:~/labs/devnet-src/sample-app$

Step 10: Investigate other bash scripts. If you have little or no experience creating bash scripts, take some time to search the internet for bash tutorials, bash examples, and bash games.

Part 3: Create a Sample Web App Before we can launch an application in a Docker container, we first need to have the app. In this part, you will create a very simple Python script that will display the IP address of the client when the client visits the web page.

Step 1: Install Flask and open a port on the DEVASC VM firewall. Web application developers using Python typically leverage a framework. A framework is a code library to make it easier for developers to create reliable, scalable and maintainable web applications. Flask is a web application framework written in Python. Other frameworks include Tornado and Pyramid. You will use this framework to create the sample web app. Flask receives requests and then provides a response to the user in the web app. This is useful for dynamic web applications because it allows user interaction and dynamic content. What makes your sample web app dynamic is that it will be displaying the IP address of the client. Note: Understanding Flask functions, methods, and libraries are beyond the scope of this course. It is used in this lab to show how quickly you can get a web application up and running. If you want to learn more, search the internet for more information and tutorials on the Flask framework. Open a terminal window and import flask. devasc@labvm:~/labs/devnet-src/sample-app$ pip3 install flask

Step 2: Open the sample_app.py file. Open the sample_app.py file located in the /sample-app directory. You can do this inside VS Code or you can use a command-line text editor like nano or vim.

Step 3: Add the commands to import methods from flask. Add the following commands to import the required methods from the flask library. from flask import Flask from flask import request

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 3 of 12

www.netacad.com

Lab - Build a Sample Web App in a Docker Container

Step 4: Create an instance of the Flask class. Create an instance of the Flask class and name it sample. Be sure to use two underscores before and after the "name". sample = Flask(__name__)

Step 5: Define a method to display the client IP address. Next, configure Flask so that when a user visits the default page (root directory), it displays a message with the IP address of the client. @sample.route("/") def main(): return "You are calling me from " + request.remote_addr + "\n" Notice the @sample.route("/") Flask statement. Frameworks such as Flask use a routing technique (.route) to refer to an application URL (this not to be confused with network routing). Here the "/" (root directory) is bound to the main() function. So, when the user goes to http:://localhost:8080/ (root directory) URL, the output of the return statement will be displayed in the browser.

Step 6: Configure the app to run locally. Finally, configure Flask to run the app locally at http://0.0.0.0:8080, which is also http://localhost:8080. Be sure to use two underscores before and after "name", and before and after "main". if __name__ == "__main__": sample.run(host="0.0.0.0", port=8080)

Step 7: Save and run your sample web app. Save your script and run it from the command line. You should see the following output which indicates that your “sample-app” server is running. If you do not see the following output or if you receive an error message, check your sample_app.py script carefully. devasc@labvm:~/labs/devnet-src/sample-app$ python3 sample_app.py * Serving Flask app "sample-app" (lazy loading) * Environment: production WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Debug mode: off * Running on http://0.0.0.0:8080/ (Press CTRL+C to quit)

Step 8: Verify you the server is running. You can verify the server is running in one of two ways. a. Open the Chromium web browser and enter 0.0.0.0:8080 in the URL field. You should get the following output: You are calling me from 127.0.0.1 If you receive an "HTTP 400 Bad Request" response, check your sample_app.py script carefully. b. Open another terminal window and use the command-line URL tool (cURL) to verify the server’s response. devasc@labvm:~/labs/devnet-src/sample-app$ curl http://0.0.0.0:8080 You are calling me from 127.0.0.1

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 4 of 12

www.netacad.com

Lab - Build a Sample Web App in a Docker Container

devasc@labvm:~/labs/devnet-src/sample-app$

Step 9: Stop the server. Return to the terminal window where the server is running and press CTRL+C to stop the server.

Part 4: Configure the Web App to use Website Files In this part, build out the sample web app to include an index.html page and style.css specification. The index.html is typically the first page loaded in a client’s web browser when visiting your website. The style.css is a style sheet used to customize the look of the web page.

Step 1: Explore the directories that will be used by the web app. The directories templates and static are already in the sample-app directory. Open the index.html and style.css to view their contents. If you are familiar with HTML and CSS, feel free to customize these directories and files as much as you like. However, be sure you keep the embedded {{request.remote_addr}} Python code in the index.html file as this is the dynamic aspect of the sample web app. devasc@labvm:~/labs/devnet-src/sample-app$ cat templates/index.html

Sample app

You are calling me from {{request.remote_addr}}

devasc@labvm:~/labs/devnet-src/sample-app$ cat static/style.css body {background: lightsteelblue;}

devasc@labvm:~/labs/devnet-src/sample-app$

Step 2: Update the Python code for the sample web app. Now that you have explored the basic website files, you need to update the sample_app.py file so that it renders the index.html file instead of just returning data. Generating HTML content using Python code can be cumbersome, especially when using conditional statements or repeating structures. The HTML file can be rendered in Flask automatically using the render_template function. This requires importing the render_template method from the flask library and editing to the return function. Make the highlighted edits to your script. from flask import Flask from flask import request from flask import render_template sample = Flask(__name__) @sample.route("/") def main(): return render_template("index.html") if __name__ == "__main__": © 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 5 of 12

www.netacad.com

Lab - Build a Sample Web App in a Docker Container

sample.run(host="0.0.0.0", port=8080)

Step 3: Save and run your script. Save and run your sampe-app.py script. You should get output like the following: devasc@labvm:~/labs/devnet-src/sample-app$ python3 sample_app.py * Serving Flask app "sample-app" (lazy loading) * Environment: production WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Debug mode: off * Running on http://0.0.0.0:8080/ (Press CTRL+C to quit)

Note: If you got Traceback output and an error with the message with something like OSError: [Errno 98] Address already in use, then you did not shutdown your previous server. Return to the terminal window where that server is running and press CTRL+C to end the server process. Re-run your script.

Step 4: Verify your program is running. Again, you can verify your program is running in one of two ways. a. Open the Chromium web browser and enter 0.0.0.0:8080 in the URL field. You should get the same output as before. However, your background will be light steel blue and the text will be formatted as H1. You are calling me from 127.0.0.1 b. Open another terminal window and use the curl command to verify the server’s response. This is where you will see the result of the HTML code rendered automatically using the render_template function. In this case, you will get all the HTML content. However, the dynamic Python code will be replaced with the value for {{request.remote_addr}}. Also, notice your prompt will be on the same line as the last line of HMTL output. Press ENTER to get a new line. devasc@labvm:~/labs/devnet-src/sample-app$ curl http://0.0.0.0:8080

Sample app

You are calling me from 127.0.0.1

devasc@labvm:~/labs/devnet-src/sample-app$

devasc@labvm:~/labs/devnet-src/sample-app$

Step 5: Stop the server. Return to the terminal window where the server is running and press CTRL+C to stop the server.

Part 5: Create a Bash Script to Build and Run a Docker Container An application can be deployed on a bare metal server (physical server dedicated to a single-tenant environment) or in a virtual machine, like you just did in the previous Part. It can also be deployed in a containerized solution like Docker. In this part, you will create a bash script and add commands to it that complete the following tasks to build and run a Docker container: •

Create temporary directories to store the website files.



Copy the website directories and sample_app.py to the temporary directory.

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 6 of 12

www.netacad.com

Lab - Build a Sample Web App in a Docker Container



Build a Dockerfile.



Build the Docker container.



Start the container and verify it is running.

Step 1: Create temporary directories to store the website files. Open the sample-app.sh bash script file in the ~/labs/devnet-src/sample-app directory. Add the ‘she-bang’ and the commands to create a directory structure with tempdir as the parent folder. #!/bin/bash mkdir tempdir mkdir tempdir/templates mkdir tempdir/static

Step 2: Copy the website directories and sample_app.py to the temporary directory. in the sample-app.sh file, add the commands to copy the website directory and script to tempdir. cp sample_app.py tempdir/. cp -r templates/* tempdir/templates/. cp -r static/* tempdir/static/.

Step 3: Create a Dockerfile. In this step, you enter the necessary bash echo commands to the sample-app.sh file to create a Dockerfile in the tempdir. This Dockerfile will be used to build the container. a. You need Python running in the container, so add the Docker FROM command to install Python in the container. echo "FROM python" >> tempdir/Dockerfile b. Your sample_app.py script needs Flask, so add the Docker RUN command to install Flask in the container. echo "RUN pip install flask" >> tempdir/Dockerfile c.

Your container will need the website folders and the sample_app.py script to run the app, so add the Docker COPY commands to add them to a directory in the Docker container. In this example, you will create /home/myapp as the parent directory inside the Docker container. Besides copying the sample_app.py file to the Dockerfile, you will also be copying the index.html file from the templates directory and the style.css file from the static directory. echo "COPY echo "COPY echo "COPY

./static /home/myapp/static/" >> tempdir/Dockerfile ./templates /home/myapp/templates/" >> tempdir/Dockerfile sample_app.py /home/myapp/" >> tempdir/Dockerfile

d. Use the Docker EXPOSE command to expose port 8080 for use by the webserver. echo "EXPOSE 8080" >> tempdir/Dockerfile e. Finally, add the Docker CMD command to execute the Python script. echo "CMD python /home/myapp/sample_app.py" >> tempdir/Dockerfile

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 7 of 12

www.netacad.com

Lab - Build a Sample Web App in a Docker Container

Step 4: Build the Docker container. Add the commands to the sample-app.sh file tol switch to the tempdir directory and build the Docker container. The docker build command -t option allows you to specify the name of the container and the trailing period (.) indicates that you want the container built in the current directory. cd tempdir docker build -t sampleapp .

Step 5: Start the container and verify it is running. a. Add the docker run command to the sample-app.sh file to start the container. docker run -t -d -p 8080:8080 --name samplerunning sampleapp The docker run options indicate the following: o

-t specifies that you want a terminal created for the container so the you can access it at the command line.

o

-d indicates that you want the container to run in the background and print the container ID when executing the docker ps -a command.

o

-p specifies that you want to publish the container’s ports to the host. Then provide a range of ports. In this case, 8080 to 8080 (8080:8080)

o

--name specifies first what you want to call the instance of the container (samplerunning) and then the container image that the instance will be based on (sampleapp). The instance name can be anything you want. However, the image name needs to match the container name you specified in the docker build command (sampleapp).

b. Add the docker ps -a command to display all currently running Docker containers. This command will be the last one executed by the bash script. docker ps -a

Step 6: Save your bash script.

Part 6: Build, Run, and Verify the Docker Container In this part, you will execute bash script which will make the directories, copy over the files, create a Dockerfile, build the Docker container, run an instance of the Docker container, and display output from the docker ps -a command showing details of the container currently running. Then you will investigate the Docker container, stop the container from running, and remove the container. Note: Be sure you stopped any other web server processes you may still have running from the previous parts of this lab.

Step 1: Execute the bash script. Execute the bash script from the command line. You should see output similar to the following. After creating the tempdir directories, the script executes the commands to build the Docker container. Notice that Step 7/7 in the output executes the sample_app.py that creates the web server. Also, notice the container ID. You will see this in the Docker command prompt later in the lab. devasc@labvm:~/labs/devnet-src/sample-app$ bash ./sample-app.sh Sending build context to Docker daemon Step 1/7 : FROM python latest: Pulling from library/python 90fe46dd8199: Pulling fs layer 35a4f1977689: Pulling fs layer

6.144kB

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 8 of 12

www.netacad.com

Lab - Build a Sample Web App in a Docker Container

bbc37f14aded: Pull complete 74e27dc593d4: Pull complete 4352dcff7819: Pull complete deb569b08de6: Pull complete 98fd06fa8c53: Pull complete 7b9cc4fdefe6: Pull complete 512732f32795: Pull complete Digest: sha256:ad7fb5bb4770e08bf10a895ef64a300b288696a1557a6d02c8b6fba98984b86a Status: Downloaded newer image for python:latest ---> 4f7cd4269fa9 Step 2/7 : RUN pip install flask ---> Running in 32d28026afea Collecting flask Downloading Flask-1.1.2-py2.py3-none-any.whl (94 kB) Collecting click>=5.1 Downloading click-7.1.2-py2.py3-none-any.whl (82 kB) Collecting Jinja2>=2.10.1 Downloading Jinja2-2.11.2-py2.py3-none-any.whl (125 kB) Collecting Werkzeug>=0.15 Downloading Werkzeug-1.0.1-py2.py3-none-any.whl (298 kB) Collecting itsdangerous>=0.24 Downloading itsdangerous-1.1.0-py2.py3-none-any.whl (16 kB) Collecting MarkupSafe>=0.23 Downloading MarkupSafe-1.1.1-cp38-cp38-manylinux1_x86_64.whl (32 kB) Installing collected packages: click, MarkupSafe, Jinja2, Werkzeug, itsdangerous, flask Successfully installed Jinja2-2.11.2 MarkupSafe-1.1.1 Werkzeug-1.0.1 click-7.1.2 flask-1.1.2 itsdangerous-1.1.0 Removing intermediate container 32d28026afea ---> 619aee23fd2a Step 3/7 : COPY ./static /home/myapp/static/ ---> 15fac1237eec Step 4/7 : COPY ./templates /home/myapp/templates/ ---> dc807b5cf615 Step 5/7 : COPY sample_app.py /home/myapp/ ---> d4035a63ae14 Step 6/7 : EXPOSE 8080 ---> Running in 40c2d35aa29a Removing intermediate container 40c2d35aa29a ---> eb789099a678 Step 7/7 : CMD python /home/myapp/sample_app.py ---> Running in 41982e2c6209 Removing intermediate container 41982e2c6209 ---> a2588e9b0593 Successfully built a2588e9b0593 Successfully tagged sampleapp:latest 8953a95374ff8ebc203059897774465312acc8f0ed6abd98c4c2b04448a56ba5 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 9 of 12

www.netacad.com

Lab - Build a Sample Web App in a Docker Container

8953a95374ff sampleapp "/bin/sh -c 'python …" Up Less than a second 0.0.0.0:8080->8080/tcp samplerunning

1 second ago

devasc@labvm:~/labs/devnet-src/sample-app$

Step 2: Investigate the running Docker container and the web app. a. The creation of the tempdir directories is not shown in the output for the script. You could add echo commands to print out messages when they are successfully created. You can also verify they are there with the ls command. Remember, this directory has the files and folders used to build the container and launch the web app. It is not the container that was built. devasc@labvm:~/labs/devnet-src/sample-app$ ls tempdir/ Dockerfile

sample_app.py

static

templates

devasc@labvm:~/labs/devnet-src/sample-app$ b. Notice the Dockerfile created by your bash script. Open this file to see how it looks in its final form without the echo commands. devasc@labvm:~/labs/devnet-src/sample-app$ cat tempdir/Dockerfile FROM python RUN pip install flask COPY ./static /home/myapp/static/ COPY ./templates /home/myapp/templates/ COPY sample_app.py /home/myapp/ EXPOSE 8080 CMD python /home/myapp/sample_app.py c.

The output for the docker ps -a command may be hard to read depending on the width of your terminal display. You can redirect it to a text file where you can view it better without word wrapping. devasc@labvm:~/labs/devnet-src/sample-app$ docker ps -a >> running.txt devasc@labvm:~/labs/devnet-src/sample-app$

d. The Docker container creates its own IP address from a private network address space. Verify the web app is running and reporting the IP address. In a web browser at http://localhost:8080, you should see the message You are calling me from 172.17.0.1 formatted as H1 on a light steel blue background. You can also use the curl command, if you like. devasc@labvm:~/labs/devnet-src/sample-app$ curl http://172.17.0.1:8080

Sample app

You are calling me from 172.17.0.1

devasc@labvm:~/labs/devnet-src/sample-app$

devasc@labvm:~/labs/devnet-src/sample-app$ e. By default, Docker uses the IPv4 172.17.0.0/16 subnet for container networking. (This address can be changed if necessary.) Enter the command ip address to display all the IP addresses used by your instance of the DEVASC VM. You should see the loopback address 127.0.0.1 that the web app used earlier in the lab and the new Docker interface with the IP address 172.17.0.1. devasc@labvm:~/labs/devnet-src/sample-app$ ip address

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 10 of 12

www.netacad.com

Lab - Build a Sample Web App in a Docker Container

1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever

4: docker0: mtu 1500 qdisc noqueue state UP group default link/ether 02:42:c2:d1:8a:2d brd ff:ff:ff:ff:ff:ff inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0 valid_lft forever preferred_lft forever inet6 fe80::42:c2ff:fed1:8a2d/64 scope link valid_lft forever preferred_lft forever

Step 3: Access and explore the running container. Remember that a Docker container is a way of encapsulating everything you need to run your application so that it can easily be deployed in a variety of environments--not just in your DEVASC VM. a. To access the running container, enter the docker exec -it command specifying the name of the running container (samplerunning) and that you want a bash shell (/bin/bash). The -i option specifies that you want it to be interactive and the -t option specifies that you want terminal access. The prompt changes to root@containerID. Your container ID will be different than the one shown below. Notice the container ID matches the ID shown in the output from docker ps -a. devasc@labvm:~/labs/devnet-src/sample-app$ docker exec -it samplerunning /bin/bash root@8953a95374ff:/# b. You are now in root access for the samplerunning Docker container. From here, you can use Linux commands to explore the Docker container. Enter ls to see the directory structure at the root level. root@8953a95374ff:/# ls bin boot

dev etc

home lib

lib64 media

mnt opt

proc root

run sbin

srv sys

tmp usr

var

root@8953a95374ff:/# c.

Recall that in your bash script, you added commands in the Dockerfile that copied your app directories and files to the home/myapp directory. Enter the ls command again for that folder to see your sample_app.py script and directories. To get a better understanding of what is included in your Docker container, you may wish to use the ls command to examine other directories such as /etc and /bin. root@8953a95374ff:/# ls home/myapp/ sample_app.py static templates root@8953a95374ff:/#

d. Exit the Docker container to return to the DEVASC VM command line. root@8953a95374ff:/# exit exit

devasc@labvm:~/labs/devnet-src/sample-app$

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 11 of 12

www.netacad.com

Lab - Build a Sample Web App in a Docker Container

Step 4: Stop and remove the Docker container. a. You can stop the Docker container with the docker stop command specifying the name of the running container. It will take a few seconds to clean up and cache the container. You can see that it still exists by entering the docker ps -a command. However, if you refresh the web page for http://localhost:8080, you will see the web app is no longer running. devasc@labvm:~/labs/devnet-src/sample-app$ docker stop samplerunning samplerunning

devasc@labvm:~/labs/devnet-src/sample-app$ docker ps -a CONTAINER ID IMAGE STATUS PORTS df034cb53e72 sampleapp Exited (137) 20 seconds ago

COMMAND

CREATED

NAMES "/bin/sh -c 'python …" samplerunning

49 minutes ago

devasc@labvm:~/labs/devnet-src/sample-app$ b. You can restart a stopped container with the docker start command. The container will immediately spin up. devasc@labvm:~/labs/devnet-src/sample-app$ docker start samplerunning samplerunning

devasc@labvm:~/labs/devnet-src/sample-app$ c.

To permanently remove the container, first stop it and then remove it with the docker rm command. You can always rebuild it again executing the sample-app program. Use the docker ps -a command to verify the container has been removed. devasc@labvm:~/labs/devnet-src/sample-app$ docker stop samplerunning samplerunning devasc@labvm:~/labs/devnet-src/sample-app$ docker rm samplerunning samplerunning devasc@labvm:~/labs/devnet-src/sample-app$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES devasc@labvm:~/labs/devnet-src/sample-app$

End of Document

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 12 of 12

www.netacad.com

LAB 6.3.6 Lab - Build a CI/CD Pipeline Using Jenkins (Instructor Version) Instructor Note: Red font color or gray highlights indicate text that appears in the instructor copy only.

Objectives Part 1: Launch the DEVASC VM Part 2: Commit the Sample App to Git Part 3: Modify the Sample App and Push Changes to Git Part 4: Download and Run the Jenkins Docker Image Part 5: Configure Jenkins Part 6: Use Jenkins to Run a Build of Your App Part 7: Use Jenkins to Test a Build Part 8: Create a Pipeline in Jenkins

Background / Scenario In this lab, you will commit the Sample App code to a GitHub repository, modify the code locally, and then commit your changes. You will then install a Docker container that includes the latest version of Jenkins. You will configure Jenkins and then use Jenkins to download and run your Sample App program. Next, you will create a testing job inside Jenkins that will verify your Sample App program successfully runs each time you build it. Finally, you will integrate your Sample App and testing job into a Continuous Integration/Continuous Development pipeline that will verify your Sample App is ready to be deployed each time you change the code.

Required Resources •

1 PC with operating system of your choice



Virtual Box or VMWare



DEVASC Virtual Machine

Instructions Part 1: Launch the DEVASC VM If you have not already completed the Lab - Install the Virtual Machine Lab Environment, do so now. If you have already completed that lab, launch the DEVASC VM now.

Part 2: Commit the Sample App to Git In this part, you will create a GitHub repository to commit the sample-app files you created in a previous lab. You created a GitHub account in a previous lab. If you have not done so yet, visit github.com now and create an account.

Step 1: Login to GitHub and create a new repository. a. Login at https://github.com/ with your credentials. b. Select the "New repository" button or click on the "+" icon in the upper right corner and select "New repository". © 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 1 of 15

www.netacad.com

Lab - Build a CI/CD Pipeline Using Jenkins

c.

Create a repository using the following information: Repository name: sample-app Description: Explore CI/CD with GitHub and Jenkins Public/Private: Private

d. Select: Create repository

Step 2: Configure your Git credentials locally in the VM. Open a terminal window with VS Code in the DEVASC VM. Use your name in place of "Sample User" for the name in quotes " ". Use @example.com for your email address. devasc@labvm:~$ git config --global user.name "Sample User" devasc@labvm:~$ git config --global user.email [email protected]

Step 3: Initialize a directory as the Git repository. You will use the sample-app files you created in a previous lab. However, those files are also stored for your convenience in the /labs/devnet-src/jenkins/sample-app directory. Navigate to the jenkins/sample-app directory and initialize it as a Git repository. devasc@labvm:~$ cd labs/devnet-src/jenkins/sample-app/ devasc@labvm:~/labs/devnet-src/jenkins/sample-app$ git init Initialized empty Git repository in /home/devasc/labs/devnet-src/jenkins/sampleapp/.git/

devasc@labvm:~/labs/devnet-src/jenkins/sample-app$

Step 4: Point Git repository to GitHub repository. Use the git remote add command to add a Git URL with a remote alias of "origin" and points to the newly created repository on GitHub. Using the URL of the Git repository you created in Step 1, you should only need to replace the github-username in the following command with your GitHub username. Note: Your GitHub username is case-sensitive. devasc@labvm:~/labs/devnet-src/jenkins/sample-app$ git remote add origin https://github.com/github-username/sample-app.git devasc@labvm:~/labs/devnet-src/jenkins/sample-app$

Step 5: Stage, commit, and push the sample-app files to the GitHub repository. a. Use the git add command to stage the files in the jenkins/sample-app directory. Use the asterisk (*) argument to stage all files in the current directory. devasc@labvm:~/labs/devnet-src/jenkins/sample-app$ git add * b. Use the git status command to see the files and directories that are staged and ready to be committed to your GitHub repository. devasc@labvm:~/labs/devnet-src/jenkins/sample-app$ git status On branch master No commits yet Changes to be committed: (use "git rm --cached ..." to unstage) new file: sample-app.sh new file: sample_app.py © 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 2 of 15

www.netacad.com

Lab - Build a CI/CD Pipeline Using Jenkins

new file: new file:

static/style.css templates/index.html

devasc@labvm:~/labs/devnet-src/jenkins/sample-app$ c.

Use the git commit command to commit the staged files and start tracking changes. Add a message of your choice or use the one provided here. devasc@labvm:~/labs/devnet-src/jenkins/sample-app$ git commit -m "Committing sample-app files." [master 4030ab6] Committing sample-app files 4 files changed, 46 insertions(+) create mode 100644 sample-app.sh create mode 100644 sample_app.py create mode 100644 static/style.css create mode 100644 templates/index.html

d. Use the git push command to push your local sample-app files to your GitHub repository. devasc@labvm:~/labs/devnet-src/jenkins/sample-app$ git push origin master Username for 'https://github.com': username Password for 'https://[email protected]': password Enumerating objects: 9, done. Counting objects: 100% (9/9), done. Delta compression using up to 2 threads Compressing objects: 100% (5/5), done. Writing objects: 100% (8/8), 1.05 KiB | 1.05 MiB/s, done. Total 8 (delta 0), reused 0 (delta 0) To https://github.com/AllJohns/sample-app.git d0ee14a..4030ab6 master -> master

devasc@labvm:~/labs/devnet-src/jenkins/sample-app$ Note: If, instead of a request for your username, you get a message from VS Code with the message, The extension ‘Git’ wants to sign in using GitHub, then you misconfigured either your GitHub credentials in Step 2 and/or the GitHub URL in Step 4. The URL must have the correct case-sensitive username and the name of the repository that you created in Step 1. To reverse your previous git add command, use the command git remote rm origin. Then return to Step 2 making sure to enter the correct credentials and, in Step 4, entering the correct URL. Note: If, after entering your username and password, you get a fatal error stating repository is not found, you most likely submitted an incorrect URL. You will need to reverse your git add command with the git remote rm origin command.

Part 3: Modify the Sample App and Push Changes to Git In Part 4, you will install a Jenkins Docker image that will use port 8080. Recall that your sample-app files are also specifying port 8080. The Flask server and Jenkins server cannot both use 8080 at the same time. In this part, you will change the port number used by the sample-app files, run the sample-app again to verify it works on the new port, and then push your changes to your GitHub repository.

Step 1: Open the sample-app files. Make sure you are still in the ~/labs/devnet-src/jenkins/sample-app directory as these are the files that are associated with your GitHub repository. Open both sample_app.py and sample-app.sh for editing.

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 3 of 15

www.netacad.com

Lab - Build a CI/CD Pipeline Using Jenkins

Step 2: Edit the sample-app files. a. In sample_app.py, change the one instance of port 8080 to 5050 as shown below. from flask import Flask from flask import request from flask import render_template sample = Flask(__name__) @sample.route("/") def main(): return render_template("index.html") if __name__ == "__main__": sample.run(host="0.0.0.0", port=5050)

b. In sample-app.sh, change the three instances of port 8080 to 5050 as shown below. #!/bin/bash mkdir tempdir mkdir tempdir/templates mkdir tempdir/static cp sample_app.py tempdir/. cp -r templates/* tempdir/templates/. cp -r static/* tempdir/static/. echo echo echo echo echo echo echo

"FROM python" >> tempdir/Dockerfile "RUN pip install flask" >> tempdir/Dockerfile "COPY ./static /home/myapp/static/" >> tempdir/Dockerfile "COPY ./templates /home/myapp/templates/" >> tempdir/Dockerfile "COPY sample_app.py /home/myapp/" >> tempdir/Dockerfile "EXPOSE 5050" >> tempdir/Dockerfile "CMD python /home/myapp/sample_app.py" >> tempdir/Dockerfile

cd tempdir docker build -t sampleapp . docker run -t -d -p 5050:5050 --name samplerunning sampleapp docker ps -a

Step 3: Build and verify the sample-app. a. Enter the bash command to build your app using the new port 5050. devasc@labvm:~/labs/devnet-src/jenkins/sample-app$ bash ./sample-app.sh Sending build context to Docker daemon Step 1/7 : FROM python ---> 4f7cd4269fa9 Step 2/7 : RUN pip install flask

6.144kB

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 4 of 15

www.netacad.com

Lab - Build a CI/CD Pipeline Using Jenkins

---> Using cache ---> 57a74c0dff93 Step 3/7 : COPY ./static /home/myapp/static/ ---> Using cache ---> e70310436097 Step 4/7 : COPY ./templates /home/myapp/templates/ ---> Using cache ---> e41ed6d0f933 Step 5/7 : COPY sample_app.py /home/myapp/ ---> 0a8d152f78fd Step 6/7 : EXPOSE 5050 ---> Running in d68f6bfbcffb Removing intermediate container d68f6bfbcffb ---> 04fa04a1c3d7 Step 7/7 : CMD python /home/myapp/sample_app.py ---> Running in ed48fdbc031b Removing intermediate container ed48fdbc031b ---> ec9f34fa98fe Successfully built ec9f34fa98fe Successfully tagged sampleapp:latest d957a4094c1781ccd7d86977908f5419a32c05a2a1591943bb44eeb8271c02dc CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d957a4094c17 sampleapp "/bin/sh -c 'python …" 1 second ago Up Less than a second 0.0.0.0:5050->5050/tcp samplerunning

devasc@labvm:~/labs/devnet-src/jenkins/sample-app$ b. Open a browser tab and navigate to localhost:5050. You should see the message You are calling me from 172.17.0.1. c.

Shut down the server when you have verified that it is operating on port 5050.

Step 4: Push your changes to GitHub. a. Now you are ready to push your changes to your GitHub repository. Enter the following commands. devasc@labvm:~/labs/devnet-src/jenkins/sample-app$ git add * devasc@labvm:~/labs/devnet-src/jenkins/sample-app$ git status On branch master Changes to be committed: (use "git restore --staged ..." to unstage) modified: sample-app.sh modified: sample_app.py new file: tempdir/Dockerfile new file: tempdir/sample_app.py new file: tempdir/static/style.css new file: tempdir/templates/index.html

devasc@labvm:~/labs/devnet-src/jenkins/sample-app$ git commit -m "Changed port from 8080 to 5050." [master 98d9b2f] Changed port from 8080 to 5050. 6 files changed, 33 insertions(+), 3 deletions(-)

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 5 of 15

www.netacad.com

Lab - Build a CI/CD Pipeline Using Jenkins

create create create create

mode mode mode mode

100644 100644 100644 100644

tempdir/Dockerfile tempdir/sample_app.py tempdir/static/style.css tempdir/templates/index.html

devasc@labvm:~/labs/devnet-src/jenkins/sample-app$ git push origin master Username for 'https://github.com': username Password for 'https://[email protected]': password Enumerating objects: 9, done. Counting objects: 100% (9/9), done. Delta compression using up to 2 threads Compressing objects: 100% (6/6), done. Writing objects: 100% (6/6), 748 bytes | 748.00 KiB/s, done. Total 6 (delta 2), reused 0 (delta 0) remote: Resolving deltas: 100% (2/2), completed with 2 local objects. To https://github.com/AllJohns/sample-app.git a6b6b83..98d9b2f master -> master

devasc@labvm:~/labs/devnet-src/jenkins/sample-app$ b. You can verify that your GitHub repository is updated by visiting https://github.com/githubuser/sample-app. You should see your new message (Changed port from 8080 to 5050.) and that the latest commit timestamp has been updated.

Part 4: Download and Run the Jenkins Docker Image In this part, you will download the Jenkins Docker image. You will then start an instance of the image and verify that the Jenkins server is running.

Step 1: Download the Jenkins Docker image. The Jenkins Docker image is stored here: https://hub.docker.com/r/jenkins/jenkins. At the time of the writing of this lab, that site specifies that you use the docker pull jenkins/jenkins command to download the latest Jenkins container. You should get output similar to the following: devasc@labvm:~/labs/devnet-src/jenkins/sample-app$ docker pull jenkins/jenkins Using default tag: latest latest: Pulling from jenkins/jenkins 3192219afd04: Pulling fs layer 17c160265e75: Pulling fs layer cc4fe40d0e61: Pulling fs layer 9d647f502a07: Pulling fs layer d108b8c498aa: Pulling fs layer 1bfe918b8aa5: Pull complete dafa1a7c0751: Pull complete 650a236d0150: Pull complete cba44e30780e: Pull complete 52e2f7d12a4d: Pull complete d642af5920ea: Pull complete e65796f9919e: Pull complete 9138dabbc5cc: Pull complete f6289c08656c: Pull complete 73d6b450f95c: Pull complete

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 6 of 15

www.netacad.com

Lab - Build a CI/CD Pipeline Using Jenkins

a8f96fbec6a5: Pull complete 9b49ca1b4e3f: Pull complete d9c8f6503715: Pull complete 20fe25b7b8af: Pull complete Digest: sha256:717dcbe5920753187a20ba43058ffd3d87647fa903d98cde64dda4f4c82c5c48 Status: Downloaded newer image for jenkins/jenkins:latest docker.io/jenkins/jenkins:latest

devasc@labvm:~/labs/devnet-src/jenkins/sample-app$

Step 2: Start the Jenkins Docker container. Enter the following command on one line. You may need to copy it to a text editor if you are viewing a PDF version of this lab to avoid line breaks. This command will start the Jenkins Docker container and then allow Docker commands to be executed inside your Jenkins server. devasc@labvm:~/labs/devnet-src/jenkins/sample-app$ docker run --rm -u root -p 8080:8080 -v jenkins-data:/var/jenkins_home -v $(which docker):/usr/bin/docker -v /var/run/docker.sock:/var/run/docker.sock -v "$HOME":/home --name jenkins_server jenkins/jenkins:lts The options used in this docker run command are as follows: o

--rm - This option automatically removes the Docker container when you stop running it.

o

-u - This option specifies the user. You want this Docker container to run as root so that all Docker commands entered inside the Jenkins server are allowed.

o

-p - This option specifies the port the Jenkins server will run on locally.

o

-v - These options bind mount volumes needed for Jenkins and Docker. The first -v specifies where Jenkins data will be stored. The second -v specifies where to get Docker so that you can run Docker inside the Docker container that is running the Jenkins server. The third -v specifies the PATH variable for the home directory.

Step 3: Verify the Jenkins server is running. The Jenkins server should now be running. Copy the admin password that displays in the output, as shown in the following. Do not enter any commands in this server window. If you accidentally stop the Jenkins server, you will need to re-enter the docker run command from Step 2 above. After the initial install, the admin password is displayed as shown below.

************************************************************* ************************************************************* ************************************************************* Jenkins initial setup is required. An admin user has been created and a password generated. Please use the following password to proceed to installation: 77dc402e31324c1b917f230af7bfebf2 git init /var/jenkins_home/workspace/BuildAppJob # timeout=10 Fetching upstream changes from https://github.com/github-user/sample-app > git --version # timeout=10 using GIT_ASKPASS to set credentials > git fetch --tags --progress -- https://github.com/github-user/sample-app +refs/heads/*:refs/remotes/origin/* # timeout=10 > git config remote.origin.url https://github.com/github-user/sample-app # timeout=10 > git config --add remote.origin.fetch +refs/heads/*:refs/remotes/origin/* # timeout=10 > git config remote.origin.url https://github.com/github-user/sample-app # timeout=10 Fetching upstream changes from https://github.com/github-user/sample-app using GIT_ASKPASS to set credentials > git fetch --tags --progress -- https://github.com/github-user/sample-app +refs/heads/*:refs/remotes/origin/* # timeout=10 > git rev-parse refs/remotes/origin/master^{commit} # timeout=10 > git rev-parse refs/remotes/origin/origin/master^{commit} # timeout=10 Checking out Revision 230ca953ce83b5d6bdb8f99f11829e3a963028bf (refs/remotes/origin/master) > git config core.sparsecheckout # timeout=10 > git checkout -f 230ca953ce83b5d6bdb8f99f11829e3a963028bf # timeout=10 Commit message: "Changed port numbers from 8080 to 5050" > git rev-list --no-walk 230ca953ce83b5d6bdb8f99f11829e3a963028bf # timeout=10 [BuildAppJob] $ /bin/sh -xe /tmp/jenkins1084219378602319752.sh

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 10 of 15

www.netacad.com

Lab - Build a CI/CD Pipeline Using Jenkins

+ bash ./sample-app.sh Sending build context to Docker daemon

6.144kB

Step 1/7 : FROM python ---> 4f7cd4269fa9 Step 2/7 : RUN pip install flask ---> Using cache ---> 57a74c0dff93 Step 3/7 : COPY ./static /home/myapp/static/ ---> Using cache ---> aee4eb712490 Step 4/7 : COPY ./templates /home/myapp/templates/ ---> Using cache ---> 594cdc822490 Step 5/7 : COPY sample_app.py /home/myapp/ ---> Using cache ---> a001df90cf0c Step 6/7 : EXPOSE 5050 ---> Using cache ---> eae896e0a98c Step 7/7 : CMD python /home/myapp/sample_app.py ---> Using cache ---> 272c61fddb45 Successfully built 272c61fddb45 Successfully tagged sampleapp:latest 9c8594e62079c069baf9a88a75c13c8c55a3aeaddde6fd6ef54010953c2d3fbb CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 9c8594e62079 sampleapp "/bin/sh -c 'python …" Less than a second ago Up Less than a second 0.0.0.0:5050->5050/tcp samplerunning e25f233f9363 jenkins/jenkins:lts "/sbin/tini -- /usr/…" 29 minutes ago Up 29 minutes 0.0.0.0:8080->8080/tcp, 50000/tcp jenkins_server Finished: SUCCESS

Step 6: Open another web browser tab and verify sample app is running. Type in the local address, localhost:5050. You should see the content of your index.html displayed in light steel blue background color with You are calling me from 172.17.0.1 displayed in as H1.

Part 7: Use Jenkins to Test a Build In this part, you will create a second job that tests the build to ensure that it is working properly. Note: You need to stop and remove the samplerunning docker container. devasc@labvm:~/labs/devnet-src/jenkins/sample-app$ docker stop samplerunning samplerunning

devasc@labvm:~/labs/devnet-src/jenkins/sample-app$ docker rm samplerunning samplerunning

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 11 of 15

www.netacad.com

Lab - Build a CI/CD Pipeline Using Jenkins

Step 1: Start a new job for testing your sample-app. a. Return to the Jenkins web browser tab and click the Jenkins link in the top left corner to return to the main dashboard. b. Click the New Item link to create a new job. c.

In the Enter an item name field, fill in the name TestAppJob.

d. Click Freestyle project as the job type. e. Scroll to the bottom and click OK.

Step 2: Configure the Jenkins TestAppJob. a. Add a description for your job. For example, "My first Jenkins test." b. Leave Source Code Management set to None. c.

Click the Build Triggers tab and check the box, Build after other projects are built. For Projects to watch, fill in the name BuildAppJob.

Step 3: Write the test script that should run after a stable build of the BuildAppJob. a. Click the Build tab. b. Click Add build step and choose Execute shell. c.

Enter the following script. The if command should be all on one line including the ; then. This command will grep the output returned from the cURL command to see if You are calling me from 172.17.0.1 is returned. If true, the script exits with a code of 0, which means that there are no errors in the BuildAppJob build. If false, the script exits with a code of 1 which means the BuildAppJob failed. if curl http://172.17.0.1:5050/ | grep "You are calling me from 172.17.0.1"; then exit 0 else exit 1 fi

d. Click Save and then the Back to Dashboard link on the left side.

Step 4: Have Jenkins run the BuildAppJob job again. a. In the top right corner, click enable auto refresh if it is not already enabled. b. You should now see your two jobs listed in a table. For the BuildAppJob job, click the build button on the far right (a clock with an arrow).

Step 5: Verify both jobs completed. If all goes well, you should see the timestamp for the Last Success column update for both BuildAppJob and TestAppJob. This means your code for both jobs ran without error. But you can also verify this for yourself. Note: If timestamps do not update, make sure enable auto refresh is turned on by clicking the link in the top right corner. a. Click the Link for TestAppJob. Under Permalinks, click the link for your last build, and then click Console Output. You should see output similar to the following: Started by upstream project "BuildAppJob" build number 13 originally caused by: Started by user admin Running as SYSTEM © 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 12 of 15

www.netacad.com

Lab - Build a CI/CD Pipeline Using Jenkins

Building in workspace /var/jenkins_home/workspace/TestAppJob [TestAppJob] $ /bin/sh -xe /tmp/jenkins1658055689664198619.sh + grep You are calling me from 172.17.0.1 + curl http://172.17.0.1:5050/ % Total % Received % Xferd Average Speed Time Time Dload Upload Total Spent

Time Left

Current Speed

0 100

0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-0 177 100 177 0 0 29772 0 --:--:-- --:--:-- --:--:-- 35400 You are calling me from 172.17.0.1 + exit 0 Finished: SUCCESS

b. It is not necessary to verify your sample app is running because the TestAppJob already did this for you. However, you can open a browser tab for 172.17.0.1:5050 to see that it is indeed running.

Part 8: Create a Pipeline in Jenkins Although you can currently run your two jobs by simply clicking the Build Now button for the BuildAppJob, software development projects are typically much more complex. These projects can benefit greatly from automating builds for continuous integration of code changes and continuously creating development builds that are ready to deploy. This is the essence of CI/CD. A pipeline can be automated to run based on a variety of triggers including periodically, based on a GitHub poll for changes, or from a script run remotely. However, in this part you will script a pipeline in Jenkins to run your two apps whenever you click the pipeline Build Now button.

Step 1: Create a Pipeline job. a. Click the Jenkins link in the top left, and then New Item. b. In the Enter an item name field, type SamplePipeline. c.

Select Pipeline as the job type.

d. Scroll to the bottom and click OK.

Step 2: 2. Configure the SamplePipeline job. a. Along the top, click the tabs and investigate each section of the configuration page. Notice that there are a number of different ways to trigger a build. For the SamplePipeline job, you will trigger it manually. b. In the Pipeline section, add the following script. node { stage('Preparation') { catchError(buildResult: 'SUCCESS') { sh 'docker stop samplerunning' sh 'docker rm samplerunning' } } stage('Build') { build 'BuildAppJob' } stage('Results') { build 'TestAppJob' }

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 13 of 15

www.netacad.com

Lab - Build a CI/CD Pipeline Using Jenkins

}

This script does the following:

c.

o

In creates a single node build as opposed to a distributed or multi node. Distributed or multi node configurations are for larger pipelines than the one you are building in this lab and are beyond the scope of this course.

o

In the Preparation stage, the SamplePipeline will first make sure that any previous instances of the BuildAppJob docker container are stopped and removed. But if there is not yet a running container you will get an error. Therefore, you use the catchError function to catch any errors and return a “SUCCESS” value. This will ensure that pipeline continues on to the next stage.

o

In the Build stage, the SamplePipeline will build your BuildAppJob.

o

In the Results stage, the SamplePipeline will build your TestAppJob.

Click Save and you will be returned to the Jenkins dashboard for the SamplePipeline job.

Step 3: Run the SamplePipeline. On the left, click Build Now to run the SamplePipeline job. If you coded your Pipeline script without error, then the Stage View should show three green boxes with number of seconds each stage took to build. If not, click Configure on the left to return to the SamplePipeline configuration and check your Pipeline script.

Step 4: 4. Verify the SamplePipeline output. Click the latest build link under Permalinks, and then click Console Output. You should see output similar to the following: Started by user admin Running in Durability level: MAX_SURVIVABILITY [Pipeline] Start of Pipeline [Pipeline] node Running on Jenkins in /var/jenkins_home/workspace/SamplePipeline [Pipeline] { [Pipeline] stage [Pipeline] { (Preparation) [Pipeline] catchError [Pipeline] { [Pipeline] sh + docker stop samplerunning samplerunning [Pipeline] sh + docker rm samplerunning samplerunning [Pipeline] } [Pipeline] // catchError [Pipeline] } [Pipeline] // stage [Pipeline] stage [Pipeline] { (Build) [Pipeline] build (Building BuildAppJob) Scheduling project: BuildAppJob Starting building: BuildAppJob #15 [Pipeline] } [Pipeline] // stage © 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 14 of 15

www.netacad.com

Lab - Build a CI/CD Pipeline Using Jenkins

[Pipeline] stage [Pipeline] { (Results) [Pipeline] build (Building TestAppJob) Scheduling project: TestAppJob Starting building: TestAppJob #18 [Pipeline] } [Pipeline] // stage [Pipeline] } [Pipeline] // node [Pipeline] End of Pipeline Finished: SUCCESS End of document

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 15 of 15

www.netacad.com

LAB 6.5.10 Lab - Explore the Evolution of Password Methods (Instructor Version) Instructor Note: Red font color or gray highlights indicate text that appears in the instructor copy only.

Objectives Part 1: Launch the DEVASC VM Part 2: Explore Python Code Storing Passwords in Plain Text Part 3: Explore Python Code Storing Passwords Using a Hash

Background / Scenario In this lab, you will create an application that stores a username and password in plaintext in a database using python code. You will then test the server to ensure that not only were the credentials stored correctly, but that a user can use them to login. You will then perform the same actions, but with a hashed password so that the credentials cannot be read. It is important to securely store credentials and other data to prevent different servers and systems from being compromised.

Required Resources •

1 PC with operating system of your choice



Virtual Box or VMWare



DEVASC Virtual Machine

Instructions Part 1: Launch the DEVASC VM If you have not already completed the Lab - Install the Virtual Machine Lab Environment, do so now. If you have already completed that lab, launch the DEVASC VM now.

Part 2: Demonstrate the Application Instructor Note: You can use the script at the end of the lab to demonstrate the application. Your instructor may demonstrate the Password Plain Text and Hashing Application. However, you will create this script step by step in this lab. The application first stores a username and password in plaintext in a web service database. It then validates that the credentials were stored and work properly. The second method, hashing the password, also stores them and tests them in the web service database.

Part 3: Install Packages and Create a Web Service In this Part, you will use Flask to create a simple web service that requires user authentication. User authentication requires a database which will be satisfied using SQLite.

Step 1: Open the security directory in VS Code and install Python packages. a. Open VS code. Then click File > Open Folder... and navigate to the devnet-src/security directory. Click OK.

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 1 of 11

www.netacad.com

Lab - Explore the Evolution of Password Methods

b. In the EXPLORER panel, click the password-evolution.py placeholder file to open it. c.

Open a terminal in VS Code. Click Terminal > New Terminal.

d. Use the following commands to install the packages needed in this lab. These packages may already be installed on your VM. If so, you will get a Requirement already satisfied message. devasc@labvm:~/labs/devnet-src/security$ pip3 install pyotp Defaulting to user installation because normal site-packages is not writeable Collecting pyotp Using cached pyotp-2.3.0-py2.py3-none-any.whl (10 kB) Installing collected packages: pyotp Successfully installed pyotp-2.3.0

devasc@labvm:~/labs/devnet-src/security$ pip3 install flask Defaulting to user installation because normal site-packages is not writeable Collecting flask Using cached Flask-1.1.2-py2.py3-none-any.whl (94 kB) Requirement already satisfied: click>=5.1 in /home/devasc/.local/lib/python3.8/sitepackages (from flask) (7.1.2) Requirement already satisfied: Jinja2>=2.10.1 in /usr/lib/python3/dist-packages (from flask) (2.10.1) Requirement already satisfied: itsdangerous>=0.24 in /home/devasc/.local/lib/python3.8/site-packages (from flask) (1.1.0) Requirement already satisfied: Werkzeug>=0.15 in /home/devasc/.local/lib/python3.8/site-packages (from flask) (1.0.1) Installing collected packages: flask Successfully installed flask-1.1.2 devasc@labvm:~/labs/devnet-src/security$

Step 2: Import libraries. In the password-evolution.py file, add the following code. Notice the command, db_name = 'test.db'. This is an SQL database (sqlite3) that stores the usernames and passwords that you will be creating. import pyotp #generates one-time passwords import sqlite3 #database for username/passwords import hashlib #secure hashes and message digests import uuid #for creating universally unique identifiers from flask import Flask, request app = Flask(__name__) #Be sure to use two underscores before and after "name" db_name = 'test.db'

Step 3: Create a local web service. a. Next, add the following Flask code into the file to create the first phrase of web content at the root path. When the user goes to URL (root directory), the output of the return statement will be displayed in the browser. @app.route('/') def index(): return 'Welcome to the hands-on lab for an evolution of password systems!'

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 2 of 11

www.netacad.com

Lab - Explore the Evolution of Password Methods

b. Add the following code to the file to create a local web service on port 5000 with a self-signed TLS certificate. The parameter ssl_context=’adhoc’ allows you to run an application over HTTPS without having to use certificates or when using a self-signed certificate. Be sure to use two underscores before and after name and main. if __name__ == '__main__': app.run(host='0.0.0.0', port=5000, ssl_context='adhoc') c.

Save and run the password-evolution.py file. The nohup (no hangup) command keeps the process running even after exiting the shell or terminal. The & makes the command run in the background. devasc@labvm:~/labs/devnet-src/security$ nohup python3 password-evolution.py & [1] 26329

devasc@labvm:~/labs/devnet-src/security$ nohup: ignoring input and appending output to 'nohup.out' devasc@labvm:~/labs/devnet-src/security$ d. Prese Enter to get a new command prompt. e. Your Flask server is now running. In VS Code in the /security folder, you should see the nohup.out text file created by Flask. Click the file to read its output. f.

Verify that the web service has started. Be sure to use HTTPS and not HTTP. The -k option allows curl to perform "insecure" SSL connections and transfers. Without the -k option, you will receive an error message, "SSL certificate problem: self-signed certificate". The command will display the message from the return command you coded in your script. devasc@labvm:~/labs/devnet-src/security$ curl -k https://0.0.0.0:5000/ Welcome to the hands-on lab for an evolution of password systems!devasc@labvm:~/labs/devnet-src/security$

g. Press Enter to get a command prompt one a new line. h. Before continuing, terminate the script. Use the following command to stop it: devasc@labvm:~/labs/devnet-src/security$ pkill -f password-evolution.py devasc@labvm:~/labs/devnet-src/security$

Part 4: Explore Python Code Storing Passwords in Plain Text When passwords were first used, they were simply stored in a database as plaintext. When the user entered their credentials, the system looked up the password to see if it matched. The system was very easy to implement, but also very insecure. In this Part, you will modify the password-evolution.py python file to allow it to store user identity in the test.db database. You will then create a user and perform an authentication against these credentials. Finally, you will examine the test.db database to verify they were stored in plaintext.

Step 1: Remove the server configuration. Remove the following lines from the password-evolution.py python file. You will add this code back later. if __name__ == '__main__': app.run(host='0.0.0.0', port=5000, ssl_context='adhoc')

Step 2: Configure the server to store credentials. a. Append (copy) the following Flask code to configure the server to store a username and password for a user in plaintext. Using the HTTP POST method, this code allows a user to create ("signup") a new

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 3 of 11

www.netacad.com

Lab - Explore the Evolution of Password Methods

username and password that will be stored in the test.db SQL database file. Later when the user enters in a username and password, this code will return the message "signup success". ######################################### Plain Text ######################################################### @app.route('/signup/v1', methods=['POST']) def signup_v1(): conn = sqlite3.connect(db_name) c = conn.cursor() c.execute('''CREATE TABLE IF NOT EXISTS USER_PLAIN (USERNAME TEXT PRIMARY KEY NOT NULL, PASSWORD TEXT NOT NULL);''') conn.commit() try: c.execute("INSERT INTO USER_PLAIN (USERNAME,PASSWORD) " "VALUES ('{0}', '{1}')".format(request.form['username'], request.form['password'])) conn.commit() except sqlite3.IntegrityError: return "username has been registered." print('username: ', request.form['username'], ' password: ', request.form['password']) return "signup success" Note: Be careful of word wrap in the above code. Be sure to indent properly or the code may not work correctly. b. Append (copy) the following Flask code to your password-evolution.py file to verify the new account credentials. def verify_plain(username, password): conn = sqlite3.connect('test.db') c = conn.cursor() query = "SELECT PASSWORD FROM USER_PLAIN WHERE USERNAME = '{0}'".format(username) c.execute(query) records = c.fetchone() conn.close() if not records: return False return records[0] == password c.

Append (copy) the following Flask code to your password-evolution.py file. This code is used during each login attempt to read the parameters from an HTTP request and verify the account. If the login is successful, the message "login success" will be returned, otherwise the user will see the message "Invalid username/password". @app.route('/login/v1', methods=['GET', 'POST']) def login_v1(): error = None if request.method == 'POST': if verify_plain(request.form['username'], request.form['password']):

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 4 of 11

www.netacad.com

Lab - Explore the Evolution of Password Methods

error = 'login success' else: error = 'Invalid username/password' else: error = 'Invalid Method' return error

Step 3: Run the server and test it. a. Add back the server configuration code you deleted earlier. if __name__ == '__main__': app.run(host='0.0.0.0', port=5000, ssl_context='adhoc') b. Save and run the script to start the updated web service. devasc@labvm:~/labs/devnet-src/security$ nohup python3 password-evolution.py & [1] 27826 devasc@labvm:~/labs/devnet-src/security$ nohup: ignoring input and appending output to 'nohup.out'

c.

Use the following curl commands to create (signup) a two user accounts, alice and bob, and send a POST to the web service. Each command includes the username, password, and the signup function being called that stores this information including the password as plaintext. You should see the "signup success" message from the return command that you included in the previous step. Note: After each command, press Enter to get a command prompt on a new line. devasc@labvm:~/labs/devnet-src/security$ curl -k -X POST -F 'username=alice' -F 'password=myalicepassword' 'https://0.0.0.0:5000/signup/v1' signup successdevasc@labvm:~/labs/devnet-src/security$ devasc@labvm:~/labs/devnet-src/security$ curl -k -X POST -F 'username=bob' -F 'password=passwordforbob' 'https://0.0.0.0:5000/signup/v1' signup successdevasc@labvm:~/labs/devnet-src/security$ devasc@labvm:~/labs/devnet-src/security$

Step 4: Verify your new users can login. a. Use the following curl commands to verify that both users can login with their passwords that are stored in plaintext. devasc@labvm:~/labs/devnet-src/security$ curl -k -X POST -F 'username=alice' -F 'password=myalicepassword' 'https://0.0.0.0:5000/login/v1' login successdevasc@labvm:~/labs/devnet-src/security$ devasc@labvm:~/labs/devnet-src/security$ devasc@labvm:~/labs/devnet-src/security$ curl -k -X POST -F 'username=bob' -F 'password=passwordforbob' 'https://0.0.0.0:5000/login/v1' login successdevasc@labvm:~/labs/devnet-src/security$ b. Terminate the server. login successdevasc@labvm:~/labs/devnet-src/security$ pkill -f passwordevolution.py [1]+

Terminated

nohup python3 password-evolution.py

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 5 of 11

www.netacad.com

Lab - Explore the Evolution of Password Methods

devasc@labvm:~/labs/devnet-src/security$

Step 5: Verify the contents of test.db. You may have noticed that SQLite created a test.db file in your /security folder. You can cat this file and see the username and passwords for alice and bob. However, in this step you will use an application for viewing SQLite database files. a. Open the DB Browser for SQLite application o

Select the menu icon on the lower-left of the VM.

o

Select: Applications > All

o

Select :DB Browser for SQLite

b. After the DB Browser for SQLIte is running, open the test.db file:

c.

o

Select: File > Open database…

o

Navigate to the labs/devnet-src/security directory and select test.db.

o

Click Open.

In the Database Structure tab, notice the USER_PLAIN table that coincides with the code you created earlier.

d. Expand the table to see the two fields: USERNAME and PASSWORD. e. Select the Browse Data tab. The Table: USER_PLAIN is already selected. Here you can see usernames bob and alice along with their passwords in plaintext. f.

Close the DB Browser for SQLite application.

Part 5: Password Hashing in Python Instead of storing passwords in plaintext, you can hash it when it is created. When the password is hashed, it is converted into an unreadable collection of characters. This prevents anyone from converting it back to its correct, plaintext version. Even if the database is stolen it cannot be used because the hash is not known. You will now modify the password-evolution.py file to create a web API that can accept a web request and save a new user's password in a hashed format.

Step 1: Remove the server configuration. a. Remove the following two lines from the password-evolution.py file. These lines will be appended again later. if __name__ == '__main__': app.run(host='0.0.0.0', port=5000, ssl_context='adhoc')

Step 2: Configure the server to store credentials. a. Add the following code to the bottom of the file to enable the server to hash the password using SHA256 hashing method. Notice that this code is similar to the code you included previously. This code allows a user to create ("signup") a new username and password that will be stored in the test.db SQL database file. The difference is the that the passwords will be stored as a hash value instead of being in plaintext. This routine uses sha256 but does not salt the hash. You will see the implications of using a hash without salt when you view the test.db database file. ######################################### Password Hashing #########################################################

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 6 of 11

www.netacad.com

Lab - Explore the Evolution of Password Methods

@app.route('/signup/v2', methods=['GET', 'POST']) def signup_v2(): conn = sqlite3.connect(db_name) c = conn.cursor() c.execute('''CREATE TABLE IF NOT EXISTS USER_HASH (USERNAME TEXT PRIMARY KEY NOT NULL, HASH TEXT NOT NULL);''') conn.commit() try: hash_value = hashlib.sha256(request.form['password'].encode()).hexdigest() c.execute("INSERT INTO USER_HASH (USERNAME, HASH) " "VALUES ('{0}', '{1}')".format(request.form['username'], hash_value)) conn.commit() except sqlite3.IntegrityError: return "username has been registered." print('username: ', request.form['username'], ' password: ', request.form['password'], ' hash: ', hash_value) return "signup success" b. Append (copy) the following code to your password-evolution.py file to verify that the password has been stored only in hashed format. The code defines the function verify_hash which compares the username and the password in hash format. When the comparison is true, the password has been stored only in its hash format. def verify_hash(username, password): conn = sqlite3.connect(db_name) c = conn.cursor() query = "SELECT HASH FROM USER_HASH WHERE USERNAME = '{0}'".format(username) c.execute(query) records = c.fetchone() conn.close() if not records: return False return records[0] == hashlib.sha256(password.encode()).hexdigest() c.

Append (copy) the following code to your password-evolution.py file. The following code reads the parameters from an HTTP POST request and verifies that the user has provided the correct password during login. @app.route('/login/v2', methods=['GET', 'POST']) def login_v2(): error = None if request.method == 'POST': if verify_hash(request.form['username'], request.form['password']): error = 'login success' else: error = 'Invalid username/password'

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 7 of 11

www.netacad.com

Lab - Explore the Evolution of Password Methods

else: error = 'Invalid Method' return error

Step 3: Run the server and test it. a. Add back the server configuration code you deleted earlier. if __name__ == '__main__': app.run(host='0.0.0.0', port=5000, ssl_context='adhoc') b. Save and then run the script to start the updated web service. devasc@labvm:~/labs/devnet-src/security$ nohup python3 password-evolution.py & [1] 28411 devasc@labvm:~/labs/devnet-src/security$ nohup: ignoring input and appending output to 'nohup.out'

c.

Use the following curl commands to creates three new user accounts with a hashed password. Notice that two of the users, rick and allan, are using the same password. devasc@labvm:~/labs/devnet-src/security$ curl -k -X POST -F 'username=rick' F 'password=samepassword' 'https://0.0.0.0:5000/signup/v2' signup successdevasc@labvm:~/labs/devnet-src/security$ devasc@labvm:~/labs/devnet-src/security$ curl -k -X POST -F 'username=allan' -F 'password=samepassword' 'https://0.0.0.0:5000/signup/v2' signup successdevasc@labvm:~/labs/devnet-src/security$ devasc@labvm:~/labs/devnet-src/security$ curl -k -X POST -F 'username=dave' F 'password=differentpassword' 'https://0.0.0.0:5000/signup/v2' signup successdevasc@labvm:~/labs/devnet-src/security$

d. Use curl commands to verify the login of all three users with their hash-stored passwords. The user allan is entered in twice, the first time with the wrong password. Notice the "Invalid username/password" that coincides with the code for this function that you added in a previous step. devasc@labvm:~/labs/devnet-src/security$ curl -k -X POST -F 'username=rick' F 'password=samepassword' 'https://0.0.0.0:5000/login/v2' login successdevasc@labvm:~/labs/devnet-src/security$ devasc@labvm:~/labs/devnet-src/security$ curl -k -X POST -F 'username=allan' -F 'password=wrongpassword' 'https://0.0.0.0:5000/login/v2' Invalid username/passworddevasc@labvm:~/labs/devnet-src/security$ devasc@labvm:~/labs/devnet-src/security$ curl -k -X POST -F 'username=allan' -F 'password=samepassword' 'https://0.0.0.0:5000/login/v2' login successdevasc@labvm:~/labs/devnet-src/security$ devasc@labvm:~/labs/devnet-src/security$ curl -k -X POST -F 'username=dave' F 'password=differentpassword' 'https://0.0.0.0:5000/login/v2' login successdevasc@labvm:~/labs/devnet-src/security$

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 8 of 11

www.netacad.com

Lab - Explore the Evolution of Password Methods

This confirms that the hashed password is safely stored, and the passwords of users are protected should they become compromised. e. Terminate the server. devasc@labvm:~/labs/devnet-src/security$ pkill -f password-evolution.py [1]+

Terminated

nohup python3 password-evolution.py

devasc@labvm:~/labs/devnet-src/security$

Step 4: Verify the contents of test.db. a. Open the DB Browser for SQLite application. b. Open the test.db file. c.

Select the tab, Database Structure. You will notice two structures that coincide with the code you included earlier: USER_PLAIN and USER HASH.

d. Select the Browse Data tab. e. The Table: USER_HASH should already be selected. You will now see the usernames rick, allan, and dave along with their hashed passwords. (You may need to adjust the table cells.) Notice that rick and allan have the same hashed passwords. This is because they had the same password and the hash function did not include a salt to make their hash unique. Salting the hash is the process of adding random data to a hash. To guarantee the uniqueness of the passwords, increase their complexity, and prevent password attacks even when the inputs are the same, a salt should be added to the input of a hash function.

Part 6: Review the Final Program The following is the complete script you created in this lab. import pyotp import sqlite3 import hashlib import uuid from flask import Flask, request app = Flask(__name__) db_name = 'test.db' @app.route('/') def index(): return 'Welcome to the hands-on lab for an evolution of password systems!' ######################################### Plain Text ######################################################### @app.route('/signup/v1', methods=['POST']) def signup_v1(): conn = sqlite3.connect(db_name) c = conn.cursor() c.execute('''CREATE TABLE IF NOT EXISTS USER_PLAIN (USERNAME TEXT PRIMARY KEY NOT NULL, PASSWORD TEXT NOT NULL);''')

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 9 of 11

www.netacad.com

Lab - Explore the Evolution of Password Methods

conn.commit() try: c.execute("INSERT INTO USER_PLAIN (USERNAME,PASSWORD) " "VALUES ('{0}', '{1}')".format(request.form['username'], request.form['password'])) conn.commit() except sqlite3.IntegrityError: return "username has been registered." print('username: ', request.form['username'], ' password: ', request.form['password']) return "signup success" def verify_plain(username, password): conn = sqlite3.connect('test.db') c = conn.cursor() query = "SELECT PASSWORD FROM USER_PLAIN WHERE USERNAME = '{0}'".format(username) c.execute(query) records = c.fetchone() conn.close() if not records: return False return records[0] == password @app.route('/login/v1', methods=['GET', 'POST']) def login_v1(): error = None if request.method == 'POST': if verify_plain(request.form['username'], request.form['password']): error = 'login success' else: error = 'Invalid username/password' else: error = 'Invalid Method' return error ######################################### Password Hashing ######################################################### @app.route('/signup/v2', methods=['GET', 'POST']) def signup_v2(): conn = sqlite3.connect(db_name) c = conn.cursor() c.execute('''CREATE TABLE IF NOT EXISTS USER_HASH (USERNAME TEXT PRIMARY KEY NOT NULL, HASH TEXT NOT NULL);''') conn.commit() try:

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 10 of 11

www.netacad.com

Lab - Explore the Evolution of Password Methods

hash_value = hashlib.sha256(request.form['password'].encode()).hexdigest() c.execute("INSERT INTO USER_HASH (USERNAME, HASH) " "VALUES ('{0}', '{1}')".format(request.form['username'], hash_value)) conn.commit() except sqlite3.IntegrityError: return "username has been registered." print('username: ', request.form['username'], ' password: ', request.form['password'], ' hash: ', hash_value) return "signup success" def verify_hash(username, password): conn = sqlite3.connect(db_name) c = conn.cursor() query = "SELECT HASH FROM USER_HASH WHERE USERNAME = '{0}'".format(username) c.execute(query) records = c.fetchone() conn.close() if not records: return False return records[0] == hashlib.sha256(password.encode()).hexdigest() @app.route('/login/v2', methods=['GET', 'POST']) def login_v2(): error = None if request.method == 'POST': if verify_hash(request.form['username'], request.form['password']): error = 'login success' else: error = 'Invalid username/password' else: error = 'Invalid Method' return error if __name__ == '__main__': app.run(host='0.0.0.0', port=5000, ssl_context='adhoc') End of document

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 11 of 11

www.netacad.com

LAB 7.0.3 Lab - Install the CSR1000v VM (Instructor Version) Instructor Note: Red font color or gray highlights indicate text that appears in the instructor copy only.

Objectives Part 1: Install the CSR1000v VM on VirtualBox Part 2: Verify Communications to CSR1000v VM

Background / Scenario In this lab, you will install the CSR1000v Cloud Services Router. This is a Cisco software virtual router deployed on a virtual machine (VM) instance on x86 server hardware. When the Cisco CSR 1000v is deployed on a VM, the Cisco IOS XE software functions as if it were deployed on a traditional Cisco hardware platform. You can configure different features depending on the Cisco IOS XE software image. Note: The CSR1000v name will be shortened to CSR1kv in future labs. However, for this lab we use CSR1000v.

Required Resources •

Host computer with at least 4 GB of RAM and 2 GB of free disk space



Virtual Box or VMware



DEVASC Virtual Machine

Instructions Part 1: Install the CSR1000v VM Install the CSR1000kv VM directly on your x86 computer. It requires at least 4GB of RAM.

Step 1: Instructor only: Download the CSR1000v ISO file. Note: Only the instructor or anyone with proper credentials is allowed to download ISO files from Cisco. This step must be done by the instructor. a. To download the CSR1000vd ISO go to: https://software.cisco.com/download/home/284364978/type/282046477/release/Fuji-16.9.5 Note: To download software from cisco.com, you must be an active NetAcad instructor and have a CCO account with the activated NetAcad Maintenance contract. b. Select the download icon to the right of the following file: Cisco CSR1000V IOS XE Universal - CRYPTO ISO csr1000v-universalk9.16.09.05.iso c.

The instructor may now distribute this ISO to students to use in the DevNet Associate course only.

Instructor Note: It is strongly recommended that you allow students to go through the rest of the installation process. Virtual machine management is an essential skill for them to practice.

Step 2: Download the CSR1000v VM OVA file. Download the DEVASC_CSR1000v VM zip file. This file contains both the VirtualBox and VMware template files. Unzip the file to access the VMs. © 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 1 of 5

www.netacad.com

Lab - Install the CSR1000v VM

Step 3: Install the CSR1000v VM. a. Open Oracle VirtualBox Manager or VMware Workstation. b. Select File > Import in VirtualBox or File > Open in VMware. In VMware Workstation Player, select Player > File > Open. c.

In VirtualBox, select the file CSR1000v_for_VirtualBox.ova and click Open and Import. In VMware, select the file CSR1000v_for_VMware.ova and click Open.

d. Click Import. e. You will now see the CSR1000v VM added to VirtualBox or VMware.

Step 4: Update the installation ISO location. a. Select the Virtual Machine Settings or click Edit virtual machine settings. b. In the VM Settings, go to the very first CD Drive setting.

c.



In VirtualBox: VM Settings > Storage > CD device (the first CD Drive in the list)



In VMware: VM Settings > the first "CD/DVD (IDE)" Drive in the list

In the first CD Drive settings, replace the currently used ISO file •

In VirtualBox: Attributes > CD icon > Choose a disk file ...



In VMware: Next to "Use ISO image file", click Browse.

d. Select the ISO file you received from your instructor in Step 1. At the time this lab was written, the file name was csr1000v-universalk9.16.09.05.iso. However, the version (16.09.05) may have changed, altering the file name. e. Do NOT change the Second CD Drive settings. That is used for the initial configuration of the router. f.

Click OK to save the Virtual Machine settings.

Step 5: For VirtualBox on Mac and Linux, verify the CSR1000v is using a Host-Only Adapter. a. In VirtualBox, click File > Host Network Manager… b. Verify that there is a host adapter with a name such as vxboxnet0 with an IPv4 Address/Mask 192.168.56.1/24. It is important that your host-only adapter is on the 192.168.56.0/24 network. c.

If host adapter does not exist, click Create.

d. If the IPv4 address is not on 192.168.56.1/24, select the adapter and click Properties. Modify the IPv4 address and click Close.

Step 6: Start CSR1000v VM. a. Select the CSR1000v VM and click Start or Power On. b. If you receive the following message, continue with this step, otherwise, go to the next step: Could not start the machine DEVASC-CSR1000v because the following physical network interfaces were not found: VirtualBox Host-Only Ethernet Adapter (adapter 1) You can either change the machine's network settings or stop the machine. c.

Verify the following: Adapter 1 - Attached to: Host-only Adapter

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 2 of 5

www.netacad.com

Lab - Install the CSR1000v VM

d. Click OK.

Step 7: VM Loading Process. During the loading process you will see several messages including a message to Press any key to continue. You can ignore all of these messages. A selection screen will appear where you can choose different configuration options. Do not choose any configuration options. Installation will continue on its own. Wait for the initial installation process to complete. This will take several minutes the first time you boot the CSR1000v. You will begin to see IOS messages from different processes including %SSH, %PKI and %CRYPTO_ENGINE. After a few minutes the messages will stop. a. Within the VM window, press Enter. You should now see the prompt: CSR1kv>. b. Enter enable for the privileged EXEC prompt. There is no enable password. CSR1kv> enable CSR1kv#

Part 2: Verify Communications to CSR1000v VM. In this Part, you will verify communications between devices:

Step 1: Verify the CSR1000v IPv4 address. From the CSR1000v VM, use the show ip interface brief command to verify the IPv4 address of the GigabitEthernet1 interface. The CSR1000v is most likely using the IPv4 address from the 192.168.x.y address space. CSR1kv# show ip interface brief Interface GigabitEthernet1

IP-Address 192.168.56.101

OK? Method Status YES DHCP up

Protocol up

CSR1kv# Make note of this address and use it in the rest of this lab as well as other labs in this course in place of the default of 192.168.56.101.

Step 2: Launch the DEVASC VM. If you have not completed the Lab 1.1.2 Lab - Install the Virtual Machine Environment, do so now. If you have already completed that lab, launch the DEVASC VM now.

Step 3: Ping the CSR1000v VM from the DEVASC VM VM. a. Select the DEVASC VM VM. b. Open a Terminal window. c.

Ping the CSR1000v VM at its IPv4 address. devasc@labvm:~$ ping 192.168.56.101 PING 192.168.56.101 (192.168.56.101) 56(84) bytes of data. 64 bytes from 192.168.56.101: icmp_seq=1 ttl=63 time=8.04 ms 64 bytes from 192.168.56.101: icmp_seq=2 ttl=63 time=3.08 ms 64 bytes from 192.168.56.101: icmp_seq=3 ttl=63 time=1.04 ms 64 bytes from 192.168.56.101: icmp_seq=4 ttl=63 time=1.08 ms

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 3 of 5

www.netacad.com

Lab - Install the CSR1000v VM

^C --- 192.168.56.101 ping statistics --4 packets transmitted, 4 received, 0% packet loss, time 3010ms rtt min/avg/max/mdev = 1.038/3.310/8.043/2.854 ms

devasc@labvm:~$

Step 4: Establish a secure shell (SSH) session with the CSR1000v. Some of the tasks you will complete in later labs will require an SSH session with the CSR1000v. a. Connect to the CSR1000v with SSH from the DEVASC VM. Use the password cisco123! to authenticate. Notice that you are automatically in privileged EXEC mode. Enter exit to end the SSH session. devasc@labvm:~$ ssh [email protected] Password: * ** *** *** *** *** *** *** *** ** *

Cisco Networking Academy This software is provided for Educational Purposes Only in Networking Academies

* ** *** *** *** *** *** *** *** ** *

CSR1kv# exit Connection to 192.168.56.101 closed by remote host. Connection to 192.168.56.101 closed.

devasc@labvm:~$

Step 5: From the DEVASC VM, access the CSR1000v WebUI (Web User Interface). a. Open a web browser on the DEVASC VM. b. For the URL enter: https://192.168.56.101 Note: Be sure to use "https" c.

If your browser displays a warning similar to, "Your connection is not private": 1) Click Advanced. 2) Click Proceed to 192.168.56.101 (unsafe).

d. You will now see a LOGIN screen. Enter the following: 1) Username: cisco 2) Password: cisco123! 3) Click LOGIN NOW. You will now see the Dashboard for the CSR1000v. You are now accessing the CSR1000v's WebUI from the DEVASC virtual machine. © 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 4 of 5

www.netacad.com

Lab - Install the CSR1000v VM

Step 6: From your local computer, access the CSR1000v WebUI (Web User Interface). a. Open a web browser on your local computer, not inside the DEVASC VM. b. For the URL, enter: https://192.168.56.101. Note: Be sure to use "https". c.

If your browser displays a warning similar to, "Your connection is not private": 1) Click Advanced. 2) Click Proceed to 192.168.56.101 (unsafe).

d. You will now see a LOGIN screen. Enter the following: 1) Username: cisco 2) Password: cisco123! 3) Click LOGIN NOW. You will now see the Dashboard for the CSR1000v. You are now accessing the CSR1000v's WebUI from your local computer. End of document

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 5 of 5

www.netacad.com

LAB 7.4.7 Lab - Use Ansible to Back Up and Configure a Device (Instructor Version) Instructor Note: Red font color or gray highlights indicate text that appears in the instructor copy only.

Objectives Part 1: Launch the DEVASC VM and CSR1000v VM Part 2: Configure Ansible Part 3: Use Ansible to Back up a Configuration Part 4: Use Ansible to Configure a Device

Background / Scenario In this lab, you will explore the fundamentals of how to use Ansible to automate some basic device management task. First, you will configure Ansible in your DEVASC VM. Next, you will use Ansible to connect to the CSR1000v and back up its configuration. Finally, you will configure the CSR1000v with IPv6 addressing.

Required Resources •

1 PC with operating system of your choice



Virtual Box or VMWare



DEVASC Virtual Machine



CSR1000v Virtual Machine

Instructions Part 1: Launch the DEVASC VM and CSR1000v VMs If you have not already completed the Lab - Install the Virtual Machine Lab Environment, do so now. If you have already completed that lab, launch the DEVASC VM now. If you have not already completed the Lab - Install the DEVASC-LAB and CSR1000v VM, do so now. If you have already completed that lab, launch the CSR1000v VM now.

Part 2: Configure Ansible In this part, you will configure Ansible to run from a specific directory.

Step 1: Open the Ansible directory in VS Code. a. Open VS Code. b. Click File > Open Folder... and navigate to the /labs/devnet-src/ansible folder. c.

Click OK.

d. The two subdirectories for the Ansible labs are now loaded in the VS Code EXPLORER pane for your convenience. In this lab, you will work with the ansible-csr1000v directory.

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 1 of 11

www.netacad.com

Lab - Use Ansible to Back Up and Configure a Device

Step 2: Edit the Ansible inventory file. Ansible uses an inventory file called hosts that contains device information used by Ansible playbooks. The default location for the Ansible inventory file is /etc/ansible/hosts as specified in the default ansible.cfg in the same /etc/ansible directory. These default files are used when Ansible is run globally. However, in this lab you will run Ansible from the ansible-csr1000v directory. Therefore, you need separate hosts and ansible.cfg files for each lab. Note: The terms hosts file and inventory file are synonymous and will be used interchangeably throughout the Ansible labs. The Ansible inventory file defines the devices and groups of devices that are used by the Ansible playbook. The file can be in one of many formats, including YAML and INI, depending on your Ansible environment. The inventory file can list devices by IP address or fully qualified domain name (FQDN), and may include host specific parameters as well. a. Open the hosts file in the ansible-csr1000v directory. b. Add the following lines to the hosts file and save. # Enter the hosts or devices for Ansible playbooks CSR1kv ansible_user=cisco ansible_password=cisco123! ansible_host=192.168.56.101

After the comment (#), the hosts file begins with an alias, CSR1kv. An alias is used from within the Ansible playbook to reference a device. After the alias, the hosts file specifies three variables that will be used by the Ansible playbook to access the device. These are the SSH credentials Ansible needs to securely access the CSR1000v VM. o

ansible_user is a variable containing the username used to connect to the remote device. Without this, the user that is running the ansible-playbook would be used.

o

ansible_password is a variable containing the corresponding password for ansible_user. If not specified, the SSH key would be used.

o

ansible_host is a variable containing the IP address or FQDN of the device.

Step 3: Display the Ansible version and default ansible.cfg location. a. To see where Ansible stores the default ansible.cfg file, open a terminal window and navigate up one directory to the ansible parent directory. devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ cd .. devasc@labvm:~/labs/devnet-src/ansible$ b. Type ansible to get a list of the ansible commands. Notice the --version option. devasc@labvm:~/labs/devnet-src/ansible$ ansible usage: ansible [-h] [--version] [-v] [-b] [--become-method BECOME_METHOD] [--become-user BECOME_USER] [-K] [-i INVENTORY] [--list-hosts] [-l SUBSET] [-P POLL_INTERVAL] [-B SECONDS] [-o] [-t TREE] [-k] [--private-key PRIVATE_KEY_FILE] [-u REMOTE_USER] [-c CONNECTION] [-T TIMEOUT] [--ssh-common-args SSH_COMMON_ARGS]

devasc@labvm:~/labs/ansible/ansible-csr1000v$

c.

Use the ansible --version command to display version information. Notice that this lab is using version 2.9.6. Ansible includes certain default files, including a default configuration file, ansible.cfg. devasc@labvm:~/labs/ansible/ansible-csr1000v$ ansible --version ansible 2.9.6 config file = /etc/ansible/ansible.cfg

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 2 of 11

www.netacad.com

Lab - Use Ansible to Back Up and Configure a Device

configured module search path = ['/home/devasc/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules'] ansible python module location = /usr/lib/python3/dist-packages/ansible executable location = /usr/bin/ansible python version = 3.8.2 (default, Apr 27 2020, 15:53:34) [GCC 9.3.0]

devasc@labvm:~/labs/ansible/ansible-csr1000v$

Step 4: Display the default ansible.cfg file. The ansible.cfg file is used by Ansible to set certain default values. These values can be modified. Using the default path displayed in the ansible --version command, display the default configuration file. Notice this is a very long file. You can pipe the output of the cat command to more so that it displays one page at a time. Highlighted are the entries that will be in your ansible.cfg file for this lab. devasc@labvm:~/labs/devnet-src/ansible$ cat /etc/ansible/ansible.cfg | more # config file for ansible -- https://ansible.com/ # =============================================== # # # # #

nearly all parameters can be overridden in ansible-playbook or with command line flags. ansible will read ANSIBLE_CONFIG, ansible.cfg in the current working directory, .ansible.cfg in the home directory or /etc/ansible/ansible.cfg, whichever it finds first

[defaults] # some basic default values... #inventory = /etc/ansible/hosts

# uncomment this to disable SSH key host checking #host_key_checking = False

# # # #

retry files When a playbook fails a .retry file can be created that will be placed in ~/ You can enable this feature by setting retry_files_enabled to True and you can change the location of the files by setting retry_files_save_path

#retry_files_enabled = False

Notice that Ansible shows that the inventory hosts file it will use by default is /etc/ansible/hosts. In a previous step, you edited the inventory hosts file in the ansible-csr1000v directory. In the next step you will edit a new ansible.cfg file which uses the hosts inventory file that you created.

Step 5: Change the location of the ansible.cfg file. a. Ansible will use the config file located in /etc/ansible/ansible.cfg unless there is an ansible.cfg file in the current directory. Change back to the ansible-csr1000v directory. There is already a placeholder ansible.cfg file in this directory. Display the current location of ansible.cfg with the ansible --version command. © 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 3 of 11

www.netacad.com

Lab - Use Ansible to Back Up and Configure a Device

devasc@labvm:~/labs/devnet-src/ansible$ cd ansible-csr1000v/ devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ ansible --version ansible 2.9.6 config file = /home/devasc/labs/devnet-src/ansible/ansible-csr1000v/ansible.cfg

devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ b. Display the file to see that it is empty, except for a comment. You will edit this file in the next step. devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ cat ansible.cfg # Add to this file for the Ansible lab

devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$

Step 6: Edit the ansible.cfg file. Now, you need to edit your /ansible-csr1000v/ansible.cfg file to include the location of your hosts inventory file. Remember, the default config file in /etc/ansible/ansible.cfg uses the inventory file in /etc/ansible/hosts. a. Open the /ansible-csr1000v/ansible.cfg file in VS Code. b. You can remove the comment. Add the following lines to the file and save it. # config file for ansible-csr1000v [defaults] # Use local hosts file in this folder inventory=./hosts host_key_checking = False # Don't worry about RSA Fingerprints retry_files_enabled = False # Do not create them deprecation_warnings = False # Do not show warnings Like Python, the # is used for comments within the ansible.cfg file. If the entry refers to a file name such as inventory=./hosts the comment cannot come after the entry. Ansible treats the # and the comment that follows as part of the filename. Therefore, in these cases, the # comment must be on a separate line. However, variables can have a comment on the same line as shown for host_key_checking and retry_files_enabled. The ansible.cfg file tells Ansible where to find the inventory file and sets certain default parameters. The information you entered in your ansible.cfg file is: •

inventory=./hosts - Your inventory file is the hosts file in the current directory.



host_key_checking = False - The local development environment does not have SSH keys set up. You have set the host_key_checking set to False, which is the default. In a production network, host_key_checking would be set to True.



retry_files_enabled = False - When Ansible has problems running playbooks for a host, it will output the name of the host into a file in the current directory ending in .retry. To prevent clutter, it is common to disable this setting.



deprecation_warnings=False - Deprecation warnings indicate usage of legacy features that are slated for removal in a future release of Ansible. You have disabled this warning.

Step 7: SUMMARY: Your Ansible configuration files. In this Part, you configured Ansible to run in the ansible-csr1000v directory. By default, Ansible uses files in the /etc/ansible directory. The default /etc/ansible/ansible.cfg file indicates that the default inventory file is /etc/ansible/hosts.

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 4 of 11

www.netacad.com

Lab - Use Ansible to Back Up and Configure a Device

However, in this lab you need a hosts file and ansible.cfg file in your ansible-csr1000v directory. •

You edited the hosts file to contain login and IP address information for the CSR1000v router



You edited the ansible.cfg file to use the local hosts file as the inventory file (inventory=./hosts).

In the next Part, you will create a playbook to tell Ansible what to do.

Part 3: Use Ansible to Back up a Configuration In this Part, you will create an Ansible playbook that will automate the process of backing up the configuration of the CSR1000v. Playbooks are at the center of Ansible. When you want Ansible to get information or perform an action on a device or group of devices, you run a playbook to get the job done. An Ansible playbook is a YAML file containing one or more plays. Each play is a collection of tasks. •

A play is a matching set of tasks to a device or group of devices.



A task is a single action that references a module to run along with any input arguments and actions. These tasks can be simple or complex depending on the need for permissions, the order to run the tasks, and so on.

A playbook may also contain roles. A role is a mechanism for breaking a playbook into multiple components or files, simplifying the playbook and making it easier to reuse. For example, the common role is used to store tasks that can be used across all of your playbooks. Roles are beyond the scope of this lab. The Ansible YAML playbook includes objects, lists and modules. •

A YAML object is one or more key value pairs. Key value pairs are separated by a colon without the use of quotation marks, for example hosts: CSR1kv.



An object can contain other objects such as a list. YAML uses lists or arrays. A hypen “-“ is used for each element in the list.



Ansible ships with a number of modules (called the module library) that can be executed directly on remote hosts or through playbooks. An example is the ios_command module used to send commands to an IOS device and return the results. Each task typically consists of one or more Ansible modules.

You run an Ansible playbook using the ansible-playbook command, for example: ansible-playbook backup_cisco_router_playbook.yaml -i hosts The ansible-playbook command uses parameters to specify: •

The playbook you want to run (backup_cisco_router_playbook.yaml)



The inventory file and its location (-i hosts).

Step 1: Create your Ansible playbook. The Ansible playbook is a YAML file. Make sure you use the proper YAML indentation. Every space and dash is significant. You may lose some formatting if you copy and paste the code in this lab. a. In VS Code, create a new file in the ansible-csr1000v directory with the following name: backup_cisco_router_playbook.yaml b. Add the following information to the file. --- name: AUTOMATIC BACKUP OF RUNNING-CONFIG hosts: CSR1kv gather_facts: false connection: local

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 5 of 11

www.netacad.com

Lab - Use Ansible to Back Up and Configure a Device

tasks: - name: DISPLAYING THE RUNNING-CONFIG ios_command: commands: - show running-config register: config - name: SAVE OUTPUT TO ./backups/ copy: content: "{{ config.stdout[0] }}" dest: "backups/show_run_{{ inventory_hostname }}.txt"

Step 2: Examine your Ansible playbook. The playbook you have created contains one play with two tasks. The following is an explanation of your playbook: •

--- This is at the beginning of every YAML file, which indicates to YAML that this is a separate document. Each file may contain multiple documents separated by ---



name: AUTOMATIC BACKUP OF RUNNING-CONFIG - This is the name of the play.



hosts: CSR1kv - This is the alias of the previously configured hosts file. By referring to this alias in your playbook, the playbook can use all the parameters associated with this inventory file entry which includes the username, password, and IP address of the device.



gather_facts: false - Ansible was originally designed to work with Linux servers, copying Python modules to the servers for task automation. This is not necessary when working with networking devices.



connection: local - Specifies that you are not using SSH, therefore the connection is local.



tasks: - This keyword indicates one or more tasks to be performed.

The first task is to display the running-config. •

- name: DISPLAYING THE RUNNING-CONFIG - Name of the task.



ios_command: - This is an Ansible module that is used to send commands to an IOS device and return the results read from the device. However, it does not support configuration commands. The ios_config module is used for this purpose, as you will see in the next Part of this lab. Note: In the Linux terminal, you can use the ansible-doc module_name command to view the manual pages for any module and the parameters associated with that module. (e.g. ansible-doc ios_command)



commands: - This parameter is associated with the ios_command module. It is used to list IOS commands in the playbook that are to be sent to the remote IOS device. The resulting output from the command is returned.



- show running-config - This is the Cisco IOS command sent using the ios_command module.



register: config - Ansible includes registers used to capture output of a task to a variable. This entry specifies that the output from the previous show running-config command will be stored in the variable config.

The second task is to save the output: •

- name: SAVE OUTPUT TO ./backups/ - Name of the task

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 6 of 11

www.netacad.com

Lab - Use Ansible to Back Up and Configure a Device



copy: - This is an Ansible module used to copy files to a remote location. There are two parameters associated with this module: o

content: "{{ config.stdout[0] }}" - The specified value for this parameter is the data stored in the config variable, the Ansible register variable used in the previous task. Standard output (stdout) is the default file descriptor where a process can write output used in Unix-like operating systems, such as Linux and Mac OS X.

o

dest: "backups/show_run_{{ inventory_hostname }}.txt" - This is the path and file name to where the file should be copied. The inventory_hostname variable is an Ansible "magic variable" that automatically receives the hostname as configured in the hosts file. In your case, recall that this is CSR1kv. This parameter results in a file show_run_CSR1kv.txt stored in the backups directory. The file will contain the output of the show running-config command. You will create the backups directory in the next step

Step 3: Run the Ansible backup Playbook. a. In Part 1, you started the CSR1000v VM. Ping it to verify you can access it. Enter Ctrl+ C to abort the ping. devasc@labvm:~/labs/ansible/ansible-csr1000v$ ping 192.168.56.101 PING 192.168.56.101 (192.168.56.101) 56(84) bytes of data. 64 bytes from 192.168.56.101: icmp_seq=1 ttl=63 time=0.913 ms 64 bytes from 192.168.56.101: icmp_seq=2 ttl=63 time=0.875 ms ^C --- 192.168.56.101 ping statistics --2 packets transmitted, 2 received, 0% packet loss, time 1000ms rtt min/avg/max/mdev = 0.875/0.894/0.913/0.019 ms

devasc@labvm:~/labs/ansible/ansible-csr1000v$ b. Create the backups directory. As indicated in the last line of your playbook, this is the directory where the backup configuration file will be stored. devasc@labvm:~/labs/ansible/ansible-csr1000v$ mkdir backups c.

Now you can run the Ansible playbook using the ansible-playbook command: devasc@labvm:~/labs/ansible/ansible-csr1000v$ ansible-playbook backup_cisco_router_playbook.yaml PLAY [AUTOMATIC BACKUP OF RUNNING CONFIG] ***************************************** TASK [DISPLAYING THE RUNNING-CONFIG] ********************************************** ok: [CSR1kv] TASK [SAVE OUTPUT TO ./backups/] ************************************************** changed: [CSR1kv] PLAY RECAP ************************************************************************ CSR1kv : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

devasc@labvm:~/labs/ansible/ansible-csr1000v$ Note: In many examples you will see the playbook run using the -i inventory-filename option. For example:

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 7 of 11

www.netacad.com

Lab - Use Ansible to Back Up and Configure a Device

devasc@labvm:~/labs/ansible/ansible-csr1000v$ ansible-playbook backup_cisco_router_playbook.yaml -i hosts This option tells Ansible the location and name of the inventory file, the list of devices the playbook will use. This option is not necessary because you configured the inventory file name and location in your local ansible.cfg file: inventory=./hosts. You can use the -i inventory-filename option to override the information in the ansible.cfg file. The PLAY RECAP should display ok=2 changed=1 indicating a successful playbook execution. If your Ansible playbook fails, some of the things to check in your playbook are: o

Make sure your hosts and ansible.cfg files are correct.

o

Make sure the YAML indentation is correct.

o

Make sure your IOS command is correct.

o

Check all the Ansible playbook syntax.

o

Verify you can ping the CSR1000v.

If you continue to have problems: o

Try typing one line at a time and running the playbook each time.

o

Compare your file with the solutions playbook in the ansible_solutions directory.

Step 4: Verify the backup file has been created. In VS Code, open the backups folder and open the show_run_CSR1kv.txt file. You can also use the terminal window to cat the file with cat backups/show_run_CSR1kv.txt. You now have a backup of the CSR1000v configuration. devasc@labvm:~/labs/ansible/ansible-csr1000v/backups$ cat show_run_CSR1kv.txt Building configuration... Current configuration : 4004 bytes ! ! Last configuration change at 23:57:14 UTC Sun May 17 2020 ! version 16.9 service timestamps debug datetime msec service timestamps log datetime msec platform qfp utilization monitor load 80 no platform punt-keepalive disable-kernel-core platform console virtual ! hostname CSR1kv !

Part 4: Use Ansible to Configure a Device In this Part, you will create another Ansible playbook to configure IPv6 addressing on the CSR1000v router.

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 8 of 11

www.netacad.com

Lab - Use Ansible to Back Up and Configure a Device

Step 1: View your hosts inventory file. a. Re-examine your hosts inventory file. As a reminder, this file contains the alias CSR1kv and three inventory variables for the username, password, and host IP address. The playbook for this Part will also use this file and the ansible.cfg file you created early in the lab. devasc@labvm:~/labs/ansible/ansible-csr1000v$ cat hosts # Enter the hosts or devices for Ansible playbooks CSR1kv ansible_user=cisco ansible_password=cisco123! ansible_host=192.168.56.101 devasc@labvm:~/labs/ansible/ansible-csr1000v$

Step 2: Create a new playbook. a. In VS Code, create a new file in the ansible-csr1000v directory with the following name: cisco_router_ipv6_config_playbook.yaml b. Add the following information to the file. Make sure you use the proper YAML indentation. Every space and dash is significant. You may lose some formatting if you copy and paste. --- name: CONFIGURE IPv6 ADDRESSING hosts: CSR1kv gather_facts: false connection: local tasks: - name: SET IPv6 ADDRESS ios_config: parents: "interface GigabitEthernet1" lines: - description IPv6 ADDRESS - ipv6 address 2001:db8:acad:1::1/64 - ipv6 address fe80::1:1 link-local - name: SHOW IPv6 INTERFACE BRIEF ios_command: commands: - show ipv6 interface brief register: output - name: SAVE OUTPUT ./ios_configurations/ copy: content: "{{ output.stdout[0] }}" dest: "ios_configurations/IPv6_output_{{ inventory_hostname }}.txt"

Step 3: Examine your Ansible playbook. Much of this playbook is similar to the playbook you created in the previous Part. The main difference is the first task SET IPv6 ADDRESS. The following is a brief description of the items in the task:

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 9 of 11

www.netacad.com

Lab - Use Ansible to Back Up and Configure a Device



ios_config: - This is an Ansible module used to configure an IOS device. You can use the ansible-doc ios_config command to see the details for the parents and lines parameters used in this playbook.



parents: "interface GigabitEthernet1" - This parameter indicates the IOS interface configuration mode.



lines: - An ordered set of IOS commands are configured in this section, specifying the IPv6 addressing information for the GigabitEthernet1 interface.

The rest of the playbook is similar to the tasks in the previous Part. The second task uses the ios_command module and the command show ipv6 interface brief to display output and send it to the register output. The last task saves the information in the register output to a file IPv6_output_CSR1kv.txt in the ios_configurations subdirectory.

Step 4: Run the Ansible playbook to configure IPv6 addressing on the CSR1000v VM. a. In Part 1, you started the CSR1000v VM. Ping it to verify you can access it. Enter Ctrl+ C to abort the ping. devasc@labvm:~/labs/ansible/ansible-csr1000v$ ping 192.168.56.101 PING 192.168.56.101 (192.168.56.101) 56(84) bytes of data. 64 bytes from 192.168.56.101: icmp_seq=1 ttl=63 time=0.913 ms 64 bytes from 192.168.56.101: icmp_seq=2 ttl=63 time=0.875 ms ^C --- 192.168.56.101 ping statistics --2 packets transmitted, 2 received, 0% packet loss, time 1000ms rtt min/avg/max/mdev = 0.875/0.894/0.913/0.019 ms devasc@labvm:~/labs/ansible/ansible-csr1000v$

b. Create the directory ios_configurations. As indicated in the last line of your playbook, this is the directory where the output for the show ipv6 interface brief command will be stored. devasc@labvm:~/labs/ansible/ansible-csr1000v$ mkdir ios_configurations c.

Now you can run the Ansible playbook using the ansible-playbook command. The -v verbose option can be used to display the tasks being performed in the playbook. devasc@labvm:~/labs/ansible/ansible-csr1000v$ ansible-playbook -v cisco_router_ipv6_config_playbook.yaml Using /home/devasc/labs/ansible-csr1000v/ansible.cfg as config file PLAY [CONFIGURE IPv6 ADDRESSING] *********************************************** TASK [SET IPv6 ADDRESS] ******************************************************** changed: [CSR1kv] => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"}, "banners": {}, "changed": true, "commands": ["interface GigabitEthernet1", "description IPv6 ADDRESS", "ipv6 address 2001:db8:acad:1::1/64", "ipv6 address fe80::1:1 link-local"], "updates": ["interface GigabitEthernet1", "description IPv6 ADDRESS", "ipv6 address 2001:db8:acad:1::1/64", "ipv6 address fe80::1:1 link-local"]} TASK [SHOW IPv6 INTERFACE BRIEF] *********************************************** ok: [CSR1kv] => {"changed": false, "stdout": ["GigabitEthernet1 [up/up]\n FE80::1:1\n 2001:DB8:ACAD:1::1"], "stdout_lines": [["GigabitEthernet1 [up/up]", " FE80::1:1", " 2001:DB8:ACAD:1::1"]]}

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 10 of 11

www.netacad.com

Lab - Use Ansible to Back Up and Configure a Device

TASK [SAVE OUTPUT ./ios_configurations/] *************************************** ok: [CSR1kv] => {"changed": false, "checksum": "60784fbaae4bd825b7d4f121c450effe529b553c", "dest": "ios_configurations/IPv6_output_CSR1kv.txt", "gid": 900, "group": "devasc", "mode": "0664", "owner": "devasc", "path": "ios_configurations/IPv6_output_CSR1kv.txt", "size": 67, "state": "file", "uid": 900} PLAY RECAP ********************************************************************* CSR1kv : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

devasc@labvm:~/labs/ansible/ansible-csr1000v$ The first time you run the playbook, the PLAY RECAP should display ok=3 changed=2 and failed=0 indicating a successful execution. These values may be different if you run the playbook again.

Step 5: Verify the file of the output has been created. In VS Code, open the ios_configurations folder and click the IPv6_output_CSR1kv.txt file. You can also use the terminal window to view the file with cat ios_configurations/IPv6_output_CSR1kv.txt. You now have a backup of the CSR1000v configuration. devasc@labvm:~/labs/devnet-src/ansible/ansible-csr1000v$ cat ios_configurations/IPv6_output_CSR1kv.txt GigabitEthernet1 [up/up] FE80::1:1 2001:DB8:ACAD:1::1 devasc@labvm:~/labs/ansible-csr1000v/ios_configurations$ End of document

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 11 of 11

www.netacad.com

LAB 7.4.8 Lab - Use Ansible to Automate Installing a Web Server (Instructor Version) Instructor Note: Red font color or gray highlights indicate text that appears in the instructor copy only.

Objectives Part 1: Launch the DEVASC and CSR1000v VMs Part 2: Configure Ansible Part 3 Verify Communications with the Local Webserver Part 4: Create Ansible Playbooks to Automate Webserver Installation Part 5: Add Options to Your Ansible Playbook for Apache Web Servers

Background / Scenario In this lab, you will first configure Ansible so that it can communicate with a webserver application. You will then create a playbook that will automate the process of installing Apache on the webserver. You will also create a customized playbook that installs Apache with specific instructions.

Required Resources •

1 PC with operating system of your choice



Virtual Box or VMWare



DEVASC Virtual Machine

Instructions Part 1: Launch the DEVASC and CSR1000v VMs If you have not already completed the Lab - Install the DEVASC-LAB, do so now. If you have already completed that lab, launch the DEVASC VM now.

Part 2: Configure Ansible The DEVASC VM comes preinstalled with a number of dummy IPv4 addresses you can use for various scenarios and simulations. In this Part, you will configure Ansible to use one of the dummy IPv4 address for a local webserver.

Step 1: Open a terminal in the DEVASC-LABVM. Step 2: Enable the SSH server. The SSH server is disabled in the DEVASC-LABVM, along with other services that are typically not required. Start it with the following command. devasc@labvm:~$ sudo systemctl start ssh devasc@labvm:~$ Note: The SSH server and sshpass utility have already been installed in your VM. For your reference, these are installed using the following commands:

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 1 of 9

www.netacad.com

Lab - Use Ansible to Automate Installing a Web Server

Install SSH devasc@labvm:~$ sudo apt-get install openssh-server Install sshpass devasc@labvm:~$ sudo apt-get install sshpass

Step 3: Open the ansible directory in VS Code. a. Open VS Code. b. Click File > Open Folder... and navigate to the /labs/devnet-src/ansible folder. c.

Click OK.

d. The two subdirectories for the Ansible labs are now loaded in the VS Code EXPLORER pane for your convenience. In this lab, you will work with the ansible-apache directory.

Step 4: Edit the Ansible inventory file a. Open the hosts file in the ansible-apache directory. b. Add the following lines to the hosts file and save. [webservers] 192.0.2.3 ansible_ssh_user=devasc ansible_ssh_pass=Cisco123!

c.

The credentials devasc and Cisco123! are admin credentials for the DEVASC VM. The IPv4 address you will use for this lab is 192.0.2.3. This is a static IPv4 address on the VM under the dummy0 interface, as shown in the output for the ip addr command. devasc@labvm:~/labs/devnet-src/ansible$ ip addr 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: enp0s3: mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 08:00:27:97:ae:11 brd ff:ff:ff:ff:ff:ff inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic enp0s3 valid_lft 45882sec preferred_lft 45882sec inet6 fe80::a00:27ff:fe97:ae11/64 scope link valid_lft forever preferred_lft forever 3: dummy0: mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000 link/ether a6:44:a7:e8:6a:9e brd ff:ff:ff:ff:ff:ff inet 192.0.2.1/32 scope global dummy0 valid_lft forever preferred_lft forever inet 192.0.2.2/32 scope global dummy0 valid_lft forever preferred_lft forever inet 192.0.2.3/32 scope global dummy0 valid_lft forever preferred_lft forever inet 192.0.2.4/32 scope global dummy0 valid_lft forever preferred_lft forever inet 192.0.2.5/32 scope global dummy0

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 2 of 9

www.netacad.com

Lab - Use Ansible to Automate Installing a Web Server

valid_lft forever preferred_lft forever inet6 fe80::a444:a7ff:fee8:6a9e/64 scope link valid_lft forever preferred_lft forever

devasc@labvm:~/labs/devnet-src/ansible$

Step 5: Edit the ansible.cfg file. a. In the ansible-apache subdirectory, Open the ansible.cfg. b. You can remove the comment. Add the following lines to the file and save it. The ansible.cfg file tells Ansible where to find the inventory file and sets certain default parameters. [defaults] # Use local hosts file in this folder inventory=./hosts # Don't worry about RSA Fingerprints host_key_checking = False # Do not create retry files retry_files_enabled = False

Part 3: Verify Communications with the Local Webserver In this Part, you will verify that Ansible can send commands to the local webserver.

Step 1: Use the ping module to verify that Ansible can ping the webserver. Use the Ansible ping module to verify communications with the devices listed within the webservers group of your hosts inventory file. devasc@labvm:~/labs/ansible/ansible-apache$ ansible webservers -m ping 192.0.2.3 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python3" }, "changed": false, "ping": "pong" } devasc@labvm:~/labs/ansible/ansible-apache$

If multiple devices were listed under the webservers group in your hosts inventory file, the output would indicate similar information for each device.

Step 2: Use the command module to verify Ansible can communicate with the webserver. Use the Ansible command module to verify communications with the devices listed within the webservers group of your hosts inventory file. In this example you send the argument -a "/bin/echo hello world" to ask the local webserver to respond with “hello world”. devasc@labvm:~/labs/ansible/ansible-apache$ ansible webservers -m command -a "/bin/echo hello world" 192.0.2.3 | CHANGED | rc=0 >> hello world devasc@labvm:~/labs/ansible/ansible-apache$

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 3 of 9

www.netacad.com

Lab - Use Ansible to Automate Installing a Web Server

Part 4: Create Ansible Playbooks to Automate Webserver Installation In this Part, you will create two Ansible playbooks. The first playbook will automate the echo test you did in the previous Part. Imagine you are bringing a hundred webservers online. The [webserver] group in the hosts file would list all the necessary information for each webserver. You can then use a simple playbook to verify communications with all of them with one command. The second playbook you will create will automate the installation of Apache webserver software.

Step 1: Create your Ansible playbook to test your webserver group. In this step you will create an Ansible playbook to perform the same echo command. a. In VS Code, create a new file in the ansible-apache directory with the following name: test_apache_playbook.yaml b. Add the following information to the file. Make sure you use the proper YAML indentation. Every space and dash is significant. You may lose some formatting if you copy and paste. --- hosts: webservers tasks: - name: run echo command command: /bin/echo hello world

Step 2: Run the Ansibl playbook to test your webserver group. Run the Ansible playbook using the ansible-playbook command using the -v verbose option. You should see output similar to the following. devasc@labvm:~/labs/ansible/ansible-apache$ ansible-playbook -v test_apache_playbook.yaml Using /home/devasc/labs/ansible/ansible-apache/ansible.cfg as config file PLAY [webservers] ************************************************************** TASK [Gathering Facts] ********************************************************* ok: [192.0.2.3] TASK [run echo command] ******************************************************** changed: [192.0.2.3] => {"changed": true, "cmd": ["/bin/echo", "hello", "world"], "delta": "0:00:00.002062", "end": "2020-05-20 21:35:32.346595", "rc": 0, "start": "2020-05-20 21:35:32.344533", "stderr": "", "stderr_lines": [], "stdout": "hello world", "stdout_lines": ["hello world"]} PLAY RECAP ********************************************************************* 192.0.2.3 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 devasc@labvm:~/labs/ansible/ansible-apache$

Step 3: Create your Ansible playbook to install Apache. a. In VS Code, create a new file in the ansible-apache directory with the following name: install_apache_playbook.yaml

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 4 of 9

www.netacad.com

Lab - Use Ansible to Automate Installing a Web Server

b. Add the following information to the file. Make sure you use the proper YAML indentation. Every space and dash is significant. You may lose some formatting if you copy and paste. The highlighted text is explained in the next step. --- hosts: webservers become: yes tasks: - name: INSTALL APACHE2 apt: name=apache2 update_cache=yes state=latest - name: ENABLED MOD_REWRITE apache2_module: name=rewrite state=present notify: - RESTART APACHE2 handlers: - name: RESTART APACHE2 service: name=apache2 state=restarted

Step 4: Examine your Ansible playbook. The following is an explanation of some of the significant lines in your playbook: •

hosts: webservers - This references the webservers group of devices in your hosts inventory file. This playbook will be run for all the devices with this group.



become: yes - The become keyword activates sudo command execution, which will allow tasks such as installing applications.



apt: - The apt module is used to manage packages and application installations on Linux.



handlers: - Handlers are similar to a task but are not run automatically. They are called by a task. Notice that the task ENABLED MOD_REWRITE calls the handler RESTART APACHE2.

Step 5: Run the Ansible backup to install Apache. Run the Ansible playbook using the ansible-playbook command using the -v verbose option. The first time Apache installed on your VM, the task INSTALL APACHE2 will take anywhere from 30 seconds to a few minutes depending on your internet speed. devasc@labvm:~/labs/ansible/ansible-apache$ ansible-playbook -v install_apache_playbook.yaml Using /home/devasc/labs/ansible/ansible-apache/ansible.cfg as config file PLAY [webservers] ************************************************************** TASK [Gathering Facts] ********************************************************* ok: [192.0.2.3] TASK [INSTALL APACHE2] ********************************************************* ok: [192.0.2.3] => {"cache_update_time": 1590010855, "cache_updated": true, "changed": false} TASK [ENABLED MOD_REWRITE] ***************************************************** ok: [192.0.2.3] => {"changed": false, "result": "Module rewrite enabled"} © 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 5 of 9

www.netacad.com

Lab - Use Ansible to Automate Installing a Web Server

PLAY RECAP ********************************************************************* 192.0.2.3 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 = devasc@labvm:~/labs/ansible/ansible-apache$

The PLAY RECAP should display ok and failed=0 indicating a successful playbook execution.

Step 6: Verify Apache has been installed. a. Use the following command to verify that Apache is now installed. Press "q" to quit. devasc@labvm:~/labs/ansible/ansible-apache$ sudo systemctl status apache2 ● apache2.service - The Apache HTTP Server Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor prese> Active: active (running) since Wed 2020-05-20 03:48:49 UTC; 10min ago Docs: https://httpd.apache.org/docs/2.4/ Process: 8201 ExecStart=/usr/sbin/apachectl start (code=exited, status=0/SU> Main PID: 8225 (apache2) Tasks: 55 (limit: 4654) Memory: 5.3M CGroup: /system.slice/apache2.service ├─8225 /usr/sbin/apache2 -k start ├─8229 /usr/sbin/apache2 -k start └─8230 /usr/sbin/apache2 -k start

devasc@labvm:~/labs/ansible/ansible-apache$ b. Open the Chromium web browser and enter the IPv4 address for your new server, 192.0.2.3, to see the default Apache2 web page.

Part 5: Add Options to Your Ansible Playbook for Apache Web Servers In a production environment, the Apache2 default installation is typically customized for the specific features needed by the organization. An Ansible playbook can help automate these configuration tasks, as well. In this part, you will customize your playbook by specifying that the Apache server use a different port number.

Step 1: Create your Ansible playbook for installing Apache. a. In VS Code, create a new file in the ansible-apache directory with the following name: install_apache_options_playbook.yaml b. Add the following information to the file. Make sure you use the proper YAML indentation. Every space and dash is significant. You may lose some formatting if you copy and paste. --- hosts: webservers become: yes tasks: - name: INSTALL APACHE2 apt: name=apache2 update_cache=yes state=latest - name: ENABLED MOD_REWRITE apache2_module: name=rewrite state=present

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 6 of 9

www.netacad.com

Lab - Use Ansible to Automate Installing a Web Server

notify: - RESTART APACHE2 - name: APACHE2 LISTEN ON PORT 8081 lineinfile: dest=/etc/apache2/ports.conf regexp="^Listen 80" line="Listen 8081" state=present notify: - RESTART APACHE2 - name: APACHE2 VIRTUALHOST ON PORT 8081 lineinfile: dest=/etc/apache2/sites-available/000-default.conf regexp="^" line="" state=present notify: - RESTART APACHE2 handlers: - name: RESTART APACHE2 service: name=apache2 state=restarted This playlist is very similar to the previous one with the addition of two tasks that have the webservers listen on port 8081 instead of port 80. The lineinfile module is used to replace existing lines in the /etc/apache2/ports.conf and /etc/apache2/sites-available/000-default.conf files. You can search the Ansible documentation for more information on the lineinfile module.

Step 2: Examine the two files that will be modified by the playbook. Display the files /etc/apache2/ports.conf and /etc/apache2/sites-available/000-default.conf. Notice the webserver is currently listening on port 80. devasc@labvm:~/labs/ansible/ansible-apache$ cat /etc/apache2/ports.conf # If you just change the port or add more ports here, you will likely also # have to change the VirtualHost statement in # /etc/apache2/sites-enabled/000-default.conf Listen 80

Listen 443

devasc@labvm:~/labs/ansible/ansible-apache$ cat /etc/apache2/sitesavailable/000-default.conf

# The ServerName directive sets the request scheme, hostname and port that # the server uses to identify itself. This is used when creating # redirection URLs. In the context of virtual hosts, the ServerName

devasc@labvm:~/labs/ansible/ansible-apache$

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 7 of 9

www.netacad.com

Lab - Use Ansible to Automate Installing a Web Server

Step 3: Run the Ansible Playbook. a. Run the Ansible playbook using the ansible-playbook command. devasc@labvm:~/labs/ansible/ansible-apache$ ansible-playbook install_apache_options_playbook.yaml PLAY [webservers] ************************************************************** TASK [Gathering Facts] ********************************************************* ok: [192.0.2.3] TASK [INSTALL APACHE2] ********************************************************* ok: [192.0.2.3] TASK [ENABLED MOD_REWRITE] ***************************************************** ok: [192.0.2.3] TASK [APACHE2 LISTEN ON PORT 8081] ********************************************* ok: [192.0.2.3] TASK [APACHE2 VIRTUALHOST ON PORT 8081] **************************************** ok: [192.0.2.3] PLAY RECAP ********************************************************************* 192.0.2.3 : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 devasc@labvm:~/labs/ansible/ansible-apache$

Step 4: Verify that Apache has been installed. a. View the files /etc/apache2/ports.conf and /etc/apache2/sites-available/000-default.conf again. Notice that the playbook modified these files to listen on port 8081. devasc@labvm:~/labs/ansible/ansible-apache$ cat /etc/apache2/ports.conf # If you just change the port or add more ports here, you will likely also # have to change the VirtualHost statement in # /etc/apache2/sites-enabled/000-default.conf Listen 8081

Listen 443

Listen 443

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet devasc@labvm:~/labs/ansible/ansible-apache$

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 8 of 9

www.netacad.com

Lab - Use Ansible to Automate Installing a Web Server

devasc@labvm:~/labs/ansible/ansible-apache$ cat /etc/apache2/sitesavailable/000-default.conf

# The ServerName directive sets the request scheme, hostname and port that # the server uses to identify itself. This is used when creating # redirection URLs. In the context of virtual hosts, the ServerName

devasc@labvm:~/labs/ansible/ansible-apache$

b. Open the Chromium web browser and enter the IPv4 address for your new server. But this time specify 8081 as the port number, 192.0.2.3:8081, to see the default Apache2 web page. Note: Although you can see in the ports.conf file that Apache2 is also listening on port 443, this is for secure HTTP. You have not yet configured Apache2 for secure access. This, of course, would be added to your Ansible playbook, but is beyond the scope of this course. End of document

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 9 of 9

www.netacad.com

LAB 7.6.3 Lab - Automated Testing Using pyATS and Genie (Instructor Version) Instructor Note: Red font color or gray highlights indicate text that appears in the instructor copy only.

Objectives Part 1: Launch the DEVASC VM Part 2: Create a Python Virtual Environment Part 3: Use the pyATS Testing Library Part 4: Use Genie to Parse IOS Command Output Part 5: Use Genie to Compare Configurations Part 6: Lab Cleanup and Further Investigation

Background / Scenario In this lab, you will explore the fundamentals pyATS (pronounced "py" followed by each letter individually, "A", "T". "S") and Genie. The pyATS tool is an end-to-end testing ecosystem, specializing in data-driven and reusable testing, and engineered to be suitable for Agile, rapid development iterations. Extensible by design, pyATS enables developers start with small, simple, and linear test cases, and scale towards large, complex, and asynchronous test suites. Genie extends and builds on pyATS to be used in a networking environment. Examples of features Genie provides include: •

device connectivity, parsers, and APIs



platform-agnostic Python object models for features such as OSPF and BGP



pool of reusable test cases



YAML-driven test-runner engine

Required Resources •

1 PC with operating system of your choice



Virtual Box or VMWare



DEVASC Virtual Machine



CSR1kv Virtual Machine

Instructions Part 1: Launch the DEVASC VM If you have not already completed the Lab - Install the Virtual Machine Lab Environment, do so now. If you have already completed that lab, launch the DEVASC VM now.

Part 2: Create a Python Virtual Environment In this part, you will create a Python virtual environment called a Python virtual environment or "venv".

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 1 of 21

www.netacad.com

Lab - Automated Testing Using pyATS and Genie

Step 1: Open a terminal in the DEVASC-LABVM. Double-click the Terminal Emulator icon on the desktop.

Step 2: Creating Python virtual environment (venv). The pyATS tool is best installed for individual work within a venv. A venv environment is copied from your Python base environment but kept separate from it. This enables you to avoid installing software that might permanently change the overall state of your computer. The venv environment was covered in detail in the Lab - Explore Python Development Tools earlier in the course. a. Create a pyats directory and change to that directory. You can use the characters && to combine the two commands on one line. devasc@labvm:~$ mkdir labs/devnet-src/pyats && cd labs/devnet-src/pyats devasc@labvm:~/labs/devnet-src/pyats$ b. Create a new Python virtual environment that creates the directory csr1kv in the pyats directory. devasc@labvm:~/labs/devnet-src/pyats$ python3 -m venv csr1kv Note: You can also use a period "." instead of a name of a directory if you want to create a venv environment in the current directory.

Step 3: Review your Python virtual environment (venv). a. Change directories to your new "target" directory csr1kv and list the files. Venv creates a self-contained directory tree (test-project) that contains a Python installation for a particular version of Python, plus a number of additional packages. It also creates a bin subdirectory containing a copy of the Python binary. Notice in particular the bin subdirectory and the pyvenv.cfg files that were created. devasc@labvm:~/labs/devnet-src/pyats$ cd csr1kv devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ ls -l total 20 drwxrwxr-x drwxrwxr-x drwxrwxr-x lrwxrwxrwx -rw-rw-r-drwxrwxr-x

2 2 3 1 1 3

devasc devasc devasc devasc devasc devasc

devasc devasc devasc devasc devasc devasc

4096 4096 4096 3 69 4096

May May May May May May

31 31 31 31 31 31

16:07 16:07 16:07 16:07 16:07 16:07

bin include lib lib64 -> lib pyvenv.cfg share

devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ b. Examine the contents of the pyvenv.cfg file. Notice that this file points to the location of your Python installation in /usr/bin. devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ cat pyvenv.cfg home = /usr/bin include-system-site-packages = false version = 3.8.2

devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ c.

A symbolic link (also known as a symlink) is a special type of file that serves as a reference to another file or directory. To get a better understanding of the venv and how it uses symbolic links, list Python files in the /usr/bin directory referenced in the pyvenv.cfg file. Use the ls number one option (-1) to list the files each on one line. devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ ls -1 /usr/bin/python* /usr/bin/python3 /usr/bin/python3.8

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 2 of 21

www.netacad.com

Lab - Automated Testing Using pyATS and Genie

/usr/bin/python3.8-config /usr/bin/python3-config /usr/bin/python-argcomplete-check-easy-install-script3 /usr/bin/python-argcomplete-tcsh3

devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ d. Now examine the contents of the venv-created bin subdirectory. Notice there are two files in this subdirectory, both of which are symlinks. In this case, it is a link to the Python binaries in /usr/bin. Symlinks are used to link libraries and make sure files there have consistent access to these files without having to move or create a copy of the original file. There is also a file, activate, that will be discussed next. devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ ls -l bin total 44 -rw-r--r--rw-r--r--rw-r--r--rw-r--r--rwxrwxr-x -rwxrwxr-x -rwxrwxr-x -rwxrwxr-x -rwxrwxr-x lrwxrwxrwx lrwxrwxrwx

1 1 1 1 1 1 1 1 1 1 1

devasc devasc devasc devasc devasc devasc devasc devasc devasc devasc devasc

devasc devasc devasc devasc devasc devasc devasc devasc devasc devasc devasc

2225 1277 2429 8471 267 267 258 258 258 7 16

May May May May May May May May May May May

31 31 31 31 31 31 31 31 31 31 31

16:07 16:07 16:07 16:07 16:07 16:07 16:07 16:07 16:07 16:07 16:07

activate activate.csh activate.fish Activate.ps1 easy_install easy_install-3.8 pip pip3 pip3.8 python -> python3 python3 -> /usr/bin/python3

devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ e. Launch the virtual environment using bin/activate. Notice your prompt is now preceded with (csr1kv). All the commands done from this point on are within this venv. devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ source bin/activate (csr1kv) devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ Note: The deactivate command is used to exit the venv environment and return to the normal shell environment.

Part 3: Use the pyATS Testing Library In this part, you will use pyATS, a python testing library.

Step 1: Installing pyATS. Install pyATS using pip3. This will take a few minutes. During installation you may see some errors. These can usually be ignored as long as pyATS can be verified as shown in the next step. (csr1kv) devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ pip3 install pyats[full] Collecting pyats[full] Downloading pyats-20.4-cp38-cp38-manylinux1_x86_64.whl (2.0 MB)

(csr1kv) devasc@labvm:~/labs/devnet-src/pyats/csr1kv$

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 3 of 21

www.netacad.com

Lab - Automated Testing Using pyATS and Genie

Step 2: Verifying pyATS. Verify that pyATS was successfully installed using the pyats --help command. Notice you can get additional help on any pyats command with the pyats --help command. (csr1kv) devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ pyats --help Usage: pyats [options] Commands: create diff dnac learn logs parse run secret shell pickled data validate version General Options: -h, --help

create scripts and libraries from template Command to diff two snapshots saved to file or directory Command to learn DNAC features and save to file (Prototype) Command to learn device features and save to file command enabling log archive viewing in local browser Command to parse show commands runs the provided script and output corresponding results. utilities for working with secret strings. enter Python shell, loading a pyATS testbed file and/or utlities that helps to validate input files commands related to version display and manipulation

Show help

Run 'pyats --help' for more information on a command.

(csr1kv) devasc@labvm:~/labs/devnet-src/pyats/csr1kv$

Step 3: Clone and examine the pyATS sample scripts from GitHub. a. Clone the Github pyATS sample scripts repository CiscoTestAutomation. (csr1kv) devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ git clone https://github.com/CiscoTestAutomation/examples Cloning into 'examples'... remote: Enumerating objects: 35, done. remote: Counting objects: 100% (35/35), done. remote: Compressing objects: 100% (31/31), done. remote: Total 658 (delta 11), reused 18 (delta 4), pack-reused 623 Receiving objects: 100% (658/658), 1.00 MiB | 4.82 MiB/s, done. Resolving deltas: 100% (338/338), done.

(csr1kv) devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ b. Verify the copy was successful by listing the files in the current directory. Notice there is a new subdirectory example. (csr1kv) devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ ls -l total 24 drwxrwxr-x 2 devasc devasc drwxrwxr-x 21 devasc devasc drwxrwxr-x 2 devasc devasc drwxrwxr-x 3 devasc devasc lrwxrwxrwx 1 devasc devasc

4096 4096 4096 4096 3

May May May May May

31 31 31 31 31

16:07 16:47 16:07 16:07 16:07

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

bin examples include lib lib64 -> lib

Page 4 of 21

www.netacad.com

Lab - Automated Testing Using pyATS and Genie

-rw-rw-r-drwxrwxr-x

1 devasc devasc 69 May 31 16:07 pyvenv.cfg 3 devasc devasc 4096 May 31 16:07 share

(csr1kv) devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ c.

List the files in the examples subdirectory. Notice there is a subdirectory, basic, along with a several other files. (csr1kv) devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ ls -l examples total 88 drwxrwxr-x 3 devasc devasc drwxrwxr-x 2 devasc devasc

drwxrwxr-x 2 devasc devasc

4096 May 31 16:47 abstraction_example 4096 May 31 16:47 basic 4096 May 31 16:47 uids

(csr1kv) devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ d. List the files in this basic subdirectory. This is the location of the scripts you will be using in the next step. (csr1kv) devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ ls -l examples/basic total 12 -rw-rw-r-- 1 devasc devasc 510 May 31 16:47 basic_example_job.py -rwxrwxr-x 1 devasc devasc 4475 May 31 16:47 basic_example_script.py

(csr1kv) devasc@labvm:~/labs/devnet-src/pyats/csr1kv$

Step 4: Examine the basic script files. The test declaration syntax for pyATS is based on popular Python unit-testing frameworks like pytest. It supports basic testing statements, such as an assertion that a variable has a given value, and along with explicitly providing results via specific APIs. a. The Python script you will use is basic_example_script.py. Display the content of the Python script using the cat command. Pipe it to more if you want to view it one screen or line at a time. Notice that this script contains the following sections as highlighted in the output below: •

A common setup block



Multiple testing blocks



A common Cleanup block

These blocks contain statements that prepare and/or determine readiness of the test topology (a process that can include problem injection), perform tests, and then return the topology to a known state. The Testing blocks - often referred to in pyATS documentation as the Test Cases - can each contain multiple tests, with their own Setup and Cleanup code. Best practice suggests, though, that the common Cleanup section, at the end, be designed for idempotency, meaning it should check and restore all changes made by Setup and Test, and restore the topology to its original, desired state. Note: Although it is not necessary to understand the code, you will find it helpful to read the comments within the Python script. (csr1kv) devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ cat examples/basic/basic_example_script.py | more #!/usr/bin/env python ################################################################### # basic_example.py : A very simple test script example which include: # common_setup # Tescases # common_cleanup # The purpose of this sample test script is to show the "hello world"

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 5 of 21

www.netacad.com

Lab - Automated Testing Using pyATS and Genie

# of aetest. ################################################################### # To get a logger for the script import logging # Needed for aetest script from pyats import aetest # Get your logger for your script log = logging.getLogger(__name__) ################################################################### ### COMMON SETUP SECTION ### ################################################################### # This is how to create a CommonSetup # You can have one of no CommonSetup # CommonSetup can be named whatever you want class common_setup(aetest.CommonSetup): """ Common Setup section """ # CommonSetup have subsection. # You can have 1 to as many subsection as wanted # here is an example of 2 subsections # First subsection @aetest.subsection def sample_subsection_1(self): """ Common Setup subsection """ log.info("Aetest Common Setup ") # If you want to get the name of current section, # add section to the argument of the function. # Second subsection @aetest.subsection def sample_subsection_2(self, section): """ Common Setup subsection """ log.info("Inside %s" % (section)) # And how to access the class itself ? # self refers to the instance of that class, and remains consistent # throughout the execution of that container. log.info("Inside class %s" % (self.uid)) ###################################################################

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 6 of 21

www.netacad.com

Lab - Automated Testing Using pyATS and Genie

### TESTCASES SECTION ### ################################################################### # This is how to create a testcase # You can have 0 to as many testcase as wanted # Testcase name : tc_one class tc_one(aetest.Testcase): """ This is user Testcases section """ # Testcases are divided into 3 sections # Setup, Test and Cleanup. # This is how to create a setup section @aetest.setup def prepare_testcase(self, section): """ Testcase Setup section """ log.info("Preparing the test") log.info(section) # This is how to create a test section # You can have 0 to as many test section as wanted # First test section @ aetest.test def simple_test_1(self): """ Sample test section. Only print """ log.info("First test section ") # Second test section @ aetest.test def simple_test_2(self): """ Sample test section. Only print """ log.info("Second test section ") # This is how to create a cleanup section @aetest.cleanup def clean_testcase(self): """ Testcase cleanup section """ log.info("Pass testcase cleanup") # Testcase name : tc_two class tc_two(aetest.Testcase): """ This is user Testcases section """ @ aetest.test def simple_test_1(self): """ Sample test section. Only print """ log.info("First test section ")

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 7 of 21

www.netacad.com

Lab - Automated Testing Using pyATS and Genie

self.failed('This is an intentional failure') # Second test section @ aetest.test def simple_test_2(self): """ Sample test section. Only print """ log.info("Second test section ") # This is how to create a cleanup section @aetest.cleanup def clean_testcase(self): """ Testcase cleanup section """ log.info("Pass testcase cleanup") ##################################################################### #### COMMON CLEANUP SECTION ### ##################################################################### # This is how to create a CommonCleanup # You can have 0 , or 1 CommonCleanup. # CommonCleanup can be named whatever you want :) class common_cleanup(aetest.CommonCleanup): """ Common Cleanup for Sample Test """ # # # #

CommonCleanup follow exactly the same rule as CommonSetup regarding subsection You can have 1 to as many subsection as wanted here is an example of 1 subsections

@aetest.subsection def clean_everything(self): """ Common Cleanup Subsection """ log.info("Aetest Common Cleanup ") if __name__ == '__main__': # pragma: no cover aetest.main()

(csr1kv) devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ A pyATS script is a Python file where pyATS tests are declared. It can be run directly as a standalone Python script file, generating output only to your terminal window. Alternatively, one or more pyATS scripts can be compiled into a "job" and run together as a batch, through the pyATS EasyPy module. EasyPy enables parallel execution of multiple scripts, collects logs in one place, and provides a central point from which to inject changes to the topology under test. b. Use cat to display your pyATS job file, pyats_sample_job.py. Notice the instructions on how to run this file, highlighted below. (csr1kv) devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ cat examples/basic/basic_example_job.py # To run the job: # pyats run job basic_example_job.py # Description: This example shows the basic functionality of pyats

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 8 of 21

www.netacad.com

Lab - Automated Testing Using pyATS and Genie

#

with few passing tests

import os from pyats.easypy import run # All run() must be inside a main function def main(): # Find the location of the script in relation to the job file test_path = os.path.dirname(os.path.abspath(__file__)) testscript = os.path.join(test_path, 'basic_example_script.py') # Execute the testscript run(testscript=testscript)

(csr1kv) devasc@labvm:~/labs/devnet-src/pyats/csr1kv$

Step 5: Run pyATS manually to invoke the basic test case. a. Using the pyATS job and script files, run pyATS manually to invoke the basic test case. This will verify the pyATS job and script files work properly. The information in the output is beyond the scope of this lab, however you will notice that the job and script passed all required tasks. Note: The output below was truncated. The Cisco Test Automation repository on GitHub is subject to change, which includes the pyATS job and scripts files. Your output is subject to change but should not affect your outcome. For example, an intentional failure was added to the basic_example_script.py file. This is an intentional failure and does not cause any problems. It is an example that repositories are dynamic. It is one of the highlighted lines below. (csr1kv) devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ pyats run job examples/basic/basic_example_job.py 2020-05-31T17:10:17: %EASYPY-INFO: Starting job run: basic_example_job 2020-05-31T17:10:17: %EASYPY-INFO: Runinfo directory: /home/devasc/.pyats/runinfo/basic_example_job.2020May31_17:10:16.735106 2020-05-31T17:10:17: %EASYPY-INFO: ------------------------------------------------------------------------------2020-05-31T17:10:18: %EASYPY-INFO: Starting task execution: Task-1 2020-05-31T17:10:18: %EASYPY-INFO: test harness = pyats.aetest 2020-05-31T17:10:18: %EASYPY-INFO: testscript = /home/devasc/labs/devnetsrc/pyats/csr1kv/examples/basic/basic_example_script.py 2020-05-31T17:10:18: %AETEST-INFO: +-----------------------------------------------------------------------------+ 2020-05-31T17:10:18: %AETEST-INFO: | Starting common setup |

-------+ 2020-05-31T17:10:18: %SCRIPT-INFO: First test section 2020-05-31T17:10:18: %AETEST-ERROR: Failed reason: This is an intentional failure 2020-05-31T17:10:18: %AETEST-INFO: The result of section simple_test_1 is => FAILED 2020-05-31T17:10:18: %AETEST-INFO: +-----------------------------------------------------------------------------+ 2020-05-31T17:10:18: %AETEST-INFO: | Starting section simple_test_2 |

-------+

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 9 of 21

www.netacad.com

Lab - Automated Testing Using pyATS and Genie

2020-05-31T17:10:20: %EASYPY-INFO: | 2020-05-31T17:10:20: %EASYPY-INFO: ----------------------------+

2020-05-31T17:10:20: %EASYPY-INFO: 2020-05-31T17:10:20: %EASYPY-INFO: 2020-05-31T17:10:20: %EASYPY-INFO: 2020-05-31T17:10:20: %EASYPY-INFO: 2020-05-31T17:10:20: %EASYPY-INFO: 2020-05-31T17:10:20: %EASYPY-INFO: 2020-05-31T17:10:20: %EASYPY-INFO: 2020-05-31T17:10:20: %EASYPY-INFO: 2020-05-31T17:10:20: %EASYPY-INFO: 2020-05-31T17:10:20: %EASYPY-INFO: 2020-05-31T17:10:20: %EASYPY-INFO: 2020-05-31T17:10:20: %EASYPY-INFO: 2020-05-31T17:10:20: %EASYPY-INFO: 2020-05-31T17:10:20: %EASYPY-INFO: ----------------------------+ 2020-05-31T17:10:20: %EASYPY-INFO: | 2020-05-31T17:10:20: %EASYPY-INFO: ----------------------------+ 2020-05-31T17:10:20: %EASYPY-INFO: PASSED 2020-05-31T17:10:20: %EASYPY-INFO: PASSED 2020-05-31T17:10:20: %EASYPY-INFO: FAILED 2020-05-31T17:10:20: %EASYPY-INFO: PASSED 2020-05-31T17:10:20: %EASYPY-INFO: 2020-05-31T17:10:20: %EASYPY-INFO: ----------------------------+ 2020-05-31T17:10:20: %EASYPY-INFO: | 2020-05-31T17:10:20: %EASYPY-INFO: ----------------------------+ 2020-05-31T17:10:20: %EASYPY-INFO: 2020-05-31T17:10:20: %EASYPY-INFO: PASSED 2020-05-31T17:10:20: %EASYPY-INFO: PASSED 2020-05-31T17:10:20: %EASYPY-INFO: PASSED 2020-05-31T17:10:20: %EASYPY-INFO: PASSED 2020-05-31T17:10:20: %EASYPY-INFO: PASSED 2020-05-31T17:10:20: %EASYPY-INFO: PASSED

|

Easypy Report

+--------------------------------------------------

Overall Stats Passed Passx Failed Aborted Blocked Skipped Errored TOTAL Success Rate

: : : : : : :

3 0 1 0 0 0 0

: 4 : 75.00 %

+-------------------------------------------------|

Task Result Summary

+-------------------------------------------------Task-1: basic_example_script.common_setup Task-1: basic_example_script.tc_one Task-1: basic_example_script.tc_two Task-1: basic_example_script.common_cleanup

+-------------------------------------------------|

Task Result Details

+-------------------------------------------------Task-1: basic_example_script |-- common_setup |

|-- sample_subsection_1

|

`-- sample_subsection_2

|-- tc_one |

|-- prepare_testcase

|

|-- simple_test_1

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 10 of 21

www.netacad.com

Lab - Automated Testing Using pyATS and Genie

2020-05-31T17:10:20: %EASYPY-INFO: | |-- simple_test_2 PASSED 2020-05-31T17:10:20: %EASYPY-INFO: | `-- clean_testcase PASSED 2020-05-31T17:10:20: %EASYPY-INFO: |-- tc_two FAILED 2020-05-31T17:10:20: %EASYPY-INFO: | |-- simple_test_1 FAILED 2020-05-31T17:10:20: %EASYPY-INFO: | |-- simple_test_2 PASSED 2020-05-31T17:10:20: %EASYPY-INFO: | `-- clean_testcase PASSED 2020-05-31T17:10:20: %EASYPY-INFO: `-- common_cleanup PASSED 2020-05-31T17:10:20: %EASYPY-INFO: `-- clean_everything PASSED 2020-05-31T17:10:20: %EASYPY-INFO: Sending report email... 2020-05-31T17:10:20: %EASYPY-INFO: Missing SMTP server configuration, or failed to reach/authenticate/send mail. Result notification email failed to send. 2020-05-31T17:10:20: %EASYPY-INFO: Done! Pro Tip ------Use the following command to view your logs locally: pyats logs view

(csr1kv) devasc@labvm:~/labs/devnet-src/pyats/csr1kv$

Part 4: Use Genie to Parse IOS Command Output In this Part, you will use Genie to take unstructured IOS output and parse it into JSON output. Note: Not all IOS commands are supported. Complete Genie documentation can be found at: https://developer.cisco.com/docs/genie-docs/

Step 1: Create a testbed YAML file. The pyATS and Genie tools use a YAML file to know which devices to connect to and what the proper credentials are. This file is known as a testbed file. Genie includes built-in functionality to build the testbed file for you. a. Enter the command genie --help to see all the available commands. For additional help on any command, use the parameter, as shown below, for the create command. Notice that testbed is one of the options for the create command. (csr1kv) devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ genie --help Usage: genie [options] Commands: create diff dnac learn parse

Create Testbed, parser, triggers, ... Command to diff two snapshots saved to file or directory Command to learn DNAC features and save to file (Prototype) Command to learn device features and save to file Command to parse show commands

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 11 of 21

www.netacad.com

Lab - Automated Testing Using pyATS and Genie

run environment shell pickled data General Options: -h, --help

Run Genie triggers & verifications in pyATS runtime enter Python shell, loading a pyATS testbed file and/or

Show help

Run 'genie --help' for more information on a command.

(csr1kv) devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ genie create --help Usage: genie create [options] Subcommands: parser testbed trigger General Options: -h, --help -v, --verbose -q, --quiet WARNING, ERROR,

create a new Genie parser from template create a testbed file automatically create a new Genie trigger from template

Show help Give more output, additive up to 3 times. Give less output, additive up to 3 times, corresponding to and CRITICAL logging levels

(csr1kv) devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ b. To create your testbed YAML file, enter the command below. The --output parameter will create a testbed.yml file in a directory named yaml. The directory will be automatically created. The --encodepassword parameter will encode the passwords in the YAML file. The parameter interactive means you will be asked a series of questions. Answer no to the first three questions. And then provide the following answers to create the testbed.yaml file. •

Device hostname - This must match the hostname of the device, which for this lab is CSR1kv.



IP address - This must match your CSR1kv IPv4 address you discovered earlier in this lab. Shown here is 192.168.56.101.



Username - This is the local username used for ssh, which is cisco.



Default password - This is the local password used for ssh, which is cisco123!.



Enable password - Leave blank. There is no privileged password configured on the router.



Protocol - SSH along with the key exchange group expected by the router.



OS - The OS on the router.

(csr1kv) devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ genie create testbed interactive --output yaml/testbed.yml --encode-password Start creating Testbed yaml file ... Do all of the devices have the same username? [y/n] n Do all of the devices have the same default password? [y/n] n Do all of the devices have the same enable password? [y/n] n Device hostname: CSR1kv

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 12 of 21

www.netacad.com

Lab - Automated Testing Using pyATS and Genie

IP (ip, or ip:port): 192.168.56.101 Username: cisco Default Password (leave blank if you want to enter on demand): cisco123! Enable Password (leave blank if you want to enter on demand): Protocol (ssh, telnet, ...): ssh -o KexAlgorithms=diffie-hellman-group14sha1 OS (iosxr, iosxe, ios, nxos, linux, ...): iosxe More devices to add ? [y/n] n Testbed file generated: yaml/testbed.yml

(csr1kv) devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ c.

Use cat to view the testbed.yml file in the yaml directory. Notice your entries in the YAML file. Your SSH password is encrypted and the enable password will "ASK" the user to enter the password if one is required. (csr1kv) devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ cat yaml/testbed.yml devices: CSR1kv: connections: cli: ip: 192.168.56.101 protocol: ssh -o KexAlgorithms=diffie-hellman-group14-sha1 credentials: default: password: '%ENC{w5PDosOUw5fDosKQwpbCmMKH}' username: cisco enable: password: '%ASK{}' os: iosxe type: iosxe

(csr1kv) devasc@labvm:~/labs/devnet-src/pyats/csr1kv$

Step 2: Use Genie to parse output from the show ip interface brief command into JSON. a. If you have not already completed the Lab - Install the CSR1kv VM, do so now. If you have already completed that lab, launch the CSR1kv VM now. b. In the CSR1kv VM, enter the command show ip interface brief from privileged exec mode. Your address may be incremented to some other address other than 192.168.56.101. Make note of the IPv4 address for your CSR1kv VM. You will use it later in the lab. CSR1kv> en CSR1kv# show ip interface brief Interface GigabitEthernet1

IP-Address 192.168.56.101

OK? Method Status YES DHCP up

Protocol up

CSR1kv# c.

Using your testbed YAML file, invoke Genie to parse unstructured output from the show ip interface brief command into structured JSON. This command includes the IOS command to be parsed (show ip interface brief), the YAML testbed file (testbed.yml), and the specified device in the testbed file (CSR1kv).

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 13 of 21

www.netacad.com

Lab - Automated Testing Using pyATS and Genie

(csr1kv) devasc@labvm:~/labs/devnet-src/pyats/csr1kv$ genie parse "show ip interface brief" --testbed-file yaml/testbed.yml --devices CSR1kv Enter enable password for device CSR1kv: 2020-05-31T18:59:23: %UNICON-WARNING: Device 'CSR1kv' connection 'cli' does not have IP and/or port specified, ignoring Device 'CSR1kv' connection 'cli' does not have IP and/or port specified, ignoring 0%| | 0/1 [00:00 Settings. b. Under the General tab, set the SSL certificate verification to OFF. c.

Close the Settings dialog box.

Part 4: Use Postman to Send GET Requests In this Part, you will use Postman to send a GET request to the CSR1kv to verify that you can connect to the RESTCONF service.

Step 1: Explore the Postman user interface. a. In the center, you will see the Launchpad. You can explore this area if you wish. b. Click the plus sign (+) next to the Launchpad tab to open a GET Untitled Request. This interface is where you will do all of your work in this lab.

Step 2: Enter the URL for a the CSR1kv. a. The request type is already set to GET. Leave the request type set to GET. b. In the “Enter request URL” field, type in the URL that will be used to access the RESTCONF service that is running on the CSR1kv: https://192.168.56.101/restconf/

Step 3: Enter authentication credentials. Under the URL field, there are tabs listed for Params, Authorization, Headers, Body, Pre-request Script, Test, and Settings. In this lab, you will use Authorization, Headers, and Body. a. Click the Authorization tab. b. Under Type, click the down arrow next to “Inherit auth from parent” and choose Basic Auth. c.

For Username and Password, enter the local authentication credentials for the CSR1kv: Username: cisco Password: cisco123!

d. Click Headers. Then click the 7 hidden. You can verify that the Authorization key has a Basic value that will be used to authenticate the request when it is sent to the CSR1kv.

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 4 of 14

www.netacad.com

Lab - Use RESTCONF to Access an IOS XE Router

Step 4: Set JSON as the data type to send to and receive from the CSR1kv. You can send and receive data from the CSR1kv in XML or JSON format. For this lab, you will use JSON. a. In the Headers area, click in the first blank Key field and type Content-Type for the type of key. In the Value field, type application/yang-data+json. This tells Postman to send JSON data to the CSR1kv. b. Below your Content-Type key, add another key/value pair. The Key field is Accept and the Value field is application/yang-data+json. Note: You can change application/yang-data+json to application/yang-data+xml to send and receive XML data instead of JSON data, if necessary.

Step 5: Send the API request to the CSR1kv. Postman now has all the information it needs to send the GET request. Click Send. Below Temporary Headers, you should see the following JSON response from the CSR1kv. If not, verify that you completed the previous steps in this part of the lab and correctly configured RESTCONF and HTTPS service in Part 2. { "ietf-restconf:restconf": { "data": {}, "operations": {}, "yang-library-version": "2016-06-21" } }

This JSON response verifies that Postman can now send other REST API requests to the CSR1kv.

Step 6: Use a GET request to gather the information for all interfaces on the CSR1kv. a. Now that you have a successful GET request, you can use it as a template for additional requests. At the top of Postman, next to the Launchpad tab, right-click the GET tab that you just used and choose Duplicate Tab. b. Use the ietf-interfaces YANG model to gather interface information. For the URL, add data/ietfinterfaces:interfaces: https://192.168.56.101/restconf/data/ietf-interfaces:interfaces c.

Click Send. You should see a JSON response from the CSR1kv that is similar to the output shown below. Your output may be different depending on your particular router. { "ietf-interfaces:interfaces": { "interface": [ { "name": "GigabitEthernet1", "description": "VBox", "type": "iana-if-type:ethernetCsmacd", "enabled": true, "ietf-ip:ipv4": {}, "ietf-ip:ipv6": {} } ] } }

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 5 of 14

www.netacad.com

Lab - Use RESTCONF to Access an IOS XE Router

Step 7: Use a GET request to gather information for a specific interface on the CSR1kv. In this lab, only the GigabitEthernet1 interface is configured. To specify just this interface, extend the URL to only request information for this interface. a. Duplicate your last GET request. b. Add the interface= parameter to specify an interface and type in the name of the interface. https://192.168.56.101/restconf/data/ietf-interfaces:interfaces/interface=GigabitEthernet1

Note: If you request interface information from a different Cisco device with names that use forward slashes, such as GigabitEthernet0/0/1, use the HTML code %2F for the forward slashes in the interface name. So, 0/0/1 becomes 0%2F0%2F1. c.

Click Send. You should see a JSON response from the CSR1kv that is similar to output below. Your output may be different depending on your particular router. In the default CSR1kv setup, you will not see IP addressing information. { "ietf-interfaces:interface": { "name": "GigabitEthernet1", "description": "VBox", "type": "iana-if-type:ethernetCsmacd", "enabled": true, "ietf-ip:ipv4": {}, "ietf-ip:ipv6": {} } }

d. This interface receives addressing from a Virtual Box template. Therefore, the IPv4 address is not shown under show running-config. Instead, you will see the ip address dhcp command. You can see this also in the show ip interface brief output. CSR1kv# show ip interface brief Interface GigabitEthernet1

IP-Address 192.168.56.101

OK? Method Status YES DHCP up

Protocol up

CSR1kv# e. In the next Part you will need to use the JSON response from a manually configurated interface. Open a command terminal with the CSR1kv and manually configure the GigabitEthernet1 interface with the same IPv4 address currently assigned to it by Virtual Box. CSR1kv# conf t CSR1kv(config)# interface g1 CSR1kv(config-if)# ip address 192.168.56.101 255.255.255.0 CSR1kv(config-if)# end CSR1kv# show ip interface brief Interface GigabitEthernet1

IP-Address 192.168.56.101

OK? Method Status YES manual up

Protocol up

CSR1kv# f.

Return to Postman and send your GET request again. You should now see IPv4 addressing information in the JSON response, as shown below. In the next Part, you will copy this JSON format to create a new interface. { "ietf-interfaces:interface": { "name": "GigabitEthernet1",

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 6 of 14

www.netacad.com

Lab - Use RESTCONF to Access an IOS XE Router

"description": "VBox", "type": "iana-if-type:ethernetCsmacd", "enabled": true, "ietf-ip:ipv4": { "address": [ { "ip": "192.168.56.101", "netmask": "255.255.255.0" } ] }, "ietf-ip:ipv6": {} } }

Part 5: Use Postman to Send a PUT Request In this Part, you will configure Postman to send a PUT request to the CSR1kv to create a new loopback interface. Note: If you created a Loopback interface in another lab, either remove it now or create a new one by using a different number.

Step 1: Duplicate and modify the last GET request. a. Duplicate the last GET request. b. For the Type of request, click the down arrow next to GET and choose PUT. c.

For the interface= parameter, change it to =Loopback1 to specify a new interface. https://192.168.56.101/restconf/data/ietf-interfaces:interfaces/interface=Loopback1

Step 2: Configure the body of the request specifying the information for the new loopback. a. To send a PUT request, you need to provide the information for the body of the request. Next to the Headers tab, click Body. Then click the Raw radio button. The field is currently empty. If you click Send now, you will get error code 400 Bad Request because Loopback1 does not exist yet and you did not provide enough information to create the interface. b. Fill in the Body section with the required JSON data to create a new Loopback1 interface. You can copy the Body section of the previous GET request and modify it. Or you can copy the following into the Body section of your PUT request. Notice that the type of interface must be set to softwareLoopback. { "ietf-interfaces:interface": { "name": "Loopback1", "description": "My first RESTCONF loopback", "type": "iana-if-type:softwareLoopback", "enabled": true, "ietf-ip:ipv4": { "address": [ { "ip": "10.1.1.1", "netmask": "255.255.255.0" }

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 7 of 14

www.netacad.com

Lab - Use RESTCONF to Access an IOS XE Router

] }, "ietf-ip:ipv6": {} } }

c.

Click Send to send the PUT request to the CSR1kv. Below the Body section, you should see the HTTP response code Status: 201 Created. This indicates that the resource was created successfully.

d. You can verify that the interface was created. Return to your SSH session with the CSR1kv and enter show ip interface brief. You can also run the Postman tab that contains the request to get information about the interfaces on the CSR1kv that was created in the previous Part of this lab. Open configuration window

CSR1kv# show ip interface brief Interface GigabitEthernet1 Loopback1

IP-Address 192.168.56.101 10.1.1.1

OK? Method Status YES manual up YES other up

Protocol up up

CSR1kv# Close configuration window

Part 6: Use a Python script to Send GET Requests In this Part, you will create a Python script to send GET requests to the CSR1kv.

Step 1: Create the RESTCONF directory and start the script. a. Open VS code. Then click File > Open Folder... and navigate to the devnet-src directory. Click OK. b. Open a terminal window in VS Code: Terminal > New Terminal. c.

Create a subdirectory called restconf in the /devnet-src directory. devasc@labvm:~/labs/devnet-src$ mkdir restconf devasc@labvm:~/labs/devnet-src$

d. In the EXPLORER pane under DEVNET-SRC, right-click the restconf directory and choose New File. e. Name the file restconf-get.py. a. Enter the following commands to import the modules that are required and disable SSL certificate warnings: import json import requests requests.packages.urllib3.disable_warnings() The json module includes methods to convert JSON data to Python objects and vice versa. The requests module has methods that will let you send REST requests to a URL.

Step 2: Create the variables that will be the components of the request. a. Create a variable named api_url and assign it the URL that will access the interface information on the CSR1kv. api_url = "https://192.168.56.101/restconf/data/ietf-interfaces:interfaces"

b. Create a dictionary variable named headers that has keys for Accept and Content-type and assign the keys the value application/yang-data+json. headers = { "Accept": "application/yang-data+json", "Content-type":"application/yang-data+json" } © 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 8 of 14

www.netacad.com

Lab - Use RESTCONF to Access an IOS XE Router

c.

Create a Python tuple variable named basicauth that has two keys needed for authentication, username and password. basicauth = ("cisco", "cisco123!")

Step 3: Create a variable to send the request and store the JSON response. Use the variables that were created in the previous step as parameters for the requests.get() method. This method sends an HTTP GET request to the RESTCONF API on the CSR1kv. Assign the result of the request to a variable named resp. That variable will hold the JSON response from the API. If the request is successful, the JSON will contain the returned YANG data model. a. Enter the following statement: resp = requests.get(api_url, auth=basicauth, headers=headers, verify=False)

The table below lists the various elements of this statement: Element

Explanation

resp

The variable to hold the response from the API.

requests.get()

The method that actually makes the GET request.

api_url

The variable that holds the URL address string

auth

The tuple variable created to hold the authentication information.

headers=headers

A parameter that is assigned the headers variable

verify=False

Disables verification of the SSL certificate when the request is made

b. To see the HTTP response code, add a print statement. print(resp)

c.

Save and run your script. You should get the output shown below. If not, verify all previous steps in this part as well as the SSH and RESTCONF configuration for the CSR1kv. devasc@labvm:~/labs/devnet-src$ cd restconf/ devasc@labvm:~/labs/devnet-src/restconf$ python3 restconf-get.py

devasc@labvm:~/labs/devnet-src/restconf$

Step 4: Format and display the JSON data received from the CSR1kv. Now you can extract the YANG model response values from the response JSON. a. The response JSON is not compatible with Python dictionary and list objects, so it must be converted to Python format. Create a new variable called response_json and assign the variable resp to it. Add the json() method to convert the JSON. The statement is as follows: response_json = resp.json() b. Add a print statement to display the JSON data. print(response_json)

c.

Save and run your script. You should get output similar to the following: devasc@labvm:~/labs/devnet-src/restconf$ python3 restconf-get.py

{'ietf-interfaces:interfaces': {'interface': [{'name': 'GigabitEthernet1', 'description': 'VBox', 'type': 'iana-if-type:ethernetCsmacd', 'enabled': True, 'ietfip:ipv4': {'address': [{'ip': '192.168.56.101', 'netmask': '255.255.255.0'}]}, 'ietf-

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 9 of 14

www.netacad.com

Lab - Use RESTCONF to Access an IOS XE Router

ip:ipv6': {}}, {'name': 'Loopback1', 'description': 'My first RESTCONF loopback', 'type': 'iana-if-type:softwareLoopback', 'enabled': True, 'ietf-ip:ipv4': {'address': [{'ip': '10.1.1.1', 'netmask': '255.255.255.0'}]}, 'ietf-ip:ipv6': {}}]}}

devasc@labvm:~/labs/devnet-src/restconf$ d. To prettify the output, edit your print statement to use the json.dumps() function with the “indent” parameter: print(json.dumps(response_json, indent=4))

e. Save and run your script. You should get the output shown below. This output is virtually identical to the output of your first Postman GET request. devasc@labvm:~/labs/devnet-src/restconf$ python3 restconf-get.py

{ "ietf-interfaces:interfaces": { "interface": [ { "name": "GigabitEthernet1", "description": "VBox", "type": "iana-if-type:ethernetCsmacd", "enabled": true, "ietf-ip:ipv4": { "address": [ { "ip": "192.168.56.101", "netmask": "255.255.255.0" } ] }, "ietf-ip:ipv6": {} }, { "name": "Loopback1", "description": "My first RESTCONF loopback", "type": "iana-if-type:softwareLoopback", "enabled": true, "ietf-ip:ipv4": { "address": [ { "ip": "10.1.1.1", "netmask": "255.255.255.0" } ] }, "ietf-ip:ipv6": {} } ] } }

devasc@labvm:~/labs/devnet-src/restconf$

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 10 of 14

www.netacad.com

Lab - Use RESTCONF to Access an IOS XE Router

Part 7: Use a Python Script to Send a PUT Request In this Part, you will create a Python script to send a PUT request to the CSR1kv. As was done in Postman, you will create a new loopback interface.

Step 1: Import modules and disable SSL warnings. a. In the EXPLORER pane under DEVNET-SRC, right-click the restconf directory and choose New File. b. Name the file restconf-put.py. c.

Enter the following commands to import the modules that are required and disable SSL certificate warnings: import json import requests requests.packages.urllib3.disable_warnings()

Step 2: Create the variables that will be the components of the request. a. Create a variable named api_url and assign it the URL that targets a new Loopback2 interface. Note: This variable specification should be on one line in your script. api_url = "https://192.168.56.101/restconf/data/ietfinterfaces:interfaces/interface=Loopback2"

b. Create a dictionary variable named headers that has keys for Accept and Content-type and assign the keys the value application/yang-data+json. headers = { "Accept": "application/yang-data+json", "Content-type":"application/yang-data+json" }

c.

Create a Python tuple variable named basicauth that has two values needed for authentication, username and password. basicauth = ("cisco", "cisco123!")

d. Create a Python dictionary variable yangConfig that will hold the YANG data that is required to create the new interface Loopback2. You can use the same dictionary that you used previously in Postman. However, change the interface number and address. Also, be aware that Boolean values must be capitalized in Python. Therefore, make sure that the T is capitalized in the key/value pair for “enabled”: True. yangConfig = { "ietf-interfaces:interface": { "name": "Loopback2", "description": "My second RESTCONF loopback", "type": "iana-if-type:softwareLoopback", "enabled": True, "ietf-ip:ipv4": { "address": [ { "ip": "10.2.1.1", "netmask": "255.255.255.0" } ] }, "ietf-ip:ipv6": {}

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 11 of 14

www.netacad.com

Lab - Use RESTCONF to Access an IOS XE Router

} }

Step 3: Create a variable to send the request and store the JSON response. Use the variables created in the previous step as parameters for the requests.put() method. This method sends an HTTP PUT request to the RESTCONF API. Assign the result of the request to a variable named resp. That variable will hold the JSON response from the API. If the request is successful, the JSON will contain the returned YANG data model. a. Before entering statements, please note that this variable specification should be on only one line in your script. Enter the following statements: Note: This variable specification should be on one line in your script. resp = requests.put(api_url, data=json.dumps(yangConfig), auth=basicauth, headers=headers, verify=False)

b. Enter the code below to handle the response. If the response is one of the HTTP success messages, the first message will be printed. Any other code value is considered an error. The response code and error message will be printed in the event that an error has been detected. if(resp.status_code >= 200 and resp.status_code = 200 and resp.status_code Open Folder... and navigate to the devnet-src/webex-teams directory. Click OK. b. In the EXPLORER panel, you should now see all the placeholder .py files you will use in this lab. Click the authentciation.py file. c.

Place the following code into the file. Be sure to replace your_token_here with your personal access token you copied in the previous step. import requests import json

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 2 of 10

www.netacad.com

Lab - Construct a Python Script to Manage Webex Teams

access_token = 'your_token_here' url = 'https://webexapis.com/v1/people/me' headers = { 'Authorization': 'Bearer {}'.format(access_token) } res = requests.get(url, headers=headers) print(json.dumps(res.json(), indent=4)) d. Save and run the file. You should get the same output your saw in the OpenAPI documentation. Note: The values for some of the keys have been truncated in the output below. devasc@labvm:~/labs/devnet-src/webex-teams$ python3 authentication.py { "id": "Y2lz...UyM2U", "emails": [ "[email protected]" ], "phoneNumbers": [], "displayName": "Your-First-Name Your-Last-Name", "nickName": "Your-Nick-Name", "firstName": " Your-First-Name", "lastName": "Your-Last-Name", "avatar": "https://9643-417f-9974...6baa4~1600", "orgId": "Y2lzY2...UxMGY", "created": "2012-06-15T20:23:12.529Z", "lastActivity": "2020-06-02T20:16:52.111Z", "status": "active", "type": "person" }

devasc@labvm:~/labs/devnet-src/webex-teams$

Part 4: Manage People in Webex Teams In Webex Teams, People are registered users. Through the API, you can retrieve a list of people, you can create a person, retrieve an individual person's details, update a person, and delete a person.

Step 1: Locate the API documentation for listing details of a registered Webex Teams user. a. Return to the developer.webex.com website. Under API Reference > People, click the Method for List People. b. Under Query Parameters, find the email parameter. This is the parameter you will use to find a specific user in your organization. Alternatively, you could use the displayName parameter, if you know the exact name. You can use the Try it feature.

Step 2: Use a Python script to list details of a registered Webex Teams user. a. In VS Code, click the list-people.py file. b. Place the following code into the file. Be sure to replace your_token_here with your personal access token and [email protected] with an actual registered Webex Team user in your organization. import requests

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 3 of 10

www.netacad.com

Lab - Construct a Python Script to Manage Webex Teams

import json

access_token = 'your_token_here' url = 'https://webexapis.com/v1/people' headers = { 'Authorization': 'Bearer {}'.format(access_token), 'Content-Type': 'application/json' } params = { 'email': '[email protected]' } res = requests.get(url, headers=headers, params=params) print(json.dumps(res.json(), indent=4))

c.

Save and run the script. You should get the same output similar to the following. If you get a message like, {'message': 'Invalid email address.'..., it means that you did not replace the empty email parameter with a legitimate email address for a registered Webex Teams user. The value for the id key will be used in the next API call. Note: The values for some of the keys have been truncated in the output below. devasc@labvm:~/labs/devnet-src/webex-teams$ python3 list-people.py { "notFoundIds": null, "items": [ { "id": "Y2l...2I", # You will use this value in the next step "emails": [ "[email protected]" ], "phoneNumbers": [ { "type": "mobile", "value": "+1234567690" } ], "displayName": "displayName", "nickName": "nickName", "firstName": "firstName", "lastName": "lastName", "avatar": "https://9643-417f-9974...6baa4~1600", "orgId": "Y2lzY...UxMGY", "created": "2012-06-15T20:39:19.726Z", "lastActivity": "2020-06-04T13:57:01.688Z", "status": "active", "type": "person" } ] }

devasc@labvm:~/labs/devnet-src/webex-teams$

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 4 of 10

www.netacad.com

Lab - Construct a Python Script to Manage Webex Teams

Step 3: List additional administrative details for a person. a. If you are a Webex Teams administrator, you can get additional details for a person by using the value of the person id key in your API call. Add the following code to your list-people.py script. Replace previous_id_here with value for id from the previous API call. person_id = 'previous_id_here' url = 'https://webexapis.com/v1/people/{}'.format(person_id) headers = { 'Authorization': 'Bearer {}'.format(access_token), 'Content-Type': 'application/json' } res = requests.get(url, headers=headers) print(json.dumps(res.json(), indent=4))

b. Save the file and run it. As a non-administrator, you will get information that is very similar to the previous step. devasc@labvm:~/labs/devnet-src/webex-teams$ python3 list-people.py {

} { "id": "Y2l...2I", "emails": [ "[email protected]" ], "phoneNumbers": [ { "type": "mobile", "value": "+1234567890" } ], "displayName": "displayName", "nickName": "nickName", "firstName": "firstName", "lastName": "lastName", "avatar": "https://9643-417f-9974...6baa4~1600", "orgId": "Y2l...MGY", "created": "2012-06-15T20:39:19.726Z", "lastActivity": "2020-06-04T14:39:36.535Z", "status": "active", "type": "person" } devasc@labvm:~/labs/devnet-src/webex-teams$

Part 5: Manage Rooms in Webex Teams Rooms, also called spaces in the user interface, let people send messages and files to collaborate virtually in collective meeting places. In this Part, you will list rooms, create a room, and get a room’s details.

Step 1: Locate and investigate the API documentation for rooms. a. Return to the developer.webex.com website. Under API Reference, click Rooms. © 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 5 of 10

www.netacad.com

Lab - Construct a Python Script to Manage Webex Teams

b. Explore the various API calls you can make with the Rooms API. c.

Click the GET request for List Rooms and explore the Query Parameters.

Step 2: Use a Python script to list all the rooms for an authenticated user. a. For this step, you will need to be a member of at least one room. A conversation with one other person is considered a room in Webex Teams. b. In VS Code, click the list-rooms.py file. c.

Place the following code into the file. Be sure to replace your_token_here with your personal access token. import requests access_token = 'your_token_here' url = 'https://webexapis.com/v1/rooms' headers = { 'Authorization': 'Bearer {}'.format(access_token), 'Content-Type': 'application/json' } params={'max': '100'} res = requests.get(url, headers=headers, params=params) print(res.json())

d. Save and run the file. Your output will be different than the following. Only one room is listed here. ID values have been truncated. devasc@labvm:~/labs/devnet-src/webex-teams$ python3 list-rooms.py {'items': [{'id': 'Y2l...ZTE0', 'title': 'User Name', 'type': 'direct', 'isLocked': False, 'lastActivity': '2020-06-01T16:34:56.536Z', 'creatorId': 'Y2lz...yM2U', 'created': '2020-06-01T16:30:21.816Z', 'ownerId': 'Y2lz...xMGY'} # additional rooms displayed up to 'max' value. ]}

devasc@labvm:~/labs/devnet-src/webex-teams$

Step 3: Locate and investigate the API documentation for posting to the Rooms API. a. Return to the developer.webex.com website. Under API Reference, click Rooms, if necessary. b. The Rooms API has one POST method for Create a Room. Click the link see Query Parameters that are available. In your script, you will use the required title parameter.

Step 4: Use a Python script to create a room. a. In VS Code, click the create-rooms.py file. b. Place the following code into the file. Be sure to replace your_token_here with your personal access token. Notice that this is a POST request and uses the title parameter. import requests access_token = 'your_token_here' url = 'https://webexapis.com/v1/rooms' headers = { 'Authorization': 'Bearer {}'.format(access_token), 'Content-Type': 'application/json' } © 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 6 of 10

www.netacad.com

Lab - Construct a Python Script to Manage Webex Teams

params={'title': 'DevNet Associate Training!'} res = requests.post(url, headers=headers, json=params) print(res.json())

c.

Save and run the file. You should get a response similar to the following. ID values have been truncated. The room id and title are highlighted. Copy the room ID and save it in a text file for use in the rest of this lab. devasc@labvm:~/labs/devnet-src/webex-teams$ python3 create-rooms.py {'id': 'Y2l...GNm', 'title': 'DevNet Associate Training!', 'type': 'group', 'isLocked': False, 'lastActivity': '2020-06-04T16:50:19.371Z', 'creatorId': 'Y2l...M2U', 'created': '2020-06-04T16:50:19.371Z', 'ownerId': 'Y2l...MGY'}

devasc@labvm:~/labs/devnet-src/webex-teams$ d. In your Webex Teams application, verify you now see the DevNet Associate Training! room. You are currently the only member.

Step 5: Use a Python script to get room details. What if you want to start a meeting in your new room? You can do another GET call to retrieve the Session Initiation Protocol (SIP) address, the meeting URL, and the dial-in phone numbers. a. In VS Code, click the get-room-details.py file. b. Place the following code into the file. Replace your_token_here with your personal access token. Replace your_room_id with the value you got in the previous step. import requests access_token = 'your_token_here' room_id = 'your_room_id' url = 'https://webexapis.com/v1/rooms/{}/meetingInfo'.format(room_id) headers = { 'Authorization': 'Bearer {}'.format(access_token), 'Content-Type': 'application/json' } res = requests.get(url, headers=headers) print(res.json())

c.

Save and run the file. You should get a response similar to the following. Values have been truncated. devasc@labvm:~/labs/devnet-src/webex-teams$ python3 get-room-details.py {'roomId': 'Y2l...GNm', 'meetingLink': 'https://cisco.webex.com/m/3272...a837', 'sipAddress': '[email protected]', 'meetingNumber': '162...0468', 'callInTollFreeNumber': '+1-866-...-9903', 'callInTollNumber': '+1-408-...-6800'}

devasc@labvm:~/labs/devnet-src/webex-teams$

Part 6: Manage Memberships in Webex Teams In this Part, you will use the Membership API to add someone to your room.

Step 1: Locate and investigate the API documentation for memberships. a. Return to the developer.webex.com website. Under API Reference, click Memberships. b. Explore the various API calls you can make with the Memberships API. c.

Click the GET request for List Memberships and explore the Query Parameters.

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 7 of 10

www.netacad.com

Lab - Construct a Python Script to Manage Webex Teams

Step 2: Use a Python script to list the members of the room. a. In VS Code, click the list-memberships.py file. b. Place the following code into the file. Replace your_token_here with your personal access token. Replace your_room_id with the value from you got in the previous part. import requests access_token = 'your_token_here' room_id = 'your_room_id' url = 'https://webexapis.com/v1/memberships' headers = { 'Authorization': 'Bearer {}'.format(access_token), 'Content-Type': 'application/json' } params = {'roomId': room_id} res = requests.get(url, headers=headers, params=params) print(res.json())

c.

Save and run the file. You should get a response similar to the following. You should be the only member unless you have added someone in the Webex Teams application. ID values have been truncated. devasc@labvm:~/labs/devnet-src/webex-teams$ python3 list-memberships.py {'items': [{'id': 'Y2l...RjZg', 'roomId': 'Y2l...GNm', 'personId': 'Y2l...M2U', 'personEmail': '[email protected]', 'personDisplayName': 'personDisplayName', 'personOrgId': 'Y2l...MGY', 'isModerator': False, 'isMonitor': False, 'created': '2020-06-04T16:50:19.819Z'}]}

devasc@labvm:~/labs/devnet-src/webex-teams$

Step 3: Locate and investigate the API documentation for posting to the Memberships API. a. Return to the developer.webex.com website. Under API Reference, click Memberships, if necessary. b. The Memberships API has one POST method for Create a Membership. Click the link see Query Parameters that are available. In your script, you will use the required roomID and personEmail parameters.

Step 4: Use a Python script to create a membership, adding someone to the room. For this step, you will need the email of someone else who is a registered Webex Teams user in your organization. You can use the same email you used previously to list details about a person. a. In VS Code, click the create-membership.py file. b. Place the following code into the file. Replace your_token_here with your personal access token. Replace your_room_id with the value from you got in the previous part. Replace [email protected] with the email of the person you want to add to the room. import requests access_token = 'your_token_here' room_id = 'your_room_id' person_email = '[email protected]' url = 'https://webexapis.com/v1/memberships' headers = { 'Authorization': 'Bearer {}'.format(access_token), 'Content-Type': 'application/json'

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 8 of 10

www.netacad.com

Lab - Construct a Python Script to Manage Webex Teams

} params = {'roomId': room_id, 'personEmail': person_email} res = requests.post(url, headers=headers, json=params) print(res.json())

c.

Save and run the file. You should get a response similar to the following. You should be the only member unless you have added someone in the Webex Teams application. ID values have been truncated. devasc@labvm:~/labs/devnet-src/webex-teams$ python3 list-memberships.py {'items': [{'id': 'Y2l...RjZg', 'roomId': 'Y2l...GNm', 'personId': 'Y2l...M2U', 'personEmail': '[email protected]', 'personDisplayName': 'personDisplayName', 'personOrgId': 'Y2l...MGY', 'isModerator': False, 'isMonitor': False, 'created': '2020-06-04T16:50:19.819Z'}]}

devasc@labvm:~/labs/devnet-src/webex-teams$

Part 7: Manage Messages in Webex Teams In Webex Teams, a message can contain plain text, Markdown, or a file attachment. Each message is displayed on its own line along with a timestamp and sender information. You can use this Messages API to list, create, and delete messages. In this Part, you will send a message to the room you created in this lab.

Step 1: Locate and investigate the API documentation for messages. a. Return to the developer.webex.com website. Under API Reference, click Messages. b. Explore the various API calls you can make with the Messages API. c.

Click the POST request for Create a Message and explore the Query Parameters. Notice for a simple text message, you can use the text or markdown parameter. In this step, you will specify a message with Markdown formatting. Search the internet to learn more about Markdown.

Step 2: Use a Python script to send a message to a Webex room. a. In VS Code, click the creat-markdown-message.py file. b. Place the following code into the file. Replace your_token_here with your personal access token. Replace your_room_id with the value from you got in the previous part. import requests access_token = 'your_token_here' room_id = 'your_room_id' message = 'Hello **DevNet Associates**!!' url = 'https://webexapis.com/v1/messages' headers = { 'Authorization': 'Bearer {}'.format(access_token), 'Content-Type': 'application/json' } params = {'roomId': room_id, 'markdown': message} res = requests.post(url, headers=headers, json=params) print(res.json())

c.

Save and run the file. You should get a response similar to the following. Notice that the Markdown was converted to HTML. ID values have been truncated. devasc@labvm:~/labs/devnet-src/webex-teams$ python3 create-markdownmessage.py {'id': 'Y2l...RjZg', 'roomId': 'Y2l...GNm', 'roomType': 'group', 'text': 'Hello DevNet Associates!!', 'personId': 'Y2l...M2U', 'personEmail': '[email protected]', 'markdown':

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 9 of 10

www.netacad.com

Lab - Construct a Python Script to Manage Webex Teams

'Hello **DevNet Associates**!!', 'html': '

Hello DevNet Associates!!

', 'created': '2020-06-04T19:08:49.145Z'}

devasc@labvm:~/labs/devnet-src/webex-teams$ End of document

© 2020 - 2020 Cisco and/or its affiliates. All rights reserved. Cisco Public

Page 10 of 10

www.netacad.com