La sauvegarde pour Linux n'écrit pas de lettres

Bonjour à tous!

Aujourd'hui, je veux parler de la façon de gérer Veeam Agent pour Linux à l'aide de la ligne de commande et des possibilités qu'il ouvre entre les mains compétentes d'un programmeur.

J'ai été invité à écrire un article par un commentaire sur un article précédent. Pour paraphraser la surprise de l’utilisateur: «Eh bien, comment? Le serveur n'écrit pas de lettres indiquant qu'il a été enregistré! » De plus, selon les analystes, il n'est pas le seul, sinon le fil ne serait pas apparu sur le forum. Et puisque les gens écrivent, cela signifie que quelqu'un en a besoin!

Dans l'article, je vais expliquer pourquoi cette fonctionnalité n'est pas dans le produit. Mais nous ne nous arrêterons pas là, nous ajouterons cette fonction! Nous sommes programmeurs, nous allons donc écrire une lettre et générer un rapport sous la forme d'une page html.


De plus, je vais vous montrer les commandes les plus utiles, à mon avis, qui peuvent faciliter le travail de l'administrateur.

Préparez-vous: beaucoup de code, pas d'images.

Tout d'abord, répondons à la question: «Pourquoi l'agent Veeam pour Linux n'écrit-il pas de lettres?»

Vous n'aimerez peut-être pas les réponses, ne me blâmez pas. Mais le fait est que les utilisateurs plus ou moins de grandes entreprises n'en ont pas besoin, et voici pourquoi:

  • Premièrement, pour travailler avec le courrier, vous devez soit placer le serveur smpt sur la machine locale, soit utiliser quelqu'un sur le réseau. Avec l'implémentation la plus simple (commande mail ), vous devrez installer le paquet mailutils . Et de nombreux administrateurs système ne voudront pas créer une vulnérabilité potentielle sur leur serveur de production sous la forme d'un service pouvant envoyer des lettres n'importe où. Oui, et la possibilité peut ne pas être due aux ports fermés, à l'indépendance des sous-réseaux, etc.
  • Deuxièmement, puisque le paquet mailutils peut très bien ne pas être sur le système (pour la première raison), cela n'a aucun sens d'essayer de l'utiliser. Sinon, nous pouvons obtenir une fonction qui semble être là, mais "prête à l'emploi" ne fonctionne pas, ce qui signifie qu'il y aura un fil sur le forum sur un sujet comme: "Comment configurer le serveur pour que les e-mails soient envoyés."
  • Et troisièmement, en général, aucune notification supplémentaire n'est nécessaire, car les entreprises plus ou moins grandes utilisent Veeam Backup & Replication . Sa console collecte des informations sur toutes les sauvegardes effectuées sur des référentiels bien connus. Voyez par vous-même.

Dans la version de Veeam Backup & Replication 9.5 Update 4 , il est possible d'utiliser ce produit gratuitement, mais avec une restriction sur les machines virtuelles / physiques desservies.
Si vous avez jusqu'à 3 serveurs physiques (inclus), les fonctions VBR gratuites seront plus que suffisantes pour vous.

Si vous avez plus de 3 machines, il n'y a aucun moyen de payer pour le logiciel, mais vous voulez quand même surveiller vos serveurs de manière centralisée, je vous suggère d'ajouter quelques scripts vous-même. J'aime m'amuser en python après avoir travaillé pour C / C ++.

veeamconfig nous veeamconfig commande veeamconfig . L'équipe veeamconfig donne accès à toutes les fonctionnalités du produit. Sans aucun doute, l'interface pseudographique créée à l'aide de la bibliothèque ncurses est beaucoup plus agréable à l'œil, cependant, si vous devez lier des programmes à quelque chose de nouveau, alors la CLI est notre tout.

La description des commandes de l' agent Veeam pour Linux est valable pour la version 3.0. Je n'ai pas vérifié les versions précédentes, il peut donc y avoir des différences.

