Getting Started

Config Structure

Top Level objects

Etherweaver’s can consist of two sections, of which Fabrics are optional:

config.yaml
fabrics: # A list of all fabrics
appliances: # A list of all hardware

Fabrics represent networks, or collections of network devices with inherited settings.

An appliance represents a network operating system to be configured, and it inherits settings (as well as defining it’s own).

An Example Config

config.yaml
fabrics:
   network1:
      vlans:
         4-10
     connections:
        ssh:
           username: user
           password: password!

   distribution:
      fabric: network1
      interfaces:
         1G:
            1-22:
               untagged_vlan: 4
               tagged_vlans: 5-7
            23-24:
               tagged_vlans: 4-10

appliances:
   distsw1:
      fabric: distribution
      plugin_package: cumulus
      connections:
         ssh:
            hostname: 10.5.5.33

The inheritance structure flows in this manner:

Fabric -> Child Fabric*n -> appliances.

A node specified twice will take the value of the last object to specify it in the structure.

Nodes

Nodes represent a dictionary structure that allow you to access, modify, or remove the current state of an appliance without writing any YAML. A node is represented by it’s path in the dict (which is the same as the config.yaml)

For instance, here are some valid nodes:

  • protocols.dns.nameservers
  • interfaces.1G.1
  • hostname

Nodes have different commands depending on their type. For instance single value nodes (such as hostname) generally have three commands:

  • hostname.get
  • hostname.set
  • hostname.del

List nodes will often have more command types:

  • protocols.ntp.client.servers.add: Adds a server or servers
  • protocols.ntp.client.servers.get: Gets a list of all servers
  • protocols.ntp.client.servers.set: Overwrites the server list with a new list
  • protocols.ntp.client.servers.del: If a value is specified, deletes the value, otherwise deletes all values

Additionally, there are a few meta nodes such as ‘state’. State is likely the one you will use the most, and it has one function:

  • state.apply: Applies the current config.yaml in an interactive manner

In addition there are also two additional state nodes with the following commands:

  • cstate.get: Fetch current state of the appliance
  • dstate.get: Fetch desired state of the appliance (based on config.yaml)
  • dstate.apply: Non-interactively apply the desired state without confirmation

Commands

Commands follow a simple syntax:

netweaver ‘role|*’ node value –yaml=config.yaml

The YAML state can be applied to every appliance in the infrastructure file by running the following:

netweaver.py '*' state.apply --yaml=config.yaml
sw1: []
sw2: []

The brackets will contain a list of any commands run in order to bring the switches in alignment with the current state.

You can view the current state of all appliances in the environment using the following command:

netweaver.py 'sw1' cstate.get --yaml=config.yaml
sw1:
   hostname: spine1.net.testco.org
   interfaces:
     100G: {}
     10G: {}
     1G:
       '1':
         ip:
           address: []
         tagged_vlans: [2, 3, 4]
         untagged_vlan: '7'
    ...
etherweaver.py '*' protocols.ntp.client.servers.get --yaml=config.yaml
sw1: [pool.ntp.org, 0.cumulusnetworks.pool.ntp.org, 1.cumulusnetworks.pool.ntp.org,
2.cumulusnetworks.pool.ntp.org]
sw2: [0.cumulusnetworks.pool.ntp.org, 1.cumulusnetworks.pool.ntp.org, 2.cumulusnetworks.pool.ntp.org,
pool.ntp.org]
netweaver.py 'sw1' hostname.set 'spine2' --yaml=config.yaml
 net add hostname spine2

Note

Not all appliance plugins can implement all nodes due to hardware limitations, accessing any unsupported node will result in a NotImplemented or NotSupported error.

Examples

A Simple Example

Lets imagine that you are tasked with deploying a switch fabric for a small branch office, with two switches total. Based on the needs of the office, you determine that you need two 24 port switches, which are to be configured using the following rules:

  • VLANs for Employees, VOIP phones, servers, Public Wireless, and Management interfaces
  • Ports 1-20 on both switches will be for employee usage, and will need the Employee VLAN untagged and the VOIP vlan tagged for phone passthrough
  • Ports 20-22 on both switches are reserved for Wireless access points, and need to be untagged on the Management VLAN for AP administration, and tagged on Employee and Public
  • Port 24 will be the trunk between switches

