Skip to content

Commit

Permalink
Feat(roles): add clab topology extension (avd_to_clab)
Browse files Browse the repository at this point in the history
  • Loading branch information
titom73 committed Mar 2, 2022
1 parent 6fac6cf commit 56de979
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 31 deletions.
1 change: 0 additions & 1 deletion ansible_collections/titom73/avd_tools/galaxy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ tags: ['arista', 'network', 'networking', 'eos', 'avd', 'cloudvision', 'cvp']
# range specifiers can be set and are separated by ','
dependencies:
"arista.avd": "*"
"arista.cvp": "*"
"arista.eos": "*"
"netbox.netbox": "*"
"ansible.netcommon": "*"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,29 @@

**eos_designs_to_containerlab** is a role to build a [containerlab](https://containerlab.srlinux.dev/) topology from [Arista AVD](https://www.avd.sh) project

!!! info
This role only supports l3ls-evpn topology from [arista.avd.eos_designs](https://avd.sh/en/latest/roles/eos_designs/doc/l3ls-evpn.html)

## Requirements

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

- [**containerlab**](https://containerlab.srlinux.dev/) in version `>=0.15.3`

```bash
$ containerlab version
_ _ _
_ (_) | | | |
____ ___ ____ | |_ ____ _ ____ ____ ____| | ____| | _
/ ___) _ \| _ \| _)/ _ | | _ \ / _ )/ ___) |/ _ | || \
( (__| |_|| | | | |_( ( | | | | | ( (/ /| | | ( ( | | |_) )
\____)___/|_| |_|\___)_||_|_|_| |_|\____)_| |_|\_||_|____/

version: 0.15.3
commit: 533d911
date: 2021-07-19T14:35:16Z
source: https://github.com/srl-labs/containerlab
rel. notes: https://containerlab.srlinux.dev/rn/0.15/#0153
```
## Default Variables
The following default variables are defined, and can be modified as desired:
Expand All @@ -18,6 +34,8 @@ The following default variables are defined, and can be modified as desired:
- `mgmt_network_v4`: Subnet for management IPs use for OOB
- `eapi_base`: Base port to use to expose eAPI from containers. Uses `eapi_base` + `device_id` from `arista.avd.eos_designs`
> If host has `ansible_port` defined and different than `443`, then, this value is used instead of an autogenerated one.
```yaml
# cEOS Image to use
ceos_lab_version: ceos:latest
Expand All @@ -32,25 +50,35 @@ containerlab_configuration: '{{ inventory_dir }}/containerlabs.yml'
eapi_base: 8000
```
## Requirements
## Extend your topology
- Requirements are located here: [avd-requirements](../../README.md#Requirements)
- [**containerlab**](https://containerlab.srlinux.dev/) in version `>=0.15.3`
As `arista.avd.eos_designs` only support definition of network devices, this role implement options to extend your Containerlab topology to attach additional components to your topology:
```bash
$ containerlab version
_ _ _
_ (_) | | | |
____ ___ ____ | |_ ____ _ ____ ____ ____| | ____| | _
/ ___) _ \| _ \| _)/ _ | | _ \ / _ )/ ___) |/ _ | || \
( (__| |_|| | | | |_( ( | | | | | ( (/ /| | | ( ( | | |_) )
\____)___/|_| |_|\___)_||_|_|_| |_|\____)_| |_|\_||_|____/
- `clab_nodes`: Add node definitions using Containerlab syntax
- `clab_links`: Add links to your topology using Containerlab definition
- `clab_kinds`: Add kind options to your topology
version: 0.15.3
commit: 533d911
date: 2021-07-19T14:35:16Z
source: https://github.com/srl-labs/containerlab
rel. notes: https://containerlab.srlinux.dev/rn/0.15/#0153
### Example
```yaml
clab_kinds:
linux:
image: alpine:latest


clab_nodes:
client12:
kind: linux
image: titom73/network-multitool:extra
mgmt_ipv4: 10.73.255.192
client22:
kind: linux
image: titom73/network-multitool:extra
mgmt_ipv4: 10.73.255.194

clab_links:
- endpoints: ["ceos-agg02:eth3", "client21:eth1"]
- endpoints: ["ceos-agg02:eth1", "client21:eth1"]
```
## Example Playbook
Expand Down
Original file line number Diff line number Diff line change
@@ -1,41 +1,73 @@
{# HEADER -- LOGIC implementation #}
{% set node_types = dict() %}
{% for node_type_key in node_type_keys | arista.avd.default(['spine', 'l3leaf', 'l2leaf']) | arista.avd.natural_sort %}
{# {{ node_type_key }} #}
{% if hostvars[inventory_hostname][node_type_key] is arista.avd.defined %}
{% do node_types.update({node_type_key: hostvars[inventory_hostname][node_type_key]}) %}
{% endif %}
{% endfor %}
{# CONTAINERLABS configuration rendering #}
---
name: {{ fabric_name }}
name: {{ fabric_name | lower | replace("_", "-") }}

mgmt:
network: 'mgmt_{{fabric_name}}'
network: 'mgmt-{{fabric_name | lower | replace("_", "-") }}'
ipv4_subnet: {{ mgmt_network_v4 }}

{# NODES definition #}
topology:
kinds:
ceos:
image: {{ceos_version}}
{% if clab_kinds is defined %}
{% for clab_kind_name, clab_kind in clab_kinds.items() %}
{{ clab_kind_name }}:
{{ clab_kind | to_nice_yaml| trim | indent(6)}}
{% endfor %}
{% endif %}
nodes:
{% for node_type in node_types | arista.avd.natural_sort %}
{# --------------------- NODE GROUPS LIST --------------------- #}
{% for node_group in node_types[node_type]['node_groups'] | arista.avd.natural_sort %}
{% for node in node_types[node_type]['node_groups'][node_group]['nodes'] | arista.avd.natural_sort %}
{{ node }}:
image: {{ceos_lab_version}}
mgmt_ipv4: {{ node_types[node_type]['node_groups'][node_group]['nodes'][node].mgmt_ip }}
image: {{ceos_version}}
mgmt_ipv4: {{ node_types[node_type]['node_groups'][node_group]['nodes'][node].mgmt_ip | ansible.netcommon.ipaddr('address') }}
kind: ceos
startup-config: {{ inventory_dir }}/intended/configs/{{node}}.cfg
startup-config: intended/configs/{{node}}.cfg
ports:
{% if hostvars[node].ansible_port is arista.avd.defined and hostvars[node].ansible_port %}
- {{ hostvars[node].ansible_port }}:443/tcp
{% else %}
- {{ eapi_base + node_types[node_type]['nodes'][node].id }}:443/tcp
{% endif %}
env:
TMODE: lacp
{% endfor %}
{% endfor %}
{# --------------------- FLAT NODES LIST --------------------- #}
{% for node in node_types[node_type]['nodes'] | arista.avd.natural_sort %}
{{ node }}:
image: {{ceos_lab_version}}
mgmt_ipv4: {{ node_types[node_type]['nodes'][node].mgmt_ip }}
image: {{ceos_version}}
mgmt_ipv4: {{ node_types[node_type]['nodes'][node].mgmt_ip | ansible.netcommon.ipaddr('address') }}
kind: ceos
startup-config: {{ inventory_dir }}/intended/configs/{{node}}.cfg
startup-config: intended/configs/{{node}}.cfg
ports:
{% if hostvars[node].ansible_port is arista.avd.defined and hostvars[node].ansible_port != 443 %}
- {{ hostvars[node].ansible_port }}:443/tcp
{% else %}
- {{ eapi_base + node_types[node_type]['nodes'][node].id }}:443/tcp
{% endif %}
env:
TMODE: lacp
{% endfor %}
{% endfor %}
{% if clab_nodes is defined %}
{% for clab_node_name, clab_node in clab_nodes.items() %}
{{ clab_node_name }}:
{{ clab_node | to_nice_yaml| trim | indent(6)}}
{% endfor %}
{% endif %}

{# LINKS definition #}
links:
Expand All @@ -47,7 +79,7 @@ topology:
{% for uplink_switch_interface in node_types[node_type]['node_groups'][node_group]['nodes'][node].uplink_switch_interfaces %}
{% set uplink_interfaces = node_types[node_type]['node_groups'][node_group]['nodes'][node].uplink_interfaces | arista.avd.default( node_types[node_type]['node_groups'][node_group].uplink_interfaces, node_types[node_type].defaults.uplink_interfaces ) %}
{% set uplink_switches = node_types[node_type]['node_groups'][node_group]['nodes'].uplink_switches | arista.avd.default( node_types[node_type]['node_groups'][node_group].uplink_switches, node_types[node_type].defaults.uplink_switches ) %}
- endpoints: ["{{ node }}:{{ uplink_interfaces[loop.index0] }}", "{{ uplink_switches[ loop.index0 ] }}:{{ uplink_switch_interface | replace('Ethernet', 'eth') }}"]
- endpoints: ["{{ node }}:{{ uplink_interfaces[loop.index0]| replace('Ethernet', 'eth') }}", "{{ uplink_switches[ loop.index0 ] }}:{{ uplink_switch_interface | replace('Ethernet', 'eth') }}"]
{% endfor %}
{# - End Uplink Interfaces #}
{# - MLAG interfaces #}
Expand All @@ -66,8 +98,13 @@ topology:
{% for node in node_types[node_type]['nodes'] | arista.avd.natural_sort %}
{% for uplink_switch_interface in node_types[node_type]['nodes'][node].uplink_switch_interfaces | arista.avd.natural_sort %}
{% set uplink_interfaces = node_types[node_type]['nodes'][node].uplink_interfaces | arista.avd.default( node_types[node_type].uplink_interfaces, node_types[node_type].defaults.uplink_interfaces ) %}
{% set uplink_switches = node_types[node_type]['nodes'].uplink_switches | arista.avd.default( node_types[node_type].uplink_switches, node_types[node_type].defaults.uplink_switches ) %}
- endpoints: ["{{ node }}:{{ uplink_interfaces[loop.index0] }}", "{{ uplink_switches[ loop.index0 ] }}:{{ uplink_switch_interface | replace('Ethernet', 'eth') }}"]
{% set uplink_switches = node_types[node_type]['nodes'][node].uplink_switches | arista.avd.default( node_types[node_type]['nodes'].uplink_switches, node_types[node_type].defaults.uplink_switches ) %}
- endpoints: ["{{ node }}:{{ uplink_interfaces[loop.index0] | replace('Ethernet', 'eth')}}", "{{ uplink_switches[ loop.index0 ] }}:{{ uplink_switch_interface | replace('Ethernet', 'eth') }}"]
{% endfor %}
{% endfor %}
{% endfor %}
{% if clab_links is defined %}
{% for clab_link in clab_links %}
- {{ clab_link | to_yaml}}
{%- endfor %}
{% endif %}

0 comments on commit 56de979

Please sign in to comment.