Skip to content

Commit

Permalink
BUUUUNCH of fixes in this one
Browse files Browse the repository at this point in the history
Fixed
 -ability to reprovision a port, or if it's similiar, clear the tag to remove from scope
 -issue withduplicate AMC addresses on the source config files, fixed that with some duct tape
 -added device status check before checking switch, so offline or unprovisioned switches don't consume cycles
 -added ability to handle more than 1000 clients for monitoring
 -allowed "alerting" devices to be in-scope, had some bad DNS entries, prevented from being provisioned
  • Loading branch information
wifiguru10 committed Sep 28, 2020
1 parent 728450d commit dda0363
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 12 deletions.
69 changes: 58 additions & 11 deletions autoMAC.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@

### USER CONFIGURABLE SETTINGS

org_id = '5723437235866696' #this is the org you want to monitor/configure

allowHistoryConfigs = True #this allows it to use historic configs/mac-addresstables
allowProfileConfigs = True #this allows it to "guess" on the profile based on MAC/OUI/CDP/LLDP/Vendor
WRITE = True #set this to False to test and populate debug log files
Expand Down Expand Up @@ -128,19 +130,20 @@ def validSN(SN, devices):
# the function goes through each switch and assigns priming VLAN and preps it for provisioning
def switch_wipe():
dashboard = meraki.DashboardAPI(api_key=None, base_url='https://api.meraki.com/api/v1/', print_console=False)
org_id = '577586652210266696'
networks = dashboard.organizations.getOrganizationNetworks(org_id)

networks_inscope = [] # target networks
for n in networks:
if n['tags'] is not None and 'autoMAC' in n['tags']:
networks_inscope.append(n)


switches_inscope = []
devices_inscope = []
for n in networks_inscope:
#devices = dashboarad.devices.getNetworkDevices(n['id'])
devices = dashboard.networks.getNetworkDevices(n['id'])

for d in devices:
if 'tags' in d and tag_switch_TARGET in d['tags']:
devices_inscope.append(d)
Expand Down Expand Up @@ -208,7 +211,7 @@ def main():
#client_load(clientDB) #this loads meraki "snapshot", doesn't include voice vlans, need to fix that

msDB = []
sDir = "cisco/"
sDir = "cisco/paris_raw2/"
if allowHistoryConfigs:
cisco_load(msDB, clientDB, sDir)

Expand All @@ -224,7 +227,6 @@ def main():
# Fire up Meraki API and build DB's
dashboard = meraki.DashboardAPI(api_key=None, base_url='https://api.meraki.com/api/v1/', log_file_prefix=__file__[:-3], print_console=False)
loop = True
org_id = '577586652210266696'

#load Port Config detault library
PC = portConfig()
Expand All @@ -243,6 +245,13 @@ def main():
for n in networks:
if n['tags'] is not None and 'autoMAC' in n['tags']:
networks_inscope.append(n)

online_devices = []
stats = dashboard.organizations.getOrganizationDevicesStatuses(org_id)
for s in stats:
if s['status'] == 'online' or s['status'] == 'alerting':
online_devices.append(s['serial'])


switches_inscope = []
devices_inscope = []
Expand All @@ -254,8 +263,9 @@ def main():
for d in devices:
if 'tags' in d and tag_switch_TARGET in d['tags']:
#dashboard.devices.blinkNetworkDeviceLeds(n['id'], serial=d['serial'], duration=5, duty=10, period=100 )
dashboard.devices.blinkDeviceLeds(serial=d['serial'], duration=5, duty=10, period=100 )
devices_inscope.append(d)
if d['serial'] in online_devices:
dashboard.devices.blinkDeviceLeds(serial=d['serial'], duration=5, duty=10, period=100 )
devices_inscope.append(d)

print(f'{bcolors.OKBLUE}Networks Inscope:')
for n in networks_inscope:
Expand Down Expand Up @@ -309,14 +319,36 @@ def main():
# print()

port_changes = []

total_clients = 0
# new network device function, works at network level instead of querying each switch
for n in networks_inscope:
netid = n['id']
#clients = dashboard.clients.getNetworkClients(netid, perPage=1000)
clients = dashboard.networks.getNetworkClients(netid, perPage=1000)

