From c66bddbbab3d2316442e1e4a39c88d28048136e4 Mon Sep 17 00:00:00 2001
From: msimonin <matthieu.simonin@inria.fr>
Date: Tue, 19 Feb 2019 15:20:33 +0100
Subject: [PATCH] [vmong5k] Allow to choose a working dir

This working dir is used to generate all the files and disks needed by the
provider. It must be an absolute path.

This allows the user to choose whether to store the disks on the local
filesystem on the node (working_dir=/tmp/enos_vmong5k -- this is the default)
or in the site frontend (e.g. working_dir=/home/msimonin/public/enos_vmong5k).

In addition, the vms are now launched as a regular user (the current g5k user).

Be aware that the permissions on the working dir are set to 711 whereas the
permission on the actual vm disks are set to 777 (inside the working
directory).

Fix #5
---
 .../infra/enos_vmong5k/ansible/domain.xml.j2  |   4 +-
 enoslib/infra/enos_vmong5k/ansible/site.yml   | 106 +++++++++++-------
 enoslib/infra/enos_vmong5k/configuration.py   |   3 +-
 enoslib/infra/enos_vmong5k/constants.py       |   2 +
 enoslib/infra/enos_vmong5k/provider.py        |   6 +-
 enoslib/infra/enos_vmong5k/schema.py          |   3 +-
 6 files changed, 79 insertions(+), 45 deletions(-)

diff --git a/enoslib/infra/enos_vmong5k/ansible/domain.xml.j2 b/enoslib/infra/enos_vmong5k/ansible/domain.xml.j2
index 3e701c65..7f71e87e 100644
--- a/enoslib/infra/enos_vmong5k/ansible/domain.xml.j2
+++ b/enoslib/infra/enos_vmong5k/ansible/domain.xml.j2
@@ -17,11 +17,11 @@
    <emulator>/usr/bin/kvm</emulator>
    <disk type='file' device='disk'>
      <driver name='qemu' type='qcow2'/>
-     <source file='/tmp/disks/{{ item.alias}}'/>
+     <source file='{{working_dir}}/{{ item.alias}}'/>
      <target dev='vda' bus='virtio'/>
    </disk>
    <disk type='file' device='cdrom'>
-     <source file='/tmp/cloud-init-data-{{ item.alias }}.iso'/>
+     <source file='{{ working_dir }}/cloud-init-data-{{ item.alias }}.iso'/>
      <target dev='vdb' bus='virtio'/>
      <readonly/>
    </disk>
diff --git a/enoslib/infra/enos_vmong5k/ansible/site.yml b/enoslib/infra/enos_vmong5k/ansible/site.yml
index 4e962f8b..e8558624 100644
--- a/enoslib/infra/enos_vmong5k/ansible/site.yml
+++ b/enoslib/infra/enos_vmong5k/ansible/site.yml
@@ -4,6 +4,16 @@
   vars:
     pubkey: "{{lookup('file', '~/.ssh/id_rsa.pub')}}"
   tasks:
+    - name: Enable nested virtualization
+      shell: |
+        modprobe -r kvm_intel
+        modprobe kvm_intel nested=1
+
+    - name: Add g5k_user to libvirt group
+      user:
+        name: msimonin
+        groups: libvirt
+        append: yes
 
     - name: Destroy running virtual machines (vm -1 / 1)
       virt:
@@ -11,6 +21,8 @@
         state: destroyed
       ignore_errors: yes
       with_items: "{{ vms[inventory_hostname] }}"
+      become: yes
+      become_user: "{{ g5k_user }}"
 
     - name: Unregister existing virtual machines (vm -0 / 1)
       virt:
@@ -18,74 +30,67 @@
         command: undefine
       ignore_errors: yes
       with_items: "{{ vms[inventory_hostname] }}"
+      become: yes
+      become_user: "{{ g5k_user }}"
 
-    - name: Enable nested virtualization
-      shell: |
-        modprobe -r kvm_intel
-        modprobe kvm_intel nested=1
-
-    - name: Unmount the tmpfs
-      mount:
-        path: /tmp/disks
-        state: unmounted
-      when:
-        - tmpfs is defined
-        - tmpfs
-
-    - name: Remove a tmpfs for the vms
+    - name: Create the working directory
       file:
-        path: /tmp/disks
-        state: absent
-      when:
-        - tmpfs is defined
-        - tmpfs
-
-    - name: Create a directory for hosting the virtual disks
-      file:
-        path: /tmp/disks
+        path: "{{ working_dir }}"
         state: directory
