From 27aae63b451486da176826c01cf02cff1b6bf7ea Mon Sep 17 00:00:00 2001
From: Attila Farkas <394097@mail.muni.cz>
Date: Thu, 29 Jul 2021 18:45:40 +0200
Subject: [PATCH] Fix windows provisioning

---
 sandboxcreator/ansible_generator/preconfig.py |  5 +-
 sandboxcreator/input_parser/sandbox.py        |  1 -
 sandboxcreator/resources/files/playbook.yml   | 34 ++++++++-
 .../vagrant_generator/vagrantfile.py          | 74 +++++++++++++++----
 4 files changed, 95 insertions(+), 19 deletions(-)

diff --git a/sandboxcreator/ansible_generator/preconfig.py b/sandboxcreator/ansible_generator/preconfig.py
index 0d5c004..ddd308d 100644
--- a/sandboxcreator/ansible_generator/preconfig.py
+++ b/sandboxcreator/ansible_generator/preconfig.py
@@ -15,9 +15,7 @@ class Preconfig:
     def _create_inventory(sandbox: Sandbox) -> Dict:
         groups: Dict = {"hosts": {"hosts": {}}, "routers": {"hosts": {}},
                         "ssh": {"hosts": {}}, "winrm": {"hosts": {}}}
-        all_devices: Dict = {}
         for device in sandbox.devices:
-            all_devices[device.name] = {}
             if device.device_type == DeviceType.HOST:
                 groups["hosts"]["hosts"][device.name] = {}
             elif device.device_type == DeviceType.ROUTER:
@@ -27,7 +25,7 @@ class Preconfig:
             elif device.protocol == Protocol.WINRM:
                 groups["winrm"]["hosts"][device.name] = {}
 
-        return {"all": {"hosts": all_devices, "children": groups}}
+        return {"all": {"children": groups}}
 
     @staticmethod
     def _create_host_vars(sandbox: Sandbox) -> Dict[str, Dict]:
@@ -61,6 +59,7 @@ class Preconfig:
         winrm_vars: Dict = {"ansible_connection": "winrm",
                             "ansible_user": "windows",
                             "ansible_password": "vagrant",
+                            "ansible_become_pass": "vagrant",
                             "ansible_winrm_transport": "basic",
                             "ansible_winrm_server_cert_validation": "ignore"}
 
diff --git a/sandboxcreator/input_parser/sandbox.py b/sandboxcreator/input_parser/sandbox.py
index a8efd61..2f1ae0b 100644
--- a/sandboxcreator/input_parser/sandbox.py
+++ b/sandboxcreator/input_parser/sandbox.py
@@ -255,7 +255,6 @@ class Sandbox:
 
         if router.flavor:
             memory, cpus = Sandbox._resolve_flavor(router.flavor, flavors)
-        # TODO add explicit memory and cpus definition
         else:
             memory, cpus = config["default_router_memory"], \
                            config["default_router_cpus"]
diff --git a/sandboxcreator/resources/files/playbook.yml b/sandboxcreator/resources/files/playbook.yml
index 38e1253..a44633c 100644
--- a/sandboxcreator/resources/files/playbook.yml
+++ b/sandboxcreator/resources/files/playbook.yml
@@ -43,6 +43,36 @@
       interface_static_netmask: '{{ interface.interface_netmask }}'
 
 