From the system you are running etherweaver from, copy your public ssh keys to the switches (For switches that cannot do this, you can use a username and password, but you still need to accept the public ssh key of the system on your machine to prevent man in the middle attacks.) Then you write an etherweaver state file, simple_example.yaml:

fabrics:
  network:
    vlans:
      10:
        Name: Employee
      11:
        Name: Servers
      12:
        Name: VOIP
      20:
        Name: Public Wireless
      254:
        Name: Management
    port_profiles:
      OfficePorts:
        untagged_vlan: 10
        tagged_vlans: [12]
      WirelessAccessPoint:
        untagged_vlan: 254
        tagged_vlans: [10, 20]
      Trunk:
        tagged_vlans: [10,12,20,254]
  dist_switches:
    fabric: network
    interfaces:
      1G:
        1-20:
          profile: OfficePorts
        20-22:
          profile: WirelessAccessPoint
        24:
          profile: Trunk
appliances:
  dist1:
    fabric: dist_switches
    plugin_package: cumulus
    connections:
      ssh:
        hostname: 192.168.122.254
        username: cumulus
        port: 22
    hostname: dist1
  dist2:
    fabric: dist_switches
    plugin_package: cumulus
    connections:
      ssh:
        hostname: 192.168.122.171
        username: cumulus
        port: 22
    hostname: dist2

Then, run:

etherweaver '*' state.apply --yaml=simple_example.yaml
If you continue, the following changes will be applied:
###################################
{   'dist1': [   'net add hostname dist1',
                 'net add bridge bridge vids 10-12,20,254',
                 'net add interface swp1 bridge vids 12',
                 'net add interface swp1 bridge pvid 10',
                 'net add interface swp2 bridge vids 12',
                 'net add interface swp2 bridge pvid 10',
                 'net add interface swp3 bridge vids 12',
                 'net add interface swp3 bridge pvid 10',
                 'net add interface swp4 bridge vids 12',
                 'net add interface swp4 bridge pvid 10',
                 'net add interface swp5 bridge vids 12',
                 'net add interface swp5 bridge pvid 10',
                 'net add interface swp6 bridge vids 12',
                 'net add interface swp6 bridge pvid 10',
                 'net add interface swp7 bridge vids 12',
                 'net add interface swp7 bridge pvid 10',
                 'net add interface swp8 bridge vids 12',
                 'net add interface swp8 bridge pvid 10',
                 'net add interface swp9 bridge vids 12',
                 'net add interface swp9 bridge pvid 10',
                 'net add interface swp10 bridge vids 12',
                 'net add interface swp10 bridge pvid 10',
                 'net add interface swp11 bridge vids 12',
                 'net add interface swp11 bridge pvid 10',
                 'net add interface swp12 bridge vids 12',
                 'net add interface swp12 bridge pvid 10',
                 'net add interface swp13 bridge vids 12',
                 'net add interface swp13 bridge pvid 10',
                 'net add interface swp14 bridge vids 12',
                 'net add interface swp14 bridge pvid 10',
                 'net add interface swp15 bridge vids 12',
                 'net add interface swp15 bridge pvid 10',
                 'net add interface swp16 bridge vids 12',
                 'net add interface swp16 bridge pvid 10',
                 'net add interface swp17 bridge vids 12',
                 'net add interface swp17 bridge pvid 10',
                 'net add interface swp18 bridge vids 12',
                 'net add interface swp18 bridge pvid 10',
                 'net add interface swp19 bridge vids 12',
                 'net add interface swp19 bridge pvid 10',
                 'net add interface swp20 bridge vids 10,20',
                 'net add interface swp20 bridge pvid 254',
                 'net add interface swp21 bridge vids 10,20',
                 'net add interface swp21 bridge pvid 254',
                 'net add interface swp22 bridge vids 10,20',
                 'net add interface swp22 bridge pvid 254',
                 'net add interface swp24 bridge vids 10,12,20,254'],
    'dist2': [   'net add hostname dist2',
                 'net add bridge bridge vids 10-12,20,254',
                 'net add interface swp1 bridge vids 12',
                 'net add interface swp1 bridge pvid 10',
                 'net add interface swp2 bridge vids 12',
                 'net add interface swp2 bridge pvid 10',
                 'net add interface swp3 bridge vids 12',
                 'net add interface swp3 bridge pvid 10',
                 'net add interface swp4 bridge vids 12',
                 'net add interface swp4 bridge pvid 10',
                 'net add interface swp5 bridge vids 12',
                 'net add interface swp5 bridge pvid 10',
                 'net add interface swp6 bridge vids 12',
                 'net add interface swp6 bridge pvid 10',
                 'net add interface swp7 bridge vids 12',
                 'net add interface swp7 bridge pvid 10',
                 'net add interface swp8 bridge vids 12',
                 'net add interface swp8 bridge pvid 10',
                 'net add interface swp9 bridge vids 12',
                 'net add interface swp9 bridge pvid 10',
                 'net add interface swp10 bridge vids 12',
                 'net add interface swp10 bridge pvid 10',
                 'net add interface swp11 bridge vids 12',
                 'net add interface swp11 bridge pvid 10',
                 'net add interface swp12 bridge vids 12',
                 'net add interface swp12 bridge pvid 10',
                 'net add interface swp13 bridge vids 12',
                 'net add interface swp13 bridge pvid 10',
                 'net add interface swp14 bridge vids 12',
                 'net add interface swp14 bridge pvid 10',
                 'net add interface swp15 bridge vids 12',
                 'net add interface swp15 bridge pvid 10',
                 'net add interface swp16 bridge vids 12',
                 'net add interface swp16 bridge pvid 10',
                 'net add interface swp17 bridge vids 12',
                 'net add interface swp17 bridge pvid 10',
                 'net add interface swp18 bridge vids 12',
                 'net add interface swp18 bridge pvid 10',
                 'net add interface swp19 bridge vids 12',
                 'net add interface swp19 bridge pvid 10',
                 'net add interface swp20 bridge vids 10,20',
                 'net add interface swp20 bridge pvid 254',
                 'net add interface swp21 bridge vids 10,20',
                 'net add interface swp21 bridge pvid 254',
                 'net add interface swp22 bridge vids 10,20',
                 'net add interface swp22 bridge pvid 254',
                 'net add interface swp24 bridge vids 10,12,20,254']}
