Acebit expanderar
Acebit expanderar – automationsess från Dalarna öppnar i Stockholm
Läs gärna mitt tidigare inlägg om Scrapli: Scrapli#1
TLDR: Vill du inte läsa igenom hela posten kan du bläddra längst ner på sidan för att läsa scriptet.
Jag fortsätter mitt arbete genom att använda scrapli för att utföra upprepande övningar. Den här gången kommer jag lägga till VLAN i en PortChannel.
Följande topologi arbetar vi med. Den kommer skapa konfiguration på NX01 och NX02.
Vi börjar med att importera nödvändiga moduler. Den ena gör att vi kan använda Scrapli och den andra möjliggör integration med operativsystemet.
from scrapli.driver.core import IOSXEDriver
import os
Vi skapar en lista över den utrustning som scriptet ska arbeta mot:
"""Lista med enheter som ska konfigureras"""
devices = [
"NX01",
"NX02"
]
Definierar ett användarnamn och lösenord som importeras från en variable i operativsystemet.
"""Användarnamn och lösenord för inlogg mot utrustningen som ska konfigureras.
Datat har sparas som ett systemvariable i OS"""
username = os.environ.get("USER")
password = os.environ.get("PASS")
credentials = {
"auth_username": username,
"auth_password": password,
"auth_strict_key": False,
}
"""En liten output som påminner användaren vad skriptet
genomför och på vilka enheter."""
print("This will add vlans to Nexuses:")
print("Nexus01\nNexus02")
print("PortChannel 200\nPortChannel 202\nTowards Fw Inside Interfaces\n\n---------------")
Skriptet är uppdelat i flera funktioner för att göra det enkelt att överblicka.
Jag har börjat med att skapa en main if-statement. Den frågar användaren vad för vlan som ska läggas till i Trunken. Matas ett felaktigt VLAN in kommer den att säga ifrån och sedan lägga till ett namn till vlanet.
if __name__ == "__main__":
#while för att förebygga felaktiga tecken i vlanet
newVlanBolean = False
while newVlanBolean == False:
newVlan = input("vlan: ")
newVlanBolean = newVlan.isnumeric()
if newVlanBolean == False:
print("nope, enter a valid vlan id or exit out")
#Skapar ett namn till det inmatade vlanet.
newVlanName = input("vlan name: ")
for device in devices:
connection = credentials
connection["host"] = device
print(f"Connecting to switch {device}")
"""Kallar på funktionen checkVlansInDb och matar in två värden.
Anslutningsuppgifterna till enheten och vlanet. Ifall vlanet
finns kommer funktionen svara tillbaka med True. Finns
vlanet inte med i vlandatabasen svarar funktionen tillbaka med False."""
if checkVlansInDb(connection, newVlan) == True:
print(f" vlan: {newVlan} exists in vlandb")
"""Ifall svaret är False kommer vi kalla på funktionen createVlan.
Vi skickar in anslutningsuppfigifterna, vlanet och vlan-namnet."""
else:
print(" Not in db")
createVlan(connection, newVlan, newVlanName)
print(" vlan created")
"""Nu har vi säkerställt att vlanet finns i switchen,
antingen från början eller så är det skapat. Nu behöver
# vi ta reda på om vlanet redan finns i trunken. Det gör
vi genom att kalla på funktionen checkVlansInPo200. Ifall
vlanet redan finns på interfacet kommer funktionen svara
tillbaka med True, finns vlanet inte kommer den svara
tillbaka med False"""
if checkVlansInPo200(connection, newVlan) == True:
print(f" vlan: {newVlan} exists in Po200")
"""Finns inte vlanet på interfacet kallar vi på funktionen
addVlansPo200, matar in anslutningsuppgifterna, samt vlanid."""
else:
print(f" vlan: {newVlan} does not exist in Po200")
addVlansPo200(connection, newVlan)
"""Den kommer även kolla på ett till interface, det interface
som går till FW2 så båda trunkportarna är identiska. Därför
görs samma check som mot Po200 även här"""
if checkVlansInPo202(connection, newVlan) == True:
print(f" vlan: {newVlan} exists in Po202")
else:
print(f" vlan: {newVlan} does not exist in Po202")
addVlansPo202(connection, newVlan)
Funktionen veriferar att vi inte skapar om ett vlan som redan finns i vlan databasen. Vi nyttjar sedan genie för att få vår svar mer lämplig för att parsas. Genie dokumentation
def checkVlansInDb(connection: dict, vlanId: int, newVlanName: str):
with NXOSDriver(**connection) as conn:
output = conn.send_command(f'show vlan')
"""Genie hjälper oss att formatera datat som retuneras i ett
format som är enklare för en maskin att förstå, i det här
fallet får vi tillbaka en lista"""
vlans = output.genie_parse_output()
"""if / else kolla om vlanet finns i databasen och retunerar
en boolean. True eller False"""
if str(vlanId) in vlans['vlans']:
return True
else:
return False
Blir utfallet att vlanet inte finns i vlan-databasen så behöver vi skapa vlanet. Det gör vi med hjälp av funktionen createVlan.
def createVlan(connection: dict, vlanId: int):
with NXOSDriver(**connection) as conn:
"""Den nya konfigurationen skickas till switchen med hjälpa
av send_configs som är en del av scrapli. En print för att
se att vlanet har skapats"""
conn.send_configs([f"vlan {vlanId}", f"name {newVlanName}"])
print(f"vlan {vlanId} created")
När vlanet väl är säkerställt att det finns i vlandatabasen är det dags att först säkerställa så det inte redan existerar i trunken. Det gör vi med funktionen checkVlansInPo200. Här kollar vi konfigurationen i running-config på det specifika interfacet. Med hjälp av genie omvanldar vi datat som kommer tillbaka till en läsbar lista som datorn enklare kan parsa.
def checkVlansInPo200(connection: dict, vlanId: int):
with NXOSDriver(**connection) as conn:
outputShowRunInterfacePo200 = conn.send_command(f'show running-config interface port-channel200')
outputShowRunInterfacePo200Parsed = outputShowRunInterfacePo200.genie_parse_output()
vlanListPo200 = outputShowRunInterfacePo200Parsed["interface"]["port-channel200"]["trunk_vlans"].split(",")
"""Följande for loop säkerställen att vi även får med dom
vlan som ofta presenteras som en range i en port konfiguration,
till exempel 100-200. For loopen identiferar ett sådant exempel
genom att kolla om interfacets vlan innehåller "-". Vid ett
sådant tillfälle kommer for loopen att ta bort det värdet och
ersätta det med samtliga vlan som existerar i rangen och addera
dom till vlanListPo200."""
for vlan in vlanListPo200:
if "-" in vlan:
vlanSplit = vlan.split("-")
vlanListPo200.remove(vlan)
vlanStart = int(vlanSplit[0])
vlanStop = int(vlanSplit[1])
for i in range(vlanStart, vlanStop+1):
vlanListPo200.append(str(i))
"""Här undersöker vi om listan vlanListPo200 inneåller vlanet
vi vill konfigurera. Om det är sant retuneras True, är det
falskt retuneras False."""
if vlanId in vlanListPo200:
return True
else:
return False
checkVlansInPo202 gör samma sak som checkVlansInPo200 ovan, men för det andra trunk interfacet.
def checkVlansInPo202(connection: dict, vlanId: int):
with NXOSDriver(**connection) as conn:
outputShowRunInterfacePo202 = conn.send_command(f'show running-config interface port-channel202')
outputShowRunInterfacePo202Parsed = outputShowRunInterfacePo202.genie_parse_output()
vlanListPo202 = outputShowRunInterfacePo202Parsed["interface"]["port-channel202"]["trunk_vlans"].split(",")
for vlan in vlanListPo202:
if "-" in vlan:
vlanSplit = vlan.split("-")
vlanListPo202.remove(vlan)
vlanStart = int(vlanSplit[0])
vlanStop = int(vlanSplit[1])
for i in range(vlanStart, vlanStop+1):
vlanListPo202.append(str(i))
if vlanId in vlanListPo202:
return True
else:
return False
addVlansPo200 adderar vlanet till trunkporten med kommandot switchport trunk allowed vlan add vlanId
def addVlansPo200(connection: dict, vlanId: int):
with NXOSDriver(**connection) as conn:
print(f" adding vlan: {vlanId}, on port po200")
conn.send_configs([f"interface po200", f"switchport trunk allowed vlan add {vlanId}"])
addVlansPo202 gör samma sak som addVlansPo200 fast på den andra trunk porten.
def addVlansPo202(connection: dict, vlanId: int):
with NXOSDriver(**connection) as conn:
print(f" adding vlan: {vlanId}, on port po202")
conn.send_configs([f"interface po202", f"switchport trunk allowed vlan add {vlanId}"])
from scrapli import Scrapli
from scrapli.driver.core import NXOSDriver
import os
#Lista med enheter som ska konfigureras
devices = [
"NX01",
"NX02"
]
username = os.environ.get("USER")
password = os.environ.get("PASS")
credentials = {
"auth_username": username,
"auth_password": password,
"auth_strict_key": False
}
print("This will add vlans Nexuses:")
print("Nexus01\nNexus02")
print("PortChannel 200\nPortChannel 202\nTowards FW Inside Interfaces\n\n---------------")
def checkVlansInDb(connection: dict, vlanId: int, newVlanName: str):
with NXOSDriver(**connection) as conn:
output = conn.send_command(f'show vlan')
vlans = output.genie_parse_output()
#if / else kolla om vlanet finns i databaset.
if str(vlanId) in vlans['vlans']:
return True
else:
return False
def createVlan(connection: dict, vlanId: int):
with NXOSDriver(**connection) as conn:
conn.send_configs([f"vlan {vlanId}", f"name {newVlanName}"])
print(f"vlan {vlanId} created")
def checkVlansInPo200(connection: dict, vlanId: int):
with NXOSDriver(**connection) as conn:
outputShowRunInterfacePo200 = conn.send_command(f'show running-config interface port-channel200')
outputShowRunInterfacePo200Parsed = outputShowRunInterfacePo200.genie_parse_output()
vlanListPo200 = outputShowRunInterfacePo200Parsed["interface"]["port-channel200"]["trunk_vlans"].split(",")
for vlan in vlanListPo200:
if "-" in vlan:
vlanSplit = vlan.split("-")
vlanListPo200.remove(vlan)
vlanStart = int(vlanSplit[0])
vlanStop = int(vlanSplit[1])
for i in range(vlanStart, vlanStop+1):
vlanListPo200.append(str(i))
if vlanId in vlanListPo200:
return True
else:
return False
def checkVlansInPo202(connection: dict, vlanId: int):
with NXOSDriver(**connection) as conn:
outputShowRunInterfacePo202 = conn.send_command(f'show running-config interface port-channel202')
outputShowRunInterfacePo202Parsed = outputShowRunInterfacePo202.genie_parse_output()
vlanListPo202 = outputShowRunInterfacePo202Parsed["interface"]["port-channel202"]["trunk_vlans"].split(",")
for vlan in vlanListPo202:
if "-" in vlan:
vlanSplit = vlan.split("-")
vlanListPo202.remove(vlan)
vlanStart = int(vlanSplit[0])
vlanStop = int(vlanSplit[1])
for i in range(vlanStart, vlanStop+1):
vlanListPo202.append(str(i))
if vlanId in vlanListPo202:
return True
else:
return False
def addVlansPo200(connection: dict, vlanId: int):
with NXOSDriver(**connection) as conn:
print(f" adding vlan: {vlanId}, on port po200")
conn.send_configs([f"interface po200", f"switchport trunk allowed vlan add {vlanId}"])
def addVlansPo202(connection: dict, vlanId: int):
with NXOSDriver(**connection) as conn:
print(f" adding vlan: {vlanId}, on port po202")
conn.send_configs([f"interface po202", f"switchport trunk allowed vlan add {vlanId}"])
if __name__ == "__main__":
#while för att förebygga felaktiga tecken i vlanet
newVlanBolean = False
while newVlanBolean == False:
newVlan = input("vlan: ")
newVlanBolean = newVlan.isnumeric()
if newVlanBolean == False:
print("nope, enter a valid vlan id or exit out")
newVlanName = input("vlan name: ")
for device in devices:
connection = credentials
connection["host"] = device
print(f"Connecting to switch {device}")
if checkVlansInDb(connection, newVlan, newVlanName) == True:
print(f" vlan: {newVlan} exists in vlandb")
else:
print(" Not in db")
createVlan(connection, newVlan, newVlanName)
print(" vlan created")
if checkVlansInPo200(connection, newVlan) == True:
print(f" vlan: {newVlan} exists in Po200")
else:
print(f" vlan: {newVlan} does not exist in Po200")
addVlansPo200(connection, newVlan)
if checkVlansInPo202(connection, newVlan) == True:
print(f" vlan: {newVlan} exists in Po202")
else:
print(f" vlan: {newVlan} does not exist in Po202")
addVlansPo202(connection, newVlan)
Acebit expanderar – automationsess från Dalarna öppnar i Stockholm
Acebit rekryterar Isak Ljunggren – Acebit Trainee från Högskolan Dalarna
Även Falu-Kuriren har intresserat sig för Acebit och besökt oss i Falun!
Emanuel Lipschütz ny styrelseordförande i Acebit
Nyligen stötte jag på ett scenario som innebar att ca 200 Meraki-enheter behövde byta inställning från DHCP till statisk IP-adressering. Istället för att gör...
I mina tidigare inlägg om virtuella port-channels kikade vi på vad det är och vilka delar de utgör. Det här avsnittet kommer beröra hur en grundkonfiguration...
Bakgrund Idag tänkt jag skriva några rader om att skriva concurrent kod, eller “samtidighet” om vi prompt ska översätta det till svenska. För att enklare för...
Scrapli Automation - trunk ports