Skip to content

Update updateip.py #89

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 22, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 80 additions & 53 deletions restconf_update_ipaddress/updateip.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
This script has been tested with Python 3.5, however may work with other versions.

This script targets the RESTCONF DevNet Sandbox that leverages a CSR1000v as
a target. To execute this script against a different device, update the variables
that list the connectivity, management interface, and url_base for RESTCONF.
a target. To execute this script against a different device, update the
variables and command-line arguments that list the connectivity, management
interface, and url_base for RESTCONF.

Requirements:
Python
Expand All @@ -24,51 +25,42 @@
import json
import requests
import sys
import os
from argparse import ArgumentParser
from collections import OrderedDict
from getpass import getpass
import urllib3

# Disable SSL Warnings
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)


# These variables target the RESTCONF Always-On Sandbox hosted by Cisco DevNet
HOST = 'ios-xe-mgmt.cisco.com'
PORT = '443'
USER = 'root'
PASS = 'D_Vay!_10&'

# Identifies the interface on the device used for management access
# Used to ensure the script isn't used to update the IP leveraged to manage device
MANAGEMENT_INTERFACE = "GigabitEthernet1"

# Create the base URL for RESTCONF calls
url_base = "https://{h}:{p}/restconf".format(h=HOST, p=PORT)

# Identify yang+json as the data formats
headers = {'Content-Type': 'application/yang-data+json',
'Accept': 'application/yang-data+json'}


# Function to retrieve the list of interfaces on a device
def get_configured_interfaces():
url = url_base + "/data/ietf-interfaces:interfaces"

def get_configured_interfaces(url_base, username, password):
# this statement performs a GET on the specified url
response = requests.get(url,
auth=(USER, PASS),
headers=headers,
verify=False
)
try:
response = requests.get(url_base,
auth=(username, password),
headers=headers,
verify=False
)
response.raise_for_status()
except Exception as e:
print(e, file=sys.stderr)
sys.exit(1)

# return the json as text
return response.json()["ietf-interfaces:interfaces"]["interface"]


# Used to configure the IP address on an interface
def configure_ip_address(interface, ip):
def configure_ip_address(url_base, interface, ip, username, password):
# RESTCONF URL for specific interface
url = url_base + "/data/ietf-interfaces:interfaces/interface={i}".format(i=interface)
url = url_base + "/interface={i}".format(i=interface)

# Create the data payload to reconfigure IP address
# Need to use OrderedDicts to maintain the order of elements
Expand All @@ -89,32 +81,43 @@ def configure_ip_address(interface, ip):
)])

# Use PUT request to update data
response = requests.put(url,
auth=(USER, PASS),
headers=headers,
verify=False,
json=data
)
try:
response = requests.put(url,
auth=(username, password),
headers=headers,
verify=False,
json=data
)
response.raise_for_status()
except Exception as e:
print(e, file=sys.stderr)
sys.exit(1)

print(response.text)


# Retrieve and print the current configuration of an interface
def print_interface_details(interface):
url = url_base + "/data/ietf-interfaces:interfaces/interface={i}".format(i=interface)
def print_interface_details(url_base, interface, username, password):
url = url_base + "/interface={i}".format(i=interface)

# this statement performs a GET on the specified url
response = requests.get(url,
auth=(USER, PASS),
headers=headers,
verify=False
)
try:
response = requests.get(url,
auth=(username, password),
headers=headers,
verify=False
)
response.raise_for_status()
except Exception as e:
print(e, file=sys.stderr)
sys.exit(1)

intf = response.json()["ietf-interfaces:interface"]
# return the json as text
print("Name: ", intf["name"])
print("Name: ", intf[0]["name"])
try:
print("IP Address: ", intf["ietf-ip:ipv4"]["address"][0]["ip"], "/",
intf["ietf-ip:ipv4"]["address"][0]["netmask"])
print("IP Address: ", intf[0]["ietf-ip:ipv4"]["address"][0]["ip"], "/",
intf[0]["ietf-ip:ipv4"]["address"][0]["netmask"])
except KeyError:
print("IP Address: UNCONFIGURED")
print()
Expand All @@ -124,15 +127,15 @@ def print_interface_details(interface):

# Ask the user to select an interface to configure. Ensures input is valid and
# NOT the management interface
def interface_selection(interfaces):
def interface_selection(interfaces, mgmt_if):
# Ask User which interface to configure
sel = input("Which Interface do you want to configure? ")

# Validate interface input
# Must be an interface on the device AND NOT be the Management Interface
while sel == MANAGEMENT_INTERFACE or not sel in [intf["name"] for intf in interfaces]:
while sel == mgmt_if or not sel in [intf["name"] for intf in interfaces]:
print("INVALID: Select an available interface.")
print(" " + MANAGEMENT_INTERFACE + " is used for management.")
print(" " + mgmt_if + " is used for management.")
print(" Choose another Interface")
sel = input("Which Interface do you want to configure? ")

Expand All @@ -149,13 +152,36 @@ def get_ip_info():


def main():
global do_input

"""
Simple main method calling our function.
"""

parser = ArgumentParser(
prog=sys.argv[0], description='RESTCONF interface management tool')
parser.add_argument('--hostname', '-a', type=str,
help='sandbox hostname or IP address',
default='ios-xe-mgmt.cisco.com')
parser.add_argument('--username', '-u', type=str,
help='sandbox username', default='developer')
# Identifies the interface on the device used for management access
# Used to ensure the script isn't used to update the IP leveraged to manage
# device
parser.add_argument('--management_if', '-m', type=str,
help='management interface', default='GigabitEthernet1')
parser.add_argument('--port', '-P', type=int,
help='sandbox web port', default=443)
args = parser.parse_args()

password = os.getenv('DEVNET_RESTCONF_PASSWORD')
if password is None:
password = getpass()

# Create the base URL for RESTCONF calls

url_base = "https://{h}:{p}/restconf/data/ietf-interfaces:interfaces".format(h=args.hostname, p=args.port)

# Get a List of Interfaces
interfaces = get_configured_interfaces()
interfaces = get_configured_interfaces(url_base, args.username, password)

print("The router has the following interfaces: \n")
for interface in interfaces:
Expand All @@ -164,23 +190,24 @@ def main():
print("")

# Ask User which interface to configure
selected_interface = interface_selection(interfaces)
selected_interface = interface_selection(interfaces, args.management_if)
print(selected_interface)

# Print Starting Interface Details
print("Starting Interface Configuration")
print_interface_details(selected_interface)
print_interface_details(url_base, selected_interface, args.username,
password)

# As User for IP Address to set
ip = get_ip_info()

# Configure interface
configure_ip_address(selected_interface, ip)
configure_ip_address(url_base, selected_interface, ip, args.username, password)

# Print Ending Interface Details
print("Ending Interface Configuration")
print_interface_details(selected_interface)

print_interface_details(url_base, selected_interface, args.username,
password)

if __name__ == '__main__':
sys.exit(main())