# Copyright (c) 2017-2018 Intel Corporation.
#
# 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: Remove directory
  file:
    path: "{{ '/tmp/'+node_item.hostname }}"
    state: absent

- name: Create directory
  file:
    path: "{{ '/tmp/'+node_item.hostname }}"
    state: directory
    mode: 0755

- name: Define user-data file name
  set_fact:
    user_data: "{{ '/tmp/'+node_item.hostname+'/user-data' }}"

- name: Define image-dir
  set_fact:
    image_dir: "{{ '/var/lib/libvirt/images/' }}"

- name: Create a new empty file for user-data
  file:
    path: "{{ user_data }}"
    state: touch

- name: Add user-data
  blockinfile:
    path: "{{ user_data }}"
    marker: "MARKER"
    content: |
      #cloud-config
      preserve_hostname: False
      hostname: {{ node_item.hostname }}
      output:
        all: ">> /var/log/cloud-init.log"
      ssh_pwauth: True
      users:
          - name: {{ node_item.user }}
            lock-passwd: False
            plain_text_passwd: {{ node_item.password }}
            chpasswd: { expire: False }
            sudo: ALL=(ALL) NOPASSWD:ALL
            ssh_pwauth: True

- name: Remove the marker
  lineinfile:
    dest: "{{ user_data }}"
    state: absent
    regexp: "MARKER"

- name: Define network-config file name
  set_fact:
    network_config: "{{ '/tmp/'+node_item.hostname+'/network-config' }}"

- name: Create a new empty file for network-config
  file:
    path: "{{ network_config }}"
    state: touch

- name: Add network-data
  blockinfile:
    path: "{{ network_config }}"
    marker: "MARKER"
    content: |
      version: 2
      ethernets:

- name: Define meta-data file name
  set_fact:
    meta_data: "{{ '/tmp/'+node_item.hostname+'/meta-data' }}"

- name: Create a new empty file for meta-data
  file:
    path: "{{ meta_data }}"
    state: touch

- name: Add meta-data
  blockinfile:
    path: "{{ meta_data }}"
    marker: "MARKER"
    content: |
      instance-id: {{ node_item.hostname }}
      local-hostname: {{ node_item.hostname }}

- name: Remove the marker
  lineinfile:
    dest: "{{ meta_data }}"
    state: absent
    regexp: "MARKER"

- name: Define xml file name
  set_fact:
    xml_file: "{{ '/tmp/'+node_item.hostname+'/'+node_item.hostname+'.xml' }}"

- name: Create a new empty file for xml file
  file:
    path: "{{ xml_file }}"
    state: touch

- name: Add root "domain" node
  blockinfile:
    path: "{{ xml_file }}"
    marker: ""
    content: |
      <domain>
      </domain>

- name: Add "type" attribute to "domain" node
  xml:
    path: "{{ xml_file }}"
    xpath: /domain
    attribute: type
    value: "kvm"
    pretty_print: yes

- name: Add new children nodes to "domain" node
  xml:
    path: "{{ xml_file }}"
    xpath: /domain
    add_children:
      - name: "{{ node_item.hostname }}"
      - memory: "{{ node_item.ram }}"
      - vcpu: "{{ node_item.vcpus }}"
      - os
      - cpu
      - devices
    pretty_print: yes

- name: Add "unit" attribute to "memory" node
  xml:
    path: "{{ xml_file }}"
    xpath: /domain/memory
    attribute: unit
    value: "MB"
    pretty_print: yes

- name: Add "placement" attribute to "vcpu" node
  xml:
    path: "{{ xml_file }}"
    xpath: /domain/vcpu
    attribute: placement
    value: "static"
    pretty_print: yes

- name: Add new children nodes to "os" node
  xml:
    path: "{{ xml_file }}"
    xpath: /domain/os
    add_children:
      - type: "hvm"
      - boot
    pretty_print: yes

- name: Add "arch" attribute to "type" node
  xml:
    path: "{{ xml_file }}"
    xpath: /domain/os/type
    attribute: arch
    value: "x86_64"
    pretty_print: yes

- name: Add "dev" attribute to "boot" node
  xml:
    path: "{{ xml_file }}"
    xpath: /domain/os/boot
    attribute: dev
    value: "hd"
    pretty_print: yes

- name: Add new children nodes to "cpu" node
  xml:
    path: "{{ xml_file }}"
    xpath: /domain/cpu
    add_children:
      - cache
    pretty_print: yes