L'interface CLI de Veeam Agent pour Linux est assez pratique et bien documentée. Entrez simplement veeamconfig --help et vous obtiendrez une liste des commandes disponibles:

 $sudo veeamconfig --help Veeam Agent for Linux (c) Veeam Software AG Usage: veeamconfig [command] Commands: repository - Backup repositories management vbrserver - Veeam Backup and Replication servers management job - Backup jobs management backup - Backups management point - Restore points management license - License management agreement - End User License Agreement management config - Import/export configuration schedule - Jobs schedule configuration cloud - Cloud provider management mode - Operation mode session - Sessions management ui - User interface aap - Application-aware processing version, --version, -v - Product version help, --help, -h - Short help 

Pour voir ce que chaque commande vous permet de faire, appelez simplement veeamconfig config --help . Nous obtenons:

 Veeam Agent for Linux (c) Veeam Software AG Usage: veeamconfig config [command] Commands: import - Import repositories and jobs into database export - Export repositories and jobs from database grabLogs - Collect support logs bundle patchiso - Create custom Veeam Recovery Media adding all hardware drivers from this system help, --help, -h - Short help 

Ici, d'ailleurs, nous pouvons voir la grabLogs log collection. Il vous permettra de collecter rapidement tous les journaux nécessaires à l'assistance. C'est au cas où quelque chose se passe mal.

Il y a aussi une équipe intéressante qui est apparue dans la version 3.0:

 $ sudo veeamconfig agreement --help Veeam Agent for Linux (c) Veeam Software AG Usage: veeamconfig agreement [command] Commands: acceptEula - Accept Veeam End User License Agreements acceptThirdPartyLicenses - Accept Veeam 3rd party License Agreement show - Show End User License Agreements acceptance status help, --help, -h - Short help 

Le fait est qu'à partir de la version 3.0, l'utilisateur est tenu d'accepter explicitement les accords de licence. Cela ressemble à ceci:

 $ sudo veeamconfig job list I accept Veeam Software End User License Agreement: /usr/share/doc/veeam/EULA (yes/no | y/n): yes I accept the terms of the following 3rd party software components license agreements: /usr/share/doc/veeam/3rd_party (yes/no | y/n): 

Par conséquent, le fonctionnement de vos scripts peut être perturbé. Afin de ne pas entrer dans chaque machine et de ne pas effectuer cette procédure manuellement, les commandes suivantes ont été fournies:

 veeamconfig agreement acceptEula veeamconfig agreement acceptThirdPartyLicenses 

Ils vous permettent d'accepter des accords de licence sans plus de questions.

Mais nous nous sommes écartés du sujet de la rédaction d'une lettre.

Pour la tâche de surveillance de l'état du serveur, nous avons besoin de la commande veeamconfig session list . Il produit quelque chose comme:

 Job name Type ID State Started at Finished at bj-home Backup {dbe48e88-3df7-4712-a472-09af8fed4e80} Success 2018-12-05 15:43 2018-12-05 15:44 bj-home Backup {c178a799-2935-4bd6-883b-b11278000076} Success 2018-12-05 16:26 2018-12-05 16:26 bj-home Backup {3405dad3-0016-4a00-933e-60ef66b30324} Success 2018-12-06 06:00 2018-12-06 06:00 

Eh bien, il y a des informations ici quand le serveur a été sauvegardé et quel a été le succès. En principe, il est déjà possible de collecter le «exhaust» dans un fichier et de l'envoyer par lettre. Cependant, en un an, la lettre peut augmenter d'environ 365 lignes. Et rechercher un État avec des erreurs peut sembler fastidieux. Par conséquent, nous analyserons cet «échappement» et obtiendrons une liste normale avec laquelle vous pouvez déjà faire quelque chose.

Voir tout le code ici

 class CSession: @staticmethod def List(): return subproccall( ["veeamconfig", "session", "list"] ) class CSessionInfoList(object): def __init__(self, list): self.list = list def List(self): return self.list @staticmethod def Get(): text = CSession.List() lines = text.split("\n") list = [] # session info list for line in lines: if len(line) == 0: continue words = line.split() if len(words) == 0: continue if words[0] == "Job": continue if words[0] == "Total": continue try: jobName = words[0] type = words[1] id = words[2] state = words[3] startTime = words[4] + " " + words[5] finishTime = words[6] + " " + words[7] list.append(CSessionInfo(id, type, jobName, state, startTime, finishTime)) except: print "Failed to parse [", line, "]" return CSessionInfoList(list) 

