From b1ed318d220e79070fcf6f24f63c28980ff2e0ce Mon Sep 17 00:00:00 2001
From: Dmitriy Rabotyagov <drabotyagov@vexxhost.com>
Date: Tue, 23 Jun 2020 22:36:04 +0300
Subject: [PATCH] Add ability to create system vlans

This patch brings possibiltiy to create vlan interfaces,
which later can be used with frrouting

Change-Id: I7bf49496a9075bc6c9b566f60ff76e4afecf6b29
---
 defaults/main.yml      | 16 ++++++++++++-
 tasks/frr_vlans.yml    | 52 ++++++++++++++++++++++++++++++++++++++++++
 tasks/main.yml         |  4 ++++
 templates/vlans.cfg.j2 |  7 ++++++
 tests/test.yml         | 12 ++++++++++
 tests/test_vars.yml    | 22 ++++++++++++++++++
 6 files changed, 112 insertions(+), 1 deletion(-)
 create mode 100644 tasks/frr_vlans.yml
 create mode 100644 templates/vlans.cfg.j2
 create mode 100644 tests/test_vars.yml

diff --git a/defaults/main.yml b/defaults/main.yml
index 5f284b0..9f1a199 100644
--- a/defaults/main.yml
+++ b/defaults/main.yml
@@ -11,4 +11,18 @@
 # distributed under the License is distributed on an "AS IS" BASIS,
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
-# limitations under the License.
\ No newline at end of file
+# limitations under the License.
+
+# Set with list of vlans that needs to be configured
+# frr_vlans:
+#   - vlan-raw-device: eth0
+#     id: 100
+#     address: 192.168.1.100
+#     netmask: 255.255.255.0
+#     network: 192.168.1.0
+#     broadcast: 192.168.1.255
+#     gateway: 192.168.1.1
+#     mtu: 1496
+#     up: route add -net 192.168.0.0 netmask 255.255.0.0 gw 192.168.1.1
+#     down: route del -net 192.168.0.0 netmask 255.255.0.0 gw 192.168.1.1
+frr_vlans: []
diff --git a/tasks/frr_vlans.yml b/tasks/frr_vlans.yml
new file mode 100644
index 0000000..30dc36b
--- /dev/null
+++ b/tasks/frr_vlans.yml
@@ -0,0 +1,52 @@
+---
+# Copyright 2020, VEXXHOST, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+- name: Add required vlans
+  become: true
+  become_user: root
+  block:
+    - name: Install vlan package
+      package:
+        name: vlan
+        state: present
+      register: install_vlan
+      until: install_vlan is success
+      retries: 5
+      delay: 2
+
+    - name: Load vlan modules
+      modprobe:
+        name: 8021q
+        state: present
+      when: install_vlan is changed
+
+    - name: Copy vlans config
+      template:
+        src: vlans.cfg.j2
+        dest: "/etc/network/interfaces.d/vlan-{{ item.id }}.cfg"
+      with_items: "{{ frr_vlans }}"
+      register: distribute_vlans
+
+    - name: Stop interface
+      command: "ifdown {{ item.item['vlan-raw-device'] }}.{{ item.item.id }}"
+      with_items: "{{ distribute_vlans.results }}"
+      when: item is changed
+      changed_when: false
+
+    - name: Start interface
+      command: "ifup {{ item.item['vlan-raw-device'] }}.{{ item.item.id }}"
+      with_items: "{{ distribute_vlans.results }}"
+      when: item is changed
+      changed_when: false
diff --git a/tasks/main.yml b/tasks/main.yml
index 7eab38a..c50e542 100644
--- a/tasks/main.yml
+++ b/tasks/main.yml
@@ -16,5 +16,9 @@
 - name: Gather variables for each operating system
   include_vars: "{{ ansible_os_family | lower }}.yml"
 
+- name: Create required vlan interfaces
+  include_tasks: frr_vlans.yml
+  when: frr_vlans | length > 0
+
 - name: Install frr
   include_tasks: frr_install.yml
diff --git a/templates/vlans.cfg.j2 b/templates/vlans.cfg.j2
new file mode 100644
index 0000000..e5ec7cd
--- /dev/null
+++ b/templates/vlans.cfg.j2
@@ -0,0 +1,7 @@
+
+auto {{ item['vlan-raw-device'] }}.{{ item.id }}
+iface {{ item['vlan-raw-device'] }}.{{ item.id }} inet {{ ('address' in item) | ternary('static', 'manual') }}
+{% set _ = item.pop('id') %}
+{% for key, value in item.items() %}
+    {{ key }} {{ value }}
+{% endfor %}
diff --git a/tests/test.yml b/tests/test.yml
index 001b666..ae1a654 100644
--- a/tests/test.yml
+++ b/tests/test.yml
@@ -15,6 +15,8 @@
 
 - name: Installing frr
   hosts: all
+  vars_files:
+    - test_vars.yml
   roles:
     - frrouting
 
@@ -23,6 +25,16 @@
       pause:
         seconds: 30
 
+    - name: Ping vlans ip address
+      shell: |
+        set -e
+        ping -c2 "{{ item.address }}"
+      register: _ping_vlan
+      until: _ping_vlan is success
+      retries: 5
+      delay: 10
+      with_items: "{{ frr_vlans }}"
+
     - name: Check service state
       service_facts:
 
diff --git a/tests/test_vars.yml b/tests/test_vars.yml
new file mode 100644
index 0000000..e59e1c3
--- /dev/null
+++ b/tests/test_vars.yml
@@ -0,0 +1,22 @@
+---
+# Copyright 2020, VEXXHOST, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+frr_vlans:
+  - vlan-raw-device: eth0
+    id: 100
+    address: 192.168.1.100
+    netmask: 255.255.255.0
+    network: 192.168.1.0
+    broadcast: 192.168.1.255