diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e3bd3d19388dc90303d762b8178ff0cc48076daf..a620d09ec202b3aa298e3b449a694de6cb5801f9 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,5 +1,5 @@
-image:
-  name: docker:20.10.17
+default:
+  image: $CI_REGISTRY_IMAGE:latest
 
 variables:
   CAMPUS_IP: 138.26.48.47
@@ -22,12 +22,13 @@ variables:
   PKR_VAR_networks: '["ec11e2be-8fac-46cf-8fa2-9dffb74ba5df"]'
   GIT_AUTHOR_NAME: "Gitlab runner"
   GIT_AUTHOR_EMAIL: "gitlab@runner"
-  NUM_SERVER_TO_KEEP: 5
+  NUM_SERVER_TO_KEEP: 1
   NUM_IMAGE_TO_KEEP: 30
   PKR_VAR_root_ssh_key: "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAFqqWgmYpEaGtHBeTu27ntVJpYjwq/x5aBefrvfhk8Z9lE3cuZ26vJ9n/9tGE4Zn2Pew1mpZgi6PzfJ3vMt8yA= root@master"
   DEV_KEY: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCpncAcYosVHt7HsUcE2XOYDuCi4HQnmFJv279LOcpZgXtZ6o0BM1fe5FgJS0X1ohBXQUFRuYJuJSW/GSmC1K8T+wCrKjZLJdMbqrubHV27diUZfdoVkoJy1vcAQF5nEcoTC7MpAFbBomdn2rsrpgQe8DGiURV7+soqybXV1OsIR3FFf6npnUaskHYT/oVtG9eBOnscyBxoVgbxzlmyoBLXED/sHKFw4nQSF/glYKEFiDu6TRTsBBEGvv23Qo/66QpQiFJ6TNfApNiyY9L1X+Dy8EWU6lozmNgwGDjXQ70Lr6xHnA0QGVALJlHXa6QjpgtpC5Nefsdvtf1hpfFo2VutpbSB+aq9jk3gWNN+XkhrWN5PiwP7YYJNw/WozyfL+IhwjfHZGxkuws+wGR6ZKxlX9W9Vrsq9ncYNKuhy2SdsR6s2XECQtrEQ6ZlX5jRt6Yh5M9ls5fMsWEqknDPmr1Ui6wV7NxprYngo9fLSdYO/ETIO3S6PB0aEHOZOyGitGaM06EmNpvjQn/QkkaVgt/O8wKL1o1AVzXhDMAFvtG6ejppV6kuTUHXFgSGZF6N9fnP91HuytyzC09F+NMWcmnRdrgXlHapjuuL3zzi+XLCQvk8+aYTzBKx1nU2FPMDRZ9sInGmqdTuM002E7qVbaCy4OxcWaAS/L2UVhGnHr+egYw== louistw@uab.edu"
 
 stages:
+  - pre-build
   - build
   - test
   - deploy
@@ -37,59 +38,190 @@ workflow:
     - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
     - if: $CI_PIPELINE_SOURCE == 'schedule'
 
-build_image:
-  image: $CI_REGISTRY_IMAGE:latest
+.get_build_date: &get_build_date
+  - export BUILD_DATE=$(TZ=America/Chicago date +%Y-%m-%dT%H%M%S)
+  - echo BUILD_DATE=${BUILD_DATE}
+
+.update_ansible_repo: &update_ansible_repo
+  - *get_build_date
+  - |
+    if [ ! -d $CI_PROJECT_DIR/CRI_XCBC ]; then
+      git clone https://github.com/uabrc/CRI_XCBC.git
+      cd CRI_XCBC
+      git remote add upstream https://github.com/jprorama/CRI_XCBC.git
+      cd ..
+    fi
+  - cd CRI_XCBC
+  - git config user.name "${GIT_AUTHOR_NAME}"
+  - git config user.email "${GIT_AUTHOR_EMAIL}"
+  - git fetch origin uab-prod
+  - git fetch upstream dev
+  - git checkout uab-prod
+  - git merge origin/uab-prod
+  - git checkout -b integration
+  - git merge upstream/dev
+  - export CRI_XCBC_HEAD=$(git rev-parse --short HEAD)
+  - export CRI_XCBC_dev=$(git rev-parse --short upstream/dev)
+  - export CRI_XCBC_prod=$(git rev-parse --short origin/uab-prod)
+  - cd ..
+  - export PACKER_IMAGE_HEAD=$(git rev-parse --short HEAD)
+  - echo CRI_XCBC_HEAD=${CRI_XCBC_HEAD} | tee -a $CI_PROJECT_DIR/image.env
+  - echo CRI_XCBC_dev=${CRI_XCBC_dev} | tee -a $CI_PROJECT_DIR/image.env
+  - echo CRI_XCBC_prod=${CRI_XCBC_prod} | tee -a $CI_PROJECT_DIR/image.env
+  - echo PACKER_IMAGE_HEAD=${PACKER_IMAGE_HEAD} | tee -a $CI_PROJECT_DIR/image.env
+
+.get_ansible_files: &get_ansible_files
+  - s3cmd get --force -r --host=$AWS_HOST --host-bucket=$AWS_HOST s3://cheaha-cloud-ansible-files/ ansible/files/
+
+build_docker_image:
+  image: docker:20.10.17
+  stage: pre-build
+  services:
+    - docker:20.10.16-dind
+  tags:
+    - dind
+  before_script:
+    - *get_build_date
+    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
+  script:
+    - docker build -t $CI_REGISTRY_IMAGE:$BUILD_DATE -t $CI_REGISTRY_IMAGE:latest .
+    - >
+      docker run --rm $CI_REGISTRY_IMAGE bash -c
+      'ansible --version &&
+      openstack --version &&
+      packer version &&
+      s3cmd --version &&
+      terraform --version'
+    - docker push --all-tags $CI_REGISTRY_IMAGE
+  rules:
+    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+      changes:
+        - Dockerfile
+      allow_failure: true
+
+build_base_image:
   stage: build
-  environment:
-    name: knightly
   tags:
     - build
   script:
     - |
-      if [ ! -d $CI_PROJECT_DIR/CRI_XCBC ]; then
-        git clone https://github.com/uabrc/CRI_XCBC.git
-        cd CRI_XCBC
-        git remote add upstream https://github.com/jprorama/CRI_XCBC.git
-        cd ..
+      if [ -n "${BUILT_BASE_IMAGE_ID}" ]; then
+        exit 0
+      fi
+    - *update_ansible_repo
+    - *get_ansible_files
+    - export REPO_HEAD=$(git rev-parse --short HEAD)
+    - export PKR_VAR_flavor="m1.medium"
+    - export PKR_VAR_build_instance_name="base-${REPO_HEAD}"
+    - export PKR_VAR_image_date_suffix=false
+    - |
+      if [ $CI_PIPELINE_SOURCE == 'merge_request_event' ]; then
+        export PKR_VAR_image_name="base-PR-${CI_MERGE_REQUEST_IID}"
+      elif [ $CI_PIPELINE_SOURCE == 'schedule' ]; then
+        export PKR_VAR_image_name="base-${BUILD_DATE}"
+      fi
+    - packer init openstack
+    - packer validate openstack
+    - packer build -machine-readable openstack | tee base_build.log
+    - export BUILT_BASE_IMAGE_ID=$(grep 'Image:' base_build.log | awk '{print $4}')
+    - echo BUILT_BASE_IMAGE_ID=${BUILT_BASE_IMAGE_ID} | tee -a $CI_PROJECT_DIR/image.env
+    - openstack image unset --property signature_verified $BUILT_BASE_IMAGE_ID
+  artifacts:
+    reports:
+      dotenv: image.env
+    expire_in: 30 days
+
+build_compute_image:
+  stage: build
+  needs: [build_base_image]
+  tags:
+    - build
+  script:
+    - *update_ansible_repo
+    - *get_ansible_files
+    - export PKR_VAR_source_image=${BUILT_BASE_IMAGE_ID}
+    - export REPO_HEAD=$(git rev-parse --short HEAD)
+    - export PKR_VAR_flavor="m1.medium"
+    - export PKR_VAR_build_instance_name="compute-${REPO_HEAD}"
+    - export PKR_VAR_image_date_suffix=false
+    - |
+      if [ $CI_PIPELINE_SOURCE == 'merge_request_event' ]; then
+        export PKR_VAR_image_name="compute-PR-${CI_MERGE_REQUEST_IID}"
+      elif [ $CI_PIPELINE_SOURCE == 'schedule' ]; then
+        export PKR_VAR_image_name="compute-${BUILD_DATE}"
       fi
