NoneType对象不是可迭代的python cisco meraki

时间:2019-07-13 00:31:01

标签: python-3.x

试图做一个脚本来拉我meraki组织中的所有客户。我认为我的代码无法读取要迭代的文件。

谢谢

我尝试将分片更改为我认为需要但仍存在相同错误的特定尝试安装模块

import sys, getopt, requests, json, time, datetime, os, sqlite3

#SECTION: GLOBAL VARIABLES: MODIFY TO CHANGE SCRIPT BEHAVIOUR

API_EXEC_DELAY              = 0.21 #Used in merakirequestthrottler() to avoid hitting dashboard API max request rate

#connect and read timeouts for the Requests module in seconds
REQUESTS_CONNECT_TIMEOUT    = 90
REQUESTS_READ_TIMEOUT       = 90

#SECTION: GLOBAL VARIABLES AND CLASSES: DO NOT MODIFY

LAST_MERAKI_REQUEST         = datetime.datetime.now()   #used by merakirequestthrottler()
ARG_APIKEY                  = '' #DO NOT STATICALLY SET YOUR API KEY HERE
ARG_ORGNAME                 = '' #DO NOT STATICALLY SET YOUR ORGANIZATION NAME HERE
ORG_LIST                    = None #list of organizations, networks and MRs the used API key has access to
DEVICE_DB                   = None #SQLite3 database of all network devices
MAX_CLIENT_TIMESPAN         = 2592000 #maximum timespan GET clients Dashboard API call supports

class c_Net:
    def __init__(self):
        id          = ''
        name        = ''
        shard       = 'n132.meraki.com'
        devices     = []

class c_Organization:
    def __init__(self):
        id          = ''
        name        = ''
        shard       = 'n132.meraki.com'
        nets        = []


#SECTION: General use functions

def merakirequestthrottler():
    #makes sure there is enough time between API requests to Dashboard not to hit shaper
    global LAST_MERAKI_REQUEST

    if (datetime.datetime.now()-LAST_MERAKI_REQUEST).total_seconds() < (API_EXEC_DELAY):
        time.sleep(API_EXEC_DELAY)

    LAST_MERAKI_REQUEST = datetime.datetime.now()
    return

def printhelp():
    print(readMe)


#SECTION: Meraki Dashboard API communication functions

def getInventory(p_org):
    #returns a list of all networks in an organization

    merakirequestthrottler()
    try:
        r = requests.get('https://%s/api/v0/organizations/%s/inventory' % (p_org.shard, p_org.id), headers={'X-Cisco-Meraki-API-Key': ARG_APIKEY, 'Content-Type': 'application/json'}, timeout=(REQUESTS_CONNECT_TIMEOUT, REQUESTS_READ_TIMEOUT) )
    except:
        print('ERROR 01: Unable to contact Meraki cloud')
        return(None)

    if r.status_code != requests.codes.ok:
        return(None)

    return(r.json())


def getNetworks(p_org):
    #returns a list of all networks in an organization

    merakirequestthrottler()
    try:
        r = requests.get('https://%s/api/v0/organizations/%s/networks' % (p_org.shard, p_org.id), headers={'X-Cisco-Meraki-API-Key': ARG_APIKEY, 'Content-Type': 'application/json'}, timeout=(REQUESTS_CONNECT_TIMEOUT, REQUESTS_READ_TIMEOUT) )
    except:
        print('ERROR 07: Unable to contact Meraki cloud')
        return(None)

    if r.status_code != requests.codes.ok:
        return(None)

    return(r.json())


def getOrgs():
    #returns the organizations' list for a specified admin, with filters applied

    merakirequestthrottler()
    try:
        r = requests.get('https://n132.meraki.com/api/v0/organizations', headers={'X-Cisco-Meraki-API-Key': ARG_APIKEY, 'Content-Type': 'application/json'}, timeout=(REQUESTS_CONNECT_TIMEOUT, REQUESTS_READ_TIMEOUT) )
    except:
        print('ERROR 02: Unable to contact Meraki cloud')
        return(None)

    if r.status_code != requests.codes.ok:
        return(None)

    rjson = r.json()
    orglist = []
    listlen = -1

    if ARG_ORGNAME.lower() == '/all':
        for org in rjson:
            orglist.append(c_Organization())
            listlen += 1
            orglist[listlen].id     = org['id']
            orglist[listlen].name   = org['name']
    else:
        for org in rjson:
            if org['name'] == ARG_ORGNAME:
                orglist.append(c_Organization())
                listlen += 1
                orglist[listlen].id     = org['id']
                orglist[listlen].name   = org['name']

    return(orglist)


