Comment nous avons effectué la surveillance du réseau pour 14 000 objets

Nous avions 14 000 objets, zabbix, api, python et une réticence à ajouter des objets à la main. Sous la coupe - sur la façon dont les gestionnaires de réseau ont mis en œuvre la surveillance avec l'ajout automatique de nœuds de réseau, et un peu sur la douleur que j'ai dû traverser.

Cet article se concentre davantage sur les ingénieurs réseau avec peu d'expérience en python. Contribuer à l'automatisation de la surveillance et à l'amélioration de la qualité de vie et du travail, en l'absence de mise à jour manuelle de l'ensemble du parc d'objets.



Pour faire court, nous avons construit un suivi


Salut Je m'appelle Alexander Prokhorov et, avec l'équipe d'ingénieurs réseau de notre département, nous travaillons sur un réseau en # ITX5. Notre département développe l'infrastructure réseau, la surveillance du réseau et l'automatisation. Oui, et tout ce qui concerne le transfert de données.



Je diviserais le système de surveillance en 5 sous-tâches:

  • Télécharger les données de base
  • Obtention d'informations sur l'état des objets
  • Déclencheurs et alertes
  • Rapports
  • Visualisation

Dans cet article, nous aimerions partager comment nous avons fait l'intégration de la surveillance avec les données de base dans notre entreprise.

Nous avons 14 000 propriétés commerciales et la première tâche que nous avons résolue a été la détermination des objets inaccessibles, leur nombre et leur répartition géographique.

La surveillance a été effectuée sur Zabbix . En un mot pourquoi - chanceux et hérité. Le reste:

Longue histoire.
Tout a commencé avec l'installation de la surveillance sur un ordinateur sous la table ...

Lorsque je suis venu travailler pour la société en 2013, nous n'avions pas de surveillance de réseau, bien que le réseau, à cette époque, était gros, environ 4000 objets. Nous avons appris des chutes massives (et pas si) le plus souvent de la réception d'avalanches de demandes, d'utilisateurs ou d'autres services.



Le premier a été installé Zabbix 1.8, en tant que produit en plein essor (à la mode, moderne, jeune), léger et abordable pour installer l'open source avec une grande communauté. Nous avons juste eu de la chance avec le choix.

Il n'y avait pas de ressources pour l'installation, personne n'a demandé. Il n'était pas clair si cela fonctionnerait du tout; personne n'avait aucune expérience de la mise en œuvre. Mais nous en avions besoin et nous l'avons installé sur l'ordinateur «sous la table». Niveau de redondance - UPS.

La principale question après l'installation est de savoir comment verser tous les objets (4k!) Dans la surveillance, et en même temps réussir à créer des applications qui se bloquent déjà dans Remedy. Zabbix a déjà pris en charge l'importation / exportation de xml avec des données sur les hôtes. Le nombre d'objets est important, il était inutile de créer un groupe distinct pour l'objet (et il n'apparaissait pas), et il a été décidé de télécharger un routeur d'objet en tant que nœud de réseau. Une plus grande partie de l'équipement réseau n'était pas contrôlée (déjà gérée).

L'analyse de notre fichier avec les hôtes du réseau (IPAM dans Excel) a été effectuée et elle a été reformatée en XML, que Zabbix accepte de digérer. Pas la première fois, mais tous les hôtes étaient chargés, la mise à jour était effectuée une fois tous les trois mois, supprimant les objets fermés et en ajoutant de nouveaux. Au fil du temps, il s'est avéré que Zabbix est devenu la principale et unique source d'informations pour nous et la hotline sur la disponibilité des installations et, surtout, sur les chutes de masse. Cela a permis à la hotline de se renseigner sur les accidents de masse, même la nuit, et de réveiller les ingénieurs avec des appels (à propos, quand personne ne le savait, c'était plus facile à vivre). Les coupures de courant nocturnes au bureau n'ont pas toujours permis à l'onduleur de maintenir correctement la surveillance de notre réseau. À un moment donné, nous avons commencé à faire des sauvegardes. Parce que le suivi étant instable et intermittent, les entreprises ont décidé d'organiser un groupe dédié uniquement à cette tâche. Très vite, elle a commencé à implémenter un Zabbix centralisé, qui vérifie non seulement le réseau.

