132 lines
4.6 KiB
Markdown
132 lines
4.6 KiB
Markdown
---
|
|
title: Howto Ansible/Cisco : automatisation d'infrastructure
|
|
categories automation
|
|
---
|
|
|
|
* Documentation des modules : <http://docs.ansible.com/ansible/latest/list_of_network_modules.html#ios>
|
|
|
|
Cette documentation est basée sur la version 2.2 d'Ansible que nous utilisons actuellement, et est susceptible de différer dès la version 2.3.
|
|
|
|
# Connection aux switchs
|
|
|
|
Ansible utilise python, mais ce dernier n'étant pas disponible sur les switchs, le mode de connexion n'est pas le même. Au lieu d'utiliser une connexion SSH, on doit utiliser une connexion locale : Ansible exécute le code sur la machine locale, ce qui génère les commandes qui sont ensuite envoyées par SSH sur le switch distant. Cela pose cependant un problème : le switch sur lequel on veut lancer un playbook doit être directement accessible par la machine locale, puisque le fichier ~/.ssh/config n'est pas utilisé.
|
|
|
|
On doit donc indiquer dans notre playbook comment la machine locale doit se connecter sur le switch distant dans une variable qui sera ensuite passée à chaque utilisation d'un module.
|
|
|
|
Le mode de récupération des facts par défaut d'Ansible ne fonctionne également pas, il faut le désactiver. Un module spécifique lui est dédié.
|
|
|
|
~~~{.yaml}
|
|
- hosts: switchs
|
|
gather_facts: no
|
|
connection: local
|
|
|
|
vars:
|
|
provider:
|
|
host: "{{ inventory_hostname }}"
|
|
username: "{{ ansible_user }}"
|
|
password: "{{ ansible_ssh_pass }}"
|
|
~~~
|
|
|
|
Le nom dans l'inventory doit alors correspondre au nom utilisé pour se connecter au switch. Si aucun hostname ne lui est associé, son IP doit être utilisée. Si l'on veut quand même utiliser un nom d'hôte sous forme d'alias, une variable doit être définie dans le fichier d'inventory :
|
|
|
|
~~~
|
|
[switchs]
|
|
SW01 SWITCH_IP=192.0.2.1
|
|
~~~
|
|
|
|
Et cette variable doit être utilisée dans le playbook :
|
|
|
|
~~~{.yaml}
|
|
vars:
|
|
provider:
|
|
host: "{{ SWITCH_IP }}"
|
|
username: "{{ ansible_user }}"
|
|
password: "{{ ansible_ssh_pass }}"
|
|
~~~
|
|
|
|
Ainsi, on peut choisir sur quelle machine lancer le playbook avec le nom défini dans l'inventory.
|
|
|
|
# Modules
|
|
|
|
Chaque module doit contenir la variable `provider` précédemment définie pour se connecter aux switchs :
|
|
|
|
~~~{.yaml}
|
|
- ios_XXX:
|
|
provider: "{{ provider }}"
|
|
…
|
|
~~~
|
|
|
|
## ios_facts
|
|
|
|
Le module [ios_facts](http://docs.ansible.com/ansible/latest/ios_facts_module.html) permet de récupérer les facts d'un switch.
|
|
|
|
~~~{.yaml}
|
|
- ios_facts:
|
|
provider: "{{ provider }}"
|
|
gather_subset:
|
|
- "all"
|
|
~~~
|
|
|
|
Trois type de facts peuvent être récupérés et définis avec `gather_subset` :
|
|
|
|
* `config` renvoie le contenu de la running-config.
|
|
* `interfaces` renvoie la description détaillée de chaque interface : adresse IP, description, status, adresse mac, …
|
|
* `hardware` renvoie le détail du hardware : mémoire, filesystem.
|
|
|
|
On peut ensuite vérifier que la configuration soit conforme en se servant de debug :
|
|
|
|
~~~{.yaml}
|
|
- debug:
|
|
msg: "Management interface down"
|
|
when: ansible_net_interfaces.FastEthernet0.operstatus == "administratively down"
|
|
|
|
- debug:
|
|
msg: "Domain-name not or badly configured"
|
|
when: "not 'ip domain-name example.com' in ansible_net_config"
|
|
~~~
|
|
|
|
## ios_command
|
|
|
|
Le module [ios_command](http://docs.ansible.com/ansible/latest/ios_command_module.html) permet de lancer des commandes basiques (pas en mode configuration) sur le switch.
|
|
|
|
Cela peut être utile pour récupérer des valeurs non renvoyées par les facts :
|
|
|
|
~~~{.yaml}
|
|
- ios_command:
|
|
provider: "{{ provider }}"
|
|
commands:
|
|
- show clock
|
|
register: clock
|
|
~~~
|
|
|
|
## ios_config
|
|
|
|
Le module [ios_config](http://docs.ansible.com/ansible/latest/ios_config_module.html) permet de configurer le switch en spécifiant les commandes que l'on veut appliquer :
|
|
|
|
~~~{.yaml}
|
|
- name: load new acl into device
|
|
ios_config:
|
|
provider: "{{ provider }}"
|
|
lines:
|
|
- 10 permit ip host 1.1.1.1 any log
|
|
- 20 permit ip host 2.2.2.2 any log
|
|
- 30 permit ip host 3.3.3.3 any log
|
|
- 40 permit ip host 4.4.4.4 any log
|
|
- 50 permit ip host 5.5.5.5 any log
|
|
parents: ip access-list extended test
|
|
before: no ip access-list extended test
|
|
match: exact
|
|
~~~
|
|
|
|
Cette tâche sera exécutée uniquement si la configuration actuelle ne contient pas exactement ces valeurs (`match: exact`) et est l'équivalent de :
|
|
|
|
~~~
|
|
Switch(config)#no ip access-list extended test
|
|
Switch(config)#ip access-list extended test
|
|
Switch(config-ext-nacl)#10 permit ip host 1.1.1.1 any log
|
|
Switch(config-ext-nacl)#20 permit ip host 2.2.2.2 any log
|
|
Switch(config-ext-nacl)#30 permit ip host 3.3.3.3 any log
|
|
Switch(config-ext-nacl)#40 permit ip host 4.4.4.4 any log
|
|
Switch(config-ext-nacl)#50 permit ip host 5.5.5.5 any log
|
|
~~~
|