Do you want to continue? y/[n]y
dist1: 100%|███████████████████████████████████████| 47/47 [00:04<00:00, 10.45it/s]
dist2: 100%|███████████████████████████████████████| 47/47 [00:08<00:00, 12.90it/s]
Run Complete

Now your switches are configured correctly, subsequent runs won’t do anything because the curent state and desired state match.

To complicate matters, a developer now needs to have a development server at his desk. unfortunately, his port is right in the middle of our 10-20 range, at port 11 on dist1. Not to worry though, we can place a config statement at any lower inheritance level to override the port range. All we need to do is add an interface definition for the port in question, and define profile to false in order to stop inheritance. Now our state file looks like this:

fabrics:
  network:
    vlans:
      10:
        Name: Employee
      11:
        Name: Servers
      12:
        Name: VOIP
      20:
        Name: Public Wireless
      254:
        Name: Management
    port_profiles:
      OfficePorts:
        untagged_vlan: 10
        tagged_vlans: [12]
      WirelessAccessPoint:
        untagged_vlan: 254
        tagged_vlans: [10, 20]
      Trunk:
        tagged_vlans: [10,12,20,254]
  dist_switches:
    fabric: network
    interfaces:
      1G:
        1-20:
          profile: OfficePorts
        20-22:
          profile: WirelessAccessPoint
        24:
          profile: Trunk
appliances:
  dist1:
    interfaces:
      1G:
        11:
          profile: false
          untagged_vlan: 11
    fabric: dist_switches
    plugin_package: cumulus
    connections:
      ssh:
        hostname: 192.168.122.254
        username: cumulus
        port: 22
    hostname: dist1
  dist2:
    fabric: dist_switches
    plugin_package: cumulus
    connections:
      ssh:
        hostname: 192.168.122.171
        username: cumulus
        port: 22
    hostname: dist2

And running the program gives us the following output:

$etherweaver '*' state.apply --yaml=docs/source/ExampleConfigs/simple_examplev2.yaml
If you continue, the following changes will be applied:
###################################
{'dist1': ['net add interface swp11 bridge pvid 11']}
Do you want to continue? y/[n]y
dist1: 100%|██████████| 1/1 [00:00<00:00,  1.08it/s]
Run complete

As you can see, etherweaver operated idempotently, only applying the changes from the desired state that didn’t match the current state. This allows you to easily manage and monitor config drift from within your environment.

