class ReplaceDevice(FlaskForm): #NETWORK DROPDOWN networks = merakiapi.getnetworklist(apikey, organizationid) cleannetworks = [] for network in networks: for key, value in network.items(): if key == 'id': net_id = value elif key == 'name': net_name = value else: continue cleannetworks.append([net_id, net_name]) cleannetworks.sort(key=lambda x: x[1]) cleannetworks.insert(0, [None, '* Choose...']) networkField = SelectField(u'Network Name', choices=cleannetworks) #SERIAL NUMBER FIELDS oldMX = StringField('MX to Replace: ', [ validators.Optional(), validators.Length( min=14, max=14, message='Invalid format. Must be Q2XX-XXXX-XXXX') ]) newMX = StringField('New MX: ', [ validators.Optional(), validators.Length( min=14, max=14, message='Invalid format. Must be Q2XX-XXXX-XXXX') ]) oldSwitch = StringField('Switch to Replace: ', [ validators.Optional(), validators.Length( min=14, max=14, message='Invalid format. Must be Q2XX-XXXX-XXXX') ]) newSwitch = StringField('New Switch: ', [ validators.Optional(), validators.Length( min=14, max=14, message='Invalid format. Must be Q2XX-XXXX-XXXX') ]) oldAP = StringField('AP to Replace: ', [ validators.Optional(), validators.Length( min=14, max=14, message='Invalid format. Must be Q2XX-XXXX-XXXX') ]) newAP = StringField('New AP: ', [ validators.Optional(), validators.Length( min=14, max=14, message='Invalid format. Must be Q2XX-XXXX-XXXX') ]) submitField = SubmitField('Submit')
def spark_get_networks_cmd(api_key, org_id, room_id): dashboard_response = merakiapi.getnetworklist(api_key, org_id) table = PrettyTable(["Network ID", "Network Name", "Tags"]) for row in dashboard_response: net_id = row['id'] net_name = row['name'] net_tags = row['tags'] table_row = [net_id, net_name, net_tags] table.add_row(table_row) payload = { 'roomId': str(room_id), 'text': str(table.get_string(sortby="Network Name")) } bot_response_to_spark = requests.post(spark_url, data=json.dumps(payload), headers=spark_header) print(bot_response_to_spark.status_code) print(str(table.get_string(sortby="Network Name")))
def bulkupdate(): form = BulkForm() if form.validate_on_submit(): message = [] allnetworkstochange = [] mxnetworkstochange = [] mrnetworkstochange = [] networks = merakiapi.getnetworklist(apikey, organizationid) for network in networks: mxnetworktypes = ['combined', 'appliance'] mrnetworktypes = ['combined', 'wireless'] if (network['tags'] == ''): continue else: temptags = str(network['tags']).split(' ') for tag in temptags: if tag.strip() == form.tagField.data: allnetworkstochange.append(network['id']) if any(x in network['type'] for x in mxnetworktypes): mxnetworkstochange.append(network['id']) if any(x in network['type'] for x in mrnetworktypes): mrnetworkstochange.append(network['id']) continue #SET IPS if form.setips.data == True: for network in mxnetworkstochange: netname = merakiapi.getnetworkdetail(apikey, network) print("CHANGING IPS SETTINGS FOR NETWORK: {}".format( netname['name'])) if form.ipsmode.data == 'disabled': result = merakiapi.updateintrusion(apikey, network, mode=form.ipsmode.data) else: result = merakiapi.updateintrusion( apikey, network, mode=form.ipsmode.data, idsRulesets=form.ipsrules.data) if result == None: message.append( 'IPS settings successfully updated for Network: <strong>{}</strong>' .format(netname['name'])) else: message.append(result) ###FINISH VPN if form.setvpn.data == True: hubnets = [] defaults = [] if 'none' not in form.hub1.data: hubnets.append(form.hub1.data) defaults.insert(0, form.default1.data) if 'none' not in form.hub2.data: hubnets.append(form.hub2.data) defaults.insert(1, form.default2.data) if 'none' not in form.hub3.data: hubnets.append(form.hub3.data) defaultsinsert(2, form.default3.data) for network in mxnetworkstochange: vpnsettings = merakiapi.getvpnsettings(apikey, network) print(vpnsettings) if 'subnets' in vpnsettings: merakiapi.updatevpnsettings(apikey, network, mode='spoke', subnets=vpnsettings['subnets'], hubnetworks=hubnets, defaultroute=defaults) else: merakiapi.updatevpnsettings(apikey, network, mode='spoke', hubnetworks=hubnets, defaultroute=defaults) #SET SSID PSK if form.setpsk.data == True: for network in mrnetworkstochange: ssid = merakiapi.getssiddetail(apikey, network, form.ssidnum.data) result = merakiapi.updatessid( apikey, network, form.ssidnum.data, ssid['name'], ssid['enabled'], ssid['authMode'], ssid['encryptionMode'], ssid['ipAssignmentMode'], form.ssidpsk.data) if result == None: message = Markup( 'SSID Successfully updated for Network: <strong>{}</strong>' .format(network)) else: message = result #SEND MESSAGE TO SUBMIT PAGE flash(message) return redirect('/submit') return render_template('bulk.html', title='Meraki Bulk Changes', form=form)
#flask run --host=0.0.0.0 # import merakiapi, config from flask import Flask, render_template, redirect, flash, Markup from flask_wtf import FlaskForm from wtforms import StringField, SelectField, SubmitField, TextAreaField, PasswordField, BooleanField, validators import datetime import re, sys #CHANGE THESE TO MATCH DESIRED MERAKI ORGANIZATION apikey = config.apikey organizationid = config.organizationid #NETWORK DROPDOWN networks = merakiapi.getnetworklist(apikey, organizationid) cleannetworks = [] for network in networks: for key, value in network.items(): if key == 'id': net_id = value elif key == 'name': net_name = value else: continue cleannetworks.append([net_id, net_name]) cleannetworks.sort(key=lambda x: x[1]) cleannetworks.insert(0, [None, '* Choose...']) #TEMPLATE DROPDOWN templates = merakiapi.gettemplates(apikey, organizationid)
import merakiapi apikey = 'ENTER API KEY HERE' orgid = 'ENTER ORG ID HERE' templatename = 'ENTER THE NAME OF THE TARGET TEMPLATE HERE' templates = merakiapi.gettemplates(apikey, orgid) for template in templates: if template['name'] == templatename: templateid = template['id'] mxnetworks = [] orgnets = merakiapi.getnetworklist(apikey, orgid) for network in orgnets: if network['type'] == 'appliance' and network['name'][:2] == 'zz': mxnetworks.append({'id': network['id'], 'name': network['name']}) for mxnetwork in mxnetworks: newnet = True vlans = merakiapi.getvlans(apikey, mxnetwork['id']) if vlans is None: pass elif newnet is True: print('\nBinding Network - {0}'.format(str(mxnetwork['name']))) merakiapi.bindtotemplate(apikey, mxnetwork['id'], templateid) newnet = False x = 0
def main(argv): outfile = 'results.out' backupfile = 'backup.vpn' hasinput = False hasoutput = False hasinvalidin = False try: opts, args = getopt.getopt(argv, "hi:o:", ["ifile=", "ofile="]) except getopt.GetoptError: print( 'Usage: python3 sample-vpnhub-migrate.py -i <inputfile> -o <outputfile>' ) sys.exit(2) for opt, arg in opts: if opt == '-h': print( 'Usage: python3 sample-vpnhub-migrate.py -i <inputfile> -o <outputfile>' ) sys.exit() elif opt in ("-i", "--ifile"): inputfile = arg hasinput = True elif opt in ("-o", "--ofile"): outfile = arg hasoutput = True if hasinput is False: print( 'Usage: python3 sample-vpnhub-migrate.py -i <inputfile> -o <outputfile>\n' ) print('Input file must be specified') exit() if hasoutput is False: print( '\n***WARNING***\nNo output file specified, "{0}" will be used for output' .format(str(outfile))) print('\n*** Original VPN JSON results will be backed up to {0}'.format( str(backupfile))) try: filein = open(inputfile) fileout = open(outfile, 'w') backup = open(backupfile, 'w') vpnnetmap = list(csv.DictReader(filein)) originalmap = copy.deepcopy(vpnnetmap) keys = vpnnetmap[0].keys() if len(keys) % 2 != 1 or len(keys) < 3: raise KeyError( 'Invalid number of columns, CSV file must include a network name and at least one pair of ' 'hubname and defaultroute definitions, e.g. "networkname,vpn1hubname,vpn1defaultroute"' ) numhubs = int(((len(keys) - 1) / 2)) newhublist = [] newhub = {} orgnets = merakiapi.getnetworklist(apikey, org, suppressprint=True) for idx, vl in enumerate(vpnnetmap): invalidentry = False originalmap[idx].update({'error': None, 'posterror': None}) if not any(n['name'] == str(vl['networkname']) for n in orgnets): originalmap[idx]['error'] = 'INVALID NETWORK NAME' hasinvalidin = True invalidentry = True else: networkdetails = next( (net for net in orgnets if net['name'] == vl['networkname']), None) if networkdetails is not None: nid = str(networkdetails['id']) oldvpn = merakiapi.getvpnsettings(apikey, nid, suppressprint=True) backup.write(json.dumps(oldvpn) + '\n') newvpn = copy.deepcopy(oldvpn) newvpn.update({'networkId': nid}) else: oldvpn = None if oldvpn['mode'] == 'none' or oldvpn is None: originalmap[idx][ 'error'] = 'NETWORK NOT CURRENTLY CONFIGURED FOR VPN' hasinvalidin = True invalidentry = True else: x = 1 while x <= numhubs: # if not any(n['name'] == vl['vpn{0}hubname'.format(str(x))] for n in orgnets): # originalmap[idx]['error'] == 'INVALID HUB NAME FOR HUB {0}'.format(str(x)) # hasinvalidin == True newhub.clear() hubkey = 'vpn' + str(x) + 'hubname' drkey = 'vpn' + str(x) + 'defaultroute' if vl[hubkey] is not None and vl[drkey] is not None: temphubid = (n['id'] for n in orgnets if n['name'] == vl[hubkey]) newhub['hubId'] = ''.join(temphubid) if str(vl[drkey]).lower() in { 'true', 'false' } and vl[drkey] is not None: if str(vl[drkey]).lower() == 'true': newhub['useDefaultRoute'] = bool(1) elif str(vl[drkey]).lower() == 'false': newhub['useDefaultRoute'] = bool(0) newhublist.append(copy.deepcopy(newhub)) else: originalmap[idx]['error'] = 'HUB {0}, INVALID DEFAULT ROUTE MUST BE TRUE/FALSE IF HUB' \ 'DEFINED'.format(str(x)) hasinvalidin = True invalidentry = True x += 1 if newvpn['mode'] != 'none' and invalidentry is not True: newvpn['hubs'] = newhublist headers = { 'x-cisco-meraki-api-key': format(str(apikey)), 'Content-Type': 'application/json' } nid = newvpn.pop('networkId', None) putdata = json.dumps(newvpn) puturl = '{0}/networks/{1}/siteToSiteVpn'.format( str(base_url), str(nid)) dashboard = requests.put(puturl, data=putdata, headers=headers) if dashboard.status_code == 200: print('\nUpdated Network - "{0}"'.format(str(nid))) else: originalmap[idx][ 'posterror'] = 'UNABLE TO POST - STATUS CODE {0}'.format( str(dashboard.status_code)) hasinvalidin == True for e in originalmap: try: if e['error'] is not None or e['posterror'] is not None: print(json.dumps(e) + '\n', file=fileout) except KeyError: pass if hasinvalidin == True: print( '\n****ERRORS FOUND IN INPUT FILE****\nInvalid Entries in input CSV, see {0} for details' .format(str(outfile))) except IOError: print("***ERROR***\nInput file does not exist: {0}".format( str(inputfile))) exit() finally: filein.close() fileout.close() backup.close()
# Create a list of Org ID's called org_id_list # For every row of JSON output, append the value of "v" (org ID) when k = 'id' for row in org_ids_json: # print row for k, v in row.iteritems(): if k == 'id': org_id_list.append(v) else: continue # print org_id_list # For every 'org' in org_id_list, use the getnetworklist function in the # merakiapi library (Rob Watt) feeding it the api_key and Org ID it needs for org in org_id_list: per_net_list = merakiapi.getnetworklist(api_key, org) for row in per_net_list: # For each 'row' of JSON in per_net_list, print the row to the terminal print "Raw JSON: %s \n" % row # for watching live # print str(row['type']) # just an example of how to reference a # specific value in the JSON for key, value in row.iteritems(): # print "k,v is %s,%s" % (key,value) # example if key == 'name': net_name = value elif key == 'id': net_id = value else: continue csv_row_text = "%s, %s" % (str(net_id), str(net_name)) csv_writer.writerow([csv_row_text])
def main(argv): outputfile = 'results.csv' hasinput = False hasoutput = False hasinvalidin = False try: opts, args = getopt.getopt(argv, "hi:o:", ["ifile=", "ofile="]) except getopt.GetoptError: print( 'Usage: python3 config-extractor.py -i <inputfile> -o <outputfile>' ) sys.exit(2) for opt, arg in opts: if opt == '-h': print( 'Usage: python3 config-extractor.py -i <inputfile> -o <outputfile>' ) sys.exit() elif opt in ("-i", "--ifile"): inputfile = arg hasinput = True elif opt in ("-o", "--ofile"): outputfile = arg hasoutput = True if hasinput is False: print( 'Usage: python3 config-extractor.py -i <inputfile> -o <outputfile>\n' ) print('Input file must be specified') exit() if hasoutput is False: print( '\n***WARNING***\nNo output file specified, "{0}" will be used for output' .format(str(outputfile))) try: infile = open(inputfile) vpnnetmap = list(csv.reader(infile)) errorcsv = inputfile + '.error' except IOError: print("***ERROR***\nInput file does not exist: {0}".format( str(inputfile))) exit() finally: infile.close() orgnets = merakiapi.getnetworklist(apikey, org, suppressprint=True) hubs = [] for net in orgnets: if net['type'] in ('appliance', 'combined'): vpntype = merakiapi.getvpnsettings(apikey, net['id'], suppressprint=True) if vpntype['mode'] == 'hub': hubs.append({'id': net['id'], 'name': net['name']}) vpnnetmap.pop(0) originalmap = copy.deepcopy(vpnnetmap) out = open(outputfile, 'w+') for idx, v in enumerate(vpnnetmap): x = 1 invalidname = False try: v[0] = next(item for item in orgnets if item['name'] == v[0])['id'] except StopIteration: print('\n***ERROR***\nNetwork name "{0}" is invalid'.format( str(v[0]))) v[0] = 'INVALID NAME' originalmap[idx][0] = 'INVALID NAME' hasinvalidin = True invalidname = True if invalidname == False: while x < len(v) and len(v) > 1: if x % 2 == 0: if str(v[x]).lower() not in ['true', 'false']: print( '\n***ERROR***\nVPN hub default route must BE True or False' ) v[x] = 'NOT TRUE/FALSE' originalmap[idx][x] = 'NOT TRUE/FALSE' hasinvalidin = True else: try: v[x] = next(item for item in hubs if item['name'] == v[x])['id'] except StopIteration: print( '\n***ERROR***\n"{0}" is not a valid VPN Hub Network - See output file for details' .format(str(v[x]))) v[x] = 'INVALID HUB' originalmap[idx][x] = 'INVALID HUB' hasinvalidin = True x += 1 for idx, n in enumerate(vpnnetmap): if ('INVALID HUB' in n) or ('NOT TRUE/FALSE' in n) or ('INVALID NAME' in n): pass else: newhubs = [] oldvpn = merakiapi.getvpnsettings(apikey, n[0], suppressprint=True) for h, d in zip(n[1::2], n[2::2]): newhubs.append({'useDefaultRoute': bool(d), 'hubId': h}) newvpn = copy.deepcopy(oldvpn) newvpn['hubs'] = newhubs headers = { 'x-cisco-meraki-api-key': format(str(apikey)), 'Content-Type': 'application/json' } putdata = json.dumps(newvpn) puturl = '{0}/networks/{1}/siteToSiteVpn'.format( str(base_url), str(n[0])) dashboard = requests.put(puturl, data=putdata, headers=headers) if dashboard.status_code == 200: print('\nUpdating Network - "{0}"'.format( str(originalmap[idx][0]))) print('Network:\n{0}\nOld Data:\n{1}\nNew Data:\n{2}'.format( str(originalmap[idx][0]), str(oldvpn), str(newvpn)), file=out) else: print('Network:\n{0}\nAPI Call Failed\n{1}'.format( str(originalmap[idx][0]), str(dashboard.text)), file=out) if hasinvalidin == True: print( '\n****ERRORS FOUND IN INPUT FILE****\nInvalid Entries in input CSV, see {0} for details' .format(str(errorcsv))) with open(errorcsv, 'w+', newline='') as f: writer = csv.writer(f) writer.writerows(originalmap) f.close()
def main(argv): outfile = 'results.out' backupfile = 'backup.vpn' hasinput = False hasoutput = False hasinvalidin = False try: opts, args = getopt.getopt(argv, "hi:o:", ["ifile=", "ofile="]) except getopt.GetoptError: print('Usage: python3 sample-vpnhub-migrate.py -i <inputfile> -o <outputfile>') sys.exit(2) for opt, arg in opts: if opt == '-h': print('Usage: python3 sample-vpnhub-migrate.py -i <inputfile> -o <outputfile>') sys.exit() elif opt in ("-i", "--ifile"): inputfile = arg hasinput = True elif opt in ("-o", "--ofile"): outfile = arg hasoutput = True if hasinput is False: print('Usage: python3 sample-vpnhub-migrate.py -i <inputfile> -o <outputfile>\n') print('Input file must be specified') exit() if hasoutput is False: print('\n***WARNING***\nNo output file specified, "{0}" will be used for output'.format(str(outfile))) print('\n*** Original VPN JSON results will be backed up to {0}'.format(str(backupfile))) try: filein = open(inputfile) fileout = open(outfile, 'w') backup = open(backupfile, 'w') vpnnetmap = list(csv.DictReader(filein)) originalmap = copy.deepcopy(vpnnetmap) keys = vpnnetmap[0].keys() if len(keys) % 2 != 1 or len(keys) < 3: raise KeyError('Invalid number of columns, CSV file must include a network name and at least one pair of ' 'hubname and defaultroute definitions, e.g. "networkname,vpn1hubname,vpn1defaultroute"') numhubs = int(((len(keys) - 1) / 2)) newhublist = [] newhub = {} orgnets = merakiapi.getnetworklist(apikey, org, suppressprint=True) for idx, vl in enumerate(vpnnetmap): invalidentry = False originalmap[idx].update({'error': None, 'posterror': None}) if not any(n['name'] == str(vl['networkname']) for n in orgnets): originalmap[idx]['error'] = 'INVALID NETWORK NAME' hasinvalidin = True invalidentry = True else: networkdetails = next((net for net in orgnets if net['name'] == vl['networkname']), None) if networkdetails is not None: nid = str(networkdetails['id']) oldvpn = merakiapi.getvpnsettings(apikey, nid, suppressprint=True) backup.write(json.dumps(oldvpn) + '\n') newvpn = copy.deepcopy(oldvpn) newvpn.update({'networkId': nid}) else: oldvpn = None if oldvpn['mode'] == 'none' or oldvpn is None: originalmap[idx]['error'] = 'NETWORK NOT CURRENTLY CONFIGURED FOR VPN' hasinvalidin = True invalidentry = True else: x = 1 while x <= numhubs: # if not any(n['name'] == vl['vpn{0}hubname'.format(str(x))] for n in orgnets): # originalmap[idx]['error'] == 'INVALID HUB NAME FOR HUB {0}'.format(str(x)) # hasinvalidin == True newhub.clear() hubkey = 'vpn' + str(x) + 'hubname' drkey = 'vpn' + str(x) + 'defaultroute' if vl[hubkey] is not None and vl[drkey] is not None: temphubid = (n['id'] for n in orgnets if n['name'] == vl[hubkey]) newhub['hubId'] = ''.join(temphubid) if str(vl[drkey]).lower() in {'true', 'false'} and vl[drkey] is not None: if str(vl[drkey]).lower() == 'true': newhub['useDefaultRoute'] = bool(1) elif str(vl[drkey]).lower() == 'false': newhub['useDefaultRoute'] = bool(0) newhublist.append(copy.deepcopy(newhub)) else: originalmap[idx]['error'] = 'HUB {0}, INVALID DEFAULT ROUTE MUST BE TRUE/FALSE IF HUB' \ 'DEFINED'.format(str(x)) hasinvalidin = True invalidentry = True x += 1 if newvpn['mode'] != 'none' and invalidentry is not True: newvpn['hubs'] = newhublist headers = { 'x-cisco-meraki-api-key': format(str(apikey)), 'Content-Type': 'application/json' } nid = newvpn.pop('networkId', None) putdata = json.dumps(newvpn) puturl = '{0}/networks/{1}/siteToSiteVpn'.format(str(base_url), str(nid)) dashboard = requests.put(puturl, data=putdata, headers=headers) if dashboard.status_code == 200: print('\nUpdated Network - "{0}"'.format(str(nid))) else: originalmap[idx]['posterror'] = 'UNABLE TO POST - STATUS CODE {0}'.format(str(dashboard.status_code)) hasinvalidin == True for e in originalmap: try: if e['error'] is not None or e['posterror'] is not None: print(json.dumps(e) + '\n', file=fileout) except KeyError: pass if hasinvalidin == True: print('\n****ERRORS FOUND IN INPUT FILE****\nInvalid Entries in input CSV, see {0} for details' .format(str(outfile))) except IOError: print("***ERROR***\nInput file does not exist: {0}".format(str(inputfile))) exit() finally: filein.close() fileout.close() backup.close()
# "new" template while retaining and re-applying VLAN IP address configuration # ######################################################################################################################## import merakiapi import my_vars # API key, Org, and Config template ID's can be set directly in this script instead of importing from a my_vars file apikey = my_vars.api_key orgid = my_vars.org_id old_templateid = my_vars.old_template_id new_templateid = my_vars.new_template_id mxnetworks = [] # GET the list of networks under an Org ID orgnets = merakiapi.getnetworklist(apikey, orgid) # Create a list of networks bound to "old" configTemplateId for network in orgnets: for k, v in network.items(): if k == 'configTemplateId' and v == old_templateid: print('Network: {0} is bound to old template ID: {1} !'.format( str(network['name']), str(old_templateid))) mxnetworks.append({'id': network['id'], 'name': network['name']}) # Loop through each network, GET VLAN info, unbind/bind old/new template for mxnetwork in mxnetworks: newnet = True vlans = merakiapi.getvlans(apikey, mxnetwork['id']) print('Storing current VLAN IP addressing...\n{0}'.format(str(vlans))) if vlans is None:
notes = 'This text will be inserted in the notes field of all devices' # API doesn't provide gateway information for devices, this variable allows defining gateway manually gateway = '###.###.###.###' # Check for existing bulk import file, if it doesn't exist create new file with header line if os.path.isfile(bncfile): writefile = open(bncfile, 'a+') else: writefile = open(bncfile, 'w+') print('Network name,Serial,Network tags,Name,Tags,Address,Notes,Static IP,Netmask,Gateway,DNS1,DNS2,VLAN', file=writefile) orgnetworks = merakiapi.getnetworklist(apikey, org, suppressprint=True) for network in orgnetworks: networkname = network['name'] if 'tags' not in network: networktags = '' else: networktags = network['tags'] devicelist = merakiapi.getnetworkdevices(apikey, network['id'], suppressprint=True) for device in devicelist: if 'serial' not in device: serialnum = '' else: serialnum = device['serial'] if 'name' not in device: devicename = ''
# Create a list of Org ID's called org_id_list # For every row of JSON output, append the value of "v" (org ID) when k = 'id' for row in org_ids_json: # print row for k,v in row.iteritems(): if k == 'id': org_id_list.append(v) else: continue # print org_id_list # For every 'org' in org_id_list, use the getnetworklist function in the # merakiapi library (Rob Watt) feeding it the api_key and Org ID it needs for org in org_id_list: per_net_list = merakiapi.getnetworklist(api_key,org) for row in per_net_list: # For each 'row' of JSON in per_net_list, print the row to the terminal print "Raw JSON: %s \n" % row # for watching live # print str(row['type']) # just an example of how to reference a # specific value in the JSON for key, value in row.iteritems(): # print "k,v is %s,%s" % (key,value) # example if key == 'name': net_name = value elif key == 'id': net_id = value else: continue csv_row_text = "%s, %s" % (str(net_id), str(net_name)) csv_writer.writerow([csv_row_text])
class AddProvisionForm(FlaskForm): #ADDRESS FIELD addressField = TextAreaField( 'Street Address: ', [validators.Optional(), validators.length(max=200)]) #SERIAL NUMBER FIELDS serialField1 = StringField('Serial Number 1*: ', [ validators.InputRequired(), validators.Length( min=14, max=14, message='Invalid format. Must be Q2XX-XXXX-XXXX') ]) serialField2 = StringField('Serial Number 2: ', [ validators.Optional(), validators.Length( min=14, max=14, message='Invalid format. Must be Q2XX-XXXX-XXXX') ]) serialField3 = StringField('Serial Number 3: ', [ validators.Optional(), validators.Length( min=14, max=14, message='Invalid format. Must be Q2XX-XXXX-XXXX') ]) serialField4 = StringField('Serial Number 4: ', [ validators.Optional(), validators.Length( min=14, max=14, message='Invalid format. Must be Q2XX-XXXX-XXXX') ]) serialField5 = StringField('Serial Number 5: ', [ validators.Optional(), validators.Length( min=14, max=14, message='Invalid format. Must be Q2XX-XXXX-XXXX') ]) serialField6 = StringField('Serial Number 6: ', [ validators.Optional(), validators.Length( min=14, max=14, message='Invalid format. Must be Q2XX-XXXX-XXXX') ]) serialField7 = StringField('Serial Number 7: ', [ validators.Optional(), validators.Length( min=14, max=14, message='Invalid format. Must be Q2XX-XXXX-XXXX') ]) serialField8 = StringField('Serial Number 8: ') nameField1 = StringField('Device Name: ', [validators.Optional()]) nameField2 = StringField('Device Name: ', [validators.Optional()]) nameField3 = StringField('Device Name: ', [validators.Optional()]) nameField4 = StringField('Device Name: ', [validators.Optional()]) nameField5 = StringField('Device Name: ', [validators.Optional()]) nameField6 = StringField('Device Name: ', [validators.Optional()]) nameField7 = StringField('Device Name: ', [validators.Optional()]) nameField8 = StringField('Device Name: ', [validators.Optional()]) submitField = SubmitField('Submit') #NETWORK DROPDOWN networks = merakiapi.getnetworklist(apikey, organizationid) cleannetworks = [] for network in networks: for key, value in network.items(): if key == 'id': net_id = value elif key == 'name': net_name = value else: continue cleannetworks.append([net_id, net_name]) cleannetworks.sort(key=lambda x: x[1]) cleannetworks.insert(0, [None, '* Choose...']) networkField = SelectField(u'Network Name', choices=cleannetworks)
def provisionNetwork(): form = CreateProvisionForm() if form.validate_on_submit(): message = [] postSerials = [] postNames = [] postNetwork = form.networkTextField.data #print(postNetwork) postTemplate = form.templateField.data #BUILD ARRAY OF SERIAL NUMBERS FROM FORM postSerials.append(form.serialField1.data) postSerials.append(form.serialField2.data) postSerials.append(form.serialField3.data) postSerials.append(form.serialField4.data) postSerials.append(form.serialField5.data) postSerials.append(form.serialField6.data) postSerials.append(form.serialField7.data) postSerials.append(form.serialField8.data) postSerials = [element.upper() for element in postSerials] postSerials postNames.append(form.nameField1.data) postNames.append(form.nameField2.data) postNames.append(form.nameField3.data) postNames.append(form.nameField4.data) postNames.append(form.nameField5.data) postNames.append(form.nameField6.data) postNames.append(form.nameField7.data) postNames.append(form.nameField8.data) #CREATE NETWORK AND BIND TO TEMPLATE result = merakiapi.addnetwork(apikey, organizationid, postNetwork, "appliance switch wireless", "", "America/Los_Angeles") #GET NEW NETWORK ID networks = merakiapi.getnetworklist(apikey, organizationid) for network in networks: if network['name'] == postNetwork: newnetwork = network['id'] break message = Markup( "New Network created: <strong>{}</strong> with ID: <strong>{}</strong>" .format(postNetwork, newnetwork)) flash(message) #BIND TO TEMPLATE if form.templateField.data is not "": bindresult = merakiapi.bindtotemplate(apikey, newnetwork, postTemplate) message = Markup( "Network: <strong>{}</strong> bound to Template: <strong>{}</strong>" .format(postNetwork, postTemplate)) flash(message) #ADD SERIALS TO NETWORK for i, serial in enumerate(postSerials): #SKIP EMPTY SERIAL NUMBER TEXT BOXES if serial is '': continue #EASTER EGG elif "ILOVEMERAKI" in serial: message = Markup("<img src='/static/meraki.png' />") else: result = merakiapi.adddevtonet(apikey, newnetwork, serial) if result == None: #SET ADDRESS AND NAME merakiapi.updatedevice(apikey, newnetwork, serial, name=postNames[i], address=form.addressField.data, move='true') #API RETURNS EMPTY ON SUCCESS, POPULATE SUCCESS MESSAGE MANUALLY netname = merakiapi.getnetworkdetail(apikey, newnetwork) message = Markup( 'Device with serial <strong>{}</strong> successfully added to Network: <strong>{}</strong>' .format(serial, netname['name'])) #404 MESSAGE FOR INVALID SERIAL IS BLANK, POPULATE ERROR MESSAGE MANUALLY elif result == 'noserial': message = Markup( 'Invalid serial <strong>{}</strong>'.format(serial)) else: message = result #SEND MESSAGE TO SUBMIT PAGE flash(message) return redirect('/submit') return render_template('indextemplate.html', title='Meraki Device Provisioning', form=form)
import merakiapi # # Sample Python Script Using Meraki API module to pull VLAN Details for MX Devices in an organization # Enter API Key and Organization ID into variables # apikey = 'xxxxx' organizationid = 'xxxxxxxxxxx' networks = merakiapi.getnetworklist(apikey, organizationid) for row in networks: vlans = merakiapi.getvlans(apikey, row['id']) print('VLAN Details for Network ID {0}'.format(str(row['id']))) for vlanrow in vlans: vlandetail = merakiapi.getvlandetail(apikey, row['id'], vlanrow['id']) print(vlandetail, end='\n')
def miles(): form = MilesForm() if form.validate_on_submit(): apikey = 'b085d5d5afd8d448948e1e9b35ee03a6d5db6543' organizationid = '209700' messages = [] networks = merakiapi.getnetworklist(apikey, organizationid) query = form.queryField.data.lower() workingquestion = ['how is ', 'how\'s ', 'hows '] workingwords = [' working', ' doing', ' operating', ' performing'] for word in workingwords: if word in query: for question in workingquestion: if question in query: part1 = query.split(question, 1)[1] netordev = part1.split(word, 1)[0] for network in networks: if network['name'].lower() == netordev: netname = network['name'] netid = network['id'] result = merakiapi.getwhconnectionstats( apikey, netid, timespan=86400) messages.append( Markup( "In the last day, <strong>{}</strong> had: " .format(netname))) messages.append( Markup( "<strong>{}</strong> association failures" .format(result['assoc']))) messages.append( Markup( "<strong>{}</strong> authentication failures" .format(result['auth']))) messages.append( Markup("<strong>{}</strong> DHCP failures". format(result['dhcp']))) messages.append( Markup("<strong>{}</strong> DNS failures". format(result['dns']))) messages.append( Markup( "and <strong>{}</strong> successful connections" .format(result['success']))) print(messages) continue listclients = [ 'list clients for ', 'client list for ', 'list of clients for ', 'show me clients for', 'show me a list of clients for', 'show clients for ' ] for word in listclients: if word in query: netordev = query.split(word, 1)[1] for network in networks: if network['name'].lower() == netordev: netname = network['name'] netid = network['id'] clientcount = 0 clients = merakiapi.getnetworkclients(apikey, netid, timespan=86400, perpage=100) messages.append( Markup( "<table><th colspan=5><h3>Clients for {}</h3></th><tr><td><strong>Description</strong></td><td><strong>MAC Address</strong></td><td><strong>IP Address</strong></td><td><strong>VLAN</strong></td><td><strong>SSID</strong></td></tr>" .format(str(netname)))) for client in clients: clientcount += 1 messages.append( Markup( "<tr><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td></tr>" .format(str(client['description']), str(client['mac']), str(client['ip']), str(client['vlan']), str(client['ssid'])))) messages.append( Markup( "<tr><td colspan=5><strong>Total: {}</strong></td></tr>" .format(clientcount))) messages.append(Markup("</table>")) continue clientevents = [ 'list client events for ', 'client events for ', 'list events for client ', 'list events for ', 'get client events for ', 'show client events for ' ] for word in clientevents: if word in query: c = query.split(word, 1)[1] r = re.compile('..:..:..:..:..:..') netid = "L_584342051651325437" clientmac = "" if r.match(c) is not None: client = merakiapi.getclientdetail(apikey, netid, c) clientmac = c else: clients = merakiapi.getnetworkclients(apikey, netid, timespan=86400, perpage=100) for client in clients: if str(client['description']).lower() == c: print("MATCHED! Client {} is {}".format( str(client['description']), str(client['mac']))) clientmac = client['mac'] client = merakiapi.getclientdetail( apikey, netid, clientmac) break print("Client: {}".format(clientmac)) lastweek = (datetime.datetime.now() - datetime.timedelta(days=1)).timestamp() print(lastweek) events = merakiapi.getclientevents(apikey, netid, clientmac, lastweek) print(events) messages.append( Markup( "<table><th colspan=3><h3>Events for Client {}</h3></th><tr><td><strong>Network Device</strong></td><td><strong>Occurred At</strong></td><td><strong>Event</strong></td></tr>" .format(str(client['description'])))) for event in reversed(events): messages.append( Markup("<tr><td>{}</td><td>{}</td><td>{}</td></tr>". format( str(event['deviceSerial']), datetime.datetime.utcfromtimestamp( event['occurredAt']).strftime( '%Y-%m-%d %H:%M:%S'), str(event['type'])))) messages.append(Markup("</table>")) continue ssidclients = [ 'how many clients on ssid ', 'list clients on ssid ', 'get clients on ssid ', 'show clients on ssid ', 'list clients for ssid ', 'get clients for ssid ', 'show clients for ssid ' ] for word in ssidclients: if word in query: ssid = query.split(word, 1)[1] netid = "L_584342051651325437" clientcount = 0 clients = merakiapi.getnetworkclients(apikey, netid, timespan=86400, perpage=100) messages.append( Markup( "<table><th colspan=6><h3>Clients for SSID: {}</h3></th><tr><td><strong>Description</strong></td><td><strong>MAC Address</strong></td><td><strong>IP Address</strong></td><td><strong>VLAN</strong></td><td><strong>User</strong></td></tr>" .format(str(ssid)))) for client in clients: if ssid in str(client['ssid']): clientcount += 1 messages.append( Markup( "<tr><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td></tr>" .format(str(client['description']), str(client['mac']), str(client['ip']), str(client['vlan']), str(client['user'])))) messages.append( Markup( "<tr><td colspan=5><strong>Total: {}</strong></td></tr>" .format(clientcount))) messages.append(Markup("</table>")) continue vlanclients = [ 'list clients on vlan ', 'get clients on vlan ', 'show clients on vlan ', 'list clients for vlan ', 'get clients for vlan ' ] for word in vlanclients: if word in query: vlan = query.split(word, 1)[1] netid = "L_584342051651325437" clientcount = 0 clients = merakiapi.getnetworkclients(apikey, netid, timespan=86400, perpage=100) messages.append( Markup( "<table><th colspan=5><h3>Clients for VLAN: {}</h3></th><tr><td><strong>Description</strong></td><td><strong>MAC Address</strong></td><td><strong>IP Address</strong></td><td><strong>SSID</strong></td></tr>" .format(str(vlan)))) for client in clients: if vlan in str(client['vlan']): clientcount += 1 messages.append( Markup( "<tr><td>{}</td><td>{}</td><td>{}</td><td>{}</td></tr>" .format(str(client['description']), str(client['mac']), str(client['ip']), str(client['ssid'])))) messages.append( Markup( "<tr><td colspan=4><strong>Total: {}</strong></td></tr>" .format(clientcount))) messages.append(Markup("</table>")) continue clientdetail = [ 'tell me about client ', 'tell me about ', 'show client details for ', 'show client ' ] for word in clientdetail: if word in query: c = query.split(word, 1)[1] r = re.compile('..:..:..:..:..:..') netid = "L_584342051651325437" clientmac = "" if r.match(c) is not None: client = merakiapi.getclientdetail(apikey, netid, c) clientmac = c else: clients = merakiapi.getnetworkclients(apikey, netid, timespan=86400, perpage=100) for client in clients: if str(client['description']).lower() == c: print("MATCHED! Client {} is {}".format( str(client['description']), str(client['mac']))) clientmac = client['mac'] client = merakiapi.getclientdetail( apikey, netid, clientmac) break if clientmac is "": print("No matching client found") messages.append( Markup( "<h3>No matching client found for: {}</h3>".format( c))) else: print("Client: {}".format(c)) messages.append( Markup( "<table><th colspan='6'><h3>Client Details for {}</h3></th><tr><td><strong>Description</strong></td><td><strong>MAC Address</strong></td><td><strong>IP Address</strong></td><td><strong>VLAN</strong></td><td><strong>Manufacturer</strong></td><td><strong>SSID</strong></td></tr>" .format(str(client['description'])))) messages.append( Markup( "<tr><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td></tr>" .format(str(client['description']), str(client['mac']), str(client['ip']), client['vlan'], str(client['manufacturer']), str(client['ssid'])))) messages.append(Markup("</table>")) apps = merakiapi.getclienttraffichistory( apikey, netid, clientmac) messages.append( Markup( "<table><th colspan='3'><h3>Top Applications for {}</h3></th><tr><td><strong>Application</strong></td><td><strong>Sent</strong></td><td><strong>Received</strong></td></tr>" .format(str(client['description'])))) unique = {each['application']: each for each in apps}.values() for app in unique: messages.append( Markup( "<tr><td>{}</td><td>{}</td><td>{}</td></tr>". format(str(app['application']), str(app['sent']), str(app['recv'])))) messages.append(Markup("</table>")) break #SEND MESSAGE TO SUBMIT PAGE for message in messages: flash(message) return redirect('/submit') return render_template('miles.html', title='Meraki Miles', form=form)
def main(): # read from xlsx file configurations = {} from openpyxl import load_workbook wb = load_workbook(filename='template.xlsx') first_sheet = wb.get_sheet_names()[0] ws = wb[first_sheet] my_row = [] for i in range(1, ws.max_row - 2): for j in range(1, ws.max_column - 1): my_row.append(ws.cell(row=i + 1, column=j).value) #configurations[ws.cell(row=i + 1, column=2).value + str(ws.cell(row=i + 1, column=3).value)] = SwitchPort(my_row) # dictionary print( ws.cell(row=i + 1, column=2).value + str(ws.cell(row=i + 1, column=3).value)) print(my_row) print(configurations) # API key. api_key = "8b43aaa7b92b6d3ad06234e6f581077620d3e512" # Get the organization name. print("Organization Name:") org_name = input() # Pull the organizations associated to the provided API key. orgs = merakiapi.myorgaccess(api_key, True) # Look for the organization that we want to configure. org_id = "" for org in orgs: if org_name in org["name"]: org_id = org["id"] if org_id == "": print("Organization not found.") return # Pull the networks associated with the organization. networks = merakiapi.getnetworklist(api_key, org_id, True) # Pull the devices from all of the networks. devices = [] for network in networks: devices += merakiapi.getnetworkdevices(api_key, network["id"], True) # print devices switch_ports = [] for device in devices: current_switch_ports = [] if device["model"].startswith("MS"): # current_switch_port = merakiapi.getswitchports(api_key, device["serial"]) # current_switch_port["serial"] = device["serial"] current_switch_ports = merakiapi.getswitchports( api_key, device["serial"], False) # Label all current switch ports with the serial number of the parent switch. for switch_port in current_switch_ports: switch_port["serial"] = device["serial"] # Append the switch ports for the current switch to the master list. switch_ports += current_switch_ports print(switch_ports) # Apply configuration to the devices and push them to Meraki. for switch_port in switch_ports: try: switch_port["name"] = configurations[ switch_port["serial"] + str(switch_port["number"])].name except: continue switch_port["tags"] = configurations[switch_port["serial"] + str(switch_port["number"])].tags switch_port["enabled"] = configurations[ switch_port["serial"] + str(switch_port["number"])].enabled switch_port["rstpEnabled"] = configurations[ switch_port["serial"] + str(switch_port["number"])].rstp switch_port["stpGuard"] = configurations[ switch_port["serial"] + str(switch_port["number"])].stp_guard switch_port["poeEnabled"] = configurations[ switch_port["serial"] + str(switch_port["number"])].poe switch_port["type"] = configurations[switch_port["serial"] + str(switch_port["number"])].type switch_port["vlan"] = configurations[switch_port["serial"] + str(switch_port["number"])].vlan switch_port["voiceVlan"] = configurations[ switch_port["serial"] + str(switch_port["number"])].voice_vlan switch_port["allowedVlans"] = configurations[ switch_port["serial"] + str(switch_port["number"])].allowed_vlan # print switch_port["enabled"] merakiapi.updateswitchport( api_key, switch_port["serial"], switch_port["number"], switch_port["name"], switch_port["tags"], switch_port["enabled"], switch_port["type"], switch_port["vlan"], switch_port["voiceVlan"], switch_port["allowedVlans"], switch_port["poeEnabled"], "", switch_port["rstpEnabled"], switch_port["stpGuard"], "")