+- name: Windows configuration
+  hosts: winrm
+  become: yes
+  become_method: runas
+  become_user: windows
+  vars:
+    ansible_become_pass: vagrant
+  tasks:
+
+  - name: Add aliases of all devices
+    lineinfile:
+      line: '{{ item.key }} {{ item.value }}'
+      path: /etc/hosts
+    loop: '{{ device_aliases | dict2items }}'
+
+  - name: Configure routes
+    include_role:
+      name: interface
+    loop: '{{ routes }}'
+    loop_control:
+      loop_var: interface
+    vars:
+      interface_configuration_type: static
+      interface_default_gateway: '{{ interface.interface_default_gateway | default('''') }}'
+      interface_identification: '{{ interface.interface_ip }}'
+      interface_routes: '{{ interface.interface_routes | default([]) }}'
+      interface_static_ip: '{{ interface.interface_ip }}'
+      interface_static_netmask: '{{ interface.interface_netmask }}'
+
+
 - name: Linux Host configuration
   hosts: hosts:&ssh
   become: yes
@@ -50,7 +80,7 @@
 
 
 - name: Border router configuration
-  hosts: '{{ "border_router_name" | default("!all") }}'
+  hosts: br
   become: yes
   tasks:
 
@@ -64,7 +94,7 @@
 
 
 - name: Controller configuration
-  hosts: '{{ "controller_name" | default("!all") }}'
+  hosts: controller
   become: yes
   tasks:
 
diff --git a/sandboxcreator/vagrant_generator/vagrantfile.py b/sandboxcreator/vagrant_generator/vagrantfile.py
index 69d9057..37a920c 100644
--- a/sandboxcreator/vagrant_generator/vagrantfile.py
+++ b/sandboxcreator/vagrant_generator/vagrantfile.py
@@ -1,7 +1,7 @@
 from typing import List, Optional, Union
 from pathlib import Path
 
-from sandboxcreator.input_parser.sandbox import Sandbox, Device, Protocol
+from sandboxcreator.input_parser.sandbox import Sandbox, Device, Protocol, DevicePurpose
 from sandboxcreator.io.writer import Writer
 
 
@@ -73,39 +73,47 @@ class Vagrantfile:
     def _create_root(sandbox: Sandbox) -> Block:
         """Create root of the vagrantfile with all its content"""
         content: List = Vagrantfile._add_devices(sandbox)
-        content.extend(Vagrantfile._add_preconfig(sandbox))
-        content.extend(Vagrantfile._add_provisioning(sandbox))
         return Block("configure(\"2\")", None, "config", content)
 
     @staticmethod
-    def _add_preconfig(sandbox: Sandbox) -> List[Block]:
+    def _add_preconfig(device: Device, sandbox: Sandbox,
+                       group: Optional[str] = None) -> Block:
         """Add pre-configuration block to Vagrantfile definition"""
         provisioner = "ansible" if sandbox.ansible_installed else "ansible_local"
-        content: List = Vagrantfile._add_preconfig_attributes(sandbox)
-        return [Block("vm.provision", provisioner, "ansible", content,
-                      "Ansible pre-configuration")]
+        content: List = Vagrantfile._add_preconfig_attributes(device, sandbox,
+                                                              group)
+        return Block("vm.provision", provisioner, "ansible", content,
+                     "Ansible pre-configuration")
 
     @staticmethod
-    def _add_preconfig_attributes(sandbox: Sandbox) -> List:
+    def _add_preconfig_attributes(device: Device, sandbox: Sandbox,
+                                  group: Optional[str] = None) -> List:
         """Add attributes to pre-configuration"""
         attributes: List = [String("playbook",
                                    sandbox.config["preconfig_playbook"]),
                             String("inventory_path",
                                    sandbox.config["preconfig_inventory"])]
+        if group is None:
+            attributes.append(String("limit", device.name))
+        else:
+            attributes.append(String("limit", group))
         if sandbox.verbose_ansible:
             attributes.append(String("verbose", "vv"))
         return attributes
 
     @staticmethod
-    def _add_provisioning(sandbox: Sandbox) -> List[Block]:
+    def _add_provisioning(device: Device, sandbox: Sandbox,
+                          group: Optional[str] = None) -> Block:
         """Add provisioning block to Vagrantfile definition"""
         provisioner = "ansible" if sandbox.ansible_installed else "ansible_local"
-        content: List = Vagrantfile._add_provisioning_attributes(sandbox)
-        return [Block("vm.provision", provisioner, "ansible", content,
-                      "User Ansible provisioning")]
+        content: List = Vagrantfile._add_provisioning_attributes(device,
+                                                                 sandbox, group)
+        return Block("vm.provision", provisioner, "ansible", content,
+                     "User Ansible provisioning")
 
     @staticmethod
-    def _add_provisioning_attributes(sandbox: Sandbox) -> List:
+    def _add_provisioning_attributes(device: Device, sandbox: Sandbox,
+                                     group: Optional[str] = None) -> List:
         """Add attributes to provisioning"""
         attributes: List = [String("playbook",
                                    sandbox.config["provisioning_playbook"])]
@@ -118,6 +126,11 @@ class Vagrantfile:
             attributes.append(String("galaxy_role_file",
                                      "provisioning/requirements.yml"))
             attributes.append(String("galaxy_roles_path", "provisioning/roles"))
+        if group is None:
+            attributes.append(String("limit", device.name))
+        else:
+            attributes.append(String("limit", group))
+
             attributes.append(String("galaxy_command",
                                      "sudo ansible-galaxy install --role-file="
                                      "%{role_file} --roles-path=%{roles_path} "
@@ -139,6 +152,18 @@ class Vagrantfile:
 
         return devices
 
+    @staticmethod
+    def _list_winrm_hosts(sandbox: Sandbox) -> str:
+        """Return a string with names of all winrm hosts"""
+        winrm_hosts: List[str] = []
+        for device in sandbox.devices:
+            if device.device_purpose is DevicePurpose.HOST and \
+                    device.protocol is Protocol.WINRM:
+                winrm_hosts.append(device.name)
+
+        joined_winrm_hosts: str = ",".join(winrm_hosts)
+        return joined_winrm_hosts
+
     @staticmethod
     def _add_device_attributes(device: Device, sandbox: Sandbox):
         """Add attributes to devices"""
@@ -174,6 +199,29 @@ class Vagrantfile:
                                            interface.network.cidr.netmask)]
             attributes.append(Method("vm.network", net_attributes, False))
 
+        if sandbox.ansible_installed:
+            attributes.append(Vagrantfile._add_preconfig(device, sandbox))
+            attributes.append(Vagrantfile._add_provisioning(device, sandbox))
+        else:
+            if sandbox.controller_present:
+                if device.protocol is Protocol.SSH:
+                    if device.device_purpose is DevicePurpose.CONTROLLER:
+                        attributes.append(Vagrantfile._add_preconfig(device,
+                                                                     sandbox))
+                        attributes.append(
+                            Vagrantfile._add_preconfig(device, sandbox, "winrm"))
+                        attributes.append(
+                            Vagrantfile._add_provisioning(device, sandbox,
+                                                          Vagrantfile._list_winrm_hosts(sandbox)))
+                    else:
+                        attributes.append(
+                            Vagrantfile._add_preconfig(device, sandbox))
+                        attributes.append(
+                            Vagrantfile._add_provisioning(device, sandbox))
+            else:
+                attributes.append(Vagrantfile._add_preconfig(device, sandbox))
+                attributes.append(Vagrantfile._add_provisioning(device, sandbox))
+
         return attributes
 
     def generate(self, output_file: Path, template_name: str):
-- 
GitLab