Notre vieux Zabbix a continué à vivre sous la table. Après avoir ajouté un certain nombre d'éléments, la base de données a commencé à ralentir un peu, le Web, la file d'attente et le délai d'interrogation ont augmenté, si vite que j'ai dû obtenir deux autres ordinateurs en tant que proxy et les mettre tous en croix, de sorte que la vraie réservation (et la place sous la table était terminée) . La vie en elle a été prise en charge afin d'ajouter rapidement une sorte de paramètre personnalisé à la surveillance et à l'observer. Pour le reste, nous sommes passés à une solution centralisée.

La surveillance centralisée était en charge de tous les équipements informatiques - routeurs, serveurs, caisses enregistreuses, terminaux. Après un certain temps, il a envahi un grand nombre d'articles. Pour accéder à des informations d'accessibilité inestimables, il fallait attendre un peu, peut-être même prendre un café. De plus, nous avions de plus en plus d'exigences pour une surveillance de réseau plus spécifique et personnalisée. Ayant à l'époque une certaine expérience de travail avec le système, nous avons décidé de faire l'ancienne implémentation à partir de zéro, mais à juste titre - sous le nom de zabbix.noc.x5.ru Il était situé dans le centre de données avec la mise en œuvre des fonctions nécessaires par nous-mêmes. À propos de cette introduction et du corps principal de l'article.

La version Zabbix est 3.0 LTS . Mis à jour uniquement dans les versions LTS.

Configuration - 4 machines virtuelles: serveur + base de données, proxy, proxy, Web

Par ressources, nous avons essayé de suivre les recommandations sur zabbix.com pour une implémentation large et très large.

Le premier problème auquel nous avons été confrontés a été l'ajout automatique de nœuds de réseau à la surveillance. La découverte régulière a disparu immédiatement. Notre gamme de réseaux est sur tous les espaces ouverts du supernet 10/8. De nombreuses adresses devraient être interrogées et la découverte automatique occuperait beaucoup de ressources système, mais ne résoudrait pas le problème de l'ajout d'informations non techniques sur un objet.

Comment ajouter des objets


La solution était d'utiliser des scripts externes pour ajouter des objets. Des données de base sur les objets commerciaux ont été trouvées dans le SAP utilisé dans l'entreprise. L'accès synchronisé au service Web pour le téléchargement de données directement depuis SAP n'est pas sorti, la demande pour tous les objets a pris un certain temps. Effectué un appel asynchrone. Exactement à minuit, l'exportation complète de SAP est ajoutée à ftp sous la forme de XML , et pendant la journée, les fichiers XML avec des différences par rapport aux dernières versions tombent dessus.

Zabbix a utilisé l' API Zabbix pour charger des données et a interagi avec elles à partir de Python .

À la première étape, l'ensemble de données dont nous avions besoin pour créer l'objet a été déterminé. Nous utilisons tous les signes obtenus pour la classification correcte d'un objet dans le système ou pour plus de commodité. Ces signes comprennent:

  • Adresse IP - le champ le plus important pour créer une interface de surveillance
  • ID SAP - nous avons un identifiant d'objet unique
  • Statut - ouvert / fermé
  • Nom - le nom ou le numéro de l'objet, souvent utilisé par les utilisateurs lorsqu'ils contactent
  • Lieu - adresse physique
  • Téléphone - téléphone de contact
  • Groupes - ce groupe de groupes est formé en fonction du type et de l'emplacement de l'objet



Module Sap-sync.py


XML de SAP
<?xml version="1.0" encoding="ISO-8859-1"?> <werks> <WERKS>1234</WERKS> <NAME1>4321-</NAME1> <PLANT_IP>192.168.1.50</PLANT_IP> <REGION>31</REGION> <PSTLZ>308580</PSTLZ> <CITY1>.</CITY1> <CITY2> .</CITY2> <STREET> .</STREET> <HOUSE_NUM1>1</HOUSE_NUM1> <TEL_NUMBER>(999)777-77-77</TEL_NUMBER> <BRANCH>CH</BRANCH> <REGION>CH_MSK</REGION> <REGION_NAME> </REGION_NAME> <FORMAT>CH_MSK_D</FORMAT> <STATUS> </STATUS> </werks> 