-    - cd CRI_XCBC
-    - git config user.name "${GIT_AUTHOR_NAME}"
-    - git config user.email "${GIT_AUTHOR_EMAIL}"
-    - git fetch --all
-    - git fetch origin '+refs/pull/*/head:refs/remotes/origin/pr/*'
-    - git fetch upstream '+refs/pull/*/head:refs/remotes/upstream/pr/*'
-    - git checkout uab-prod
-    - git merge origin/uab-prod
-    - git checkout -b integration
-    - git merge upstream/dev
-    - export CRI_XCBC_HEAD=$(git rev-parse --short HEAD)
-    - export CRI_XCBC_dev=$(git rev-parse --short upstream/dev)
-    - export CRI_XCBC_prod=$(git rev-parse --short origin/uab-prod)
-    - cd ..
-    - export PACKER_IMAGE_HEAD=$(git rev-parse --short HEAD)
-    - export BUILD_DATE=$(TZ=America/Chicago date +%Y%m%d)
-    - echo CRI_XCBC_HEAD=${CRI_XCBC_HEAD} | tee -a $CI_PROJECT_DIR/image.env
-    - echo CRI_XCBC_dev=${CRI_XCBC_dev} | tee -a $CI_PROJECT_DIR/image.env
-    - echo CRI_XCBC_prod=${CRI_XCBC_prod} | tee -a $CI_PROJECT_DIR/image.env
-    - echo PACKER_IMAGE_HEAD=${PACKER_IMAGE_HEAD} | tee -a $CI_PROJECT_DIR/image.env
-    - echo BUILD_DATE=${BUILD_DATE} | tee -a $CI_PROJECT_DIR/image.env
+    - packer init openstack-compute
+    - packer validate openstack-compute
+    - packer build -machine-readable openstack-compute | tee compute_build.log
+
+build_gpu_image:
+  stage: build
+  needs: [build_base_image]
+  tags:
+    - build
+  script:
+    - *update_ansible_repo
+    - *get_ansible_files
+    - FAILED=false
+    - export GPU_PLACEHOLDER_NAME="gpu1-placeholder"
+    - export GPU_PLACEHOLDER_FLAVOR="gpu1.medium"
+    - export GPU_PLACEHOLDER_IMAGE="CentOS-7-x86_64-GenericCloud-2009"
+    - export PKR_VAR_source_image=${BUILT_BASE_IMAGE_ID}
+    - export REPO_HEAD=$(git rev-parse --short HEAD)
+    - export PKR_VAR_flavor="gpu1.medium"
+    - export PKR_VAR_build_instance_name="gpu-${REPO_HEAD}"
+    - export PKR_VAR_image_date_suffix=false
+    - |
+      if [ $CI_PIPELINE_SOURCE == 'merge_request_event' ]; then
+        export PKR_VAR_image_name="gpu-PR-${CI_MERGE_REQUEST_IID}"
+      elif [ $CI_PIPELINE_SOURCE == 'schedule' ]; then
+        export PKR_VAR_image_name="gpu-${BUILD_DATE}"
+      fi
+    - packer init openstack-gpu
+    - packer validate openstack-gpu
+    - openstack server delete --wait $GPU_PLACEHOLDER_NAME
+    - packer build -machine-readable openstack-gpu | tee gpu_build.log || FAILED=true
+    - openstack server create --image $GPU_PLACEHOLDER_IMAGE --network cicd-net --flavor $GPU_PLACEHOLDER_FLAVOR $GPU_PLACEHOLDER_NAME
+    - |
+      if [ "$FAILED" = true ]; then
+        exit 1
+      fi
+  rules:
+    - if: $SKIP_GPU_BUILD == "true"
+      when: never
+    - when: always
+
+build_ood_image:
+  stage: build
+  environment:
+    name: knightly
+  tags:
+    - build
+  script:
+    - *update_ansible_repo
+    - *get_ansible_files
     - >
       curl --header "PRIVATE-TOKEN: ${ANSIBLE_VAR_TOKEN}"
       "${CI_API_V4_URL}/projects/2836/repository/files/knightly/raw?ref=main"
       -o CRI_XCBC/group_vars/knightly
-    - s3cmd get --force -r --host=$AWS_HOST --host-bucket=$AWS_HOST s3://cheaha-cloud-ansible-files/ ansible/files/
     - 'sed -i -E "s/(lts_access_key: ).*/\1\"${AWS_ACCESS_KEY_ID}\"/" CRI_XCBC/group_vars/knightly'
     - 'sed -i -E "s/(lts_secret_key: ).*/\1\"${AWS_SECRET_ACCESS_KEY}\"/" CRI_XCBC/group_vars/knightly'
+    - 'sed -i -E "s/(user_register_app_key: ).*/\1\"${SELF_REG_APP_KEY}\"/" CRI_XCBC/group_vars/knightly'
+    - 'sed -i -E "s/(celery_user_password: ).*/\1\"${CELERY_PASSWD}\"/" CRI_XCBC/group_vars/knightly'
+    - 'sed -i -E "s|(ssh_pub_key: ).*|\1\"{{ lookup(''file'', ''${SSH_PUB_KEY}'') }}\"|" CRI_XCBC/group_vars/knightly'
+    - packer init openstack-ood
     - packer validate openstack-ood
     - |
       if [ $CI_PIPELINE_SOURCE == 'merge_request_event' ]; then
         export PKR_VAR_image_name="ood-PR-${CI_MERGE_REQUEST_IID}"
+        echo INSTANCE_FLAVOR="m1.small" | tee -a $CI_PROJECT_DIR/image.env
         echo OOD_INSTANCE_NAME="ood-PR-${CI_MERGE_REQUEST_IID}" | tee -a $CI_PROJECT_DIR/image.env
         export FLOATING_IP=$(openstack floating ip create uab-campus -f value -c floating_ip_address)
         echo FLOATING_IP=$FLOATING_IP | tee -a $CI_PROJECT_DIR/image.env
         sed -i -E "s/(ood_servername: ).*/\1\"$CI_COMMIT_REF_SLUG.$FLOATING_IP.nip.io\"/" CRI_XCBC/group_vars/knightly
       elif [ $CI_PIPELINE_SOURCE == 'schedule' ]; then
         export PKR_VAR_image_name="ood-${BUILD_DATE}"
+        echo INSTANCE_FLAVOR="cpu16-64g" | tee -a $CI_PROJECT_DIR/image.env
         echo OOD_INSTANCE_NAME="ood-knightly" | tee -a $CI_PROJECT_DIR/image.env
         echo FLOATING_IP=$TEST_IP | tee -a $CI_PROJECT_DIR/image.env
       fi
@@ -104,14 +236,21 @@ build_image:
     reports:
       dotenv: image.env
 
-test:
-  image: $CI_REGISTRY_IMAGE:latest
+test_ood_image:
   stage: test
