Getting Started¶
Config Structure¶
Top Level objects¶
Etherweaver’s can consist of two sections, of which Fabrics are optional:
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¶
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.