sap-sync.py
 #!/usr/bin/python3 import sys, os, getopt, ipaddress from datetime import datetime as dt from zabbix.api import ZabbixAPI import xml.etree.cElementTree as et from report import report import existhost def ping(ip): if os.system('ping -c 2 -W 1 %s > /dev/null'%ip) == 0: return True else: return False def main(argv): global opath try: opts, args = getopt.getopt(argv,"hp:",["path="]) except getopt.GetoptError: print('sync-sap-chg.py -p <path>') sys.exit(2) for opt, arg in opts: if opt == '-h': print('sync-sap-chg.py -p <path>') sys.exit() elif opt in ("-p", "--path"): opath = arg def asynchronization(file, reportdata): zapi = ZabbixAPI(url='http://z.noc.x5.ru', user='user', password='pwd') #,    left_kidney = '17855' right_kidney = '17856' f_type={'S':'Super','D':'DK','H':'Giper','A':'DK'} format={'D':'13','S':'14','H':'12','A':'13'} region={'CT':'21','UR':'19','SZ':'17',~omit~} try: #  XML tree = et.ElementTree(file=file) root = tree.getroot() for werks in root.iter('werks'): #     Zabbix interfaces=[{ 'main':'1', 'type':'2', 'useip':'1', 'port':'161' }] shop={ 'inventory':{}, 'interfaces':interfaces, 'groups':[], 'templates':[{'templateid':'10194'}], 'inventory_mode':'1' } #,     XML di = { 'WERKS':'', ~omit~, 'STATUS':'Object Opened' } #    for item in werks: di[item.tag] = item.text #  SAPID   if item.tag == 'WERKS': n_proxy = ''.join(filter(lambda x: x.isdigit(), item.text)) # IP    .   /26 try: ipaddress.ip_interface('%s/%s'%(di['PLANT_IP'].strip(),26)) ip_chk = True except: ip_chk = False # ,   IP   if (di['PLANT_IP'] != '1.1.1.1') and ip_chk: #    if di['FORMAT'][-1] in ['D','A','S','H']: shop['inventory']['alias']=di['WERKS'] shop['inventory']['name']=di['NAME1'] shop['inventory']['poc_1_phone_a']=di['TEL_NUMBER'] shop['inventory']['location']=di['STREET'] #    if (di['FORMAT'][-1] in ['H']): shop['host']=f_type[di['FORMAT'][-1]]+di['WERKS'] shop['interfaces'][0]['ip']=str(ipaddress.ip_interface('%s/%s'%(di['PLANT_IP'].strip(),24)).network[1]) # ID     shop['templates'][0]['templateid']='29529' elif (di['FORMAT'][-1] in ['S']): ~omit~ #For D balance in proxies if int(n_proxy[-1]) % 2 == 0: shop['proxy_hostid'] = right_kidney else: shop['proxy_hostid'] = left_kidney # inventory   IP shop['inventory']['oob_ip']=shop['interfaces'][0]['ip'] #    format  region shop['groups']=[{'groupid':'9'}] shop['groups'].append({'groupid':format[di['FORMAT'][-1]]}) shop['groups'].append({'groupid':region[di['FORMAT'][:2]]}) #   if di['STATUS'] == ' ': shop['status']='0' else: shop['status']='1' #   T = dt.date(dt.now()).strftime("%d %B %Y") shop['inventory']['date_hw_decomm'] = T #      Zabbix hostid = existhost.exist(shop['host']) ip = shop['interfaces'][0]['ip'] #  - ! if hostid == 0 and shop['status'] == '0' and ping(ip): zapi.host.create(shop) reportdata['new'].append(di['WERKS']) #   - ! elif hostid != 0 and di['PLANT_IP'] != '1.1.1.1': #  HOSTID  shop['hostid']=hostid #     shop.pop('interfaces') zapi.host.update(shop) reportdata['update'].append(di['WERKS']) #     os.system('mv %s /mnt/ftp/old_data/'%(file)) except: reportdata['error'].append(di['WERKS']) report('   %s.   :%s'%(file, str(reportdata['error'])), 'SAP Sync Failed!') sys.exit() def checking(path): files = os.listdir(path) files.sort() reportdata ={'new':[], 'update':[], 'error':[]} for file in files: asynchronization(path+file, reportdata) if files != []: report(' %s  ! \n  %s . \n  sap:\n %s. \n  %s . \n  sap:\n %s'%(str(files), len(reportdata['new']), str(reportdata['new']), len(reportdata['update']), str(reportdata['update'])), 'SAP Sync Succeed!') if __name__ == "__main__": main(sys.argv[1:]) checking(opath) 