+  needs: [build_ood_image]
   environment:
     name: knightly
   tags:
     - build
   script:
+    - FAILED=false
+    - |
+      eval $(ssh-agent -s)
+      chmod 400 "$SSH_PRIV_KEY"
+      ssh-add "$SSH_PRIV_KEY"
+      mkdir ~/.ssh
+      chmod 700 ~/.ssh
     - OLD_INSTANCE_IP=$(openstack floating ip list --floating-ip-address $CHEAHA_IP -c "Fixed IP Address" -f value)
     - echo $OLD_INSTANCE_IP
     - |
@@ -140,16 +279,31 @@ test:
       -c id -f value --image $BUILT_OOD_IMAGE_ID
       --network openstack-cheaha-internal
       --security-group ood-https-ports
+      --security-group node-exporter
       --security-group allow-ssh
       --user-data user_data.txt
-      --flavor m1.medium
+      --flavor $INSTANCE_FLAVOR
       --wait
       $OOD_INSTANCE_NAME)
     - echo NEW_INSTANCE_ID=$NEW_INSTANCE_ID | tee -a instance.env
     - openstack server add floating ip $NEW_INSTANCE_ID $FLOATING_IP
     - >
       curl --retry 10 --retry-delay 20 --retry-connrefused https://knightly.rc.uab.edu/Shibboleth.sso/Metadata --resolve knightly.rc.uab.edu:443:$FLOATING_IP -kf
-      || (openstack server delete $NEW_INSTANCE_ID && openstack image delete $BUILT_OOD_IMAGE_ID && false)
+      || FAILED=true
+    - |
+      if [ $CI_PIPELINE_SOURCE == 'merge_request_event' ]; then
+        ssh -o StrictHostKeyChecking=no acctsvc@$FLOATING_IP '[ $(mount | grep "type nfs" | wc -l) -eq 6 ]' || FAILED=true
+      elif [ $CI_PIPELINE_SOURCE == 'schedule' ]; then
+        cp "$SSH_KNOWN_HOSTS" ~/.ssh/known_hosts
+        chmod 644 ~/.ssh/known_hosts
+        ssh acctsvc@$FLOATING_IP '[ $(mount | grep "type nfs" | wc -l) -eq 6 ]' || FAILED=true
+      fi
+    - |
+      if [ "$FAILED" = true ]; then
+        openstack server delete $NEW_INSTANCE_ID
+        openstack image delete $BUILT_OOD_IMAGE_ID
+        false
+      fi
     - |
       if [ $CI_PIPELINE_SOURCE = "schedule" ]; then
         openstack server remove floating ip $NEW_INSTANCE_ID $FLOATING_IP
@@ -159,7 +313,6 @@ test:
       dotenv: instance.env
 
 deploy_review:
-  image: $CI_REGISTRY_IMAGE:latest
   stage: deploy
   script:
     - echo "Deploy Review App"
@@ -174,7 +327,6 @@ deploy_review:
     - if: $CI_MERGE_REQUEST_ID
 
 stop_review:
-  image: $CI_REGISTRY_IMAGE:latest
   stage: deploy
   script:
     - openstack server delete $NEW_INSTANCE_ID
@@ -190,7 +342,6 @@ stop_review:
       when: manual
 
 deploy_knightly:
-  image: $CI_REGISTRY_IMAGE:latest
   stage: deploy
   environment:
     name: knightly
@@ -209,7 +360,7 @@ deploy_knightly:
       fi
     - |
       SERVER_TO_BE_DELETE=($(openstack server list --name $OOD_INSTANCE_NAME --sort-column Image --sort-descending -f value -c ID | sed -n $(($NUM_SERVER_TO_KEEP+1))',$p'))
-      IMAGE_TO_BE_DELETE=($(openstack image list --sort-column Name --sort-descending -f value -c Name | grep -P '^ood-\d{8}$' | sed -n $(($NUM_IMAGE_TO_KEEP+1))',$p'))
+      IMAGE_TO_BE_DELETE=($(openstack image list --sort-column Name --sort-descending -f value -c Name -c ID | grep -P ' ood-\d{8}$' | sed -n $(($NUM_IMAGE_TO_KEEP+1))',$p' | awk '{print $1}'))
       for svr in ${SERVER_TO_BE_DELETE[@]}; do
         openstack server delete ${svr}
       done
@@ -230,4 +381,3 @@ deploy_cheaha:
   when: manual
   only:
     - main