Eh bien, maintenant, faisons une lettre et envoyez-la-nous.

 def SendMailsessions(): print "---" print "Sending statistic to administrator:" sessions = veeamlpb.session.CSessionInfoList.Get() recipient = "dear.admin@company.com" subject = "VAL status notification" text = "Statistic:\n" inx = 0; successCount = 0 warningCount = 0 errorCount = 0 for sessionInfo in sessions.List(): if (sessionInfo.State() == "Success"): successCount += 1 elif (sessionInfo.State() == "Warning"): warningCount += 1 else: errorCount += 1 text += str(successCount)+"/"+str(warningCount)+"/"+str(errorCount)+" Success/Warning/Error\n" text += "Last 10 session:\n" for sessionInfo in reversed(sessions.List()): if inx == 10: text += "...\n" break; text += str(inx)+" | "+sessionInfo.State()+" | "+sessionInfo.JobName()+" | "+sessionInfo.StartTime()+" / "+sessionInfo.FinishTime() + "\n" #text += inx += 1 text += "\n" text += "--------------------------------------------------------------------------------\n" text += " Yours sincerely, Veeam Agent for Linux Monitor\n" print text os.system("echo '"+text+"' | mail -s '"+subject+"' "+recipient) 

Par conséquent, après l'installation de mailutils, nous pouvons obtenir une lettre du formulaire:

 Statistic: 3/0/0 Success/Warning/Error Last 10 session: 0 | Success | bj-home | 2018-12-06 06:00 / 2018-12-06 06:00 1 | Success | bj-home | 2018-12-05 16:26 / 2018-12-05 16:26 2 | Success | bj-home | 2018-12-05 15:43 / 2018-12-05 15:44 -------------------------------------------------------------------------------- Yours sincerely, Veeam Agent for Linux Monitor 

La lettre affiche uniquement les 10 dernières sessions. Dans le même temps, des informations sur le nombre de sessions réussies et peu nombreuses sont affichées au tout début de la lettre. Il suffit de regarder les chiffres dans la lettre au début de la journée de travail, de vérifier le courrier et de siroter une cafetière pour comprendre que les sauvegardes de nuit ont réussi.

Si vous avez besoin de quelque chose de plus évident, vous pouvez demander des informations sur les sessions au format xml et les transférer sur votre serveur. Là, combinez les données obtenues dans un seul tableau récapitulatif qui affiche toutes les informations nécessaires dans un format pratique ou réalisable pour vous.
Nous obtenons le couple XML de lignes:

 sessionList = veeamlpb.session.CSessionList() text = sessionList.ToXml() 

Enregistrez le fichier résultant

 sessionListFileName = "session_list.xml" print "Store XML to file: ",sessionListFileName sessionListXmlFile = open(sessionListFileName, "w") sessionListXmlFile.write(text) sessionListXmlFile.close() 

Ensuite, nous envoyons le XML reçu au serveur. Une option alternative est également possible - le serveur collecte les XML des machines qui sont sauvegardées. Qui est l'initiateur n'a pas encore d'importance pour nous. Il est important que les fichiers XML soient collectés sur le serveur avec des listes de sessions de toutes les machines. J'ai choisi la première option:

 hostname = os.uname()[1] target = "user@admin-desktop:/home/user" os.system("scp ./"+sessionListFileName+" "+target+"/backups/"+hostname+"/session_list.xml") 

