Skip to content
Snippets Groups Projects
Commit 0fcae337 authored by dylan.peiry's avatar dylan.peiry
Browse files

adding labo on git

parents
Branches master
No related tags found
No related merge requests found
[hosts]
H1 ansible_host=H1
H2 ansible_host=H2
[routers]
R1 ansible_host=R1
R2 ansible_host=R2
\ No newline at end of file
- name: Configuration des interfaces réseau
hosts: all
become: yes
vars_files:
- vars.yml
tasks:
- name: Configuration des interfaces réseau des hôtes
template:
src: templates/interfaces.j2
dest: "/etc/network/interfaces.d/{{ item.key }}.cfg"
owner: root
group: root
mode: 0644
with_dict: "{{ host_interfaces[inventory_hostname] }}"
when: "'hosts' in group_names"
notify: Redémarrage du service networking
- name: Configuration des interfaces réseau des routeurs
template:
src: templates/interfaces.j2
dest: "/etc/network/interfaces.d/{{ item.key }}.cfg"
owner: root
group: root
mode: 0644
with_dict: "{{ router_interfaces[inventory_hostname] }}"
when: "'routers' in group_names"
notify: Redémarrage du service networking
- name: Vérification de la connectivité entre H1 et H2
ping:
data: 3.0.0.3
when: inventory_hostname == 'H1'
register: ping_result
- name: Affichage du résultat du ping
debug:
msg: "H1 peut ping H2 : {{ ping_result.changed }}"
when: inventory_hostname == 'H1'
handlers:
- name: Redémarrage du service networking
systemd:
name: networking
state: restarted
host_interfaces:
H1:
eth0:
ip: 1.0.0.3
netmask: 255.255.255.0
gateway: 1.0.0.1
H2:
eth0:
ip: 3.0.0.3
netmask: 255.255.255.0
gateway: 3.0.0.2
router_interfaces:
R1:
eth0:
ip: 2.0.0.1
netmask: 255.255.255.0
route: 3.0.0.0/24
gateway: 2.0.0.2
eth1:
ip: 1.0.0.1
netmask: 255.255.255.0
R2:
eth0:
ip: 2.0.0.2
netmask: 255.255.255.0
route: 1.0.0.0/24
gateway: 2.0.0.1
eth1:
ip: 3.0.0.2
netmask: 255.255.255.0
File added
report/imgs/ad_hoc_1.png

127 KiB

report/imgs/ad_hoc_create.png

259 KiB

report/imgs/ad_hoc_uptime.png

77.2 KiB

report/imgs/topologie.png

77.1 KiB