L'objectif principal de ce module est l'analyse XML et la traduction JSON pour l'API Zabbix. Il est très pratique dans ce cas d'utiliser des dictionnaires Python, comme pas besoin de les formater en plus - en utilisant le module zabbix.api , vous pouvez simplement lui fournir un dictionnaire avec la structure correcte. JSON avec la structure ressemble à ceci:

 { 'host': 'Hostname' 'groups': [...] 'interfaces': [{},{},{}] 'inventory': {} 'templates': [{},{},{}] 'inventory_mode': '1' 'proxy_hostid': 'INT' 'status': '0' } [] -  {} -  

Dans notre domaine avec l'adresse IP dans SAP, l'adresse du serveur est stockée, pas le routeur, mais en utilisant le module ipaddress, nous considérons la première adresse de sous-réseau, qui dans notre cas est toujours un routeur.

 str(ipaddress.ip_interface('%s/%s'%(di['PLANT_IP'].strip(),24)).network[1]) 

La date de la dernière mise à jour réussie est enregistrée dans l' inventaire , dans des situations controversées, elle permet de comprendre la pertinence des informations dans le système.

 #   T = dt.date(dt.now()).strftime("%d %B %Y") shop['inventory']['date_hw_decomm'] = T 

Ensuite, il est très pratique de consulter les statistiques sur la date de mise à jour dans les données d'inventaire:



Le champ le plus important - ÉTAT , "ouvert" - est ajouté et commence à être surveillé, tout autre état - désactive l'hôte. Nous ne supprimons pas les objets afin de conserver les données et statistiques historiques.

Après les tests, j'ai dû ajouter la fonction ping afin de vérifier si l'hôte est accessible avant l'ajout initial, car dans la pratique, des statuts «ouverts» ont commencé à apparaître, qui ne sont pas encore tout à fait ouverts, mais presque.

 def ping(ip): if os.system('ping -c 2 -W 1 %s > /dev/null'%ip) == 0: return True else: return False 

Auparavant, l'API Zabbix avait une fonction host.exist , mais dans les nouvelles versions, elle était combinée avec host.get . Si le nœud existe, la demande retourne hostid dans la base de données zabbix. S'il n'est pas trouvé, renvoie 0. Pour vérification, je devais maintenant ajouter existhost , mais en fait c'est host.get .

existhost.py
 #!/usr/bin/python3 import sys, getopt from zabbix.api import ZabbixAPI def main(argv): global aname try: opts, args = getopt.getopt(argv,"hn:",["name="]) except getopt.GetoptError: print('existhost.py -n <name>') sys.exit(2) for opt, arg in opts: if opt == '-h': print('existhost.py -n <name>') sys.exit() elif opt in ("-n", "--name"): aname = arg def exist(name): zapi = ZabbixAPI(url='http://z.noc.x5.ru/', user='user', password='pwd') hostget = zapi.host.get(search={'name':'%s'%name}, output='hostid') if hostget == []: return 0 else: return int(hostget[0]['hostid']) if __name__ == "__main__": main(sys.argv[1:]) print(exist(aname)) 


Enfin, nous collectons des informations sur le travail effectué, les ajoutons aux journaux, aux rapports et déplaçons le fichier traité vers le référentiel dans OLD.

report.py
 #!/usr/bin/python3 # -*- coding: utf-8 -*- import smtplib, sys from email.mime.text import MIMEText def report(message, subject): me = 'zbx-scripts@x5.ru' you = 'mail@x5.ru' smtp_server = 'smtp.ru' msg = MIMEText(message) msg['Subject'] = subject msg['From'] = me msg['To'] = you s = smtplib.SMTP(smtp_server) s.sendmail(me, [you], msg.as_string()) s.quit() if __name__ == '__main__': report(sys.argv[2], sys.argv[1]) 


En général, la base de surveillance est prête, exécutez le script dans cron for autorun et oubliez-le.



Comment remplir l'inventaire


Nous ne sommes plus nous, nous sommes des networkers.

La deuxième étape consiste à remplir les objets avec des données dont les ingénieurs ont besoin pour travailler. Il est nécessaire de voir toutes les données pour résoudre l'incident dans un seul système, afin de ne pas parcourir plusieurs systèmes, en collectant des informations en morceaux à partir de différentes sources. Et comme les principales données techniques concernent la surveillance, nous attirons également le reste dans la surveillance.
Afin de collecter et de transmettre les informations nécessaires, Zabbix a écrit l' inventaire.py , qui est largement engagé dans la collecte de données SNMP à partir de l'équipement, et dans une moindre mesure en analysant le fichier Excel.

