Introduce OpenStack Heat as additional provisioner

ONAP will mainly be installed on a Kubernetes cluster installed
on Openstack. The creation of the resources (instances, networks, etc.)
are done using Heat so this change prepares the engine for Heat
introduction by adding 2 new parameters:
- provisioner: it can be set by using -r
- uri to heat template: it can be set by using -t

Change-Id: Iedf7848519487a35a2cf5c823e23d6ba72bdb006
diff --git a/playbooks/create-libvirt-resources.yml b/playbooks/create-libvirt-resources.yml
new file mode 100644
index 0000000..89e455b
--- /dev/null
+++ b/playbooks/create-libvirt-resources.yml
@@ -0,0 +1,62 @@
+---
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 The Nordix Foundation. All rights reserved.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+
+- hosts: localhost
+  connection: local
+  become: yes
+  gather_facts: true
+  vars_files:
+    - "{{ engine_path }}/engine/var/versions.yml"
+    - "{{ engine_path }}/engine/var/global.yml"
+    - "{{ pdf_file }}"
+    - "{{ idf_file }}"
+
+  roles:
+    - role: prepare-libvirt
+    - role: create-libvirt-networks
+    - role: create-libvirt-vms
+
+  tasks:
+    - name: Get libvirt networks
+      command: virsh net-list --all
+      register: libvirt_networks
+
+    - name: List libvirt networks
+      debug:
+        msg: "{{ libvirt_networks.stdout_lines }}"
+
+    - name: Get libvirt vms
+      command: virsh list --all
+      register: libvirt_vms
+
+    - name: List libvirt vms
+      debug:
+        msg: "{{ libvirt_vms.stdout_lines }}"
+
+    - name: Get list of nodes from vbmc
+      command: vbmc list
+      environment:
+        PATH: "{{ lookup('env', 'ENGINE_VENV') }}/bin"
+      register: vbmc_vms
+
+    - name: List vbmc nodes
+      debug:
+        msg: "{{ vbmc_vms.stdout_lines }}"
+
+# vim: set ts=2 sw=2 expandtab:
diff --git a/playbooks/install-configure-bifrost.yml b/playbooks/install-configure-bifrost.yml
new file mode 100644
index 0000000..6cc80a4
--- /dev/null
+++ b/playbooks/install-configure-bifrost.yml
@@ -0,0 +1,32 @@
+---
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 The Nordix Foundation. All rights reserved.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+
+- hosts: localhost
+  connection: local
+  gather_facts: true
+  vars_files:
+    - "{{ engine_path }}/engine/var/versions.yml"
+    - "{{ engine_path }}/engine/var/global.yml"
+    - "{{ pdf_file }}"
+    - "{{ idf_file }}"
+
+  roles:
+    - role: install-configure-bifrost
+
+# vim: set ts=2 sw=2 expandtab:
diff --git a/playbooks/main.yml b/playbooks/main.yml
new file mode 100644
index 0000000..fce9928
--- /dev/null
+++ b/playbooks/main.yml
@@ -0,0 +1,27 @@
+---
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 The Nordix Foundation. All rights reserved.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+
+- name: Create libvirt resources
+  import_playbook: create-libvirt-resources.yml
+  when: not baremetal
+
+- name: Install and configure bifrost
+  import_playbook: install-configure-bifrost.yml
+
+# vim: set ts=2 sw=2 expandtab:
diff --git a/playbooks/roles/create-libvirt-networks/tasks/create-libvirt-networks.yml b/playbooks/roles/create-libvirt-networks/tasks/create-libvirt-networks.yml
new file mode 100644
index 0000000..caa3b82
--- /dev/null
+++ b/playbooks/roles/create-libvirt-networks/tasks/create-libvirt-networks.yml
@@ -0,0 +1,55 @@
+---
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 The Nordix Foundation. All rights reserved.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+- name: Destroy network '{{ item.key }}'
+  virt_net:
+    name: "{{ item.key }}"
+    state: absent
+    uri: "{{ vm_libvirt_uri }}"
+
+- name: Ensure libvirt network '{{ item.key }}' is present
+  virt_net:
+    name: "{{ item.key }}"
+    state: present
+    xml: "{{ lookup('template', 'libvirt-net.xml.j2') }}"
+    uri: "{{ vm_libvirt_uri }}"
+
+- name: Set libvirt network '{{ item.key }}' to autostart
+  virt_net:
+    name: "{{ item.key }}"
+    autostart: yes
+    uri: "{{ vm_libvirt_uri }}"
+
+- name: Ensure libvirt network '{{ item.key }}' is running
+  virt_net:
+    name: "{{ item.key }}"
+    state: active
+    uri: "{{ vm_libvirt_uri }}"
+
+- name: Get status of libvirt network '{{ item.key }}'
+  virt_net:
+    name: "{{ item.key }}"
+    command: status
+    uri: "{{ vm_libvirt_uri }}"
+  register: test_libvirt_net_status
+
+- name: Fail if libvirt network '{{ item.key }}' is not active
+  assert:
+    that: test_libvirt_net_status.status == 'active'
+
+# vim: set ts=2 sw=2 expandtab:
diff --git a/playbooks/roles/create-libvirt-networks/tasks/main.yml b/playbooks/roles/create-libvirt-networks/tasks/main.yml
new file mode 100644
index 0000000..9e33399
--- /dev/null
+++ b/playbooks/roles/create-libvirt-networks/tasks/main.yml
@@ -0,0 +1,22 @@
+---
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 The Nordix Foundation. All rights reserved.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+- include_tasks: create-libvirt-networks.yml
+  loop: "{{ lookup('dict', idf.net_config) }}"
+
+# vim: set ts=2 sw=2 expandtab:
diff --git a/playbooks/roles/create-libvirt-networks/templates/libvirt-net.xml.j2 b/playbooks/roles/create-libvirt-networks/templates/libvirt-net.xml.j2
new file mode 100644
index 0000000..ba7a3a7
--- /dev/null
+++ b/playbooks/roles/create-libvirt-networks/templates/libvirt-net.xml.j2
@@ -0,0 +1,16 @@
+<network>
+  <name>{{ item.key }}</name>
+  {% if item.key == 'public' %}
+  <forward mode='nat'>
+    <nat>
+      <port start='1024' end='65535'/>
+    </nat>
+  </forward>
+  {% endif %}
+  <bridge name='br_{{ item.key }}' stp='on' delay='0'/>
+  <ip address='{{ item.value.network | regex_replace(".0$", ".1") }}' netmask='255.255.255.0'>
+    <dhcp>
+      <range start='{{ item.value.network | regex_replace(".0$", ".2") }}' end='{{ item.value.network | regex_replace(".0$", ".200") }}'/>
+    </dhcp>
+  </ip>
+</network>
diff --git a/playbooks/roles/create-libvirt-vms/defaults/main.yml b/playbooks/roles/create-libvirt-vms/defaults/main.yml
new file mode 100644
index 0000000..b174237
--- /dev/null
+++ b/playbooks/roles/create-libvirt-vms/defaults/main.yml
@@ -0,0 +1,24 @@
+---
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 The Nordix Foundation. All rights reserved.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+vm_libvirt_uri: "{{ lookup('env', 'LIBVIRT_CONNECT_URI') | default('qemu:///system', true) }}"
+libvirt_storage_pool: "{{ lookup('env', 'LIBVIRT_STORAGE_POOL') | default('default', true) }}"
+libvirt_storage_pool_path: "/var/lib/libvirt/images"
+vm_console_log_path: "/var/log/libvirt/baremetal_logs"
+
+# vim: set ts=2 sw=2 expandtab:
diff --git a/playbooks/roles/create-libvirt-vms/tasks/create-libvirt-pool.yml b/playbooks/roles/create-libvirt-vms/tasks/create-libvirt-pool.yml
new file mode 100644
index 0000000..fb0fa6f
--- /dev/null
+++ b/playbooks/roles/create-libvirt-vms/tasks/create-libvirt-pool.yml
@@ -0,0 +1,39 @@
+---
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 The Nordix Foundation. All rights reserved.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+- name: Define a libvirt pool if not defined
+  virt_pool:
+    name: "{{ libvirt_storage_pool }}"
+    state: present
+    uri: "{{ vm_libvirt_uri }}"
+    xml: "{{ lookup('template', 'libvirt-storage-pool.xml.j2') }}"
+
+- name: Ensure libvirt pool is running
+  virt_pool:
+    name: "{{ libvirt_storage_pool }}"
+    state: active
+    autostart: yes
+    uri: "{{ vm_libvirt_uri }}"
+
+- name: Set libvirt pool to autostart
+  virt_pool:
+    name: "{{ libvirt_storage_pool }}"
+    autostart: yes
+    uri: "{{ vm_libvirt_uri }}"
+
+# vim: set ts=2 sw=2 expandtab:
diff --git a/playbooks/roles/create-libvirt-vms/tasks/create-libvirt-vms.yml b/playbooks/roles/create-libvirt-vms/tasks/create-libvirt-vms.yml
new file mode 100644
index 0000000..5423c1f
--- /dev/null
+++ b/playbooks/roles/create-libvirt-vms/tasks/create-libvirt-vms.yml
@@ -0,0 +1,103 @@
+---
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 The Nordix Foundation. All rights reserved.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+- name: Find node in PDF by node name '{{ vm.key }}'
+  set_fact:
+    hostname: "{{ vm.value }}"
+    node: "{{ nodes | selectattr('name', 'equalto', vm.key) | first }}"
+
+- name: List info on pools
+  virt_pool:
+    command: facts
+    uri: "{{ vm_libvirt_uri }}"
+
+- name: Set prealloc arg for Debian
+  set_fact:
+    prealloc: "--prealloc-metadata"
+  when:
+    - ansible_os_family == 'Debian'
+    - vm_libvirt_uri == 'qemu:///system'
+
+- name: Destroy vm '{{ hostname }}'
+  virt:
+    command: destroy
+    name: "{{ hostname }}"
+    uri: "{{ vm_libvirt_uri }}"
+  ignore_errors: true
+
+- name: Undefine vm '{{ hostname }}'
+  virt:
+    command: undefine
+    name: "{{ hostname }}"
+    uri: "{{ vm_libvirt_uri }}"
+  ignore_errors: true
+
+- name: Initialize disk information for vm '{{ hostname }}'
+  set_fact:
+    disks: [ ]
+    dev_suffix: "abcdefghijklmnopqrstuvwxyz"
+
+- name: Create target device names of all disks for vm '{{ hostname }}'
+  set_fact:
+    disks: "{{ disks + [ disk | combine( { 'dev': 'vd' + dev_suffix[disk_no] } ) ] }}"
+  with_items:
+   - "{{ node.disks }}"
+  loop_control:
+    loop_var: disk
+    index_var: disk_no
+
+- name: Setup volumes for vm '{{ hostname }}'
+  include_tasks: create-libvirt-volumes.yml
+  with_items:
+   - "{{ disks }}"
+  loop_control:
+    loop_var: disk
+
+- name: Delete logs from previous deployment
+  file:
+    path: "{{ vm_console_log_path }}/"
+    state: absent
+
+- name: Create directory for console logs
+  file:
+    path: "{{ vm_console_log_path }}"
+    state: directory
+    mode: 0755
+
+- name: Create vm '{{ hostname }}'
+  virt:
+    command: define
+    name: "{{ hostname }}"
+    uri: "{{ vm_libvirt_uri }}"
+    xml: "{{ lookup('template', 'libvirt-vm.xml.j2') }}"
+
+- name: Set virtual IPMI port for '{{ hostname }}'
+  set_fact:
+    virtual_ipmi_port: "{{ ( node.remote_management.port | default(623) | int ) }}"
+
+- name: Plug vm '{{ hostname }}' into vbmc on port '{{ virtual_ipmi_port }}'
+  command: vbmc add {{ hostname }} --libvirt-uri {{ vm_libvirt_uri }} --port {{ virtual_ipmi_port }}
+  environment:
+    PATH: "{{ lookup('env', 'ENGINE_VENV') }}/bin"
+
+- name: Start vbmc for '{{ hostname }}'
+  command: vbmc start {{ hostname }}
+  environment:
+    PATH: "{{ lookup('env', 'ENGINE_VENV') }}/bin"
+
+# vim: set ts=2 sw=2 expandtab:
diff --git a/playbooks/roles/create-libvirt-vms/tasks/create-libvirt-volumes.yml b/playbooks/roles/create-libvirt-vms/tasks/create-libvirt-volumes.yml
new file mode 100644
index 0000000..a5de66b
--- /dev/null
+++ b/playbooks/roles/create-libvirt-vms/tasks/create-libvirt-volumes.yml
@@ -0,0 +1,53 @@
+---
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 The Nordix Foundation. All rights reserved.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+
+- name: Set path to the volume created
+  set_fact:
+    vm_volume_name: "{{ hostname }}-{{ disk.name }}.qcow2"
+    vm_vol_path_prefix: "{{ ansible_libvirt_pools[libvirt_storage_pool].path }}/{{ hostname }}"
+
+- name: Delete volume '{{ vm_volume_name }}' for vm '{{ hostname }}'
+  command: >
+    virsh --connect {{ vm_libvirt_uri }}
+    vol-delete --pool {{ libvirt_storage_pool }} {{ vm_volume_name }}
+  ignore_errors: yes
+
+- name: Create volume '{{ vm_volume_name }}' for vm '{{ hostname }}'
+  command: >
+    virsh --connect {{ vm_libvirt_uri }}
+      vol-create-as {{ libvirt_storage_pool }} {{ vm_volume_name }}
+      {{ disk.disk_capacity }} --format qcow2 {{ prealloc|default("") }}
+
+- name: Pre-touch volume '{{ vm_volume_name }}' for vm '{{ hostname }}'
+  file:
+    state: touch
+    path: "{{ vm_vol_path_prefix }}-{{ disk.name }}.qcow2"
+  when: vm_libvirt_uri == 'qemu:///system'
+
+# NOTE(TheJulia): CentOS default installs with an XFS root, and chattr
+# fails to set +C on XFS.  This could be more elegant, however the use
+# case is for CI testing.
+- name: Set copy-on-write for volume on non-CentOS systems
+  command: chattr +C {{ vm_vol_path_prefix }}-{{ disk.name }}.qcow2
+  ignore_errors: yes
+  when:
+    - ansible_distribution != 'CentOS'
+    - vm_libvirt_uri == 'qemu:///system'
+
+# vim: set ts=2 sw=2 expandtab:
diff --git a/playbooks/roles/create-libvirt-vms/tasks/main.yml b/playbooks/roles/create-libvirt-vms/tasks/main.yml
new file mode 100644
index 0000000..7db8dc4
--- /dev/null
+++ b/playbooks/roles/create-libvirt-vms/tasks/main.yml
@@ -0,0 +1,48 @@
+---
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 The Nordix Foundation. All rights reserved.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+- name: Gather data from PDF and IDF
+  set_fact:
+    num_nodes: "{{ nodes | length }}"
+    vms: "{{ idf[installer_type].hostnames }}"
+    networks: "{{ idf[installer_type].network }}"
+
+- include_tasks: create-libvirt-pool.yml
+
+- name: Stop existing virtualbmc processes
+  command: killall -w vbmc
+  ignore_errors: yes
+
+- name: Remove outdated virtualbmc folder
+  file:
+    path: "{{ ansible_env.HOME }}/.vbmc/"
+    state: absent
+
+- name: Install virtualbmc
+  pip:
+    name: virtualbmc
+    version: "{{ virtualbmc_version }}"
+    virtualenv: "{{ lookup('env', 'ENGINE_VENV') }}"
+  become: no
+
+- include_tasks: create-libvirt-vms.yml
+  with_dict: "{{ vms }}"
+  loop_control:
+    loop_var: vm
+
+# vim: set ts=2 sw=2 expandtab:
diff --git a/playbooks/roles/create-libvirt-vms/templates/libvirt-storage-pool.xml.j2 b/playbooks/roles/create-libvirt-vms/templates/libvirt-storage-pool.xml.j2
new file mode 100644
index 0000000..da139af
--- /dev/null
+++ b/playbooks/roles/create-libvirt-vms/templates/libvirt-storage-pool.xml.j2
@@ -0,0 +1,6 @@
+<pool type='dir'>
+  <name>{{ libvirt_storage_pool }}</name>
+  <target>
+    <path>{{ libvirt_storage_pool_path }}</path>
+  </target>
+</pool>
diff --git a/playbooks/roles/create-libvirt-vms/templates/libvirt-vm.xml.j2 b/playbooks/roles/create-libvirt-vms/templates/libvirt-vm.xml.j2
new file mode 100644
index 0000000..6034dd1
--- /dev/null
+++ b/playbooks/roles/create-libvirt-vms/templates/libvirt-vm.xml.j2
@@ -0,0 +1,85 @@
+<domain type='kvm'>
+  <name>{{ hostname }}</name>
+  <memory unit='GiB'>{{ node.node.memory | regex_replace("G$", "") }}</memory>
+  <currentMemory unit='GiB'>{{ node.node.memory | regex_replace("G$", "") }}</currentMemory>
+  <vcpu placement='static'>{{ node.node.cores }}</vcpu>
+  <resource>
+    <partition>/machine</partition>
+  </resource>
+  <os>
+    <type arch='x86_64' machine='pc-i440fx-2.5'>hvm</type>
+    <boot dev='network'/>
+    <boot dev='hd'/>
+    <bootmenu enable='no'/>
+    <bios useserial='yes' rebootTimeout='10000'/>
+  </os>
+  <features>
+    <acpi/>
+    <apic/>
+    <pae/>
+  </features>
+  <cpu mode='{{ node.node.cpu_cflags }}'>
+    <model fallback='allow'/>
+  </cpu>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>restart</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
+    {% for disk in disks %}
+      <disk type='file' device='disk'>
+        <driver name='qemu' type='qcow2' cache='unsafe'/>
+        <source file='{{ vm_vol_path_prefix }}-{{ disk.name }}.qcow2'/>
+        <backingStore/>
+        <target dev='{{ disk.dev }}' bus='virtio'/>
+        <alias name='virtio-disk0'/>
+      </disk>
+    {% endfor %}
+    <controller type='ide' index='0'>
+      <alias name='ide'/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
+    </controller>
+    <controller type='usb' index='0'>
+      <alias name='usb'/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+    </controller>
+    <controller type='pci' index='0' model='pci-root'>
+      <alias name='pci.0'/>
+    </controller>
+{%- for net_key, net_name in networks.network_mapping.iteritems() -%}
+    <interface type='network'>
+      <source network='{{ net_name }}' bridge='br_{{ net_name }}'/>
+      <mac address='{{ node.interfaces[idf.net_config[net_name].interface].mac_address }}'/>
+      <model type='virtio'/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x0{{idf.net_config[net_name].interface + 3 }}' function='0x0'/>
+    </interface>
+{%- endfor -%}
+    <serial type='file'>
+      <source path='{{ vm_console_log_path }}/{{ hostname }}_console.log'/>
+      <target port='1'/>
+      <alias name='serial0'/>
+    </serial>
+    <console type='file'>
+      <source path='{{ vm_console_log_path }}/{{ hostname }}_console.log'/>
+      <target type='serial' port='1'/>
+      <alias name='serial0'/>
+    </console>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <graphics type='vnc' port='5902' autoport='yes' listen='127.0.0.1'>
+      <listen type='address' address='127.0.0.1'/>
+    </graphics>
+    <video>
+      <model type='cirrus' vram='16384' heads='1'/>
+      <alias name='video0'/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
+    </video>
+    <memballoon model='virtio'>
+      <alias name='balloon0'/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/>
+    </memballoon>
+  </devices>
+  <seclabel type='dynamic' model='apparmor' relabel='yes'>
+  </seclabel>
+</domain>
diff --git a/playbooks/roles/install-configure-bifrost/defaults/main.yml b/playbooks/roles/install-configure-bifrost/defaults/main.yml
new file mode 100644
index 0000000..7474995
--- /dev/null
+++ b/playbooks/roles/install-configure-bifrost/defaults/main.yml
@@ -0,0 +1,41 @@
+---
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 The Nordix Foundation. All rights reserved.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+bifrost_inventory_source: "{{ lookup('env', 'BIFROST_INVENTORY_SOURCE') | default('/tmp/baremetal.yml', true) }}"
+node_default_groups: "{{ lookup('env', 'DEFAULT_HOST_GROUPS').split() | default(['baremetal'], true) }}"
+# diskimage-builder variables
+# download_ipa is set to false as we don't want bifrost itself to download it
+download_ipa: "{{ lookup('env', 'BIFROST_DOWNLOAD_IPA') | default('false', true) }}"
+dib_os_packages: "{{ lookup('env', 'DIB_OS_PACKAGES') | default('vim,less,bridge-utils,language-pack-en,iputils-ping,rsyslog,curl,iptables', true) }}"
+# create_ipa_image is set to true which will enable us to use prebuilt image
+create_ipa_image: "{{ lookup('env', 'BIFROST_CREATE_IPA') | default('true', true) }}"
+ipa_dib_os_element: "{{ lookup('env', 'IPA_DIB_OS_ELEMENT') | default('coreos', true) }}"
+
+# this variable is set to false by default in order to ensure the deployment image is built if
+# running outside of CI/CD. If it is run as part of CI/CD, it will be overriden within job to
+# download and use a prebuilt deployment image.
+use_prebuilt_deployment_image: "{{ lookup('env', 'USE_PREBUILT_DEPLOYMENT_IMAGE') | default('false', true) }}"
+# url to repository on arm where the images will be downloaded from
+# it needs to be overriden if running outside of Nordix CI/CD
+arm_url: "{{ lookup('env', 'ARM_URL') | default('https://artifactory.nordix.org/artifactory/cloud-infra/dib', true) }}"
+# prebuilt images
+deployment_image: "{{ arm_url }}/deployment_image/{{ distro }}/deployment_image.qcow2"
+ipa_initramfs: "{{ arm_url }}/ipa_image/{{ ipa_dib_os_element }}/ipa.initramfs"
+ipa_vmlinuz: "{{ arm_url }}/ipa_image/{{ ipa_dib_os_element }}/ipa.vmlinuz"
+
+# vim: set ts=2 sw=2 expandtab:
diff --git a/playbooks/roles/install-configure-bifrost/tasks/cleanup-bifrost.yml b/playbooks/roles/install-configure-bifrost/tasks/cleanup-bifrost.yml
new file mode 100644
index 0000000..1270e86
--- /dev/null
+++ b/playbooks/roles/install-configure-bifrost/tasks/cleanup-bifrost.yml
@@ -0,0 +1,35 @@
+---
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 The Nordix Foundation. All rights reserved.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+- name: Stop existing libvirt dnsmasq processes
+  command: killall -w dnsmasq
+  ignore_errors: yes
+  become: yes
+
+- name: Remove existing files and directories
+  file:
+    path: "{{ item }}"
+    state: absent
+  with_items:
+    - "/opt/stack/"
+    - "/etc/dnsmasq.d/bifrost.dhcp-hosts.d/"
+    - "/var/lib/misc/dnsmasq.leases"
+    - "{{ ansible_env.HOME }}/.config/openstack"
+  become: yes
+
+# vim: set ts=2 sw=2 expandtab:
diff --git a/playbooks/roles/install-configure-bifrost/tasks/create-bifrost-inventory-entry.yml b/playbooks/roles/install-configure-bifrost/tasks/create-bifrost-inventory-entry.yml
new file mode 100644
index 0000000..eb906d1
--- /dev/null
+++ b/playbooks/roles/install-configure-bifrost/tasks/create-bifrost-inventory-entry.yml
@@ -0,0 +1,51 @@
+---
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 The Nordix Foundation. All rights reserved.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+- name: Find node in PDF by node name '{{ host.key }}'
+  set_fact:
+    hostname: "{{ host.value }}"
+    node: "{{ nodes | selectattr('name', 'equalto', host.key) | first }}"
+
+- name: Gather node data for '{{ hostname }}' from PDF and IDF
+  set_fact:
+    node_data:
+      name: "{{ hostname }}"
+      uuid: "{{ hostname | to_uuid }}"
+      host_groups: "{{ node_default_groups | union(host_roles[host.key]) }}"
+      driver: "{{ node.remote_management.type[0] }}"
+      driver_info:
+        power:
+          ipmi_address: "{{ node.remote_management.address }}"
+          ipmi_port: "{{ ( node.remote_management.port | default(623) | int ) }}"
+          ipmi_username: "{{ node.remote_management.user }}"
+          ipmi_password: "{{ node.remote_management.pass }}"
+          ipmi_priv_level: "{{ node.remote_management.privilege_level | default('ADMINISTRATOR') }}"
+
+      nics:
+        - mac: "{{ node.interfaces[idf.net_config[engine.pxe_network].interface].mac_address }}"
+      ansible_ssh_host: "{{ node.interfaces[idf.net_config[engine.pxe_network | default('admin')].interface].address }}"
+      ipv4_address: "{{ node.interfaces[idf.net_config[engine.pxe_network | default('admin')].interface].address }}"
+      properties:
+        cpu_arch: "{{ node.node.arch }}"
+        ram: "{{ ( node.node.memory.rstrip('G') | int ) * ( 1024 | int ) }}"
+        cpus: "{{ node.node.cpus }}"
+        disk_size: "{{ node.disks[0].disk_capacity.rstrip('G') }}"
+
+- name: Add node data of '{{ hostname }}' to bifrost inventory
+  set_fact:
+    bifrost_inventory: "{{ bifrost_inventory | combine({hostname: node_data}) }}"
diff --git a/playbooks/roles/install-configure-bifrost/tasks/create-bifrost-inventory-file.yml b/playbooks/roles/install-configure-bifrost/tasks/create-bifrost-inventory-file.yml
new file mode 100644
index 0000000..14f4556
--- /dev/null
+++ b/playbooks/roles/install-configure-bifrost/tasks/create-bifrost-inventory-file.yml
@@ -0,0 +1,36 @@
+---
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 The Nordix Foundation. All rights reserved.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+- name: Remove previous bifrost inventory {{ bifrost_inventory_source }}
+  file:
+    state: absent
+    path: "{{ bifrost_inventory_source }}"
+
+- name: Write bifrost inventory {{ bifrost_inventory_source }}
+  copy:
+    dest: "{{ bifrost_inventory_source }}"
+    content: "{{ bifrost_inventory | to_nice_yaml }}"
+
+- name: Set right permissions for bifrost inventory
+  file:
+    path: "{{ bifrost_inventory_source }}"
+    owner: "{{ ansible_env.SUDO_USER }}"
+  when: >
+    ansible_env.SUDO_USER is defined
+
+# vim: set ts=2 sw=2 expandtab:
diff --git a/playbooks/roles/install-configure-bifrost/tasks/create-bifrost-playbooks.yml b/playbooks/roles/install-configure-bifrost/tasks/create-bifrost-playbooks.yml
new file mode 100644
index 0000000..21e6e94
--- /dev/null
+++ b/playbooks/roles/install-configure-bifrost/tasks/create-bifrost-playbooks.yml
@@ -0,0 +1,31 @@
+---
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 The Nordix Foundation. All rights reserved.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+- name: Load distribution variables
+  include_vars:
+    file: "{{ distro }}.yml"
+
+- name: Generate bifrost playbooks
+  template:
+    src: "{{ item.src }}"
+    dest: "{{ item.dst }}"
+  with_items:
+    - { src: 'bifrost-install.yml.j2', dst: '{{ engine_cache }}/repos/bifrost/playbooks/bifrost-install.yml' }
+    - { src: 'bifrost-enroll-deploy.yml.j2', dst: '{{ engine_cache }}/repos/bifrost/playbooks/bifrost-enroll-deploy.yml' }
+
+# vim: set ts=2 sw=2 expandtab:
diff --git a/playbooks/roles/install-configure-bifrost/tasks/download-image.yml b/playbooks/roles/install-configure-bifrost/tasks/download-image.yml
new file mode 100644
index 0000000..0c1a932
--- /dev/null
+++ b/playbooks/roles/install-configure-bifrost/tasks/download-image.yml
@@ -0,0 +1,43 @@
+---
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 The Nordix Foundation. All rights reserved.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+- set_fact:
+    source: "{{ item.source }}"
+    destination: "{{ item.destination }}"
+    download_image: "{{ item.download }}"
+
+- block:
+  - name: Remove existing image {{ destination }}
+    file:
+      path: "{{ destination }}"
+      state: absent
+
+  - name: Get sha256sum of image {{ source }}
+    uri:
+      url: "{{ source }}"
+      method: HEAD
+    register: header
+
+  - name: Download image
+    get_url:
+      url: "{{ source }}"
+      dest: "{{ destination }}"
+      mode: 0644
+      sha256sum: "{{ header.x_checksum_sha256 }}"
+  when: download_image
+  become: yes
diff --git a/playbooks/roles/install-configure-bifrost/tasks/main.yml b/playbooks/roles/install-configure-bifrost/tasks/main.yml
new file mode 100644
index 0000000..dcd88b3
--- /dev/null
+++ b/playbooks/roles/install-configure-bifrost/tasks/main.yml
@@ -0,0 +1,84 @@
+---
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 The Nordix Foundation. All rights reserved.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+- include_tasks: cleanup-bifrost.yml
+
+- name: Clone bifrost repository and checkout '{{ bifrost_version }}'
+  git:
+    repo: "{{ bifrost_git_url }}"
+    dest: "{{ engine_cache }}/repos/bifrost"
+    version: "{{ bifrost_version }}"
+    force: yes
+  environment:
+    http_proxy: "{{ lookup('env','http_proxy') }}"
+    https_proxy: "{{ lookup('env','https_proxy') }}"
+    no_proxy: "{{ lookup('env','no_proxy') }}"
+
+- name: Install bifrost requirements
+  pip:
+    requirements: "{{ engine_cache }}/repos/bifrost/requirements.txt"
+    extra_args: --upgrade
+
+- name: Process PDF and IDF
+  set_fact:
+    num_nodes: "{{ nodes | length }}"
+    hosts: "{{ idf[installer_type].hostnames }}"
+    host_roles: "{{ idf[installer_type].nodes_roles }}"
+    networks: "{{ idf[installer_type].network }}"
+    bifrost_inventory: {}
+
+- name: Create DHCP hosts directory
+  file:
+    path: "/etc/dnsmasq.d/bifrost.dhcp-hosts.d"
+    state: directory
+    owner: "root"
+    group: "root"
+    mode: 0755
+  become: yes
+
+- include_tasks: create-bifrost-inventory-entry.yml
+  with_dict: "{{ hosts }}"
+  loop_control:
+    loop_var: host
+
+- include_tasks: create-bifrost-inventory-file.yml
+
+- include_tasks: create-bifrost-playbooks.yml
+
+- name: Create folders to put ipa and deployment images
+  file:
+    path: "{{ item }}"
+    state: directory
+    owner: root
+    group: root
+    mode: 0755
+  with_items:
+    - /httpboot
+    - /tftpboot
+  become: yes
+
+# we want users to use prebuilt ipa images but not deployment images
+# as the deployment images contain ssh public key of the user so we
+# download ipa images by default and not the deployment image
+- include_tasks: download-image.yml
+  with_items:
+    - { source: "{{ deployment_image }}", destination: "/httpboot/deployment_image.qcow2", download: "{{ use_prebuilt_deployment_image }}" }
+    - { source: "{{ ipa_initramfs }}", destination: "/httpboot/ipa.initramfs", download: "true" }
+    - { source: "{{ ipa_vmlinuz }}", destination: "/httpboot/ipa.vmlinuz", download: "true" }
+
+# vim: set ts=2 sw=2 expandtab:
diff --git a/playbooks/roles/install-configure-bifrost/templates/bifrost-enroll-deploy.yml.j2 b/playbooks/roles/install-configure-bifrost/templates/bifrost-enroll-deploy.yml.j2
new file mode 100644
index 0000000..d999a2f
--- /dev/null
+++ b/playbooks/roles/install-configure-bifrost/templates/bifrost-enroll-deploy.yml.j2
@@ -0,0 +1,105 @@
+{% raw %}
+# enroll nodes using bifrost
+- hosts: baremetal
+  name: "Enroll nodes into Ironic"
+  become: no
+  gather_facts: no
+  vars:
+    multinode_testing: true
+    inventory_dhcp: true
+    inventory_dhcp_static_ip: true
+{% endraw %}
+    network_interface: "{{ engine.pxe_interface }}"
+{% raw %}
+  roles:
+    - role: ironic-enroll-dynamic
+      delegate_to: "{{ groups['target'][0] if groups['target'] is defined else 'localhost' }}"
+#    - role: ironic-inspect-node
+#      delegate_to: "{{ groups['target'][0] if groups['target'] is defined else 'localhost' }}"
+  environment:
+    http_proxy: "{{ lookup('env','http_proxy') }}"
+    https_proxy: "{{ lookup('env','https_proxy') }}"
+    no_proxy: "{{ lookup('env','no_proxy') }}"
+
+# TODO: this is necessary to install the OS in the correct drive. This workaround can be removed once Ansible v2.8 is released, which will support
+# the root_device property in its ironic python module.
+- hosts: localhost
+  connection: local
+  become: no
+  gather_facts: no
+  tasks:
+{% endraw %}
+{% for hostname, role in hosts.items() %}
+{% set node = nodes | selectattr('name', 'equalto', hostname) | first %}
+    - name: Add root_device hints to enrolled ironic nodes
+      command: "openstack --os-cloud bifrost baremetal node set {{ role }} --property root_device='{\"size\": \"{{ node.disks[0].disk_capacity.rstrip("G") }}\" }'"
+{% endfor %}
+{% raw %}
+- hosts: localhost
+  connection: local
+  become: no
+  gather_facts: no
+  tasks:
+    - name: Get nodes from Ironic
+      command: openstack --os-cloud bifrost baremetal node list
+      register: ironic_nodes
+    - name: List Ironic nodes
+      debug:
+        msg: "{{ ironic_nodes.stdout_lines }}"
+{% endraw %}
+
+# deploy nodes using bifrost
+{% raw %}
+- hosts: baremetal
+  name: Create configuration drive files and deploy machines from inventory
+  become: no
+  gather_facts: no
+  vars:
+{% endraw %}
+    network_interface: "{{ engine.pxe_interface }}"
+    multinode_testing: true
+    write_interfaces_file: true
+    addressing_mode: dhcp
+    inventory_dhcp: true
+    inventory_dhcp_static_ip: true
+    wait_for_node_deploy: true
+    wait_timeout: 1800
+{% raw %}
+  roles:
+    - role: bifrost-configdrives-dynamic
+      delegate_to: "{{ groups['target'][0] if groups['target'] is defined else 'localhost' }}"
+    - role: bifrost-deploy-nodes-dynamic
+      delegate_to: "{{ groups['target'][0] if groups['target'] is defined else 'localhost' }}"
+
+- hosts: localhost
+  connection: local
+  become: no
+  gather_facts: no
+  tasks:
+    - name: Get nodes from Ironic
+      command: openstack --os-cloud bifrost baremetal node list
+      register: ironic_nodes
+    - name: List Ironic nodes
+      debug:
+        msg: "{{ ironic_nodes.stdout_lines }}"
+
+- hosts: localhost
+  connection: local
+  become: no
+  gather_facts: no
+{% endraw %}
+  vars_files:
+    -  "{{ bifrost_inventory_source }}"
+{% raw %}
+  tasks:
+    - name: Wait for hosts to be reachable via SSH
+      local_action:
+        module: wait_for
+        host: "{{ item }}"
+        delay: 15
+        state: started
+        port: 22
+        connect_timeout: 10
+        timeout: 1000
+      with_items: "{{ vars.groups.baremetal }}"
+{% endraw %}
diff --git a/playbooks/roles/install-configure-bifrost/templates/bifrost-install.yml.j2 b/playbooks/roles/install-configure-bifrost/templates/bifrost-install.yml.j2
new file mode 100644
index 0000000..c76fe1c
--- /dev/null
+++ b/playbooks/roles/install-configure-bifrost/templates/bifrost-install.yml.j2
@@ -0,0 +1,108 @@
+---
+{% raw %}
+- hosts: target
+  name: "Install Ironic on the target host."
+  become: yes
+  gather_facts: yes
+  vars:
+{% endraw %}
+    multinode_testing: true
+    enabled_hardware_types: ipmi
+    enable_keystone: false
+    cleaning: false
+    testing: false
+    create_image_via_dib: {{ use_prebuilt_deployment_image | bool != true }}
+    download_ipa: {{ download_ipa }}
+    create_ipa_image: {{ create_ipa_image }}
+    ipa_dib_os_element: "{{ ipa_dib_os_element }}"
+    ironic_git_branch: "{{ ironic_version }}"
+    ironicclient_source_install: false
+    ironicinspector_source_install: false
+    ironicinspectorclient_source_install: false
+    network_interface: "{{ engine.pxe_interface }}"
+    inventory_dhcp: true
+    inventory_dhcp_static_ip: true
+{% raw %}
+  roles:
+    - { role: bifrost-prep-for-install, when: skip_install is not defined }
+    - role: bifrost-keystone-install
+    - role: bifrost-ironic-install
+    - role: bifrost-keystone-client-config
+      user: "{{ ansible_env.SUDO_USER | default(ansible_user_id) }}"
+      clouds:
+        bifrost:
+          config_username: "{{ ironic.keystone.default_username }}"
+          config_password: "{{ ironic.keystone.default_password }}"
+          config_project_name: "baremetal"
+          config_region_name: "{{ keystone.bootstrap.region_name }}"
+          config_auth_url: "{{ keystone.bootstrap.public_url }}"
+        bifrost-admin:
+          config_username: "{{ keystone.bootstrap.username }}"
+          config_password: "{{ keystone.bootstrap.password }}"
+          config_project_name: "{{ keystone.bootstrap.project_name }}"
+          config_region_name: "{{ keystone.bootstrap.region_name }}"
+          config_auth_url: "{{ keystone.bootstrap.public_url }}"
+    - role: bifrost-create-dib-image
+      dib_imagename: "{{ http_boot_folder }}/ipa"
+      build_ramdisk: false
+      dib_os_element: "{{ ipa_dib_os_element }}"
+      dib_elements: "ironic-agent {{ ipa_extra_dib_elements | default('') }}"
+      when: create_ipa_image | bool == true
+    - role: bifrost-create-dib-image
+      dib_imagetype: "qcow2"
+      dib_imagename: "{{deploy_image}}"
+      dib_env_vars:
+        DIB_PYTHON_VERSION: 2
+{% endraw %}
+      dib_os_element: "{{ dib_os_element }}"
+      dib_os_release: "{{ dib_os_release }}"
+      dib_packages: "{{ dib_os_packages }}"
+{% raw %}
+      extra_dib_elements: "{{ lookup('env', 'EXTRA_DIB_ELEMENTS') | default('') }}"
+      dib_elements: "vm enable-serial-console simple-init devuser openssh-server growroot pip-and-virtualenv {{ extra_dib_elements }}"
+      dib_notmpfs: true
+      when:
+        - create_image_via_dib | bool == true
+        - transform_boot_image | bool == false
+  environment:
+    http_proxy: "{{ lookup('env','http_proxy') }}"
+    https_proxy: "{{ lookup('env','https_proxy') }}"
+    no_proxy: "{{ lookup('env', 'no_proxy') }}"
+
+- hosts: localhost
+  connection: local
+  become: yes
+  gather_facts: no
+  tasks:
+    - name: Add deploy_logs_collect field into Ironic configuration file
+      blockinfile:
+        dest: /etc/ironic/ironic.conf
+        marker: "# {mark} SET IRONIC TROUBLESHOTTING PARAMETER"
+        block: |
+          [agent]
+          deploy_logs_collect = always
+      when: "{{ lookup('env', 'VERBOSITY') }} == true"
+
+    - name: Restart Ironic service
+      service:
+        name: "{{ item }}"
+        state: restarted
+      with_items:
+        - ironic-api
+        - ironic-conductor
+        - ironic-inspector
+      when:
+        - "{{ lookup('env', 'VERBOSITY') }} == true"
+
+- hosts: localhost
+  connection: local
+  become: no
+  gather_facts: no
+  tasks:
+    - name: Get nodes from Ironic
+      command: openstack --os-cloud bifrost baremetal node list
+      register: ironic_nodes
+    - name: List Ironic nodes
+      debug:
+        msg: "{{ ironic_nodes.stdout_lines }}"
+{% endraw %}
diff --git a/playbooks/roles/install-configure-bifrost/vars/centos7.yml b/playbooks/roles/install-configure-bifrost/vars/centos7.yml
new file mode 100644
index 0000000..6e8d74d
--- /dev/null
+++ b/playbooks/roles/install-configure-bifrost/vars/centos7.yml
@@ -0,0 +1,24 @@
+---
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 The Nordix Foundation. All rights reserved.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+# below variables are used for building deployment_image.qcow2 to with the specified distro
+# and only take effect if use_prebuilt_deployment_image set to false in defaults/main.yml
+dib_os_release: "7"
+dib_os_element: "centos7"
+
+# vim: set ts=2 sw=2 expandtab:
diff --git a/playbooks/roles/install-configure-bifrost/vars/main.yml b/playbooks/roles/install-configure-bifrost/vars/main.yml
new file mode 100644
index 0000000..26e1d73
--- /dev/null
+++ b/playbooks/roles/install-configure-bifrost/vars/main.yml
@@ -0,0 +1,21 @@
+---
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 The Nordix Foundation. All rights reserved.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+bifrost_git_url: https://opendev.org/openstack/bifrost.git
+
+# vim: set ts=2 sw=2 expandtab:
diff --git a/playbooks/roles/install-configure-bifrost/vars/ubuntu1804.yml b/playbooks/roles/install-configure-bifrost/vars/ubuntu1804.yml
new file mode 100644
index 0000000..fda5662
--- /dev/null
+++ b/playbooks/roles/install-configure-bifrost/vars/ubuntu1804.yml
@@ -0,0 +1,24 @@
+---
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 The Nordix Foundation. All rights reserved.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+# below variables are used for building deployment_image.qcow2 to with the specified distro
+# and only take effect if use_prebuilt_deployment_image set to false in defaults/main.yml
+dib_os_release: "bionic"
+dib_os_element: "ubuntu-minimal"
+
+# vim: set ts=2 sw=2 expandtab:
diff --git a/playbooks/roles/prepare-libvirt/defaults/main.yml b/playbooks/roles/prepare-libvirt/defaults/main.yml
new file mode 100644
index 0000000..2924a0a
--- /dev/null
+++ b/playbooks/roles/prepare-libvirt/defaults/main.yml
@@ -0,0 +1,21 @@
+---
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 The Nordix Foundation. All rights reserved.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+vm_libvirt_uri: "{{ lookup('env', 'LIBVIRT_CONNECT_URI') | default('qemu:///system', true) }}"
+
+# vim: set ts=2 sw=2 expandtab:
diff --git a/playbooks/roles/prepare-libvirt/tasks/main.yml b/playbooks/roles/prepare-libvirt/tasks/main.yml
new file mode 100644
index 0000000..917f0c8
--- /dev/null
+++ b/playbooks/roles/prepare-libvirt/tasks/main.yml
@@ -0,0 +1,81 @@
+---
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 The Nordix Foundation. All rights reserved.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+- name: "Load distribution defaults"
+  include_vars: "{{ ansible_os_family | lower }}.yml"
+
+- name: "Install required packages"
+  package:
+    name: "{{ required_packages }}"
+    update_cache: "{{ (ansible_pkg_mgr in ['apt', 'zypper']) | ternary('yes', omit) }}"
+    state: present
+
+- name: "Restart libvirt service"
+  service:
+    name: "{{ libvirt_service_name }}"
+    state: restarted
+
+# NOTE(Shrews) We need to enable ip forwarding for the libvirt bridge to
+# operate properly with dnsmasq. This should be done before starting dnsmasq.
+- name: "Enable IP forwarding in sysctl"
+  sysctl:
+    name: "net.ipv4.ip_forward"
+    value: 1
+    sysctl_set: yes
+    state: present
+    reload: yes
+
+# NOTE(Shrews) Ubuntu packaging+apparmor issue prevents libvirt from loading
+# the ROM from /usr/share/misc.
+- name: "Look for sgabios in {{ sgabios_dir }}"
+  stat: path={{ sgabios_dir }}/sgabios.bin
+  register: test_sgabios_qemu
+
+- name: "Look for sgabios in /usr/share/misc"
+  stat: path=/usr/share/misc/sgabios.bin
+  register: test_sgabios_misc
+
+- name: "Place sgabios.bin"
+  command: cp /usr/share/misc/sgabios.bin /usr/share/qemu/sgabios.bin
+  when: >
+    test_sgabios_qemu == false and
+    test_sgabios_misc == true
+
+# NOTE(TheJulia): In order to prevent conflicts, stop
+# dnsmasq to prevent conflicts with libvirt restarting.
+# TODO(TheJulia): We shouldn't need to do this, but the
+# libvirt dhcp instance conflicts withour specific config
+# and taking this path allows us to not refactor dhcp at
+# this moment. Our DHCP serving should be refactored
+# so we don't need to do this.
+- name: "Stop default dnsmasq service"
+  service:
+    name: dnsmasq
+    state: stopped
+  ignore_errors: true
+
+# Ubuntu creates a default network when installing libvirt.
+# This network uses the 192.168.122.0/24 range and thus
+# conflicts with our admin network
+- name: Destroy default libvirt network
+  virt_net:
+    name: "default"
+    state: absent
+    uri: "{{ vm_libvirt_uri }}"
+
+# vim: set ts=2 sw=2 expandtab:
diff --git a/playbooks/roles/prepare-libvirt/vars/debian.yml b/playbooks/roles/prepare-libvirt/vars/debian.yml
new file mode 100644
index 0000000..2ee5c20
--- /dev/null
+++ b/playbooks/roles/prepare-libvirt/vars/debian.yml
@@ -0,0 +1,32 @@
+---
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 The Nordix Foundation. All rights reserved.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+sgabios_dir: /usr/share/qemu/
+libvirt_service_name: libvirt-bin
+required_packages:
+ - libvirt-bin
+ - qemu-utils
+ - qemu-kvm
+ - qemu-system-x86
+ - sgabios
+ - pkg-config
+ - libvirt-dev
+ - python-lxml
+ - python-libvirt
+
+# vim: set ts=2 sw=2 expandtab:
diff --git a/provision.sh b/provision.sh
new file mode 100755
index 0000000..2663f43
--- /dev/null
+++ b/provision.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+# ============LICENSE_START=======================================================
+#  Copyright (C) 2019 The Nordix Foundation. All rights reserved.
+# ================================================================================
+# 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+
+set -o errexit
+set -o nounset
+set -o pipefail
+
+BIFROST_ROOT_DIR="$(dirname $(realpath ${BASH_SOURCE[0]}))"
+export ANSIBLE_ROLES_PATH="$HOME/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles:${ENGINE_PATH}/engine/playbooks/roles:${ENGINE_CACHE}/repos/bifrost/playbooks/roles"
+export ANSIBLE_LIBRARY="$HOME/.ansible/plugins/modules:/usr/share/ansible/plugins/modules:${ENGINE_CACHE}/repos/bifrost/playbooks/library"
+
+# set the BAREMETAL variable
+grep -o vendor.* ${ENGINE_CACHE}/config/pdf.yml | grep -q libvirt && export BAREMETAL=false || export BAREMETAL=true
+
+# create libvirt resources if not baremetal, install and configure bifrost
+echo "Info: Prepare nodes, configure bifrost and create bifrost inventory"
+echo "-------------------------------------------------------------------------"
+cd ${ENGINE_PATH}
+ansible-playbook ${ENGINE_ANSIBLE_PARAMS} \
+  -i localhost, \
+  -e baremetal=$BAREMETAL \
+  ${BIFROST_ROOT_DIR}/playbooks/main.yml
+echo "-------------------------------------------------------------------------"
+
+# install bifrost and enroll & deploy nodes
+echo "Info: Install bifrost"
+echo "-------------------------------------------------------------------------"
+cd ${ENGINE_CACHE}/repos/bifrost/playbooks
+ansible-playbook ${ENGINE_ANSIBLE_PARAMS} \
+  -i inventory/target \
+  bifrost-install.yml
+echo "-------------------------------------------------------------------------"
+
+echo "Info: Enroll and deploy nodes using bifrost"
+echo "-------------------------------------------------------------------------"
+cd ${ENGINE_CACHE}/repos/bifrost/playbooks
+ansible-playbook ${ENGINE_ANSIBLE_PARAMS} \
+  -i inventory/bifrost_inventory.py \
+  bifrost-enroll-deploy.yml
+echo "-------------------------------------------------------------------------"
+
+echo "Info: Nodes are provisioned using bifrost!"
+echo "-------------------------------------------------------------------------"
+
+# vim: set ts=2 sw=2 expandtab: