switchs/main.py

153 lines
6.3 KiB
Python
Executable file

#!/usr/bin/env python3
from configparser import ConfigParser
import socket
from re2oapi import Re2oAPIClient
from jinja2 import Environment, FileSystemLoader
import requests
import base64
import json
config = ConfigParser()
config.read('config.ini')
api_hostname = config.get('Re2o', 'hostname')
api_password = config.get('Re2o', 'password')
api_username = config.get('Re2o', 'username')
api_client = Re2oAPIClient(api_hostname, api_username, api_password)
client_hostname = socket.gethostname().split('.', 1)[0]
all_switchs = api_client.list("switchs/ports-config/")
# Création de l'environnement Jinja
ENV = Environment(loader=FileSystemLoader('.'))
# Création du template final avec les valeurs contenues dans le dictionnaire "valeurs" - Ces valeurs sont positionnées dans un objet "temp", qui sera utilisé par le moteur, et que l'on retrouve dans le template.
class Switch:
def __init__(self):
self.additionnal = None
self.all_vlans = api_client.list("machines/vlan/")
self.settings = api_client.view("preferences/optionaltopologie/")
# Import du fichier template dans une variable "template"
self.hp_tpl = ENV.get_template("templates/hp.tpl")
self.conf = None
self.name = None
self.switch = None
self.headers = None
self.creds_dict = None
def get_conf_file_name(self):
return self.switch["short_name"] + ".conf"
def preprocess_hp(self):
"""Prérempli certains valeurs renvoyées directement à jinja, pour plus de simplicité"""
def add_to_vlans(vlans, vlan, port, tagged=True):
if not vlan['vlan_id'] in vlans:
if not tagged:
vlans[vlan['vlan_id']] = {'ports_untagged' : [str(port['port'])], 'ports_tagged' : [], 'name' : vlan['name']}
else:
vlans[vlan['vlan_id']] = {'ports_tagged' : [str(port['port'])], 'ports_untagged' : [], 'name' : vlan['name']}
else:
if not tagged:
vlans[vlan['vlan_id']]['ports_untagged'].append(str(port['port']))
else:
vlans[vlan['vlan_id']]['ports_tagged'].append(str(port['port']))
vlans = dict()
for port in self.switch['ports']:
if port['get_port_profil']['vlan_untagged']:
add_to_vlans(vlans, port['get_port_profil']['vlan_untagged'], port, tagged=False)
if port['get_port_profil']['vlan_tagged']:
for vlan in port['get_port_profil']['vlan_tagged']:
add_to_vlans(vlans, vlan, port)
arp_protect_vlans = [vlan["vlan_id"] for vlan in self.all_vlans if vlan["arp_protect"]]
dhcp_snooping_vlans = [vlan["vlan_id"] for vlan in self.all_vlans if vlan["dhcp_snooping"]]
dhcpv6_snooping_vlans = [vlan["vlan_id"] for vlan in self.all_vlans if vlan["dhcpv6_snooping"]]
igmp_vlans = [vlan["vlan_id"] for vlan in self.all_vlans if vlan["igmp"]]
mld_vlans = [vlan["vlan_id"] for vlan in self.all_vlans if vlan["mld"]]
ra_guarded = [str(port['port']) for port in self.switch['ports'] if port['get_port_profil']['ra_guard']]
loop_protected = [str(port['port']) for port in self.switch['ports'] if port['get_port_profil']['loop_protect']]
self.additionals = {'ra_guarded' : ra_guarded, 'loop_protected' : loop_protected, 'vlans' : vlans, 'arp_protect_vlans' : arp_protect_vlans, 'dhcp_snooping_vlans' : dhcp_snooping_vlans, 'dhcpv6_snooping_vlans' : dhcpv6_snooping_vlans, 'igmp_vlans' : igmp_vlans, 'mld_vlans': mld_vlans}
def gen_conf_hp(self):
"""Génère la config pour ce switch hp"""
self.preprocess_hp()
self.conf = self.hp_tpl.render(switch=self.switch, settings=self.settings, additionals=self.additionals)
def check_and_get_login(self):
"""Récupère les login/mdp du switch, renvoie false si ils sont indisponibles"""
self.creds_dict = self.switch["get_management_cred_value"]
if self.creds_dict:
return True
else:
return False
def login_hp(self):
"""Login into rest interface of this switch"""
url_login = "http://" + self.switch["ipv4"] + "/rest/v3/login-sessions"
payload_login = {
"userName" : self.creds_dict["id"],
"password" : self.creds_dict["pass"]
}
get_cookie = requests.post(url_login, data=json.dumps(payload_login))
cookie = get_cookie.json()['cookie']
self.headers = {"Cookie" : cookie}
def apply_conf_hp(self):
"""Apply config restore via rest"""
url_restore = "http://" + self.switch["ipv4"] + "/rest/v4/system/config/cfg_restore"
data = {
"server_type": "ST_TFTP",
"file_name": self.get_conf_file_name(),
"tftp_server_address": {"server_address":
{"ip_address":
{"version":"IAV_IP_V4",
"octets":self.settings["switchs_management_interface_ip"]}}},
}
# Nous lançons la requête de type POST.
post_restore = requests.post(url_restore, data=json.dumps(data), headers=self.headers)
def gen_conf_and_write(self):
"""Génère la conf suivant le bon constructeur et l'écrit"""
if self.switch["model"]:
constructor = self.switch["model"]["constructor"].lower()
if "hp" in constructor or "aruba" in constructor:
self.gen_conf_hp()
self.write_conf()
def apply_conf(self):
if self.check_and_get_login():
if self.switch["model"] and self.switch["automatic_provision"] == True and self.settings["provision_switchs_enabled"]:
constructor = self.switch["model"]["constructor"].lower()
if "hp" in constructor or "aruba" in constructor:
self.login_hp()
self.apply_conf_hp()
def write_conf(self):
"""Ecriture de la conf du switch dans le fichier qui va bien"""
with open("generated/" + self.get_conf_file_name(), 'w+') as f:
f.write(self.conf)
sw = Switch()
for switch in all_switchs:
sw.switch = switch
sw.gen_conf_and_write()
try:
sw.apply_conf()
except:
print("Erreur dans l'application de la conf pour " + switch["short_name"])