La question se pose - pourquoi ne pas utiliser les éléments intégrés et entrer leur résultat dans l' inventaire en utilisant les outils de Zabbix lui-même? Il y a trois réponses:

  1. Imbrication d'actions insuffisante, car il est souvent nécessaire d'extraire la valeur via SNMP et d'utiliser le résultat dans la requête suivante.
  2. L'exécution d'une collecte de données une fois par jour sur tous les nœuds avec un script externe ne charge pas l'activité de surveillance principale et il n'y a pas de file d'attente pour item'am
  3. Certaines données ne peuvent pas être collectées via SNMP

Les données sur les fournisseurs, dont les ingénieurs de première et de deuxième ligne ne peuvent se passer, sont stockées dans un fichier Excel sur un lecteur réseau partagé et mises à jour par les gestionnaires qui mènent les contrats de communication. L'intégration avec le fichier a suscité de grands doutes - une analyse Excel, remplie manuellement, qui peut changer la structure, le nom, l'emplacement, etc., générera très probablement des erreurs en permanence. Mais en raison du manque d'une autre source pertinente de telles données, j'ai dû l'utiliser. Afin de nous protéger d'une manière ou d'une autre de l'édition constante du script, nous avons convenu avec les gestionnaires de la structure et du remplissage correct, expliqué comment le déchargement automatique sera effectué et qu'il est important d'observer la structure actuelle. Dans la pratique, bien sûr, des erreurs se sont produites, mais nous les avons rapidement suivies, maudites, mais corrigées.

inventaire.py
 #!/usr/bin/python3 # -*- coding: utf-8 -*- import sys, json, pysnmp, ipaddress, xlrd from datetime import datetime as dt from pysnmp.entity.rfc3413.oneliner import cmdgen def snmp(host, operation, *oid): generator = cmdgen.CommandGenerator() auth_data = cmdgen.UsmUserData('user', 'pwd', 'hash') transport = cmdgen.UdpTransportTarget((host, 161)) getAtt = getattr(generator, '%sCmd'%operation) rst = (errorIndication, errorStatus, errorIndex, varBinds) = getAtt(auth_data, transport, *oid) if not errorIndication is None or errorStatus is True: return "Error: %s %s %s %s" % rst else: if operation=='get': return varBinds elif operation=='next': result=[] for var in varBinds: result.append(var) return result def xlsdata(file, sap): rb = xlrd.open_workbook(file) sheet = rb.sheet_by_index(0) base = {} for i in range(0, sheet.nrows-1): sapnum = str(round(sheet.cell(i,4).value)) if isinstance(sheet.cell(i,4).value,float) else sheet.cell(i,4).value name = str(round(sheet.cell(i,8).value)) if isinstance(sheet.cell(i,8).value,float) else sheet.cell(i,8).value if sap.upper() == sapnum.upper(): base = { 'type' : (sheet.cell(i,2).value), 'serialno_a' : (sheet.cell(i,13).value), 'serialno_b' : (sheet.cell(i,20).value), 'tag' : ('2') if sheet.cell(i, 20).value != '' else ('1'), 'macaddress_a' : (sheet.cell(i, 15).value), 'macaddress_b' : (sheet.cell(i, 22).value) } base['date_hw_purchase'] = dt.date(dt.now()).strftime("%d %B %Y") return (base) def inventory(host, sap): BGPASBASE={} for line in open('/path/a.prokhorov/integration/BGP-AS-BASE.cfg'): if ':' in line: line = line.split(':') BGPASBASE[line[0]]='%s(%s)'%(line[1].rstrip(), line[0]) ### Get Data from Operator shop = xlsdata('/mnt/oprf/providers_base.xlsx', sap) shop['date_hw_expiry'] = 'Failed' ### Get SNMP data shop['host_router'] = 'None' shop['host_netmask'] = 'None' shop['host_networks'] = 'None' try: ### Get Networks from router networks = '' for ip,mask in snmp(host, 'next', 'iso.3.6.1.2.1.4.20.1.1', 'iso.3.6.1.2.1.4.20.1.3'): networks = networks+str(ipaddress.ip_interface(u'%s/%s'%(ip[1].prettyPrint(), mask[1].prettyPrint())))+'\n' shop['host_networks']=networks ### Get BGP information bgppeers, ispnames = '','' for peer,asbgp in snmp(host, 'next', 'iso.3.6.1.2.1.15.3.1.7', 'iso.3.6.1.2.1.15.3.1.9'): asbgp = asbgp[1].prettyPrint() bgppeers = bgppeers+peer[1].prettyPrint()+'\n' ispnames = ispnames+(BGPASBASE.get(asbgp) if BGPASBASE.get(asbgp)!=None else asbgp)+'\n' shop['host_router'] = bgppeers.strip()[:38] shop['host_netmask'] = ispnames.strip()[:38] ### Get Vendor name and Model type hardware = snmp(host, 'get', 'iso.3.6.1.2.1.47.1.1.1.1.13.1', 'iso.3.6.1.2.1.47.1.1.1.1.10.1', 'iso.3.6.1.2.1.47.1.1.1.1.12.1', 'iso.3.6.1.2.1.1.1.0', 'iso.3.6.1.2.1.47.1.1.1.1.7.1') if str(hardware[0][1]) == '0235A325': shop['model'] = hardware[4][1].prettyPrint() else: shop['model'] = hardware[0][1].prettyPrint() shop['os_short'] = hardware[1][1].prettyPrint() shop['vendor'] = hardware[2][1].prettyPrint() version = hardware[3][1].prettyPrint() os = version.split('\n')[0] shop['os_full'] = version[:250] shop['os'] = ''.join(os.split(',')[:2])[:60] ### Make indicators shop['date_hw_expiry'] = 'Success' shop['date_hw_install'] = dt.date(dt.now()).strftime("%d %B %Y") except: shop.pop('host_router') shop.pop('host_netmask') shop.pop('host_networks') return shop #return json.dumps(dict([('inventory',shop)]), sort_keys=True, indent=4) if __name__ == "__main__": print(inventory(sys.argv[1], sys.argv[2])) 

