main.py 7.7 KB
Newer Older
Charlie Jacomme's avatar
Charlie Jacomme committed
1
#!/usr/bin/env python3
Maël Kervella's avatar
Maël Kervella committed
2
from configparser import ConfigParser
3
import socket
Maël Kervella's avatar
Maël Kervella committed
4 5 6

from re2oapi import Re2oAPIClient

7 8
from jinja2 import Environment, FileSystemLoader

9 10 11 12
import requests
import base64
import json

Maël Kervella's avatar
Maël Kervella committed
13 14 15
config = ConfigParser()
config.read('config.ini')

16 17 18 19 20 21 22 23
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]

24 25 26 27 28 29 30 31
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.

32 33 34 35 36

class Switch:
    def __init__(self):
        self.additionnal = None
        self.all_vlans = api_client.list("machines/vlan/")
37
        self.settings = api_client.view("preferences/optionaltopologie/")
38 39 40 41 42
        # 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
43 44
        self.headers = None
        self.creds_dict = None
45 46 47 48 49 50 51 52 53 54 55 56 57

    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']}
58
            else:
59 60 61 62
                if not tagged:
                    vlans[vlan['vlan_id']]['ports_untagged'].append(str(port['port']))
                else:
                    vlans[vlan['vlan_id']]['ports_tagged'].append(str(port['port']))
63

64
        vlans = dict()
65

66 67 68 69 70 71
        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)
72

chirac's avatar
chirac committed
73
        #Trie les ip par vlan, et les ajoute ainsi que les subnet
74 75 76 77 78 79 80
        for ip, subnet in self.switch["interfaces_subnet"].items():
            vlans[subnet[0]["vlan_id"]].setdefault("ipv4", {})
            vlans[subnet[0]["vlan_id"]]["ipv4"][ip] = subnet
        for ipv6, subnet in self.switch["interfaces6_subnet"].items():
            vlans[subnet["vlan_id"]].setdefault("ipv6", {})
            vlans[subnet["vlan_id"]]["ipv6"][ipv6] = subnet

chirac's avatar
chirac committed
81
        #Regroupement des options par vlans : dhcp_soop,arp, et dhcpv6, ainsi que igmp, mld , ra-guard et loop_protect
82 83 84
        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"]]
chirac's avatar
chirac committed
85 86
        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"]]
87 88
        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']]
89

90
        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}
91

92 93 94 95

    def gen_conf_hp(self):
        """Génère la config pour ce switch hp"""
        self.preprocess_hp()
96
        self.conf = self.hp_tpl.render(switch=self.switch, settings=self.settings, additionals=self.additionals)
97

98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
    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"
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
        provision_mode = self.settings["switchs_provision"]
        if provision_mode == "tftp":
            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"]}}},
                "is_forced_reboot_enabled": True,
            }
        elif provision_mode == "sftp":
             data = {
                "server_type": "ST_SFTP",
                "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"]}},
                    "user_name": self.settings["switchs_management_sftp_creds"]["login"],
                    "password": self.settings["switchs_management_sftp_creds"]["pass"],
                    },
                "is_forced_reboot_enabled": True,
            }
147 148
        # Nous lançons la requête de type POST.
        post_restore = requests.post(url_restore, data=json.dumps(data), headers=self.headers)
149 150 151 152 153 154 155 156 157

    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() 

158 159
    def apply_conf(self):
        if self.check_and_get_login():
160
            if self.switch["model"] and self.switch["automatic_provision"] == True and self.settings["provision_switchs_enabled"]:
161 162 163 164 165
                constructor = self.switch["model"]["constructor"].lower()
                if "hp" in constructor or "aruba" in constructor:
                    self.login_hp()
                    self.apply_conf_hp()

166
    def write_conf(self):
167
        """Ecriture de la conf du switch dans le fichier qui va bien"""
168 169
        with open("generated/" + self.get_conf_file_name(), 'w+') as f:
            f.write(self.conf)
170 171 172



173 174 175
sw = Switch()
for switch in all_switchs:
    sw.switch = switch
176
    sw.gen_conf_and_write()
177 178 179 180
    try:
        sw.apply_conf()
    except:
        print("Erreur dans l'application de la conf pour " + switch["short_name"])