lastId = ""
if len(clients) == 1000:
lastId = clients[999]['id']
clients = clients + dashboard.networks.getNetworkClients(netid, perPage=1000, startingAfter=lastId)
lastId = clients[len(clients)-1]['id']
newclients = dashboard.networks.getNetworkClients(netid, perPage=1000, startingAfter=lastId)
while len(newclients) >= 1:
#print(f'Clients {len(clients)}')
#print(f'NewClients {len(newclients)}')
#print(lastId)
clients = clients + newclients
lastId = newclients[len(newclients)-1]['id']
newclients = dashboard.networks.getNetworkClients(netid, perPage=1000, startingAfter=lastId)
if len(newclients) <= 1:
break


print(f'{bcolors.OKBLUE}Detected total {bcolors.WARNING}{len(clients)}{bcolors.OKBLUE} in Network[{bcolors.WARNING}{n["name"]}{bcolors.OKBLUE}]')
total_clients = total_clients + len(clients)
print(f'{bcolors.OKBLUE}TOTAL Clients Detected: {bcolors.WARNING}{len(clients)}{bcolors.OKBLUE} in {bcolors.WARNING}ALL{bcolors.OKBLUE} networks')

for c in clients: #interate through the ACTIVE clients on dashboard (target switches)
if c['status'] == "Offline":
continue
update = False
serial = ""
serial = c['recentDeviceSerial']
Expand All @@ -332,11 +364,13 @@ def main():
vlan = int(sourceClient['vlan'])
update = True
ovlan = int(c['vlan'])
print(f'{bcolors.FAIL}VLAN Misconfiguration Client activeVlan[{bcolors.WARNING}{ovlan}{bcolors.FAIL}] OriginalVlan[{bcolors.WARNING}{vlan}{bcolors.FAIL}]')
#print(c)
#print(f'{bcolors.OKGREEN}{c}{bcolors.ENDC}')


if isActivePort(serial, port, ports_inscope):

print(f'{bcolors.FAIL}VLAN Misconfiguration Client activeVlan[{bcolors.WARNING}{ovlan}{bcolors.FAIL}] OriginalVlan[{bcolors.WARNING}{vlan}{bcolors.FAIL}] Mac[{bcolors.WARNING}{c["mac"]}{bcolors.FAIL}] Manufacturer[{bcolors.WARNING}{c["manufacturer"]}{bcolors.FAIL}] Desc[{bcolors.WARNING}{c["description"]}{bcolors.FAIL}]')

# if there's a change, make an update
if update and c['status'] == "Online": #Changes is to be made and port is up
#print(c)
Expand Down Expand Up @@ -421,7 +455,12 @@ def main():
orig_mac = findMAC(msDB,mac)
orig_sw = getSW(msDB,orig_mac['name'])
orig_port = orig_sw.parsedCFG(orig_mac['port'])
oVlan = orig_port['vlan']
oVlan = vlan
try:
oVlan = orig_port['vlan']
except:
print(f'Failure on port: {orig_port} NewPort[{newPort}]')

if 'voiceVlan' in orig_port:
ovoiceVlan = orig_port['voiceVlan']
else:
Expand Down Expand Up @@ -454,7 +493,15 @@ def main():


else:
print(f'{bcolors.FAIL}Port is already configured{bcolors.WARNING}!!!!!{bcolors.OKBLUE}')
print(f'{bcolors.FAIL}Port is already configured{bcolors.WARNING}!!!!! Clearing port tag{bcolors.OKBLUE}')
if WRITE:
res = dashboard.switch.updateDeviceSwitchPort(S1, P1, tags=tags)
log(f'[WRITE] API updateDeviceSwitchPorts')
else:
print(f'{bcolors.OKGREEN}[READ-ONLY BYPASS]')
log(f'[READ-ONLY] API updateDeviceSwitchPorts')


print()

print()
Expand Down
12 changes: 11 additions & 1 deletion switchDB.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ def parseMAC(self):

# print(f'{vlan} {mac} {port}')

#print(f'ISTRUNK[{port}]')
#print(self.isTrunk(port))
if port == "Gi1/0/48":
continue
if self.isTrunk(port):
continue
if not mac in self.macs:
self.macs.append(mac)
if not vlan in self.vlans:
Expand All @@ -53,7 +59,11 @@ def parseMAC(self):

# this function takes file target and loads it into the parse field
def parseFile(self, target):
self.name = target.split(' ')[1].split('.')[0]
try:
self.name = target.split(' ')[1].split('.')[0]
except:
self.name = target.split('.')[0]
print("PARSED")
self.parse = CiscoConfParse(target)
parse_interfaces = self.parse.find_objects('^interface ')
self.length = str(len(parse_interfaces))
Expand Down

0 comments on commit dda0363

Please sign in to comment.