BGP-AS-BASE.cfg
3216:Beeline
9002:Retn
2854:Orange
~omit~
8359:MTS


Le fichier BGP-AS-BASE.cfg représente la correspondance du numéro AS et du nom du fournisseur. Il est nécessaire de déterminer le fournisseur avec lequel BGP est installé (soudain, il y a une erreur dans le fichier avec les contrats). La base externe n'a pas été utilisée, car Il existe de nombreux numéros AS privés.

En termes de SNMP :

  • nous demandons au routeur des sous-réseaux par OID 1.3.6.1.2.1.4.20.1.1 et des masques de sous-réseau par OID 1.3.6.1.2.1.4.20.1.3 en une seule demande. Nous le traitons, le traduisons en xxxx / xx et l'écrivons dans la cellule host_networks .
  • nous demandons des données sur les adresses IP des homologues BGP , ainsi que leur ASN , nous trouvons le nom du fournisseur par numéro dans la base de données que nous avons créée. Nous les écrivons dans les champs host_router et host_netmask . Il est important de faire immédiatement une limite de 38 caractères, car ces champs ne prennent pas en charge plus. Nos noms de champs dans la base de données ne coïncident pas toujours avec les données qu'ils stockent, car utilisé les champs existants dans la base de données Zabbix, afin de ne pas jouer avec la création de nouveaux champs dans la table. Les noms de champs corrects ont été corrigés dans le WEB, il n'y a pas eu de confusion.
  • nous téléchargeons des données sur le fournisseur, le modèle et l'équipement logiciel. Parsim, écrivez dans les variables. La conception associée à l'écriture du modèle du matériel est due au fait que pour certains modèles Cisco a un nom écrit dans un OID différent (le plus souvent pour le châssis), j'ai donc dû faire une vérification supplémentaire des données.

Le bloc entier associé à SNMP est inclus dans try-except , de sorte que s'il n'y a pas de SNMP sur l'équipement, le script ne tombe pas et nous obtenons au moins des données d'Excel par les fournisseurs. Pour comprendre quelle partie du script a été exécutée et laquelle ne l'est pas, nous notons le succès du bloc SNMP dans le champ date_hw_expiry , ainsi que la date à laquelle la dernière fois que nous avons pu supprimer toutes les données sur SNMP, et la date à laquelle la dernière fois que nous avons pu trouver les données dans le fichier Excel.