- name: Add "mode" attribute to "cpu" node
  xml:
    path: "{{ xml_file }}"
    xpath: /domain/cpu
    attribute: mode
    value: "host-passthrough"
    pretty_print: yes

- name: Add "mode" attribute to "cache" node
  xml:
    path: "{{ xml_file }}"
    xpath: /domain/cpu/cache
    attribute: mode
    value: "passthrough"
    pretty_print: yes

- name: Add new children nodes to "devices" node
  xml:
    path: "{{ xml_file }}"
    xpath: /domain/devices
    add_children:
      - disk:
          type: file
          device: disk
      - controller:
          type: virtio-serial
          index: '0'
      - serial:
          type: pty
      - console:
          type: pty
          tty: '/dev/pts/14'
      - graphics:
          type: vnc
          port: '-1'
          autoport: 'yes'
    pretty_print: yes

- name: Add new children nodes to "disk" node
  xml:
    path: "{{ xml_file }}"
    xpath: /domain/devices/disk
    add_children:
      - driver:
          name: qemu
          type: qcow2
      - source:
          file: "{{ '/var/lib/libvirt/images/'+node_item.hostname+'.qcow2' }}"
      - target:
          dev: vda
          bus: virtio
      - alias:
          name: virtio-disk0
    pretty_print: yes

- name: Add new children nodes to "graphics" node
  xml:
    path: "{{ xml_file }}"
    xpath: /domain/devices/graphics
    add_children:
      - listen:
          type: address
          address: 0.0.0.0
    pretty_print: yes

- name: Add new children nodes to "devices" node
  xml:
    path: "{{ xml_file }}"
    xpath: /domain/devices
    add_children:
      - disk:
          type: file
          device: cdrom
    pretty_print: yes

- name: Add new children nodes to "disk" node
  xml:
    path: "{{ xml_file }}"
    xpath: /domain/devices/disk
    add_children:
      - source:
          file: "{{ '/var/lib/libvirt/images/'+node_item.hostname+'-ci-data.img' }}"
      - target:
          dev: hdb
          bus: ide
      - readonly
    pretty_print: yes

- name: Configure controller
  xml:
    path: "{{ xml_file }}"
    xpath: /domain/devices/controller
    add_children:
      - alias:
          name: virtio-serial0
    pretty_print: yes

- name: Configure serial
  xml:
    path: "{{ xml_file }}"
    xpath: /domain/devices/serial
    add_children:
      - source:
          path: '/dev/pts/14'
      - target:
          port: '0'
      - alias:
          name: 'serial0'
    pretty_print: yes

- name: Configure console
  xml:
    path: "{{ xml_file }}"
    xpath: /domain/devices/console
    add_children:
      - source:
          path: '/dev/pts/14'
      - target:
          port: '0'
          type: 'serial'
      - alias:
          name: 'serial0'
    pretty_print: yes

- set_fact:
    slot_address: 5

- name: Populate network-config and add interface to xml file
  include_tasks: create_interfaces.yml
  extra_vars: "{{ network_config xml_file slot_address mac_address_counter }}"
  loop_control:
    loop_var: interface_item
  with_items: "{{ node_item.interfaces }}"

- name: Create directory
  file:
    path: "{{ '/tmp/'+node_item.hostname }}"
    state: directory
    mode: 0755

- name: Generate iso image
  shell: >
    genisoimage -output {{ image_dir+node_item.hostname+'-ci-data.img' }} -volid cidata -joliet
    -r {{ '/tmp/'+node_item.hostname+'/network-config' }} {{ '/tmp/'+node_item.hostname+'/user-data' }} {{ '/tmp/'+node_item.hostname+'/meta-data' }}
    &>> {{ '/tmp/'+node_item.hostname+'/hostname.log' }}

- name: Copy and convert the ubuntu image
  shell: >
    qemu-img convert -O qcow2 {{ node_item.image }} {{ image_dir+node_item.hostname+'.qcow2' }}

- name: Resize image
  shell: >
    qemu-img resize {{ image_dir+node_item.hostname+'.qcow2' }} {{ node_item.disk }}M

- name: Define the VMs
  virt:
    command: define
    name: "{{ node_item.hostname }}"
    xml: "{{ lookup('file', '/tmp/'+node_item.hostname+'/'+node_item.hostname+'.xml') }}"

- name: Start the VMs
  virt:
    command: create
    name: "{{ node_item.hostname }}"