def getShardHost(p_org):
    #Looks up shard URL for a specific org. Use this URL instead of 'api.meraki.com'
    # when making API calls with API accounts that can access multiple orgs.
    #On failure returns None

    merakirequestthrottler()
    try:
        r = requests.get('https://n132.meraki.com/api/v0/organizations/%s/snmp' % p_org.id, headers={'X-Cisco-Meraki-API-Key': ARG_APIKEY, 'Content-Type': 'application/json'}, timeout=(REQUESTS_CONNECT_TIMEOUT, REQUESTS_READ_TIMEOUT) )
    except:
        print('ERROR 03: Unable to contact Meraki cloud')
        return None

    if r.status_code != requests.codes.ok:
        return None

    rjson = r.json()

    return(rjson['hostname'])


def refreshOrgList():
    global ORG_LIST
    global DEVICE_DB

    print('INFO: Starting org list refresh at %s...' % datetime.datetime.now())

    flag_firstorg = True
    orglist = getOrgs()

    if not orglist is None:
        for org in orglist:
            print('INFO: Processing org "%s"' % org.name)

            org.shard = 'n132.meraki.com'
            orgshard = getShardHost(org)
            if not orgshard is None:
                org.shard = orgshard
            netlist = getNetworks(org)
            devlist = getInventory(org)

            if not devlist is None and not netlist is None:

                DEVICE_DB = sqlite3.connect(':memory:')
                dbcursor = DEVICE_DB.cursor()
                dbcursor.execute('''CREATE TABLE devices (serial text, name text, networkId text, mac text, type text, model text)''')
                dbcursor.execute('''CREATE TABLE ouis (oui text)''')
                DEVICE_DB.commit()

                for device in devlist:
                    if not device['networkId'] is None:
                        devType = 'merakiDevice'
                        if device['model'][:2] in ['MR','MS','MX','Z1','Z3']:
                            devType = 'merakiNetworkDevice'
                        dbcursor.execute('''INSERT INTO devices VALUES (?,?,?,?,?,?)''', (device['serial'],device['name'],device['networkId'],device['mac'],devType,device['model']))
                        dbcursor.execute('''INSERT INTO ouis VALUES (?)''', (device['mac'][:8],))
                DEVICE_DB.commit()   

                flag_firstnet = True

                for net in netlist:
                    if net['type'] != 'systems manager': #ignore systems manager nets
                        dbcursor.execute('''SELECT serial, name, model FROM devices WHERE networkId = ? AND type = ?''', (net['id'],'merakiNetworkDevice'))

                        devicesofnet = dbcursor.fetchall()

                        if len(devicesofnet) > 0: #network has MR, MS, MX, Zx
                            if flag_firstnet:
                                if flag_firstorg:
                                    ORG_LIST = []
                                    lastorg = -1
                                    flag_firstorg = False

                                ORG_LIST.append(org)
                                lastorg += 1
                                lastnet = -1
                                ORG_LIST[lastorg].nets = []

                                flag_firstnet = False

                            ORG_LIST[lastorg].nets.append(c_Net())
                            lastnet += 1
                            ORG_LIST[lastorg].nets[lastnet].id      = net['id']
                            ORG_LIST[lastorg].nets[lastnet].name    = net['name']
                            ORG_LIST[lastorg].nets[lastnet].shard   = org.shard
                            ORG_LIST[lastorg].nets[lastnet].devices = []

                            for device in devicesofnet:
                                ORG_LIST[lastorg].nets[lastnet].devices.append(device)

    LAST_ORGLIST_REFRESH = datetime.datetime.now()      
    print('INFO: Refresh complete at %s' % LAST_ORGLIST_REFRESH)

    return None


def getclientlist(p_shardhost, p_serial, p_timespan):

    merakirequestthrottler()
    try:
        r = requests.get('https://%s/api/v0/devices/%s/clients?timespan=%s' % (p_shardhost, p_serial, p_timespan), headers={'X-Cisco-Meraki-API-Key': ARG_APIKEY, 'Content-Type': 'application/json'}, timeout=(REQUESTS_CONNECT_TIMEOUT, REQUESTS_READ_TIMEOUT) )
    except:
        print('ERROR 04: Unable to contact Meraki cloud')
        return(None)

    if r.status_code != requests.codes.ok:
        return(None)

    return(r.json())  


