diff --git a/examples/layer2/README.md b/examples/layer2/README.md new file mode 100644 index 0000000..9812546 --- /dev/null +++ b/examples/layer2/README.md @@ -0,0 +1,34 @@ +# Layer 2 networking with Equinix Metal + +This example playbook demonstrates the use of the `equinix.cloud.metal_connection`, `equinix.cloud.metal_device`, and `equinix.cloud.metal_port` modules to configure Layer 2 connectivity from an Equinix Metal device to an AWS S3 bucket over a Metal-billed Fabric interconnection. + +## Overview + +The [playbook](main.yml) creates a new project, creates 2 VLANs, provisions a device, and configures the device through different [network types](https://deploy.equinix.com/developers/docs/metal/layer2-networking/overview/#network-configuration-types). + + +## Prerequisites + +Before running the playbook, you will need to have the following: + +- Ansible installed on your local machine. +- The Equinix Ansible Collection installed. You can install it using the following command: + ```bash + ansible-galaxy collection install equinix.cloud + ``` +- An Equinix Metal API token. You can obtain an API token from the Equinix Metal Portal. Set the environment variable METAL_AUTH_TOKEN to your API token: + ```bash + export METAL_AUTH_TOKEN=your_api_token_here + ``` + +## Variables + +You can customize some variables from [vars/equinix_metal_vars.yml](vars/equinix_metal_vars.yml). + +## Running the Playbook + +To run the playbook, navigate to the directory containing the playbook file `main.yml` and run the following command: + +```bash +ansible-playbook main.yml +``` diff --git a/examples/layer2/main.yml b/examples/layer2/main.yml new file mode 100644 index 0000000..322edd1 --- /dev/null +++ b/examples/layer2/main.yml @@ -0,0 +1,108 @@ +--- +- name: Equinix Metal Example Playbook + hosts: localhost + gather_facts: no + tasks: + - name: Include the required variables + include_vars: "vars/equinix_metal_vars.yml" + + # Equinix resources + - name: Create a project + equinix.cloud.metal_project: + name: "{{ project_name }}" + register: project + + - name: create a vlan + equinix.cloud.metal_vlan: + project_id: "{{ project.id }}" + metro: "{{ metro }}" + vxlan: "1234" + register: vlan + + - name: create a VRF + equinix.cloud.metal_vrf: + name: example-vrf + metro: "{{ metro }}" + local_asn: 65000 + ip_ranges: + - 192.168.200.0/25 + project_id: "{{ project.id }}" + register: vrf + + - name: create a VRF IP reservation + equinix.cloud.metal_reserved_ip_block: + project_id: "{{ project.id }}" + vrf_id: "{{ vrf.id }}" + type: "vrf" + metro: "{{ metro }}" + network: 192.168.200.0 + cidr: 25 + register: vrf_ip_reservation + + - name: create a VRF Metal Gateway + equinix.cloud.metal_gateway: + project_id: "{{ project.id }}" + ip_reservation_id: "{{ vrf_ip_reservation.id }}" + virtual_network_id: "{{ vlan.id }}" + register: gateway + + # Create a device + # TODO: gateway module does not expose the + # gateway IP so I'm hard-coding it for now. + # In the future it should be referenced as + # {{gateway.ip}} (or similar) instead. The + # device IP address should also be calculated + # rather than hard-coded + - name: Create a device + equinix.cloud.metal_device: + project_id: "{{ project.id }}" + metro: "{{ metro }}" + hostname: "{{ device_hostname }}" + operating_system: "{{ operating_system }}" + plan: "{{ plan }}" + state: present + userdata: |2 + #!/bin/bash + + cat <> /etc/network/interfaces + auto bond0.{{vlan.vxlan}} + iface bond0.{{vlan.vxlan}} inet static + address 192.168.200.2 + netmask 255.255.255.128 + post-up route add -net 192.168.200.0/25 gw 192.168.200.1 + post-up route add -net {{aws_network_cidr}} gw 192.168.200.1 + EOF + + systemctl restart networking + register: device + + - name: capture port ids for device + set_fact: + bond_port_id: "{{ device.network_ports | selectattr('name', 'match', 'bond0') | map(attribute='id') | first }}" + eth1_port_id: "{{ device.network_ports | selectattr('name', 'match', 'eth1') | map(attribute='id') | first }}" + + - name: convert bond port to hybrid bonded mode + equinix.cloud.metal_port: + id: "{{ bond_port_id }}" + bonded: true + layer2: false + vlan_ids: + - "{{ vlan.id }}" + + # NOTE: I initially wrote this as a redundant connection + # but decided that was unnecessary; Ansible attempted to + # update the connection in place and threw a weird validation + # error from pydantic. IIRC redundancy can't be updated + # in place, so we should probably protect against that but + # also the error message was not useful + - name: create a Metal-billed VRF interconnection + equinix.cloud.metal_connection: + project_id: "{{ project.id }}" + metro: "{{ metro }}" + name: "{{ interconnection_name }}" + type: "shared" + speed: "1Gbps" + service_token_type: a_side + redundancy: primary + vrfs: + - "{{ vrf.id }}" diff --git a/examples/layer2/vars/equinix_metal_vars.yml b/examples/layer2/vars/equinix_metal_vars.yml new file mode 100644 index 0000000..2917ee5 --- /dev/null +++ b/examples/layer2/vars/equinix_metal_vars.yml @@ -0,0 +1,7 @@ +project_name: my_metal_layer2_project +device_hostname: layer2-device +metro: sv +operating_system: ubuntu_20_04 +plan: c3.small.x86 +interconnection_name: "layer2 interconnection" +aws_network_cidr: 10.0.0.0/24