Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a role to collect EOS commands #502

Merged
merged 17 commits into from
Dec 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion ansible_collections/arista/avd/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ This repository provides roles for Ansible's collection __arista.avd__ with the
- [__arista.avd.eos_config_deploy_cvp__](roles/eos_config_deploy_cvp/README.md) - Deploys intended configuration via CloudVision.
- [__arista.avd.eos_config_deploy_eapi__](roles/eos_config_deploy_eapi/README.md) - Deploys intended configuration via eAPI.
- [__arista.avd.cvp_configlet_upload__](roles/cvp_configlet_upload/README.md) - Uploads configlets from a local folder to CloudVision Server.
- [__arista.avd.eos_validate_state__](roles/eos_validate_state/README.md) - Validate operational states of Arista EOS devices
- [__arista.avd.eos_validate_state__](roles/eos_validate_state/README.md) - Validate operational states of Arista EOS devices.
- [__arista.avd.eos_snapshot__](roles/eos_snapshot/README.md) - Collect commands on EOS devices and generate reports.

![Arista AVD Overview](media/example-playbook-evpn-deploy-cvp.gif)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,7 @@ pre_running_config_backup_dir: '{{ root_dir }}/{{ pre_running_config_backup_dir_
# EOS state validation directory name
eos_validate_state_name: 'reports'
eos_validate_state_dir: '{{ root_dir }}/{{ eos_validate_state_name }}'

# EOS snapshots directory name
snapshots_backup_dir_name: 'snapshots'
snapshots_backup_dir: '{{ root_dir }}/{{ snapshots_backup_dir_name }}'
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
mode: 0755
delegate_to: localhost
run_once: True

- name: "Create folders for Fabric documentation"
when: type is defined and fabric_name is defined and type == "spine" and spine.nodes | list | first == inventory_hostname #Only run for first spine per fabric
file:
Expand Down Expand Up @@ -98,3 +98,11 @@
mode: 0755
delegate_to: localhost
run_once: True

- name: Create output directory for each EOS device
file:
path: "{{ snapshots_backup_dir }}"
state: directory
mode: 0755
delegate_to: localhost
run_once: True
160 changes: 160 additions & 0 deletions ansible_collections/arista/avd/roles/eos_snapshot/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# Ansible Role: eos_snapshot

**Table of Contents:**

