SDN实战
SDN小demo
关于项目
项目名称:基于Cisco NX-API REST实现对NXOS 9000v的远程管理系统
项目目标:编写一个程序实现对多台N9KV可视化配置与管理
实现方式:以python脚本为基础编写程序通过对NX-API REST的调用实现功能
环境介绍
python版本:python3.6.7
NXOS 9000v:思科的一个虚拟虚拟交换机与传统的思科交换机差不多,可以进行相关功能的配置但是转发数据的能力与实际设备相差甚远,一般用于测试与验证。[思科关于NXOS 9000v的文档]
环境搭建
1.安装Python3
- 首先去Python官网下载所需Python版本
- 在安装时建议选择,会自动帮你配置环境变量。
- 安装好后再dos中输入python -V 进行验证是否安装成功。
- 需要用pip去安装requests包,即在dos中pip install requests,验证安装成功在dos中输入pip list 会显示requests相关信息即安装成功。(可能需要安装pip,可以去百度)
2.搭建NXOS 9000v(以下统称为N9KV)
有四种方式来实现对N9KV的搭建:
- 使用Workstation完成单机搭建
- 使用ESXi 6.0完成组网测试
- 利用Dcloud/VIRL资源做练习
- 使用EVE平台实现复杂场景搭建
以上四种方式各有利弊,本人使用了第一种方式来搭建N9KV,如想知道其他搭建方式的可联系本小白。
使用Workstation完成单机搭建N9KV
以下是环境搭建的关键步骤:
- 下载N9KV镜像。链接: https://pan.baidu.com/s/1yABOanA_WqNIyjRTw4CM4Q 提取码: xc1s
- 安装此虚拟机的标准配置是:8G memory(最小5G),4vCPU,4G hard disk,1 serial port,1 NIC
需要注意的地方,红色部分第一个网络适配器是给交换机的配置端口需要用桥接模式并于其他网络是配置进行区分,其他网络适配器需要与此区分;蓝色部分需要添加一个穿行端口在交换机第一次启动后使用管道的方式进行配置端口(mg 0)进行配置。
完成上述步骤后就可启动交换机,当加载完1268M数据后,使用putty软件通过管道的方式进行N9KV的初始化配置。
当putty中出现Abort Power On Auto Prvisioning时输入yes,后会出现possaword是否需要加密的信息(自己随意,本小白选择了no),即可进行密码的设置,后会出现是否dialog(no)。以上就完成了基本的配置。
- 即可登录,登陆后首先给管理口配置(mg 0)IP地址,即进入管理模式:int mg 0 后ip add 你的ip地址/子网掩码。因为不支持自动加载镜像,需要做如下操作:switch(config)# boot nxos bootflash:nxos.9.2.3.bin ,如不进行此步操作你的N9KV下一次将无法启动。配置完后切记保存:switch(config)# copy running-config startup-config
这时在交换机开启的状态下你可以用putty用两种方式来进行配置与管理交换机1.接着使用管道的方式2.使用ssh的方式输入你刚刚个mg 0配置的ip地址进行管理与配置。(经本人实验如果需要使用ssh的方式,需先用管道的方式将交换机启动)
以上就是用Workstation搭建N9KV的关键过程。
使用北向接口配置与管理N9KV
有两种北向接口方式来配置N9KV:
- REST‐API CLI
- NX‐API REST
本小白使用方式2实现功能以下介绍的为方式2,如需方式1的相关材料可联系本小白,也可去思科官网完成学习与练习。
确定了方式我们就可进行脚本编写实现对N9KV的管理与配置。参考文档
以下是本小白的demo:
import tkinter as tk
import os
from tkinter import *
from tkinter import Entry
import createVlan
import tkinter.messagebox
import json
import selectSystemInfo
import selectVlanInfo
import selectMacAddress
import SaveFigure
import selectStpInfo
import configStp
ip = ''
user = ''
password = ''
def identityIp():
window3 = tk.Tk()
window3.title('验证登陆')
window3.geometry('500x600')
lab = tk.Label(text="验证登陆", font=('Arial', 14), master=window3)
lab.place(x=200, y=100)
lab1 = tk.Label(text="IP", font=('Arial', 14), master=window3)
lab1.place(x=130, y=150)
lab3 = tk.Label(text="用户名", font=('Arial', 14), master=window3)
lab3.place(x=130, y=200)
lab2 = tk.Label(text="密码", font=('Arial', 14), master=window3)
lab2.place(x=130, y=250)
ent = tk.Entry(window3, font=('Arial', 14))
ent.place(x=200, y=150)
ent2 = tk.Entry(window3, font=('Arial', 14))
ent2.place(x=200, y=200)
ent3 = tk.Entry(window3, font=('Arial', 14), show="*")
ent3.place(x=200, y=250)
def getIp():
global ip
global user
global password
ip = ent.get()
user = ent2.get()
password = ent3.get()
show()
but = tk.Button(text="确定登陆", font=('Arial', 14), master=window3, command=getIp)
but.place(x=200, y=300)
window3.mainloop()
def show():
infoJson = selectSystemInfo.selectSystemInfo(ip, user, password)
info = json.loads(json.dumps(infoJson))
windows = tk.Tk()
windows.title("Demo")
windows.geometry('1000x600')
lable1 = tk.Label(text="HOSTNAME:", font=('Arial', 13), master=windows)
lable1.place(x=120, y=30)
lable1_var = tk.Label(text=info["name"], font=('Arial', 13), master=windows)
lable1_var.place(x=220, y=30)
lable2 = tk.Label(text="SERIAL NUMBER:", font=('Arial', 13), master=windows)
lable2.place(x=420, y=30)
lable2_var = tk.Label(text=info["serial"], font=('Arial', 13), master=windows)
lable2_var.place(x=565, y=30)
lable3 = tk.Label(text="UPTIME:", font=('Arial', 13), master=windows)
lable3.place(x=730, y=30)
lable3_var = tk.Label(text=info["systemUpTime"], font=('Arial', 13), master=windows)
lable3_var.place(x=800, y=30)
link = tk.Label(text='__________________________________________________________________________________'
'__________________________________________________________________________________'
'________________________________', master=windows)
link.place(x=10, y=60)
# VLan
Label_1 = tk.Label(text="VLAN:", font=('Arial', 20), master=windows)
Label_1.place(x=150, y=200)
ButtonVlanSelect = tk.Button(text="Select", font=('Arial', 15), command=vlanSelect, master=windows)
ButtonVlanSelect.place(x=300, y=200)
ButtonVlanConfig = tk.Button(text="Config", font=('Arial', 15), command=vlanConfig, master=windows)
ButtonVlanConfig.place(x=450, y=200)
# SP
def stp():
configStp.configStp(user, password, ip)
Label_2 = tk.Label(text="Stp:", font=('Arial', 20), master=windows)
Label_2.place(x=150, y=350)
ButtonSpSelect = tk.Button(text="Select", font=('Arial', 15), command=spSelect, master=windows)
ButtonSpSelect.place(x=300, y=350)
ButtonSpConfig = tk.Button(text="Config", font=('Arial', 15), command=stp, master=windows)
ButtonSpConfig.place(x=450, y=350)
# Mac
def selectMac():
info = selectMacAddress.selectMacAddress(ip, user, password)
tk.messagebox.showinfo(message=info)
lable3 = tk.Label(text="Mac", font=('Arial', 20), master=windows)
lable3.place(x=150, y=500)
button3_1 = tk.Button(windows, font=('Arial', 15), text="查看Mac", command=selectMac)
button3_1.place(x=300, y=500)
# Save
def save():
SaveFigure.save(ip, user, password)
Button_save = tk.Button(text="Save", font=('Arial', 20), master=windows, command=save)
Button_save.place(x=800, y=530)
windows.mainloop()
def vlanSelect():
wind1 = tk.Tk()
wind1.title("vlan select")
wind1.geometry('1200x600')
idE = tk.Entry(wind1, font=('Arial', 14))
idE.place(x=200, y=100)
def get():
id = idE.get()
info = selectVlanInfo.selectVlanInfo(id, user, password, ip)
labInfo = tk.Label(text=info, font=('Arial', 14), master=wind1, width=70, height=6, wraplength=600, justify='left', anchor="nw")
labInfo.place(x=500, y=150)
labDn = tk.Label(text=info["dn"], font=('Arial', 14), master=wind1)
labDn.place(x=500, y=300)
LabVlan = tk.Label(text=info["clearTs"], font=('Arial', 14), master=wind1)
LabVlan.place(x=500, y=400)
LabInB = tk.Label(text=info["inBcastOctets"], font=('Arial', 14), master=wind1)
LabInB.place(x=500, y=500)
idButton = tk.Button(text="select", font=('Arial', 14), master=wind1, command=get)
idButton.place(x=460, y=90)
# vlan = selectVlanInfo.selectVlanInfo(id)
Lab1 = tk.Label(text="Info:", font=('Arial', 15), master=wind1)
Lab1.place(x=200, y=150)
Lab2 = tk.Label(text="DN:", font=('Arial', 15), master=wind1)
Lab2.place(x=200, y=300)
Lab3 = tk.Label(text="VlanInfo:", font=('Arial', 15), master=wind1)
Lab3.place(x=200, y=400)
Lab4 = tk.Label(text="inBcastOctets", font=('Arial', 15), master=wind1)
Lab4.place(x=200, y=500)
wind1.mainloop()
def vlanConfig():
wind2 = tk.Tk()
wind2.title("vlan config")
wind2.geometry('800x600')
a = StringVar()
a.set('ID<3967')
ent = tk.Entry(wind2, font=('Arial', 15), textvariable=a)
ent.place(x=50, y=123)
def creat():
id = ent.get()
if int(id) > 3967:
tkinter.messagebox.showinfo(message="请输入小于3967的数")
return
else:
createVlan.createVlan(id, user, password, ip)
button = tk.Button(text="创建Vlan", font=('Arial', 15), master=wind2, command=creat)
button.place(x=300, y=123)
wind2.mainloop()
def spSelect():
try:
msg = selectStpInfo.selectStpInfo(user, password, ip)
tk.messagebox.showinfo(message=msg)
except:
tk.messagebox.showinfo(message="error")
def stpConfig():
win4 = tk.Tk()
win4.title("sp config")
win4.geometry('800x600')
def stp():
configStp.configStp(user, password, ip)
button = tk.Button(text="button", font=('Arial', 15), master=win4, command=stp)
button.place(x=80, y=100)
win4.mainloop()
if __name__ == '__main__':
identityIp()
查询N9KV信息
import requests, urllib3
def selectSystemInfo(ip,user,password):
# Disable Self-Signed Cert warning for demo
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Assign requests.Session instance to session variable
session = requests.Session()
# Define URL and PAYLOAD variables
URL = "https://"+str(ip)+"/api/aaaLogin.json"
PAYLOAD = {
"aaaUser": {
"attributes": {
"name": user,
"pwd": password
}
}
}
# Obtain an authentication cookie
session.post(URL,json=PAYLOAD,verify=False)
# Define SYS_URL variable
SYS_URL = "https://"+str(ip)+"/api/mo/sys.json"
# Obtain system information by making session.get call
# then convert it to JSON format then filter to system attributes
sys_info = session.get(SYS_URL,verify=False).json()["imdata"][0]["topSystem"]["attributes"]
# Print hostname, serial nmber, uptime and current state information
# obtained from the NXOSv9k
return sys_info
创建vlan
import requests, urllib3
import tkinter.messagebox
# Disable Self-Signed Cert warning for demo
def createVlan(vlan_id ,user, password, ip="192.168.1.30"):
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Assign requests.Session instance to session variable
session = requests.Session()
# Define URL and PAYLOAD variables
URL = "https://"+str(ip)+"/api/aaaLogin.json"
PAYLOAD = {
"aaaUser": {
"attributes": {
"name": user,
"pwd": password
}
}
}
# Obtain an authentication cookie
session.post(URL, json=PAYLOAD, verify=False)
# Define SYS_URL variable
# 创建vlan2
SYS_URL = "https://"+str(ip)+"/api/mo/sys/bd.json"
PAYLOAD = {
"bdEntity": {
"children": [
{
"l2BD": {
"attributes": {
"fabEncap": "vlan-"+str(vlan_id),
"pcTag": "1"
}}}]}}
session.post(SYS_URL, json=PAYLOAD, verify=False)
vlan_info = session.get(SYS_URL, verify=False).json
a = str(200)
if a in str(vlan_info):
tkinter.messagebox.showinfo(title="State", message="创建成功")
else:
tkinter.messagebox.showinfo(title="State", message="创建失败")
查询vlan信息
import requests, urllib3
import json
# Disable Self-Signed Cert warning for demo
def selectVlanInfo(id, user, password, ip='192.168.1.30'):
# Disable Self-Signed Cert warning for demo
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Assign requests.Session instance to session variable
session = requests.Session()
# Define URL and PAYLOAD variables
URL = "https://" + str(ip) + "/api/aaaLogin.json"
PAYLOAD = {
"aaaUser": {
"attributes": {
"name": user,
"pwd": password
}
}
}
# Obtain an authentication cookie
session.post(URL, json=PAYLOAD, verify=False)
# Define SYS_URL variable
# 查询vlan2信息
SYS_URL = "https://" + str(ip) + "/api/node/mo/sys/bd/bd-[vlan-" + str(id) + "]/dbgVlanStats.json"
# Obtain system information by making session.get call
# then convert it to JSON format then filter to system attributes
vlan_info = session.get(SYS_URL, verify=False).json()["imdata"][0]["l2VlanStats"]["attributes"]
vlan_info_loads = json.loads(json.dumps(vlan_info))
return vlan_info_loads
设置STP为RSTP
import requests, urllib3
import tkinter.messagebox
# Disable Self-Signed Cert warning for demo
def configStp(user, password, ip='192.168.1.30'):
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Assign requests.Session instance to session variable
session = requests.Session()
# Define URL and PAYLOAD variables
URL = "https://"+str(ip)+"/api/aaaLogin.json"
PAYLOAD = {
"aaaUser": {
"attributes": {
"name": user,
"pwd": password
}
}
}
# Obtain an authentication cookie
session.post(URL, json=PAYLOAD, verify=False)
# Define SYS_URL variable
# 创建vlan2
SYS_URL = "https://"+str(ip)+"/api/mo/sys/stp/inst.json"
PAYLOAD = {
"stpInst": {
"attributes": {
"mode": "pvrst"
}
}
}
session.post(SYS_URL, json=PAYLOAD, verify=False)
stp_info = session.get(SYS_URL, verify=False).json
a = str(200)
if a in str(stp_info):
tkinter.messagebox.showinfo(title="State", message="创建成功")
else:
tkinter.messagebox.showinfo(title="State", message="创建失败")
查询STP信息
import requests, urllib3
import json
# Disable Self-Signed Cert warning for demo
def selectStpInfo(user, password, ip='192.168.1.30'):
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Assign requests.Session instance to session variable
session = requests.Session()
# Define URL and PAYLOAD variables
URL = "https://"+str(ip)+"/api/aaaLogin.json"
PAYLOAD = {
"aaaUser": {
"attributes": {
"name": user,
"pwd": password
}
}
}
# Obtain an authentication cookie
session.post(URL,json=PAYLOAD,verify=False)
# Define SYS_URL variable
# 查询STP信息
SYS_URL = "https://"+str(ip)+"/api/mo/sys/stp.json?rsp-subtree=full"
# Obtain system information by making session.get call
# then convert it to JSON format then filter to system attributes
STP_info = session.get(SYS_URL, verify=False).json()
info = json.loads(json.dumps(STP_info))
protocol = info["imdata"][0]["stpEntity"]["children"][0]["stpInst"]["children"][15]["stpVlan"]["attributes"]["protocol"]
msg = "Spanning tree enabled protocol "+protocol
return msg
查看MAC地址表信息
import requests, urllib3
# Disable Self-Signed Cert warning for demo
def selectMacAddress(ip, user, password):
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Assign requests.Session instance to session variable
session = requests.Session()
# Define URL and PAYLOAD variables
URL = "https://"+str(ip)+"/api/aaaLogin.json"
PAYLOAD = {
"aaaUser": {
"attributes": {
"name": user,
"pwd": password
}
}
}
# Obtain an authentication cookie
session.post(URL, json=PAYLOAD, verify=False)
# Define SYS_URL variable
SYS_URL = "https://"+str(ip)+"/api/mo/sys/mac/table.json?rsp-subtree=full"
# Obtain system information by making session.get call
# then convert it to JSON format then filter to system attributes
MACtable_info = session.get(SYS_URL, verify=False).json()
# Print raw data
return MACtable_info
保存配置
import requests, urllib3
import tkinter.messagebox
def save(ip, user, password):
# Disable Self-Signed Cert warning for demo
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# Assign requests.Session instance to session variable
session = requests.Session()
# Define URL and PAYLOAD variables
URL = "https://"+str(ip)+"/api/aaaLogin.json"
PAYLOAD = {
"aaaUser": {
"attributes": {
"name": user,
"pwd": password
}
}
}
# Obtain an authentication cookie
session.post(URL, json=PAYLOAD, verify=False)
# Define SYS_URL variable
SYS_URL = "https://"+str(ip)+"//api/mo/sys/action.json"
PAYLOAD = {
"actionLSubj": {
"attributes": {
"dn": "sys/action/lsubj-[sys]"
},
"children" : [{
"topSystemCopyRSLTask": {
"attributes": {
"adminSt": "start",
"dn": "sys/action/lsubj-[sys]/topSystemCopyRSLTask",
"freq": "one-shot"
}
}
}]
}
}
session.post(SYS_URL, json=PAYLOAD, verify=False)
info = session.get(SYS_URL, verify=False).json
a = str(200)
if a in str(info):
tkinter.messagebox.showinfo(title="State", message="保存成功")
else:
tkinter.messagebox.showinfo(title="State", message="保存失败")
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 2924854739@qq.com
文章标题:SDN实战
本文作者:DROBP
发布时间:2019-08-07, 15:43:59
最后更新:2019-08-12, 11:46:09
原始链接:https://DROBP.github.io/2019/08/07/SDN实战/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。