-
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..1191b3097fb32450af99a960bc634563cd586c3e
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,26 @@
+FROM python:3.8-slim
+
+ENV S3CMD_VER=2.3.0
+ENV ANSIBLE_VER=4.10.0
+ENV OSC_VER=5.8.0
+ENV TF_VER=1.4.6
+ENV PACKER_VER=1.9.4
+
+RUN apt-get update && apt-get install --no-install-recommends -y \
+    git \
+    ssh \
+    curl \
+    wget \
+    unzip \
+ && rm -rf /var/lib/apt/lists/*
+RUN wget https://releases.hashicorp.com/packer/${PACKER_VER}/packer_${PACKER_VER}_linux_amd64.zip \
+    && unzip packer_${PACKER_VER}_linux_amd64.zip -d /usr/local/bin \
+    && rm packer_${PACKER_VER}_linux_amd64.zip
+RUN wget https://releases.hashicorp.com/terraform/${TF_VER}/terraform_${TF_VER}_linux_amd64.zip \
+    && unzip terraform_${TF_VER}_linux_amd64.zip -d /usr/local/bin \
+    && rm terraform_${TF_VER}_linux_amd64.zip
+RUN pip install --no-cache-dir --upgrade pip \
+ && pip install --no-cache-dir \
+    s3cmd==$S3CMD_VER \
+    ansible==$ANSIBLE_VER \
+    python-openstackclient==$OSC_VER
diff --git a/ansible/compute.yml b/ansible/compute.yml
index 4003b8f769c59c1947b4c4dfbb7a6dac7a8844ae..198454852c2e28cc47ea8661a45fce7fae6f44fb 100644
--- a/ansible/compute.yml
+++ b/ansible/compute.yml
@@ -5,7 +5,7 @@
   roles:
     - { name: 'install_packages', tags: 'install_packages' }
     - { name: 'pam_slurm_adopt', tags: 'pam_slurm_adopt' }
-    - { name: 'lmod_user', tags: 'lmod_user'}
+    - { name: 'install_nhc', tags: 'install_nhc'}
 
 - name: Setup node for use as a virtual cheaha node
   ansible.builtin.import_playbook: cheaha.yml
diff --git a/ansible/files/nux-dextop.repo b/ansible/files/nux-dextop.repo
index dd4a382e43ca145fa82e2fb3b0451ee785410726..1ee4ace274472d5ba82a769f1d0661e76bf8a4f4 100644
--- a/ansible/files/nux-dextop.repo
+++ b/ansible/files/nux-dextop.repo
@@ -1,6 +1,6 @@
 [nux-dextop]
 name=Nux.Ro RPMs for general desktop use
-baseurl=http://li.nux.ro/download/nux/dextop/el7/$basearch/ http://mirror.li.nux.ro/li.nux.ro/nux/dextop/el7/$basearch/
+baseurl=http://li.nux.ro/download/nux/dextop/el7/$basearch/
 enabled=1
 gpgcheck=1
 gpgkey=http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro
diff --git a/ansible/gpu.yml b/ansible/gpu.yml
index 5d032dce95f4741643cd86dcfa3783bdfdfa9213..b6ec44d471b8e7fb15e333fef66ce5210620b7c3 100644
--- a/ansible/gpu.yml
+++ b/ansible/gpu.yml
@@ -5,3 +5,8 @@
   roles:
     - { name: 'install_packages', tags: 'install_packages' }
     - { name: 'cuda_driver', tags: 'cuda_driver' }
+    - { name: 'pam_slurm_adopt', tags: 'pam_slurm_adopt' }
+    - { name: 'install_nhc', tags: 'install_nhc'}
+
+- name: Setup node for use as a virtual cheaha node
+  ansible.builtin.import_playbook: cheaha.yml
diff --git a/ansible/group_vars/all b/ansible/group_vars/all
index 665d5cdfccf013d3bc0ac080119ce3c6c56d6591..e55be3c6b5c2ad77a3195681900b9b84a6a25585 100644
--- a/ansible/group_vars/all
+++ b/ansible/group_vars/all
@@ -4,3 +4,9 @@
   yum_repo_files: []
   pkg_list: []
   slurm_version: 18.08.9
+  
+# NHC related
+  nhc_download_url: "https://github.com/mej/nhc/releases/download/1.4.3/lbnl-nhc-1.4.3-1.el7.noarch.rpm"
+  nhc_download_path: "/tmp"
+  nhc_git_repo: "https://gitlab.rc.uab.edu/rc/nhc.git"
+  nhc_git_repo_path: "/tmp/nhc"
diff --git a/ansible/group_vars/base b/ansible/group_vars/base
index 232c36d1debcc6dffa039fd7006f5d43f85519f5..71ce49998bcd7e633858dc53fdd49cc1fbe167ac 100644
--- a/ansible/group_vars/base
+++ b/ansible/group_vars/base
@@ -28,7 +28,6 @@
     - "OpenIPMI-libs"
     - "OpenIPMI-modalias"
     - "PackageKit-glib"
-    - "Red_Hat_Enterprise_Linux-Release_Notes-7-en-US"
     - "SDL"
     - "Thunar"
     - "abattis-cantarell-fonts"
@@ -75,7 +74,6 @@
     - "atkmm"
     - "atlas"
     - "atlas-devel"
-    - "atom"
     - "atril"
     - "atril-caja"
     - "atril-libs"
@@ -183,9 +181,6 @@
     - "cjkuni-uming-fonts"
     - "clucene-contribs-lib"
     - "clucene-core"
-    - "clusterkit"
-    - "clusterkit"
-    - "clusterkit"
     - "clutter"
     - "clutter-gst2"
     - "clutter-gst3"
@@ -277,7 +272,6 @@
     - "dracut-config-rescue"
     - "dracut-network"
     - "dstat"
-    - "dump_pr"
     - "dvd+rw-tools"
     - "dwz"
     - "dyninst"
@@ -399,7 +393,6 @@
     - "geoclue2"
     - "geoclue2-libs"
     - "geocode-glib"
-    - "geoipupdate"
     - "gettext"
     - "gettext-common-devel"
     - "gettext-devel"
@@ -471,16 +464,6 @@
     - "google-noto-emoji-fonts"
     - "gparted"
     - "gperftools-libs"
-    - "gpfs.base"
-    - "gpfs.callhome-ecc-client"
-    - "gpfs.docs"
-    - "gpfs.ext"
-    - "gpfs.gpl"
-    - "gpfs.gskit"
-    - "gpfs.gss.pmsensors"
-    - "gpfs.java"
-    - "gpfs.license.std"
-    - "gpfs.msg.en_US"
     - "gpgme"
     - "gpm-libs"
     - "graphite2"
@@ -590,7 +573,6 @@
     - "ibus-setup"
     - "ibus-table"
     - "ibus-table-chinese"
-    - "ibutils2"
     - "icedax"
     - "icedtea-web"
     - "ilmbase"
@@ -662,7 +644,6 @@
     - "keyutils-libs-devel"
     - "khmeros-base-fonts"
     - "khmeros-fonts-common"
-    - "knem"
     - "kpartx"
     - "kpatch"
     - "krb5-devel"
@@ -1301,7 +1282,6 @@
     - "mtools"
     - "mtr"
     - "mutter"
-    - "mxm"
     - "mythes"
     - "mythes-en"
     - "nano"
@@ -1375,7 +1355,6 @@
     - "opencore-amr"
     - "openjpeg-libs"
     - "openjpeg2"
-    - "openmpi"
     - "openscap"
     - "openscap-scanner"
     - "opensm"
@@ -1686,58 +1665,36 @@
     - "python-warlock"
     - "python-wrapt"
     - "python-yubico"
-    - "python2-adal"
     - "python2-asn1crypto"
-    - "python2-babel"
     - "python2-backports-functools_lru_cache"
     - "python2-blockdev"
     - "python2-boto"
     - "python2-certifi"
-    - "python2-chardet"
-    - "python2-cmd2"
-    - "python2-contextlib2"
     - "python2-crypto"
     - "python2-cryptography"
     - "python2-dateutil"
-    - "python2-extras"
     - "python2-futures"
-    - "python2-gunicorn"
     - "python2-idna"
     - "python2-iso8601"
     - "python2-jmespath"
     - "python2-jsonpatch"
-    - "python2-jsonpointer"
     - "python2-jsonschema"
-    - "python2-jwt"
-    - "python2-ldap"
-    - "python2-markupsafe"
     - "python2-mimeparse"
     - "python2-mock"
-    - "python2-monotonic"
     - "python2-msgpack"
-    - "python2-msrest"
-    - "python2-msrestazure"
-    - "python2-munch"
     - "python2-oauthlib"
     - "python2-olefile"
-    - "python2-os-service-types"
-    - "python2-pexpect"
-    - "python2-pillow"
     - "python2-pip"
     - "python2-ptyprocess"
     - "python2-pyasn1"
     - "python2-pyasn1-modules"
     - "python2-pyatspi"
-    - "python2-pyparsing"
-    - "python2-pyperclip"
     - "python2-pyxdg"
-    - "python2-requests"
     - "python2-rpm-macros"
     - "python2-rsa"
     - "python2-setuptools"
     - "python2-subprocess32"
     - "python2-traceback2"
-    - "python2-unittest2"
     - "python2-urllib3"
     - "python2-wcwidth"
     - "python3"
@@ -1758,9 +1715,6 @@
     - "pyusb"
     - "pyxattr"
     - "qemu-guest-agent"
-    - "qemu-img-ev"
-    - "qemu-kvm-common-ev"
-    - "qemu-kvm-ev"
     - "qpdf-libs"
     - "qrencode-libs"
     - "qt"
@@ -1798,7 +1752,6 @@
     - "redhat-lsb-submod-multimedia"
     - "redhat-lsb-submod-security"
     - "redhat-menus"
-    - "redhat-release-server"
     - "redhat-rpm-config"
     - "redhat-support-lib-python"
     - "redhat-support-tool"
@@ -1876,7 +1829,6 @@
     - "sgpio"
     - "shadow-utils"
     - "shared-mime-info"
-    - "sharp"
     - "shim-x64"
     - "sil-abyssinica-fonts"
     - "sil-nuosu-fonts"
@@ -2660,7 +2612,6 @@
     - "ttmkfdir"
     - "tumbler"
     - "tuned"
-    - "turbovnc"
     - "twolame-libs"
     - "tzdata"
     - "tzdata-java"
diff --git a/ansible/group_vars/compute b/ansible/group_vars/compute
index eb73c7f148b4642cb047a7491859cf1f96c1b23f..98bd90e5f3e59ec37ec1879b352357e19f2ea3de 100644
--- a/ansible/group_vars/compute
+++ b/ansible/group_vars/compute
@@ -3,7 +3,7 @@
     - TurboVNC.repo
     - cm.repo
   pkg_list:
-    - "Lmod"
+    - "Lmod-7.8.11"
     - "atftp-server"
     - "cluster-tools-dell"
     - "cluster-tools-slave"
@@ -36,7 +36,6 @@
     - "cm-libprometheus"
     - "cm-lua"
     - "cm-mariadb-libs"
-    - "cm-modules-init-client"
     - "cm-openssl"
     - "cm-python2"
     - "cm-python36"
@@ -47,7 +46,6 @@
     - "cmdaemon"
     - "cmdaemon-remotecm"
     - "confuse"
-    - "env-modules"
     - "gcc-recent"
     - "gdb-recent"
     - "lshw"
@@ -61,43 +59,22 @@
     - "net-snmp-recent"
     - "node-installer-slave"
     - "openvpn"
-    - "pbspro-ce-client"
-    - "pbspro-client"
     - "perl-Config-IniFiles"
-    - "python-azure-sdk"
     - "python-dogpile-cache"
     - "python-isodate"
     - "python-netaddr"
     - "python-netifaces"
-    - "python-oslo-i18n-lang"
-    - "python-oslo-utils-lang"
     - "python-setuptools_scm"
     - "python-testtools"
-    - "python-vcrpy"
     - "python-websockify"
-    - "python2-cffi"
-    - "python2-cinderclient"
     - "python2-cliff"
     - "python2-debtcollector"
     - "python2-deprecation"
     - "python2-fixtures"
     - "python2-funcsigs"
-    - "python2-glanceclient"
-    - "python2-heatclient"
     - "python2-ipaddress"
-    - "python2-keystoneauth1"
-    - "python2-keystoneclient"
-    - "python2-novaclient"
-    - "python2-openstacksdk"
-    - "python2-os-client-config"
-    - "python2-osc-lib"
-    - "python2-oslo-config"
-    - "python2-oslo-i18n"
-    - "python2-oslo-serialization"
-    - "python2-oslo-utils"
     - "python2-pbr"
     - "python2-positional"
-    - "python2-pyOpenSSL"
     - "python2-pysocks"
     - "python2-pyyaml"
     - "python2-requests-oauthlib"
@@ -105,10 +82,7 @@
     - "python2-rfc3986"
     - "python2-six"
     - "python2-stevedore"
-    - "python2-swiftclient"
     - "sdparm"
-    - "sge-client"
-    - "shorewall"
     - "sshpass"
     - "swig"
-    - "turbovnc"
+    - "turbovnc-2.2.6*"
diff --git a/ansible/group_vars/gpu b/ansible/group_vars/gpu
index ad9aa51ae61838f6d72e0ae061dda1c877bad851..cd65f8881469975d311684e50c50ee3bc5720b06 100644
--- a/ansible/group_vars/gpu
+++ b/ansible/group_vars/gpu
@@ -1,6 +1,91 @@
 ---
-  yum_repo_files: []
+  yum_repo_files:
+    - TurboVNC.repo
+    - cm.repo
   pkg_list:
+    - "Lmod-7.8.11"
+    - "atftp-server"
+    - "cluster-tools-dell"
+    - "cluster-tools-slave"
+    - "cm-boost"
+    - "cm-config-ceph-release-luminous"
+    - "cm-config-cm"
+    - "cm-config-dhclient"
+    - "cm-config-dracut-slave"
+    - "cm-config-grub"
+    - "cm-config-ldap-client"
+    - "cm-config-limits"
+    - "cm-config-man"
+    - "cm-config-named"
+    - "cm-config-network-slave"
+    - "cm-config-nfsclient"
+    - "cm-config-rootfiles-slave"
+    - "cm-config-selinux"
+    - "cm-config-ssh-slave"
+    - "cm-config-sysctl-slave"
+    - "cm-config-syslog-slave"
+    - "cm-config-systemd"
+    - "cm-config-xntp-slave"
+    - "cm-config-yum"
+    - "cm-curl"
+    - "cm-dhcp"
+    - "cm-freeipmi"
+    - "cm-ipmitool"
+    - "cm-ipxe-slave"
+    - "cm-libpam"
+    - "cm-libprometheus"
+    - "cm-lua"
+    - "cm-mariadb-libs"
+    - "cm-openssl"
+    - "cm-python2"
+    - "cm-python36"
+    - "cm-slave"
+    - "cm-uge-client"
+    - "cmburn"
+    - "cmburn-slave"
+    - "cmdaemon"
+    - "cmdaemon-remotecm"
+    - "confuse"
+    - "gcc-recent"
+    - "gdb-recent"
+    - "lshw"
+    - "lua-bit32"
+    - "lua-filesystem"
+    - "lua-json"
+    - "lua-lpeg"
+    - "lua-posix"
+    - "lua-term"
+    - "mysql++"
+    - "net-snmp-recent"
+    - "node-installer-slave"
+    - "openvpn"
+    - "perl-Config-IniFiles"
+    - "python-dogpile-cache"
+    - "python-isodate"
+    - "python-netaddr"
+    - "python-netifaces"
+    - "python-setuptools_scm"
+    - "python-testtools"
+    - "python-websockify"
+    - "python2-cliff"
+    - "python2-debtcollector"
+    - "python2-deprecation"
+    - "python2-fixtures"
+    - "python2-funcsigs"
+    - "python2-ipaddress"
+    - "python2-pbr"
+    - "python2-positional"
+    - "python2-pysocks"
+    - "python2-pyyaml"
+    - "python2-requests-oauthlib"
+    - "python2-requestsexceptions"
+    - "python2-rfc3986"
+    - "python2-six"
+    - "python2-stevedore"
+    - "sdparm"
+    - "sshpass"
+    - "swig"
+    - "turbovnc-2.2.6*"
     - "cuda-dcgm"
     - "cuda-dcgm-libs"
     - "cuda-dcgm-nvvs"
diff --git a/ansible/roles/cuda_driver/tasks/main.yml b/ansible/roles/cuda_driver/tasks/main.yml
index fde04c1edb6cfb0ddb825e352a0d0f9c63e98641..d411731c6593a8f550217ff15190f4aafd1288c9 100644
--- a/ansible/roles/cuda_driver/tasks/main.yml
+++ b/ansible/roles/cuda_driver/tasks/main.yml
@@ -16,11 +16,11 @@
       - cuda-dcgm.x86_64
       - cuda-dcgm-libs
       - cuda-dcgm-devel
-    state: present
+    state: latest
 
 - name: start cuda-driver service
   ansible.builtin.systemd:
-    name: cuda-driver
+    name: "{{ item }}"
     state: started
     enabled: yes
   loop:
diff --git a/ansible/roles/install_nhc/tasks/main.yml b/ansible/roles/install_nhc/tasks/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..4e9d90a60de3090bb58fcdf77a7f14b9ea8ff1be
--- /dev/null
+++ b/ansible/roles/install_nhc/tasks/main.yml
@@ -0,0 +1,28 @@
+---
+- name: Download the rpm
+  ansible.builtin.get_url:
+    url: "{{ nhc_download_url }}"
+    dest: "{{ nhc_download_path }}"
+
+- name: Clone the NHC config repo
+  ansible.builtin.git:
+    repo: "{{ nhc_git_repo }}"
+    dest: "{{ nhc_git_repo_path }}"
+
+- name: Install NHC
+  ansible.builtin.yum:
+    name: "{{ nhc_download_url }}"
+    state: latest
+
+- name: Copy config files
+  ansible.builtin.copy:
+    src: "{{ nhc_git_repo_path }}/{{ item.src }}" 
+    dest: "{{ item.dest }}"
+    owner: root
+    group: root
+    mode: '0644'
+    remote_src: true
+  loop:
+    - { src: 'nhc.conf' , dest: '/etc/nhc/' }
+    - { src: 'nhc.etc.sysconfig', dest: '/etc/sysconfig/nhc/' }
+
diff --git a/ansible/roles/lmod_user/tasks/main.yaml b/ansible/roles/lmod_user/tasks/main.yaml
deleted file mode 100644
index 825538ead9d8024b1256bb3dcf09255f9b804046..0000000000000000000000000000000000000000
--- a/ansible/roles/lmod_user/tasks/main.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
----
-- name: Setup rsyslog
-  template:
-    src: rsyslog.j2
-    dest: /etc/rsyslog.d/moduleTracking-client.conf
-
-- name: Restart rsyslog
-  service:
-    name: rsyslog
-    state: restarted
diff --git a/ansible/roles/lmod_user/templates/rsyslog.j2 b/ansible/roles/lmod_user/templates/rsyslog.j2
deleted file mode 100644
index 537711acbc8c253a11fe540cde9cdd7655620f34..0000000000000000000000000000000000000000
--- a/ansible/roles/lmod_user/templates/rsyslog.j2
+++ /dev/null
@@ -1,2 +0,0 @@
-if $programname contains 'ModuleUsageTracking' then @{{ lmod_db_host_machine }}
-&~
diff --git a/ansible/roles/pam_slurm_adopt/tasks/main.yml b/ansible/roles/pam_slurm_adopt/tasks/main.yml
index 4f027f2df5c96a8094dd3303660dc04c3ba88a9d..1493946c6a6746483093301aefbf227ece8f0076 100644
--- a/ansible/roles/pam_slurm_adopt/tasks/main.yml
+++ b/ansible/roles/pam_slurm_adopt/tasks/main.yml
@@ -1,4 +1,12 @@
 ---
+- name: Install slurm-client packages
+  ansible.builtin.yum:
+    name: "{{ item }}"
+    state: present
+  loop:
+    - munge
+    - "slurm-client-{{ slurm_version }}"
+
 # restrict user access to nodes
 - name: Get version and release for slurm-pam pkg
   shell: rpm -q --qf "%{VERSION}-%{RELEASE}\n" slurm-client
@@ -41,6 +49,6 @@
 - name: Update secure access config for the node
   lineinfile:
     dest: /etc/security/access.conf
-    line: "-:ALL EXCEPT root mhanby_ cmcclung_ (sysadmins) (atlab):ALL"
+    line: "-:ALL EXCEPT root mhanby_ cmcclung_ centos (sysadmins) (atlab):ALL"
     owner: root
     mode: 0644
diff --git a/openstack-compute/nodeimage.pkr.hcl b/openstack-compute/nodeimage.pkr.hcl
index e6f39d8a3e93dbb83f95e0f57e4ded5a08e32aed..15941bab1900a056d3d67bdba2db2bd5d94a31fb 100644
--- a/openstack-compute/nodeimage.pkr.hcl
+++ b/openstack-compute/nodeimage.pkr.hcl
@@ -1,42 +1,57 @@
+packer {
+  required_plugins {
+    openstack = {
+      version = "~> 1"
+      source  = "github.com/hashicorp/openstack"
+    }
+    ansible = {
+      version = "~> 1"
+      source  = "github.com/hashicorp/ansible"
+    }
+  }
+}
+
 locals {
-    local_image_name = "${var.image_name}${var.image_date_suffix ? formatdate("YYYYMMDDHHmm", timestamp()): ""}"
+  local_image_name = "${var.image_name}${var.image_date_suffix ? formatdate("YYYYMMDDHHmm", timestamp()) : ""}"
 }
 
 source "openstack" "image" {
-  skip_create_image = var.skip_create_image
-  image_name        = local.local_image_name
-  source_image_name = var.source_image
-  image_members     = var.image_membership
+  skip_create_image         = var.skip_create_image
+  image_name                = local.local_image_name
+  source_image              = var.source_image
+  image_members             = var.image_membership
   image_auto_accept_members = var.auto_accept_members
-  image_tags        = var.image_tags
-  flavor            = var.flavor
-  instance_name     = var.build_instance_name
-
-  floating_ip_network = var.floating_ip_network
-  networks = var.networks
-  security_groups = var.security_groups
-
-  ssh_username = var.ssh_username
+  image_tags                = var.image_tags
+  image_disk_format         = var.image_format
+  volume_size               = var.volume_size
+  flavor                    = var.flavor
+  instance_name             = var.build_instance_name
+  use_blockstorage_volume   = true
+  floating_ip_network       = var.floating_ip_network
+  networks                  = var.networks
+  security_groups           = var.security_groups
+  ssh_username              = var.ssh_username
 }
 
 build {
   sources = ["source.openstack.image"]
 
   provisioner "ansible" {
-    groups = ["compute"]
+    use_proxy     = false
+    user          = var.ssh_username
+    groups        = ["compute"]
     playbook_file = "./ansible/compute.yml"
-    roles_path = "./ansible/roles"
+    roles_path    = "./ansible/roles"
     extra_arguments = [
       "--extra-vars", "root_ssh_key='${var.root_ssh_key}'"
     ]
   }
+
   provisioner "ansible" {
-    use_proxy =  false
+    use_proxy        = false
+    user             = var.ssh_username
+    groups           = ["compute"]
     ansible_env_vars = ["ANSIBLE_HOST_KEY_CHECKING=False"]
-    playbook_file = "../CRI_XCBC/ood-packer.yaml"
-    extra_arguments = [
-      "-t enable_lmod",
-      "-t lmod_user",
-    ]
+    playbook_file    = "./CRI_XCBC/compute-packer.yaml"
   }
 }
diff --git a/openstack-compute/variables.pkr.hcl b/openstack-compute/variables.pkr.hcl
index 09827195aba2322d506e5a2b57e1f16092e4738b..20efd641406f81250b3cb1cc6514f5078ee2a503 100644
--- a/openstack-compute/variables.pkr.hcl
+++ b/openstack-compute/variables.pkr.hcl
@@ -1,5 +1,5 @@
 variable "root_ssh_key" {
-  type = string
+  type        = string
   description = "The root key to use for ssh"
 }
 
@@ -9,6 +9,12 @@ variable "image_name" {
   description = "Name of the image in openstack"
 }
 
+variable "image_format" {
+  type        = string
+  default     = "qcow2"
+  description = "The format of the resulting image"
+}
+
 variable "image_date_suffix" {
   type        = bool
   default     = false
@@ -34,8 +40,8 @@ variable "auto_accept_members" {
 }
 
 variable "skip_create_image" {
-  type = bool
-  default = false
+  type        = bool
+  default     = false
   description = "A boolean value for skipping image creation at the end of the build"
 }
 
@@ -50,29 +56,35 @@ variable "flavor" {
 }
 
 variable "floating_ip_network" {
-  type = string
+  type        = string
   description = "floating ip network to use with (temporary) ip assignmnet to a vm"
 }
 
 variable "networks" {
-  type = list(string)
+  type        = list(string)
   description = "List of network UUIDs to assign to the network"
 }
 
 variable "security_groups" {
-  type = list(string)
-  default = []
+  type        = list(string)
+  default     = []
   description = "A list of security groups to add - you should make sure ssh access is open to the machine"
 }
 
 variable "build_instance_name" {
-  type = string
-  default = "compute"
+  type        = string
+  default     = "compute"
   description = "A name of build instance used for image build"
 }
 
 variable "ssh_username" {
-  type = string
-  default = "centos"
+  type        = string
+  default     = "centos"
   description = "The default username to use for SSH"
 }
+
+variable "volume_size" {
+  type        = number
+  default     = 20
+  description = "The default volume size for building iamge"
+}
\ No newline at end of file
diff --git a/openstack-gpu/nodeimage.pkr.hcl b/openstack-gpu/nodeimage.pkr.hcl
index 02720c2d434a2c6a70a79deae9fb37716869c171..0f375e1bc9399aa6291c55e076cffe3d06abf3e6 100644
--- a/openstack-gpu/nodeimage.pkr.hcl
+++ b/openstack-gpu/nodeimage.pkr.hcl
@@ -1,29 +1,57 @@
+packer {
+  required_plugins {
+    openstack = {
+      version = "~> 1"
+      source  = "github.com/hashicorp/openstack"
+    }
+    ansible = {
+      version = "~> 1"
+      source  = "github.com/hashicorp/ansible"
+    }
+  }
+}
+
 locals {
-    local_image_name = "${var.image_name}${var.image_date_suffix ? formatdate("YYYYMMDDHHmm", timestamp()): ""}"
+  local_image_name = "${var.image_name}${var.image_date_suffix ? formatdate("YYYYMMDDHHmm", timestamp()) : ""}"
 }
 
 source "openstack" "image" {
-  image_name        = local.local_image_name
-  source_image_name = var.source_image
-  flavor            = var.flavor
-
-  floating_ip_network = var.floating_ip_network
-  networks = var.networks
-  security_groups = var.security_groups
-
-  ssh_username = var.ssh_username
+  skip_create_image         = var.skip_create_image
+  image_name                = local.local_image_name
+  source_image              = var.source_image
+  image_members             = var.image_membership
+  image_auto_accept_members = var.auto_accept_members
+  image_tags                = var.image_tags
+  image_disk_format         = var.image_format
+  volume_size               = var.volume_size
+  flavor                    = var.flavor
+  instance_name             = var.build_instance_name
+  use_blockstorage_volume   = true
+  floating_ip_network       = var.floating_ip_network
+  networks                  = var.networks
+  security_groups           = var.security_groups
+  ssh_username              = var.ssh_username
 }
 
-# regular instance
 build {
   sources = ["source.openstack.image"]
 
   provisioner "ansible" {
-    groups = ["gpu"]
+    use_proxy     = false
+    user          = var.ssh_username
+    groups        = ["gpu"]
     playbook_file = "./ansible/gpu.yml"
-    roles_path = "./ansible/roles"
+    roles_path    = "./ansible/roles"
     extra_arguments = [
       "--extra-vars", "root_ssh_key='${var.root_ssh_key}'"
     ]
   }
+
+  provisioner "ansible" {
+    use_proxy        = false
+    user             = var.ssh_username
+    groups           = ["compute"]
+    ansible_env_vars = ["ANSIBLE_HOST_KEY_CHECKING=False"]
+    playbook_file    = "./CRI_XCBC/compute-packer.yaml"
+  }
 }
diff --git a/openstack-gpu/variables.pkr.hcl b/openstack-gpu/variables.pkr.hcl
index 322fb9d56469aee86ae656d3bd82b9b2a081be68..f9614ecdb65bdba8a200cc7de56393c89b25599e 100644
--- a/openstack-gpu/variables.pkr.hcl
+++ b/openstack-gpu/variables.pkr.hcl
@@ -1,20 +1,50 @@
 variable "root_ssh_key" {
-  type = string
+  type        = string
   description = "The root key to use for ssh"
 }
 
 variable "image_name" {
   type        = string
-  default     = "cluster-image-gpu"
+  default     = "cluster-image"
   description = "Name of the image in openstack"
 }
 
+variable "image_format" {
+  type        = string
+  default     = "qcow2"
+  description = "The format of the resulting image"
+}
+
 variable "image_date_suffix" {
   type        = bool
   default     = false
   description = "Append a date to the image name (in YYYYMMDDHHMMSS format)"
 }
 
+variable "image_tags" {
+  type        = list(string)
+  default     = []
+  description = "List of tags to be associated to the resulting image"
+}
+
+variable "image_membership" {
+  type        = list(string)
+  default     = []
+  description = "Projects/tenants to share the image in openstack with"
+}
+
+variable "auto_accept_members" {
+  type        = bool
+  default     = false
+  description = "A boolean value for auto accepting image in the projects/tenants defined in image_membership."
+}
+
+variable "skip_create_image" {
+  type        = bool
+  default     = false
+  description = "A boolean value for skipping image creation at the end of the build"
+}
+
 variable "source_image" {
   type        = string
   description = "The name of the source image to use"
@@ -25,24 +55,36 @@ variable "flavor" {
   description = "The name of the flavor to use"
 }
 
-variable "ssh_username" {
-  type = string
-  default = "centos"
-  description = "The default username to use for SSH"
-}
-
 variable "floating_ip_network" {
-  type = string
+  type        = string
   description = "floating ip network to use with (temporary) ip assignmnet to a vm"
 }
 
 variable "networks" {
-  type = list(string)
+  type        = list(string)
   description = "List of network UUIDs to assign to the network"
 }
 
 variable "security_groups" {
-  type = list(string)
-  default = []
+  type        = list(string)
+  default     = []
   description = "A list of security groups to add - you should make sure ssh access is open to the machine"
 }
+
+variable "build_instance_name" {
+  type        = string
+  default     = "gpu"
+  description = "A name of build instance used for image build"
+}
+
+variable "ssh_username" {
+  type        = string
+  default     = "centos"
+  description = "The default username to use for SSH"
+}
+
+variable "volume_size" {
+  type        = number
+  default     = 20
+  description = "The default volume size for building iamge"
+}
\ No newline at end of file
diff --git a/openstack-ood/nodeimage.pkr.hcl b/openstack-ood/nodeimage.pkr.hcl
index 6f637593e1b66e948e92c10cc1e3bb6fbf92eabd..b31d7a1724bada0b8dbe1002b026d11571c294de 100644
--- a/openstack-ood/nodeimage.pkr.hcl
+++ b/openstack-ood/nodeimage.pkr.hcl
@@ -1,40 +1,57 @@
+packer {
+  required_plugins {
+    openstack = {
+      version = "~> 1"
+      source  = "github.com/hashicorp/openstack"
+    }
+    ansible = {
+      version = "~> 1"
+      source  = "github.com/hashicorp/ansible"
+    }
+  }
+}
+
 locals {
-    local_image_name = "${var.image_name}${var.image_date_suffix ? formatdate("-YYYYMMDDHHmm", timestamp()): ""}"
+  local_image_name = "${var.image_name}${var.image_date_suffix ? formatdate("-YYYYMMDDHHmm", timestamp()) : ""}"
 }
 
 source "openstack" "image" {
-  skip_create_image = var.skip_create_image
-  image_name        = local.local_image_name
-  source_image_name = var.source_image
-  image_members     = var.image_membership
+  skip_create_image         = var.skip_create_image
+  image_name                = local.local_image_name
+  source_image              = var.source_image
+  image_members             = var.image_membership
   image_auto_accept_members = var.auto_accept_members
-  image_tags        = var.image_tags
-  flavor            = var.flavor
-  instance_name     = var.build_instance_name
-
-  floating_ip_network = var.floating_ip_network
-  networks = var.networks
-  security_groups = var.security_groups
-
-  ssh_username = var.ssh_username
+  image_tags                = var.image_tags
+  image_disk_format         = var.image_format
+  volume_size               = var.volume_size
+  flavor                    = var.flavor
+  instance_name             = var.build_instance_name
+  use_blockstorage_volume   = true
+  floating_ip_network       = var.floating_ip_network
+  networks                  = var.networks
+  security_groups           = var.security_groups
+  ssh_username              = var.ssh_username
 }
 
 build {
   sources = ["source.openstack.image"]
 
   provisioner "ansible" {
-    user = var.ssh_username
-    groups = ["ood"]
+    use_proxy     = false
+    user          = var.ssh_username
+    groups        = ["ood"]
     playbook_file = "./ansible/ood.yml"
-    roles_path = "./ansible/roles"
+    roles_path    = "./ansible/roles"
     extra_arguments = [
       "--extra-vars", "root_ssh_key='${var.root_ssh_key}'"
     ]
   }
+
   provisioner "ansible" {
-    user = var.ssh_username
-    groups = ["ood", "knightly"]
+    use_proxy        = false
+    user             = var.ssh_username
+    groups           = ["ood", "knightly"]
     ansible_env_vars = ["ANSIBLE_HOST_KEY_CHECKING=False"]
-    playbook_file = "./CRI_XCBC/ood-packer.yaml"
+    playbook_file    = "./CRI_XCBC/ood-packer.yaml"
   }
 }
diff --git a/openstack-ood/variables.pkr.hcl b/openstack-ood/variables.pkr.hcl
index 5082805e08faa68325e6cd7b5ec18bb89467c623..5a6f608cc01a4134e3d276f4a0960e4d2c530f4c 100644
--- a/openstack-ood/variables.pkr.hcl
+++ b/openstack-ood/variables.pkr.hcl
@@ -1,5 +1,5 @@
 variable "root_ssh_key" {
-  type = string
+  type        = string
   description = "The root key to use for ssh"
 }
 
@@ -9,6 +9,12 @@ variable "image_name" {
   description = "Name of the image in openstack"
 }
 
+variable "image_format" {
+  type        = string
+  default     = "qcow2"
+  description = "The format of the resulting image"
+}
+
 variable "image_date_suffix" {
   type        = bool
   default     = false
@@ -34,8 +40,8 @@ variable "auto_accept_members" {
 }
 
 variable "skip_create_image" {
-  type = bool
-  default = false
+  type        = bool
+  default     = false
   description = "A boolean value for skipping image creation at the end of the build"
 }
 
@@ -50,29 +56,35 @@ variable "flavor" {
 }
 
 variable "floating_ip_network" {
-  type = string
+  type        = string
   description = "floating ip network to use with (temporary) ip assignmnet to a vm"
 }
 
 variable "networks" {
-  type = list(string)
+  type        = list(string)
   description = "List of network UUIDs to assign to the network"
 }
 
 variable "security_groups" {
-  type = list(string)
-  default = []
+  type        = list(string)
+  default     = []
   description = "A list of security groups to add - you should make sure ssh access is open to the machine"
 }
 
 variable "build_instance_name" {
-  type = string
-  default = "ood"
+  type        = string
+  default     = "ood"
   description = "A name of build instance used for image build"
 }
 
 variable "ssh_username" {
-  type = string
-  default = "centos"
+  type        = string
+  default     = "centos"
   description = "The default username to use for SSH"
 }
+
+variable "volume_size" {
+  type        = number
+  default     = 20
+  description = "The default volume size for building iamge"
+}
\ No newline at end of file
diff --git a/openstack/nodeimage.pkr.hcl b/openstack/nodeimage.pkr.hcl
index 509ae3cde0684fd1a02a913ae760d8ae737c419e..e9666e9fd68065396c631cce139e91c30b2cc213 100644
--- a/openstack/nodeimage.pkr.hcl
+++ b/openstack/nodeimage.pkr.hcl
@@ -1,34 +1,57 @@
+packer {
+  required_plugins {
+    openstack = {
+      version = "~> 1"
+      source  = "github.com/hashicorp/openstack"
+    }
+    ansible = {
+      version = "~> 1"
+      source  = "github.com/hashicorp/ansible"
+    }
+  }
+}
+
 locals {
-    local_image_name = "${var.image_name}${var.image_date_suffix ? formatdate("-YYYYMMDDHHmm", timestamp()): ""}"
+  local_image_name = "${var.image_name}${var.image_date_suffix ? formatdate("-YYYYMMDDHHmm", timestamp()) : ""}"
 }
 
 source "openstack" "image" {
-  skip_create_image = var.skip_create_image
-  image_name        = local.local_image_name
-  source_image_name = var.source_image
-  image_members     = var.image_membership
+  skip_create_image         = var.skip_create_image
+  image_name                = local.local_image_name
+  source_image              = var.source_image
+  image_members             = var.image_membership
   image_auto_accept_members = var.auto_accept_members
-  image_tags        = var.image_tags
-  flavor            = var.flavor
-  instance_name     = var.build_instance_name
-
-  floating_ip_network = var.floating_ip_network
-  networks = var.networks
-  security_groups = var.security_groups
-
-  ssh_username = var.ssh_username
+  image_tags                = var.image_tags
+  image_disk_format         = var.image_format
+  volume_size               = var.volume_size
+  flavor                    = var.flavor
+  instance_name             = var.build_instance_name
+  use_blockstorage_volume   = true
+  floating_ip_network       = var.floating_ip_network
+  networks                  = var.networks
+  security_groups           = var.security_groups
+  ssh_username              = var.ssh_username
 }
 
 build {
   sources = ["source.openstack.image"]
 
   provisioner "ansible" {
-    user = var.ssh_username
-    groups = ["base"]
+    use_proxy     = false
+    user          = var.ssh_username
+    groups        = ["base"]
     playbook_file = "./ansible/base.yml"
-    roles_path = "./ansible/roles"
+    roles_path    = "./ansible/roles"
     extra_arguments = [
       "--extra-vars", "root_ssh_key='${var.root_ssh_key}'"
     ]
   }
+
+  provisioner "ansible" {
+    use_proxy        = false
+    user             = var.ssh_username
+    groups           = ["base"]
+    ansible_env_vars = ["ANSIBLE_HOST_KEY_CHECKING=False"]
+    playbook_file    = "./CRI_XCBC/compute-packer.yaml"
+  }
 }
diff --git a/openstack/variables.pkr.hcl b/openstack/variables.pkr.hcl
index 09827195aba2322d506e5a2b57e1f16092e4738b..ba10499de0da596228dec6fc7f229880eccee33f 100644
--- a/openstack/variables.pkr.hcl
+++ b/openstack/variables.pkr.hcl
@@ -1,5 +1,5 @@
 variable "root_ssh_key" {
-  type = string
+  type        = string
   description = "The root key to use for ssh"
 }
 
@@ -9,6 +9,12 @@ variable "image_name" {
   description = "Name of the image in openstack"
 }
 
+variable "image_format" {
+  type        = string
+  default     = "qcow2"
+  description = "The format of the resulting image"
+}
+
 variable "image_date_suffix" {
   type        = bool
   default     = false
@@ -34,8 +40,8 @@ variable "auto_accept_members" {
 }
 
 variable "skip_create_image" {
-  type = bool
-  default = false
+  type        = bool
+  default     = false
   description = "A boolean value for skipping image creation at the end of the build"
 }
 
@@ -50,29 +56,35 @@ variable "flavor" {
 }
 
 variable "floating_ip_network" {
-  type = string
+  type        = string
   description = "floating ip network to use with (temporary) ip assignmnet to a vm"
 }
 
 variable "networks" {
-  type = list(string)
+  type        = list(string)
   description = "List of network UUIDs to assign to the network"
 }
 
 variable "security_groups" {
-  type = list(string)
-  default = []
+  type        = list(string)
+  default     = []
   description = "A list of security groups to add - you should make sure ssh access is open to the machine"
 }
 
 variable "build_instance_name" {
-  type = string
-  default = "compute"
+  type        = string
+  default     = "base"
   description = "A name of build instance used for image build"
 }
 
 variable "ssh_username" {
-  type = string
-  default = "centos"
+  type        = string
+  default     = "centos"
   description = "The default username to use for SSH"
 }
+
+variable "volume_size" {
+  type        = number
+  default     = 20
+  description = "The default volume size for building iamge"
+}
\ No newline at end of file