-        mode: 777
-
-    - name: Mount the tmpfs
-      shell: "mount -t tmpfs -o size={{ tmpfs }} tmpfs /tmp/disks"
-      when:
-        - tmpfs is defined
-        - tmpfs
+        mode: 0711
+        recurse: true
+      become: yes
+      become_user: "{{ g5k_user }}"
 
     - name: Removing previous cloud init data
       file:
-        path: "/tmp/cloud-init-data-{{ item.alias }}"
+        path: "{{ working_dir }}/cloud-init-data-{{ item.alias }}"
         state: absent
       loop: "{{ vms[inventory_hostname] }}"
+      become: yes
+      become_user: "{{ g5k_user }}"
 
     - name: Removing previous cloud init data iso
       file:
-        path: "/tmp/cloud-init-data-{{ item.alias }}.iso"
+        path: "{{ working_dir }}/cloud-init-data-{{ item.alias }}.iso"
         state: absent
       loop: "{{ vms[inventory_hostname] }}"
+      become: yes
+      become_user: "{{ g5k_user }}"
 
     - name: Creating cloud init data directory
       file:
-        path: "/tmp/cloud-init-data-{{ item.alias }}"
+        path: "{{ working_dir }}/cloud-init-data-{{ item.alias }}"
         state: directory
       loop: "{{ vms[inventory_hostname] }}"
+      become: yes
+      become_user: "{{ g5k_user }}"
 
     - name: Generate meta-data for cloud-init
       template:
         src: meta-data.j2
-        dest: "/tmp/cloud-init-data-{{ item.alias }}/meta-data"
+        dest: "{{ working_dir }}/cloud-init-data-{{ item.alias }}/meta-data"
       loop: "{{ vms[inventory_hostname] }}"
+      become: yes
+      become_user: "{{ g5k_user }}"
 
-    - name: Generate user data for cloud-init
+    - name: Generate g5k_user data for cloud-init
       template:
         src: user-data.j2
-        dest: "/tmp/cloud-init-data-{{ item.alias }}/user-data"
+        dest: "{{ working_dir }}/cloud-init-data-{{ item.alias }}/user-data"
       loop: "{{ vms[inventory_hostname] }}"
+      become: yes
+      become_user: "{{ g5k_user }}"
 
     #  Create one iso per vm
     - name: Create the iso for cloud-init
-      shell: "cd /tmp &&  genisoimage -output cloud-init-data-{{ item.alias }}.iso -volid cidata -joliet -rock cloud-init-data-{{ item.alias }}/user-data cloud-init-data-{{ item.alias }}/meta-data"
+      shell: > 
+        cd {{ working_dir }} 
+        && 
+        genisoimage -output cloud-init-data-{{ item.alias }}.iso -volid cidata -joliet -rock cloud-init-data-{{ item.alias }}/user-data cloud-init-data-{{ item.alias }}/meta-data
       loop: "{{ vms[inventory_hostname] }}"
+      become: yes
+      become_user: "{{ g5k_user }}"
 
     - name: Check base image
       stat:
@@ -97,13 +102,30 @@
         msg: "Base image does not exist. Verify this path is valid: {{ base_image }}"
       when: p.stat.exists == False
 
-      # NOTE(msimonin): We don't copy in the ramfs in a first iteration
     - name: Copy base image
-      shell: "cp {{ base_image }} /tmp/kenan-base-image.qcow2"
+      shell: > 
+        ls {{ working_dir }}/enos_vmong5k-base-image.qcow2 
+        || 
+        cp {{ base_image }} {{ working_dir }}/enos_vmong5k-base-image.qcow2
+      become: yes
+      become_user: "{{ g5k_user }}"
+
+    - name: Removing previous disk
+      file:
+        path: "{{ working_dir }}/{{ item.alias }}"
+        state: absent
+      with_items: "{{ vms[inventory_hostname] }}"
+      become: yes
+      become_user: "{{ g5k_user }}"
 
     - name: Link virtual image to base image
-      shell: "qemu-img create -f qcow2 -o backing_file=/tmp/kenan-base-image.qcow2 /tmp/disks/{{ item.alias }}"
+      shell: |
+        qemu-img create -f qcow2 -o backing_file={{ working_dir}}/enos_vmong5k-base-image.qcow2 {{ working_dir }}/{{ item.alias }}
+        # I know ...
+        chmod 777 {{ working_dir }}/{{ item.alias }}
       with_items: "{{ vms[inventory_hostname] }}"