Maintenant, côté serveur, il reste à traiter les données reçues et à faire une belle page html.

 import veeamlpb import os import datetime import xml.etree.ElementTree as xml def main(): hosts = [] backupsDirectory = "/home/user/backups" for item in os.listdir(backupsDirectory): if item in [".", ".."]: continue if os.path.isdir(os.path.join(backupsDirectory,item)): hosts.append(item) print "item: ",item if len(hosts) == 0: return 0 backupSessionMap = {} for host in hosts: print "found host: ", host sessionInfoFile = os.path.join(os.path.join(backupsDirectory,host), "session_list.xml") sessionList = veeamlpb.session.CSessionInfoList.FromXmlFile(sessionInfoFile) backupSessionMap[host] = sessionList for sessionInfo in sessionList.List(): print "Session:",sessionInfo.ToString() html = xml.Element("html") body = xml.SubElement(html, "body", {"style":"background-color: #00b336;"}) xml.SubElement(body,"h1").text = "Report at "+datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") xml.SubElement(body,"h2").text = "Statistic:" for host in hosts: sessionList = backupSessionMap[host] success=0 warning=0 error=0 if len(sessionList.List()) == 0: continue for sessionInfo in sessionList.List(): if sessionInfo.State() == "Success": success +=1 elif sessionInfo.State() == "Warning": warning +=1 else: error +=1 latestSessionInfo = sessionList.List()[-1] attr = {} if latestSessionInfo.State() == "Success": #attr["style"] = "background-color: #00b336;" attr["style"] = "background-color: #005f4b; color: white;" elif latestSessionInfo.State() == "Warning": attr["style"] = "background-color: #93ea20;" else: attr["style"] = "background-color: #ba0200; color: white;" xml.SubElement(xml.SubElement(body,"p"),"span", attr).text = \ host + " - "+str(success)+"/"+str(warning)+"/"+str(error)+" Success/Warning/Error" for host in hosts: sessionList = backupSessionMap[host] xml.SubElement(body,"h2").text = host+":" tableStyle =xml.SubElement(body,"style") tableStyle.attrib["type"] = "text/css" tableStyle.text = "TABLE {border: 1px solid green;} TD{ border: 1px solid green; padding: 4px;}" table = xml.SubElement(body,"table") thead = xml.SubElement(table, "thead") xml.SubElement(thead, "th").text = "Number" xml.SubElement(thead, "th").text = "State" xml.SubElement(thead, "th").text = "Job name" xml.SubElement(thead, "th").text = "Start at" xml.SubElement(thead, "th").text = "Complete at" tbody = xml.SubElement(table, "tbody") inx = 0 for sessionInfo in reversed(sessionList.List()): if inx == 10: break; tr = xml.SubElement(tbody,"tr") xml.SubElement(tr, "td").text = str(inx) attr ={} if sessionInfo.State() == "Success": pass elif sessionInfo.State() == "Warning": attr["style"] ="background-color: #93ea20;" else: attr["style"] ="background-color: #ba0200; color: white;" xml.SubElement(tr, "td", attr).text = sessionInfo.State() xml.SubElement(tr, "td").text = sessionInfo.JobName() xml.SubElement(tr, "td").text = sessionInfo.StartTime() xml.SubElement(tr, "td").text = sessionInfo.FinishTime() inx += 1 xml.ElementTree(html).write("summary.html", encoding='utf-8', method='html') return 0 exit(main()) 

En conséquence, le rapport est prêt:



Je n'avais aucune tâche pour faire un beau produit. La tâche était de montrer que la question de la collecte de statistiques peut être résolue dans des scripts en un à deux jours.

En principe, si vous développez les idées présentées ici, vous pouvez créer un «Moniteur de sauvegarde ouvert pour Veeam Agent pour Linux». À mon avis, un bon sujet pour les cours en Python, ou peut-être même pour un diplôme, ou juste une excuse pour pratiquer la programmation sur un projet open source. D'accord, il vaut mieux pratiquer la programmation que de devenir un elfe de niveau 80.

Tout le code peut être trouvé à http://www.github.com/CodeImp/veeampy/ . Téléchargez, utilisez, complétez et bifurquez sur la santé.

Veuillez noter que le code est distribué sous la licence GPL-2, peut contenir des erreurs, etc. Tout est comme d'habitude dans le monde de l'open source. Donc, avant d'utiliser en production - n'oubliez pas de conduire dans un laboratoire de test.

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


All Articles