---
geometry: margin=2cm
---
# Labo 3 : Network Automation avec Ansible
Rapport sur la prise en main et réalisation du labo, par Dylan Peiry.
Sources disponibles sur [https://gitedu.hesge.ch/dylan.peiry/labo3-ansible](https://gitedu.hesge.ch/dylan.peiry/labo3-ansible)
Executer le playbook avec `ansible-playbook -i ansible/inv.ini ansible/playbook.yml --extra-vars=ansible/vars.yml`
## 1 - Topologie
![Topologie d'un routeur dans un routeur](imgs/topologie.png)
<p align="center">
Topologie pour configuration simple par Ansible
</p>
### 0 - Préparation
Execution script, préparation des machines
### A - Commandes ad-hoc
* Que fait la commande `ansible -m ping -i "H1,H2,R1,R2" all`
* Elle va essayer de ping tous les hôtes passés en paramètres et répondre pour chacun d'eux avec la valeur `pong` si l'hôte est joignable, ce n'est pas un ping ICMP
![Output `ansible -m ping -i "H1,H2,R1,R2" all`](imgs/ad_hoc_1.png)
<p align="center">
Output <i>ansible -m ping -i "H1,H2,R1,R2" all</i>
</p>
* La commande pour afficher l'uptime de toutes les machines est la suivante `ansible -m command -i "H1,H2,R1,R2" all -a uptime`
![Output ansible -m command -i "H1,H2,R1,R2" all -a uptime](imgs/ad_hoc_uptime.png)
<p align="center">
Output <i>ansible -m command -i "H1,H2,R1,R2" all -a uptime</i>
</p>
* La commande pour créer un fichier `/tmp/hello.txt` sur toutes les machines et la suivante : `ansible -m command -i "H1,H2,R1,R2" all -a "touch /tmp/hello.txt`. Pour vérifier que le fichier a bien été créé, on peut ensuite éxecuter `ansible -m command -i "H1,H2,R1,R2" all -a "ls /tmp"`
![Commandes ansible -m command -i "H1,H2,R1,R2" all -a ("touch /tmp/hello.txt" / "ls /tmp") ](imgs/ad_hoc_create.png)
<p align="center">
Commandes <i>ansible -m command -i "H1,H2,R1,R2" all -a ("touch /tmp/hello.txt" / "ls /tmp")</i>
</p>
* Quelle est la différence entre les modules `command`, `shell` et `raw`?
* `command`: Permet d'éxecuter les binaires
* `ansible -m command -i "H1,H2,R1,R2" all -a "touch example.txt"
* `shell`: Permet d'éxecuter des commandes en profitant des fonctionnalités offertes par le shell comme les pipes ou les redirections
* `ansible -m command -i "H1,H2,R1,R2" all -a "ls /tmp | grep example.txt"
* `raw`: Permet d'éxecuter des commandes sur les hôtes distants quand ils ne bénificient pas d'intépréteur python, afin d'installer python par exemple, pour ensuite pouvoir utiliser `shell` ou `command`
* `ansible -m raw -i "H1,H2,R1,R2" all -a "touch example.txt"
## 2 - Routage et adressage
### A - Playbook Ansible
Pour la configuration à l'aide d'Ansible, j'ai créé 3 fichiers différents:
* Le fichier inventaire `inv.ini` contenant les groupes routers et hosts
```
[hosts]
H1 ansible_host=H1
H2 ansible_host=H2
[routers]
R1 ansible_host=R1
R2 ansible_host=R2
```
On définit les variables ansible_host afin de dire à Ansible de se connecter en utilisant les hosts configurés avec le script du premier labo.
* Ensuite, nous avons le fichier `vars.yml` qui contient les configurations des interfaces pour les routeurs et les hôtes avec des variables. Ce fichier sera chargé par le playbook.
```
host_interfaces:
H1:
eth0:
ip: 1.0.0.3
netmask: 255.255.255.0
gateway: 1.0.0.1
H2:
eth0:
ip: 3.0.0.3
netmask: 255.255.255.0
gateway: 3.0.0.2
router_interfaces:
R1:
eth0:
ip: 2.0.0.1
netmask: 255.255.255.0
route: 3.0.0.0/24
gateway: 2.0.0.2
eth1:
ip: 1.0.0.1
netmask: 255.255.255.0
R2:
eth0:
ip: 2.0.0.2
netmask: 255.255.255.0
route: 1.0.0.0/24
gateway: 2.0.0.1
eth1:
ip: 3.0.0.2
netmask: 255.255.255.0
```
Les interfaces sont séparées en 2 groupes a chaque fois sous lesquels on liste les hôtes ou routeurs puis les variables. Les valeurs sont définies en fonction de la topologie du réseau virtuel donnée dans l'énoncé.
* Finalement, nous avons le fichier `playbook.yml` qui va s'occuper de configurer le tout en éxecutant les tâchs définies sur les hôtes.
```
- name: Configuration des interfaces réseau
hosts: all
become: yes
vars_files:
- vars.yml
tasks:
- name: Configuration des interfaces réseau des hôtes
template:
src: templates/interfaces.j2
dest: "/etc/network/interfaces.d/{{ item.key }}.cfg"
owner: root
group: root
mode: 0644
with_dict: "{{ host_interfaces[inventory_hostname] }}"
when: "'hosts' in group_names"
notify: Redémarrage du service networking
- name: Configuration des interfaces réseau des routeurs
template:
src: templates/interfaces.j2
dest: "/etc/network/interfaces.d/{{ item.key }}.cfg"
owner: root
group: root
mode: 0644
with_dict: "{{ router_interfaces[inventory_hostname] }}"
when: "'routers' in group_names"
notify: Redémarrage du service networking
- name: Vérification de la connectivité entre H1 et H2
ping:
data: 3.0.0.3
when: inventory_hostname == 'H1'
register: ping_result
- name: Affichage du résultat du ping
debug:
msg: "H1 peut ping H2 : {{ ping_result.changed }}"
when: inventory_hostname == 'H1'
handlers:
- name: Redémarrage du service networking
systemd:
name: networking
state: restarted
```
Nous définissions 2 tâches, une pour les hôtes et une pour les routeurs, ensuite grâce a des conditions nous chargerons les variables des hôtes du bon groupe. Finalement, nous bouclons sur les valeurs des variables du fichier `vars.yml` et nous y passons au fichier de template Jinja2 `interfaces.j2` dans lequel nous récupérons les valeurs et éxecutons des commandes.
```
auto {{ item.key }}
iface {{ item.key }} inet static
address {{ item.value.ip }}
netmask {{ item.value.netmask }}
{% if item.value.gateway is defined %}
post-up ip route add default via {{ item.value.gateway }}
{% endif %}
{% if item.value.route is defined %}
post-up ip route add {{ item.value.route }} via {{ item.value.gateway }}
{% endif%}
```
### B - Vérification du bon fonctionnement
Nous vérifions grâce à une tâche finale dans notre playbook que H1 puisse pinger H2 après avoir mis en place les interfaces ainsi que les routes.
```
- name: Vérification de la connectivité entre H1 et H2
ping:
data: 3.0.0.3
when: inventory_hostname == 'H1'
register: ping_result
- name: Affichage du résultat du ping
debug:
msg: "H1 peut ping H2 : {{ ping_result.changed }}"
when: inventory_hostname == 'H1'
```
Nous pingons H2 que quand l'hôte actuel est H1 grâce à `when`
File added
#!/bin/bash
ssh_config="$HOME/config.d/ssh_config"
function parse_ssh_config () {
# loop through each host in the ssh_config...
# get the name
# ssh in to the machine
# change the hostname
# exit
while IFS= read -r line; do
machine_name=$(echo "$line" | grep -Po '(?<=Host )[A-Z]{1}[1-9]{1}')
if [[ -n "${machine_name}" ]]; then
ssh -n "$machine_name" hostname "$machine_name"
echo "Changed hostname of $machine_name to $machine_name"
fi
done < "$ssh_config"
}
parse_ssh_config
\ No newline at end of file
#!/usr/bin/env python3
import requests
import jinja2
import json
import sys
import os
from typing import Tuple, List
PROJECTS_URL = "https://gns3.hepiapp.ch/v2/projects"
SSH_CONFIG_DST = "~/config.d"
SSH_CONFIG_PATH = f"{SSH_CONFIG_DST}/ssh_config"
SSH_CONFIG_TEMPLATE = "ssh_config"
environment = jinja2.Environment(loader=jinja2.FileSystemLoader("templates/"))
def usage():
print(f"{sys.argv[0]} PROJECT_NAME")
def get_projects_nodes_url(project_name: str) -> Tuple[bool, str]:
"""
if found, returns url
else, returns error message
"""
r = requests.get(PROJECTS_URL)
project_uuid = -1
if r.status_code == 200:
projects = r.json()
for project in projects:
if project.get('name').lower() == project_name.lower():
project_uuid = project.get('project_id')
if project_uuid == -1:
return False, f"Le projet {project_name} n'existe pas"
return True, f"{PROJECTS_URL}/{project_uuid}/nodes"
def get_hosts_from_nodes_url(project_nodes_url: str) -> List:
hosts = []
r = requests.get(project_nodes_url)
if r.status_code == 200:
nodes = r.json()
for node in nodes:
if node.get('console_type') == 'telnet':
hosts.append({
"name": node.get('name'),
"ip": node.get('console_host'),
"port": node.get('console') + 1
})
return hosts
def generate_ssh_config(hosts: List):
output_path = os.path.expanduser(SSH_CONFIG_PATH)
output_template = environment.get_template(SSH_CONFIG_TEMPLATE)
context = {
"hosts": hosts
}
# create custom conf dir
output_dir = os.path.expanduser(SSH_CONFIG_DST)
if os.path.exists(output_dir) is False:
os.mkdir(output_dir)
print(f"...created dir {output_dir}")
with open(output_path, mode="w+", encoding="utf-8") as f:
f.write(output_template.render(context))
print(f"...wrote {output_path}")
if __name__ == '__main__':
if len(sys.argv) < 2:
usage()
exit(-1)
project_name = sys.argv[1]
print(f"Project {project_name}")
found, response = get_projects_nodes_url(project_name=project_name)
if not found:
print(response)
exit(-1)
hosts = get_hosts_from_nodes_url(project_nodes_url=response)
generate_ssh_config(hosts=hosts)
auto {{ item.key }}
iface {{ item.key }} inet static
address {{ item.value.ip }}
netmask {{ item.value.netmask }}
{% if item.value.gateway is defined %}
post-up ip route add default via {{ item.value.gateway }}
{% endif %}
{% if item.value.route is defined %}
post-up ip route add {{ item.value.route }} via {{ item.value.gateway }}
{% endif%}
\ No newline at end of file
{% for host in hosts %}
Host {{host.name}}
User root
Hostname {{host.ip}}
Port {{host.port}}
StrictHostKeychecking no
UserKnownHostsFile /dev/null
IdentityFile ~/.ssh/gns3.rsa
{% endfor %}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment