diff --git a/Deployment/playbooks/openrc.sh b/Deployment/playbooks/openrc.sh
new file mode 100644
index 0000000000000000000000000000000000000000..8841b3e64b0e2747092e3230590744a72beb8d97
--- /dev/null
+++ b/Deployment/playbooks/openrc.sh
@@ -0,0 +1,50 @@
+#!/usr/bin/env bash
+#
+# Copyright (c) 2023.
+# Cluster and Cloud Computing(comp90024)
+# Assignment 2-Team 58-Melbourne
+#
+# Authors:
+# * Solmaz Maabi-871603
+# *
+# *
+# *
+#
+
+# To use an OpenStack cloud you need to authenticate against the Identity
+# service named keystone, which returns a **Token** and **Service Catalog**.
+# The catalog contains the endpoints for all services the user/tenant has
+# access to - such as Compute, Image Service, Identity, Object Storage, Block
+# Storage, and Networking (code-named nova, glance, keystone, swift,
+# cinder, and neutron).
+#
+# *NOTE*: Using the 3 *Identity API* does not necessarily mean any other
+# OpenStack API is version 3. For example, your cloud provider may implement
+# Image API v1.1, Block Storage API v2, and Compute API v2.0. OS_AUTH_URL is
+# only for the Identity API served through keystone.
+export OS_AUTH_URL=https://keystone.rc.nectar.org.au:5000/v3/
+# With the addition of Keystone we have standardized on the term **project**
+# as the entity that owns the resources.
+export OS_PROJECT_ID=de79ce1221224946a12432e03ca8f52a
+export OS_PROJECT_NAME="unimelb-comp90024-2023-grp-58"
+export OS_USER_DOMAIN_NAME="Default"
+if [ -z "$OS_USER_DOMAIN_NAME" ]; then unset OS_USER_DOMAIN_NAME; fi
+export OS_PROJECT_DOMAIN_ID="default"
+if [ -z "$OS_PROJECT_DOMAIN_ID" ]; then unset OS_PROJECT_DOMAIN_ID; fi
+# unset v2.0 items in case set
+unset OS_TENANT_ID
+unset OS_TENANT_NAME
+# In addition to the owning entity (tenant), OpenStack stores the entity
+# performing the action as the **user**.
+export OS_USERNAME="s.maabi@student.unimelb.edu.au"
+# With Keystone you pass the keystone password.
+echo "Please enter your OpenStack Password for project $OS_PROJECT_NAME as user $OS_USERNAME: "
+read -sr OS_PASSWORD_INPUT
+export OS_PASSWORD=$OS_PASSWORD_INPUT
+# If your configuration has multiple regions, we set that information here.
+# OS_REGION_NAME is optional and only valid in certain environments.
+export OS_REGION_NAME="Melbourne"
+# Don't leave a blank variable, unset it if it was empty
+if [ -z "$OS_REGION_NAME" ]; then unset OS_REGION_NAME; fi
+export OS_INTERFACE=public
+export OS_IDENTITY_API_VERSION=3
\ No newline at end of file
diff --git a/Deployment/playbooks/roles/openstack-common/tasks/main.yaml b/Deployment/playbooks/roles/openstack-common/tasks/main.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..f3e7f4512f0e348292cf85e9b876ddc141e79cf6
--- /dev/null
+++ b/Deployment/playbooks/roles/openstack-common/tasks/main.yaml
@@ -0,0 +1,16 @@
+---
+# Install dependencies on the host
+- name: Install pip
+  become: true
+  ansible.builtin.apt:
+    name: ["python3-dev", "python3-setuptools", "python3-pip"]
+    state: latest
+    update_cache: true
+  when: ansible_distribution == "Ubuntu"
+# sudo apt-get update && sudo apt-get install python3-dev python3-setuptools python-pip
+
+- name: Update pip
+  ansible.builtin.pip:
+    name: ["pip", "openstacksdk"]
+    state: latest
+# pip install --upgrade pip && pip install openstacksdk
diff --git a/Deployment/playbooks/roles/openstack-instance/tasks/main.yaml b/Deployment/playbooks/roles/openstack-instance/tasks/main.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..0367c67bcc02887953c64abf6fbd0469558773fd
--- /dev/null
+++ b/Deployment/playbooks/roles/openstack-instance/tasks/main.yaml
@@ -0,0 +1,40 @@
+---
+# Create an instance on NeCTAR
+- name: Create an instance
+  openstack.cloud.server:
+    name: "{{ item.name }}"
+    auto_floating_ip: false
+    availability_zone: "{{ availability_zone }}"
+    flavor: "{{ instance_flavor }}"
+    image: "{{ instance_image }}"
+    key_name: "{{ instance_key_name }}"
+    # network: "{{ instance_network }}"
+    security_groups: "{{ sg_names }}"
+    timeout: 600
+    volumes: "{{ item.volumes }}"
+    state: present
+    wait: true
+  loop: "{{ instances }}"
+  register: os_instance
+
+- ansible.builtin.debug:
+    msg: "Instance {{ item.server.name }} has been created. IP address is {{ item.server.access_ipv4 }}"
+  loop: "{{ os_instance.results }}"
+  when: item.server is defined
+
+- name: Wait for connection
+  ansible.builtin.wait_for:
+    host: "{{ item.server.access_ipv4 }}"
+    port: 22
+    timeout: 120
+    search_regex: OpenSSH
+  loop: "{{ os_instance.results }}"
+  when: item.server is defined
+
+# Add hosts to Ansible in-memory inventory
+- name: Add host
+  ansible.builtin.add_host:
+    name: "{{ item.server.access_ipv4 }}"
+    groups: COMP90024
+  loop: "{{ os_instance.results }}"
+  when: item.server is defined
diff --git a/Deployment/playbooks/roles/openstack-security-group/tasks/main.yaml b/Deployment/playbooks/roles/openstack-security-group/tasks/main.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..65e68771fcab7733f37b2e64a4dedc62e242afe4
--- /dev/null
+++ b/Deployment/playbooks/roles/openstack-security-group/tasks/main.yaml
@@ -0,0 +1,40 @@
+---
+# Create a security group
+- name: Create a security group
+  openstack.cloud.security_group:
+    name: "{{ item.name }}"
+    description: "{{ item.description }}"
+    state: present
+    security_group_rules:
+      - ether_type: IPv6
+        protocol: any
+        direction: egress
+        port_range_min: 1
+        port_range_max: 65535
+        remote_ip_prefix: ::/0
+      - ether_type: IPv4
+        protocol: any
+        direction: egress
+        port_range_min: 1
+        port_range_max: 65535
+        remote_ip_prefix: 0.0.0.0/0
+  loop: "{{ security_groups }}"
+
+- name: Create a list of security group names
+  ansible.builtin.set_fact:
+    sg_names: "{{ sg_names|default([]) + [ item.name ] }}"
+  loop: "{{ security_groups }}"
+
+- ansible.builtin.debug:
+    msg: "Security group(s) {{ sg_names }} have been created."
+
+# Create security group rules
+- name: Create security group rules
+  openstack.cloud.security_group_rule:
+    security_group: "{{ item.name }}"
+    protocol: "{{ item.protocol }}"
+    port_range_min: "{{ item.port_range_min }}"
+    port_range_max: "{{ item.port_range_max }}"
+    remote_ip_prefix: "{{ item.remote_ip_prefix }}"
+    state: present
+  loop: "{{ security_groups }}"
diff --git a/Deployment/playbooks/roles/openstack-volume/tasks/main.yaml b/Deployment/playbooks/roles/openstack-volume/tasks/main.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..2bf2bb36a931e4bea6702da4cf03fae7f399b196
--- /dev/null
+++ b/Deployment/playbooks/roles/openstack-volume/tasks/main.yaml
@@ -0,0 +1,21 @@
+---
+# Create volumes from vars
+- name: Create volume(s) on NeCTAR
+  openstack.cloud.volume:
+    display_name: "{{ item.vol_name }}"
+    size: "{{ item.vol_size }}"
+    availability_zone: "{{ availability_zone }}"
+    wait: true
+    timeout: 600
+    state: present
+  loop: "{{ volumes }}"
+  register: os_vol
+
+# Get a list of volume Ids from the return value of os_volume
+- name: Create a list of volume Ids
+  ansible.builtin.set_fact:
+    os_vol_ids: "{{ os_vol_ids|default([]) + [ item.volume.id ] }}"
+  loop: "{{ os_vol.results }}"
+
+- ansible.builtin.debug:
+    msg: "Volume {{ os_vol_ids }} has been created."
diff --git a/Deployment/playbooks/vars/comm.yaml b/Deployment/playbooks/vars/comm.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..515b32e0772f66d52a8519136ac432662e5de95a
--- /dev/null
+++ b/Deployment/playbooks/vars/comm.yaml
@@ -0,0 +1,44 @@
+# Common vars
+availability_zone: melbourne-qh2-uom
+instance_image: bbaf16f8-2484-48d7-b455-42209cc4b8d2
+instance_key_name: intance_key
+instance_flavor: uom.mse.2c9g
+
+
+# Volume
+volumes:
+  - vol_name: data@instance_1
+    vol_size: 60
+  - vol_name: data@instance_2
+    vol_size: 60
+  - vol_name: data@instance_3
+    vol_size: 60
+  - vol_name: data@instance_4
+    vol_size: 60
+
+
+# Security group
+security_groups:
+  - name: ssh
+    description: "security group for SSH access"
+    protocol: tcp
+    port_range_min: 22
+    port_range_max: 22
+    remote_ip_prefix: 0.0.0.0/0
+  - name: demo_http
+    description: "security group for HTTP"
+    protocol: tcp
+    port_range_min: 80
+    port_range_max: 80
+    remote_ip_prefix: 0.0.0.0/0
+
+# Instance
+instances:
+  - name: instance_1
+    volumes: ["data@instance_1"]
+  - name: instance_2
+    volumes: ["data@instance_2"]
+  - name: instance_3
+    volumes: ["data@instance_3"]
+  - name: instance_4
+    volumes: ["data@instance_4"]