Tout cela revient sous la forme de JSON prêt pour Zabbix.

La mise à jour de toutes les données d'inventaire est lancée une fois par jour, déchargeant tous les hôtes et démarrant l' inventaire.py pour chaque objet.

mp-update.py
 #!/usr/bin/python3 # -*- coding: utf-8 -*- from multiprocessing import Pool import time from zabbix.api import ZabbixAPI from inventory import inventory from report import report def updating(shop): try: shop['inventory'] = inventory(shop['interfaces'][0]['ip'], shop['host'][-4:]) shop.pop('interfaces') shop['inventory_mode'] = '1' shop.pop('host') print (shop['hostid']) return zapi.host.update(shop) except: print(">>>",shop['hostid']) with open ('/home/local/integration/error.txt', 'a') as err: err.write(shop['hostid']) err.write("\n") if __name__ =='__main__': t = time.time() zapi = ZabbixAPI(url='http://z.noc.x5.ru/', user='user', password='pwd') shopbase = zapi.host.get(output=['host', 'hostid'], groupids= ['12', '13', '14'], monitored="1", selectInterfaces=['ip']) pool = Pool(processes=10) p=[0 for x in range(0,len(shopbase))] for i in range(0, len(shopbase), 10): print ("Index:", i,"\n",shopbase[i],"\n") pool.map(updating,shopbase[i:i+10]) pool.close() pool.join() print(time.time()-t) report('    Zabbix.', 'Inventory updating succeed') 


Le multitraitement est utilisé (un exemple est tiré des vastes étendues d'Internet). Pour effectuer une recherche, nous utilisons l' ID SAP , que nous avons dans le nom d'hôte. La sortie résultante est écrite mise à jour 'ohm dans Zabbix.

Résumé


Pour la mise en œuvre de toutes les intégrations, mises à jour automatiques et mises à jour des mécanismes intégrés, l'API Zabbix est plus que suffisant. Les principales fonctions utilisées sont host.get , host.create et host.update , qui ensemble vous permettent de contrôler entièrement la création et la mise à jour de la base de données des objets de surveillance. Les données d'entrée de ces fonctions peuvent être soumises à partir de tous les systèmes et sources disponibles.

Les principaux modules python qui nous ont aidés à faire face à cette tâche: pysnmp , xlrd , zabbix.api , xml , ipaddress , json .
xlrd - analyse Excel.
xml - Analyse XML.
pysnmp - extraire des données SNMP de l'équipement.

L'interaction SNMP est plus facile que SSH, du moins parce que dans la pratique, le matériel répond plus rapidement à SNMP qu'à SSH, l'analyse syntaxique des réponses SNMP est pratiquement inutile, bien que les CLI des différents fournisseurs soient souvent très différentes les unes des autres, et les conclusions sont les mêmes. les équipes peuvent différer même dans différents modèles du même fournisseur.

Les principaux OID appliqués:
iso.3.6.1.2.1.4.20.1.1 - adresses de toutes les interfaces de routeur
iso.3.6.1.2.1.4.20.1.3 - masques de sous-réseau de toutes les interfaces de routeur
iso.3.6.1.2.1.15.3.1.7 - tous les homologues BGP du routeur
iso.3.6.1.2.1.15.3.1.9 - AS de tous les homologues BGP du routeur
iso.3.6.1.2.1.47.1.1.1.1.13.1 - modèle
iso.3.6.1.2.1.47.1.1.1.1.10.1 - version courte du logiciel
iso.3.6.1.2.1.47.1.1.1.1.1.12.1 - fournisseur
iso.3.6.1.2.1.1.1.0 - version détaillée du logiciel
ISO.3.6.1.2.1.47.1.1.1.1.7.1 - modèle, type de châssis

Le tableau de bord a dû être ajouté un peu pour diviser les problèmes sur les réseaux de distribution et ne pas les interférer dans un tas. Ajoutez également plusieurs champs, par exemple ip, nom et adresse du fournisseur, de sorte qu'en cas d'accident de masse, il suffira de copier-coller depuis le navigateur dans le message tous les objets présentant un problème, avec immédiatement toutes les données nécessaires au fournisseur.


«Workview» a été écrit séparément , dans lequel nous pouvons trouver toutes les informations collectées, ainsi que les graphiques qui sont collectés pour cet objet.

Source: https://habr.com/ru/post/fr438754/


All Articles