CLAG

The cumulus switches we have been using as an example also support a feature known as Clustering Link Aggregation, or CLAG.

This allows two independent switches to share link aggregation groups without a single point of failure, and without stacking. This is an excellent use case for fabric inheritance, as there are attributes that the switches share, as well as plenty that they don’t. Here is an example CLAG configuration with etherweaver:

fabrics:
  network:
    vlans:
      10:
        Name: Employee
      11:
        Name: Servers
      12:
        Name: VOIP
      20:
        Name: Public Wireless
      254:
        Name: Management
    port_profiles:
      OfficePorts:
        untagged_vlan: 10
        tagged_vlans: [12]
      WirelessAccessPoint:
        untagged_vlan: 254
        tagged_vlans: [10, 20]
      Trunk:
        tagged_vlans: [10,12,20,254]
  spine_cluster:
    fabric: network
    clag:
      shared_mac: 44:38:39:FF:01:01
    interfaces:
      1G:
        9-10:
          bond_slave: peerlink
        1:
          bond_slave: po1
        2:
          bond_slave: po2
      bond:
        po1:
          clag_id: 1
          profile: Trunk
        po2:
          clag_id: 2
          profile: Trunk
appliances:
  spine1:
    fabric: spine_cluster
    hostname: dist1
    plugin_package: cumulus
    connections:
      ssh:
        hostname: 192.168.122.89
        username: cumulus
        port: 22
    clag:
      priority: 1000
      backup_ip: 192.168.122.18
      clag_cidr: [169.254.2.1/30]
      peer_ip: 169.254.2.2
  spine2:
    fabric: spine_cluster
    hostname: dist2
    plugin_package: cumulus
    connections:
      ssh:
        hostname: 192.168.122.18
        username: cumulus
        port: 22
    clag:
      priority: 0
      backup_ip: 192.168.122.89
      clag_cidr: [169.254.2.2/30]
      peer_ip: 169.254.2.1

Applying this state file looks like this:

$ etherweaver "*" state.apply --yaml=clag_example.yaml
If you continue, the following changes will be applied:
###################################
{   'spine1': [   'net add hostname dist1',
                  'net add bridge bridge vids 10-12,20,254',
                  'net add bond peerlink bond slaves swp9',
                  'net add bond peerlink bond slaves swp10',
                  'net add bond po1 bond slaves swp1',
                  'net add bond po2 bond slaves swp2',
                  'net add interface peerlink.4094 clag backup-ip '
                  '192.168.122.18',
                  'net add interface peerlink.4094 ip address 169.254.2.1/30',
                  'net add interface peerlink.4094 clag peer-ip 169.254.2.2',
                  'net add interface peerlink.4094 clag priority 1000',
                  'net add interface peerlink.4094 clag sys-mac '
                  '44:38:39:FF:01:01',
                  'net add bond po1 bridge vids 10,12,20,254',
                  'net add bond po2 bridge vids 10,12,20,254'],
    'spine2': [   'net add hostname dist2',
                  'net add bridge bridge vids 10-12,20,254',
                  'net add bond peerlink bond slaves swp9',
                  'net add bond peerlink bond slaves swp10',
                  'net add bond po1 bond slaves swp1',
                  'net add bond po2 bond slaves swp2',
                  'net add interface peerlink.4094 clag backup-ip '
                  '192.168.122.89',
                  'net add interface peerlink.4094 ip address 169.254.2.2/30',
                  'net add interface peerlink.4094 clag peer-ip 169.254.2.1',
                  'net add interface peerlink.4094 clag priority 0',
                  'net add interface peerlink.4094 clag sys-mac '
                  '44:38:39:FF:01:01',
                  'net add bond po1 bridge vids 10,12,20,254',
                  'net add bond po2 bridge vids 10,12,20,254']}
Do you want to continue? y/[n]y
spine1: 100%|███████████████████████████████████████| 13/13 [00:01<00:00,  7.17it/s]
spine2: 100%|███████████████████████████████████████| 13/13 [00:06<00:00,  5.02it/s]


Run complete

Note

When testing state files in a virtual environment such as GNS3 or vagrant, the cumulus switches clag will not function unless you add ‘clagd-args –vm’ to /etc/network/interfaces under the peerlink.4094 interface section on both switches.