#SECTION: main

def main(argv):
    global ARG_APIKEY
    global ARG_ORGNAME

    #initialize command line arguments
    ARG_APIKEY      = ''
    ARG_ORGNAME     = ''
    arg_numresults  = ''
    arg_mode        = ''
    arg_filter      = ''    

    #get command line arguments
    try:
        opts, args = getopt.getopt(argv, 'hk:o:m:')
    except getopt.GetoptError:
        printhelp()
        sys.exit(2)

    for opt, arg in opts:
        if   opt == '-h':
            printhelp()
            sys.exit()
        elif opt == '-k':
            ARG_APIKEY      = arg
        elif opt == '-o':
            ARG_ORGNAME     = arg
        elif opt == '-m':
            arg_mode        = arg

    #check that all mandatory arguments have been given
    if ARG_APIKEY == '':
        printhelp()
        sys.exit(2)        

    #set defaults for empty command line arguments
    if ARG_ORGNAME == '':
        ARG_ORGNAME = '/all'

    refreshOrgList()

    if ORG_LIST is None or DEVICE_DB is None:
        print('ERROR 05: No organizations with network devices access points for the specified API key')
        sys.exit(2)

    DEVcursor   = DEVICE_DB.cursor()

    for org in ORG_LIST:
        flag_firstNet = True
        orgClientList = []
        reportFileName = 'clients_' + org.name + '_' + str(datetime.datetime.now()).replace(':','.') + '.csv'
        print ('INFO: Processing org "%s"' % org.name)
        for net in org.nets:
            print ('INFO: Processing net "%s"' % net.name)
            for dev in net.devices:
                clients = getclientlist(org.shard, dev[0], MAX_CLIENT_TIMESPAN)
                for client in clients:
                    DEVcursor.execute('''SELECT oui FROM ouis WHERE oui = ?''', (client['mac'][:8],))
                    matchingMerakiOuis = DEVcursor.fetchall()
                    if len(matchingMerakiOuis) == 0: #client device is not, in fact, a Meraki device neighbour
                        if flag_firstNet:
                            flag_firstNet = False
                            print('INFO: Creating file "' + reportFileName + '"')
                            try:
                                f = open(reportFileName, 'w')
                                f.write('id,mac,description,mdnsName,dhcpHostname,ip,vlan,switchport,usageKBSentToClient,usageKBRecvFromClient,networkId,networkName,reportedByDevSerial,reportedByDevName,reportedByDevModel\n')
                            except:
                                print('ERROR 06: Unable to open file "' + reportFileName + '" for writing')
                                sys.exit(2)

                        try:
                            f.write(str(client['id']) + ',' +
                                    str(client['mac']) + ',' +
                                    str(client['description']) + ',' +
                                    str(client['mdnsName']) + ',' +
                                    str(client['dhcpHostname']) + ',' +
                                    str(client['ip']) + ',' +
                                    str(client['vlan']) + ',' +
                                    str(client['switchport']) + ',' +
                                    str(int(client['usage']['sent'])) + ',' +
                                    str(int(client['usage']['recv'])) + ',' +
                                    str(net.id) + ',' +
                                    str(net.name) + ',' +
                                    str(dev[0]) + ',' +
                                    str(dev[1]) + ',' +
                                    str(dev[2]) + '\n' )
                        except:
                            print('ERROR 08: Unable to write to file "' + reportFileName + '"')
                            sys.exit(2)


    DEVICE_DB.close()

    try:
        f.close()
    except:
        print ('INFO: Unable to close file (not open?)')

if __name__ == '__main__':
    main(sys.argv[1:])

跟踪错误:

Traceback (most recent call last):
  File "orgsclientcsv.py", line 351, in <module>
    main(sys.argv[1:])
  File "orgsclientcsv.py", line 308, in main
    for client in clients:
TypeError: 'NoneType' object is not iterable 

结果应该是一个csv文件,该文件将为我提供手机mac地址序列号制造商的列表,但实际输出仅是像iphone这样的手机mac地址

0 个答案:

没有答案