+      become: yes
+      become_user: "{{ g5k_user }}"
 
     - name: Define virtual machines (vm 0 / 1)
       virt:
@@ -111,9 +133,13 @@
         command: define
         xml: "{{ lookup('template', 'domain.xml.j2') }}"
       with_items: "{{ vms[inventory_hostname] }}"
+      become: yes
+      become_user: "{{ g5k_user }}"
 
     - name: Launch virtual machines (vm 1 / 1)
       virt:
         name: "{{ item.alias }}"
         state: running
       with_items: "{{ vms[inventory_hostname] }}"
+      become: yes
+      become_user: "{{ g5k_user }}"
diff --git a/enoslib/infra/enos_vmong5k/configuration.py b/enoslib/infra/enos_vmong5k/configuration.py
index da4bc49b..1a218410 100644
--- a/enoslib/infra/enos_vmong5k/configuration.py
+++ b/enoslib/infra/enos_vmong5k/configuration.py
@@ -3,7 +3,7 @@ import uuid
 from ..configuration import BaseConfiguration
 from .constants import (DEFAULT_FLAVOUR, DEFAULT_IMAGE, DEFAULT_JOB_NAME,
                         DEFAULT_NETWORKS, DEFAULT_NUMBER, DEFAULT_QUEUE,
-                        DEFAULT_WALLTIME, FLAVOURS)
+                        DEFAULT_WALLTIME, DEFAULT_WORKING_DIR, FLAVOURS)
 from .schema import SCHEMA
 
 
@@ -17,6 +17,7 @@ class Configuration(BaseConfiguration):
         self.queue = DEFAULT_QUEUE
         self.walltime = DEFAULT_WALLTIME
         self.image = DEFAULT_IMAGE
+        self.working_dir = DEFAULT_WORKING_DIR
 
         self._machine_cls = MachineConfiguration
         self._network_cls = str
diff --git a/enoslib/infra/enos_vmong5k/constants.py b/enoslib/infra/enos_vmong5k/constants.py
index 525514c7..fe0db87c 100644
--- a/enoslib/infra/enos_vmong5k/constants.py
+++ b/enoslib/infra/enos_vmong5k/constants.py
@@ -41,3 +41,5 @@ DEFAULT_FLAVOUR = "tiny", FLAVOURS["tiny"]
 DEFAULT_NETWORKS = ["enos_network"]
 
 DEFAULT_NUMBER = 1
+
+DEFAULT_WORKING_DIR = "/tmp/enos_vmong5k"
diff --git a/enoslib/infra/enos_vmong5k/provider.py b/enoslib/infra/enos_vmong5k/provider.py
index 95d20f86..8f6380c3 100644
--- a/enoslib/infra/enos_vmong5k/provider.py
+++ b/enoslib/infra/enos_vmong5k/provider.py
@@ -147,7 +147,11 @@ def start_virtualmachines(provider_conf, g5k_roles, vmong5k_roles):
     vms_by_host = _index_by_host(vmong5k_roles)
 
     extra_vars = {'vms': vms_by_host,
-                  'base_image': provider_conf.image}
+                  'base_image': provider_conf.image,
+                  # push the g5k user in the env 
+                  'g5k_user': os.environ.get('USER'),
+                  'working_dir': provider_conf.working_dir
+                  }
     #pm_inventory_path = os.path.join(os.getcwd(), "pm_hosts")
     #generate_inventory(*g5k_init, pm_inventory_path)
     # deploy virtual machines with ansible playbook
diff --git a/enoslib/infra/enos_vmong5k/schema.py b/enoslib/infra/enos_vmong5k/schema.py
index 90d18f2a..d300e304 100644
--- a/enoslib/infra/enos_vmong5k/schema.py
+++ b/enoslib/infra/enos_vmong5k/schema.py
@@ -9,7 +9,8 @@ SCHEMA = {
         "job_name": {"type": "string"},
         "queue": {"type": "string", "enum": QUEUE_TYPES},
         "walltime": {"type": "string"},
-        "image": {"type": "string"}
+        "image": {"type": "string"},
+        "working_dir": {"type": "string"}
     },
     "additionalProperties": False,
     "required": ["resources"],
-- 
GitLab