- [Ansible Role: eos_snapshot](#ansible-role-eos_snapshot)
- [Overview](#overview)
- [Role Inputs and Outputs](#role-inputs-and-outputs)
- [Default Variables](#default-variables)
- [Requirements](#requirements)
- [Example Playbook](#example-playbook)
- [Input example](#input-example)
- [inventory/inventory.ini](#inventoryinventoryini)
- [inventory/group_vars/DC1.yml](#inventorygroup_varsdc1yml)
- [Usage example](#usage-example)
- [License](#license)

## Overview

**eos_snapshot** is a role leveraged to collect commands on Arista EOS devices and generate a report.
It supports reports with the following format: text, markdown, json and yaml.

## Role Inputs and Outputs

Figure 1 below provides a visualization of the roles inputs, and outputs and tasks.

![Figure 1: Ansible Role eos_snapshot](media/role_eos_snapshot.png)

**Inputs:**

Ansible inventory to connect to EOS devices.
The default variables can be changed to select a report format and include others commands.

**Outputs:**

- text files: one file per device and show command
- markdown file: one report per device. There is a table of content at the begining of the file.
- json file: one report per fabric
- yaml file: one report per fabric

**Tasks:**

1. Create output structure
2. Collect show commands on device
3. Save the collected commands
4. Generate a JSON report
5. Generate a YAML report
6. Generate a markdown report

## Default Variables

The following default variables are defined, and can be modified as desired:

```yaml
---

root_dir: '{{ inventory_dir }}'
snapshots_backup_dir_name: 'commands'
snapshots_backup_dir: '{{ root_dir }}/{{ commands_backup_dir_name }}'

# list of desired formats. Supported values are markdown, json and text.
# text: one file per device and show command
# markdown: one report per device
# json: one report per fabric
# yaml: one report per fabric
output_format:
- text
- markdown
# - json
# - yaml

commands_list:
- show lldp neighbors
- show ip interface brief
- show interfaces description
- show version
- show running-config
```

## Requirements

Requirements are located here: [avd-requirements](../../README.md#Requirements)

## Example Playbook

```yaml
---
- name: Collect commands
hosts: DC1_FABRIC
connection: local
gather_facts: false
collections:
- arista.avd
tasks:
- name: Collect commands
import_role:
name: eos_snapshot
```

## Input example

### inventory/inventory.ini

```yaml
---
all:
children:
DC1:
children:
DC1_FABRIC:
children:
DC1_SPINES:
hosts:
switch2:
ansible_host: 10.83.28.190
DC1_L3LEAFS:
children:
DC1_LEAF1:
hosts:
switch1:
ansible_host: 10.83.28.216
DC1_LEAF2:
hosts:
switch3:
ansible_host: 10.83.28.191
```

### inventory/group_vars/DC1.yml

```yaml
ansible_user: 'arista'
ansible_password: 'arista'
ansible_network_os: eos
ansible_become: yes
ansible_become_method: enable
```

```yaml
output_format:
- text
- markdown
# - json
# - yaml

commands_to_collect:
- show lldp neighbors
- show ip interface brief
- show interfaces description
- show version
- show running-config
```

## Usage example

```shell
ansible-playbook playbooks/pb_collect_yml --inventory inventory/inventory.yml
```

## License

Project is published under [Apache 2.0 License](../../LICENSE)
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
# defaults file for eos_snapshot

root_dir: '{{ inventory_dir }}'
snapshots_backup_dir_name: 'snapshots'
snapshots_backup_dir: '{{ root_dir }}/{{ snapshots_backup_dir_name }}'

# list of desired formats. Supported values are markdown, yaml, json and text.
# text: one file per device and show command
# markdown: one report per device
# json: one report per fabric
# yaml: one report per fabric
output_format:
- text
- markdown
# - json
# - yaml

commands_list:
- show lldp neighbors
- show ip interface brief
- show interfaces description
- show version
- show running-config
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
# handlers file for eos_commands_collect
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
galaxy_info:
author: Arista Ansible Team <ansible@arista.com>
description: Collect show commands on EOS devices and generate reports
issue_tracker_url: https://github.com/aristanetworks/ansible-avd/issues
company: Arista Networks
license: Apache-2.0
min_ansible_version: 2.9
galaxy_tags: ['arista', 'network', 'networking', 'eos', 'avd', 'cloudvision', 'cvp']
dependencies: []
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
# tasks file for eos_snapshot

- name: Create output directory for each EOS device
file:
path: "{{ snapshots_backup_dir }}/{{ inventory_hostname }}"
state: directory
when: ("text" in output_format or "markdown" in output_format)

- name: run show commands on remote EOS devices
eos_command:
commands: "{{ item }}"
with_items: "{{ commands_list }}"
ignore_errors: true
register: cli_output

- name: save collected commands in text files
template:
src: device_text_command.j2
dest: "{{ snapshots_backup_dir }}/{{ inventory_hostname }}/{{ item.item }}.txt"
loop: "{{ cli_output.results }}"
when: '"text" in output_format'

- name: Generate json report for fabric
template:
src: fabric_json_output.j2
dest: "{{ snapshots_backup_dir }}/report.json"
delegate_to: localhost
run_once: true
when: '"json" in output_format'

- name: Generate yaml report for fabric
template:
src: fabric_yaml_output.j2
dest: "{{ snapshots_backup_dir }}/report.yaml"
delegate_to: localhost
run_once: true
when: '"yaml" in output_format'

- name: Generate markdown report for fabric
include_tasks: "markdown.yml"
when:
- '"markdown" in output_format'
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
- name: Create md_fragments directory for each EOS device
file:
path: "{{ snapshots_backup_dir }}/{{ inventory_hostname }}/md_fragments"
state: directory

- name: save collected commands in md files
template:
src: md_report.j2
dest: "{{ snapshots_backup_dir }}/{{ inventory_hostname }}/md_fragments/{{ item.item }}.md"
loop: "{{ cli_output.results }}"

- name: generate table of content report
template:
src: md_table_of_content.j2
dest: "{{ snapshots_backup_dir }}/{{ inventory_hostname }}/md_fragments/0_table_of_content.md"

- name: Assembling md_fragments
assemble:
src: "{{ snapshots_backup_dir }}/{{ inventory_hostname }}/md_fragments"
dest: "{{ snapshots_backup_dir }}/{{ inventory_hostname }}/report.md"

- name: Delete md_fragments directory for each EOS device
file:
path: "{{ snapshots_backup_dir }}/{{ inventory_hostname }}/md_fragments"
state: absent
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{{ item.stdout[0] | default ('not supported command') }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"devices": {
{% for node in groups[fabric_name] | arista.avd.natural_sort %}
"{{ node }}": {
{% for command in commands_list %}
"{{ command | replace(" ","_") }}":
{{ hostvars[node].cli_output.results[0].stdout[0] | to_nice_json | indent(12) }}
{%- if not loop.last %}
,
{% else %}

}
{%- endif %}
{%- endfor %}
{%- if not loop.last %}
,
{% else %}

}
{% endif %}
{% endfor %}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
devices:
{% for node in groups[fabric_name] | arista.avd.natural_sort %}
{{ node }}:
{% for command in commands_list %}
"{{ command }}":
{{ hostvars[node].cli_output.results[0].stdout[0] | to_nice_yaml(indent=2) | trim | indent(6) }}
{% endfor %}
{% endfor %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## {{ item.item }}

```
{{ item.stdout[0] | default ('not supported command') }}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# {{ inventory_hostname }} Commands Output

## Table of Contents

{% for command in commands_list %}
- [{{ command }}](#{{ command | replace(" ","-") }})
{% endfor %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
localhost

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
- hosts: localhost
remote_user: root
roles:
- eos_commands_collect
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
# vars file for eos_commands_collect