diff --git a/contrib/network-storage/heketi/roles/provision/tasks/bootstrap.yml b/contrib/network-storage/heketi/roles/provision/tasks/bootstrap.yml
index 788f01f4b6bfad654c41d583481f26b879ffa015..572913a63e0df630c42d1b0966d27d21da9090cf 100644
--- a/contrib/network-storage/heketi/roles/provision/tasks/bootstrap.yml
+++ b/contrib/network-storage/heketi/roles/provision/tasks/bootstrap.yml
@@ -32,13 +32,16 @@
 - name: "Prepare heketi volumes."
   include_tasks: "bootstrap/volumes.yml"
 
+# Remove bootstrap heketi
+- name: "Tear down bootstrap."
+  include_tasks: "bootstrap/tear-down.yml"
+
 # Prepare heketi storage
 - name: "Test heketi storage."
   command: "{{ bin_dir }}/kubectl get secrets,endpoints,services,jobs --output=json"
   changed_when: false
   register: "heketi_storage_state"
-- command: "{{ bin_dir }}/kubectl get secrets,endpoints,services,jobs --output=json"
-  register: "job"
+# ensure endpoints actually exist before trying to move database data to it
 - name: "Create heketi storage."
   include_tasks: "bootstrap/storage.yml"
   vars:
@@ -51,7 +54,3 @@
     - "heketi_storage_state.stdout|from_json|json_query(endpoints_query)|length == 0"
     - "heketi_storage_state.stdout|from_json|json_query(service_query)|length == 0"
     - "heketi_storage_state.stdout|from_json|json_query(job_query)|length == 0"
-
-# Remove bootstrap heketi
-- name: "Tear down bootstrap."
-  include_tasks: "bootstrap/tear-down.yml"
diff --git a/contrib/network-storage/heketi/roles/provision/tasks/bootstrap/deploy.yml b/contrib/network-storage/heketi/roles/provision/tasks/bootstrap/deploy.yml
index 3580707d524f43c48bc4c9c2443dcbf6d4e946e2..3037d8b77ca10ea9041a66faf6c3366cebb29998 100644
--- a/contrib/network-storage/heketi/roles/provision/tasks/bootstrap/deploy.yml
+++ b/contrib/network-storage/heketi/roles/provision/tasks/bootstrap/deploy.yml
@@ -6,6 +6,7 @@
 - name: "Kubernetes Apps | Install and configure Heketi Bootstrap"
   kube:
     name: "GlusterFS"
+    kubectl: "{{bin_dir}}/kubectl"
     filename: "{{ kube_config_dir }}/heketi-bootstrap.json"
     state: "{{ rendering.changed | ternary('latest', 'present') }}"
 - name: "Wait for heketi bootstrap to complete."
diff --git a/contrib/network-storage/heketi/roles/provision/tasks/bootstrap/storage.yml b/contrib/network-storage/heketi/roles/provision/tasks/bootstrap/storage.yml
index 1daa72ac17588cf0cd4070770432c0b5a0eeea81..ff32ef201698381488bf8d5d27f70552d31bdd9c 100644
--- a/contrib/network-storage/heketi/roles/provision/tasks/bootstrap/storage.yml
+++ b/contrib/network-storage/heketi/roles/provision/tasks/bootstrap/storage.yml
@@ -6,7 +6,8 @@
 - name: "Create heketi storage."
   kube:
     name: "GlusterFS"
-    filename: "{{ kube_config_dir }}/heketi-storage.json"
+    kubectl: "{{bin_dir}}/kubectl"
+    filename: "{{ kube_config_dir }}/heketi-storage-bootstrap.json"
     state: "present"
   vars:
     secret_query: "items[?metadata.name=='heketi-storage-secret' && kind=='Secret']"
@@ -19,21 +20,23 @@
     - "heketi_storage_state.stdout|from_json|json_query(service_query)|length == 0"
     - "heketi_storage_state.stdout|from_json|json_query(job_query)|length == 0"
   register: "heketi_storage_result"
-
-- name: "Get state of heketi storage service, endpoint, secret and job."
-  command: "{{ bin_dir }}/kubectl get secrets,endpoints,services,jobs --output=json"
+- name: "Get state of heketi database copy job."
+  command: "{{ bin_dir }}/kubectl get jobs --output=json"
   changed_when: false
   register: "heketi_storage_state"
   vars:
     heketi_storage_state: { stdout: "{}" }
-    secret_query: "items[?metadata.name=='heketi-storage-secret' && kind=='Secret']"
-    endpoints_query: "items[?metadata.name=='heketi-storage-endpoints' && kind=='Endpoints']"
-    service_query: "items[?metadata.name=='heketi-storage-endpoints' && kind=='Service']"
     job_query: "items[?metadata.name=='heketi-storage-copy-job' && kind=='Job' && status.succeeded==1]"
   until:
-    - "heketi_storage_state.stdout|from_json|json_query(secret_query)|length == 1"
-    - "heketi_storage_state.stdout|from_json|json_query(endpoints_query)|length == 1"
-    - "heketi_storage_state.stdout|from_json|json_query(service_query)|length > 0"
     - "heketi_storage_state.stdout|from_json|json_query(job_query)|length == 1"
   retries: 60
   delay: 5
+- become: true
+  template: { src: "heketi-storage-test.json.j2", dest: "{{ kube_config_dir }}/heketi-storage-test.json" }
+  register: "rendering"
+- kube:
+    name: "GlusterFS"
+    kubectl: "{{bin_dir}}/kubectl"
+    filename: "{{ kube_config_dir }}/heketi-storage-test.json"
+    state: "{{ rendering.changed | ternary('latest', 'present') }}"
+  register: "state"
diff --git a/contrib/network-storage/heketi/roles/provision/tasks/bootstrap/topology.yml b/contrib/network-storage/heketi/roles/provision/tasks/bootstrap/topology.yml
index 31d1d48cb1ecad0d802e983f795cdf7d23e7c8e0..7d2c5981e7ef4a3a49c940740e7392910615836a 100644
--- a/contrib/network-storage/heketi/roles/provision/tasks/bootstrap/topology.yml
+++ b/contrib/network-storage/heketi/roles/provision/tasks/bootstrap/topology.yml
@@ -1,20 +1,24 @@
 ---
 - name: "Get heketi topology."
+  changed_when: false
   register: "heketi_topology"
   command: "{{ bin_dir }}/kubectl exec {{ initial_heketi_pod_name }} -- heketi-cli --user admin --secret {{ heketi_admin_key }} topology info --json"
 - name: "Render heketi topology template."
   become: true
   vars: { nodes: "{{ groups['heketi-node'] }}" }
+  register: "render"
   template:
     src: "topology.json.j2"
     dest: "{{ kube_config_dir }}/topology.json"
 - name: "Copy topology configuration into container."
+  changed_when: false
   command: "{{ bin_dir }}/kubectl cp {{ kube_config_dir }}/topology.json {{ initial_heketi_pod_name }}:/tmp/topology.json"
 - name: "Load heketi topology."
-  when: "heketi_topology.stdout|from_json|json_query(\"clusters[*].nodes[*]\")|flatten|length == 0"
+  when: "render.changed"
   command: "{{ bin_dir }}/kubectl exec {{ initial_heketi_pod_name }} -- heketi-cli --user admin --secret {{ heketi_admin_key }} topology load --json=/tmp/topology.json"
   register: "load_heketi"
 - name: "Get heketi topology."
+  changed_when: false
   register: "heketi_topology"
   command: "{{ bin_dir }}/kubectl exec {{ initial_heketi_pod_name }} -- heketi-cli --user admin --secret {{ heketi_admin_key }} topology info --json"
   until: "heketi_topology.stdout|from_json|json_query(\"clusters[*].nodes[*].devices[?state=='online'].id\")|flatten|length == groups['heketi-node']|length"
diff --git a/contrib/network-storage/heketi/roles/provision/tasks/bootstrap/volumes.yml b/contrib/network-storage/heketi/roles/provision/tasks/bootstrap/volumes.yml
index bb088173e6cbe05d3895bf74f88bbd4c931ca84d..d5da1a12588602b4818a822e1644ef357b2f0567 100644
--- a/contrib/network-storage/heketi/roles/provision/tasks/bootstrap/volumes.yml
+++ b/contrib/network-storage/heketi/roles/provision/tasks/bootstrap/volumes.yml
@@ -20,7 +20,7 @@
   when: "heketi_database_volume_exists is undefined"
 - name: "Copy configuration from pod."
   become: true
-  command: "{{ bin_dir }}/kubectl cp {{ initial_heketi_pod_name }}:/heketi-storage.json {{ kube_config_dir }}/heketi-storage.json"
+  command: "{{ bin_dir }}/kubectl cp {{ initial_heketi_pod_name }}:/heketi-storage.json {{ kube_config_dir }}/heketi-storage-bootstrap.json"
 - name: "Get heketi volume ids."
   command: "{{ bin_dir }}/kubectl exec {{ initial_heketi_pod_name }} -- heketi-cli --user admin --secret {{ heketi_admin_key }} volume list --json"
   changed_when: false
diff --git a/contrib/network-storage/heketi/roles/provision/tasks/glusterfs.yml b/contrib/network-storage/heketi/roles/provision/tasks/glusterfs.yml
index e9650276a310697facfc87604c9411b9e7a576a6..e461599693777aa493103a1552a055ba82931c55 100644
--- a/contrib/network-storage/heketi/roles/provision/tasks/glusterfs.yml
+++ b/contrib/network-storage/heketi/roles/provision/tasks/glusterfs.yml
@@ -6,8 +6,14 @@
 - name: "Kubernetes Apps | Install and configure GlusterFS daemonset"
   kube:
     name: "GlusterFS"
+    kubectl: "{{bin_dir}}/kubectl"
     filename: "{{ kube_config_dir }}/glusterfs-daemonset.json"
     state: "{{ rendering.changed | ternary('latest', 'present') }}"
+- name: "Kubernetes Apps | Label GlusterFS nodes"
+  include_tasks: "glusterfs/label.yml"
+  with_items: "{{ groups['heketi-node'] }}"
+  loop_control:
+    loop_var: "node"
 - name: "Kubernetes Apps | Wait for daemonset to become available."
   register: "daemonset_state"
   command: "{{ bin_dir }}/kubectl get daemonset glusterfs --output=json --ignore-not-found=true"
@@ -16,16 +22,10 @@
     daemonset_state: { stdout: "{}" }
     ready: "{{ daemonset_state.stdout|from_json|json_query(\"status.numberReady\") }}"
     desired: "{{ daemonset_state.stdout|from_json|json_query(\"status.desiredNumberScheduled\") }}"
-  until: "ready == desired"
+  until: "ready >= 3"
   retries: 60
   delay: 5
 
-- name: "Kubernetes Apps | Label GlusterFS nodes"
-  include_tasks: "glusterfs/label.yml"
-  with_items: "{{ groups['heketi-node'] }}"
-  loop_control:
-    loop_var: "node"
-
 - name: "Kubernetes Apps | Lay Down Heketi Service Account"
   template: { src: "heketi-service-account.json.j2", dest: "{{ kube_config_dir }}/heketi-service-account.json" }
   become: true
@@ -33,5 +33,6 @@
 - name: "Kubernetes Apps | Install and configure Heketi Service Account"
   kube:
     name: "GlusterFS"
+    kubectl: "{{bin_dir}}/kubectl"
     filename: "{{ kube_config_dir }}/heketi-service-account.json"
     state: "{{ rendering.changed | ternary('latest', 'present') }}"
diff --git a/contrib/network-storage/heketi/roles/provision/tasks/heketi.yml b/contrib/network-storage/heketi/roles/provision/tasks/heketi.yml
index 44016df5e635cf652771f92c7bf5c7cd6249c002..029baef947bb25e34855f80c8bf9d3e37b480374 100644
--- a/contrib/network-storage/heketi/roles/provision/tasks/heketi.yml
+++ b/contrib/network-storage/heketi/roles/provision/tasks/heketi.yml
@@ -6,6 +6,7 @@
 - name: "Kubernetes Apps | Install and configure Heketi"
   kube:
     name: "GlusterFS"
+    kubectl: "{{bin_dir}}/kubectl"
     filename: "{{ kube_config_dir }}/heketi-deployment.json"
     state: "{{ rendering.changed | ternary('latest', 'present') }}"
 - name: "Ensure heketi is up and running."
diff --git a/contrib/network-storage/heketi/roles/provision/tasks/main.yml b/contrib/network-storage/heketi/roles/provision/tasks/main.yml
index 4adc2dbb2e80cd81a410788c6a0f970d032c60e7..23a2b4f9c72899af389d62662e608badb17d33ca 100644
--- a/contrib/network-storage/heketi/roles/provision/tasks/main.yml
+++ b/contrib/network-storage/heketi/roles/provision/tasks/main.yml
@@ -25,3 +25,6 @@
 
 - name: "Kubernetes Apps | Storage Class"
   include_tasks: "storageclass.yml"
+
+- name: "Clean up"
+  include_tasks: "cleanup.yml"
diff --git a/contrib/network-storage/heketi/roles/provision/tasks/topology.yml b/contrib/network-storage/heketi/roles/provision/tasks/topology.yml
index b9cb3e0d289814d96e75f2c254cb496d6972bf6b..dd1e272beb01b36d75d96c6be2d7abe169884f03 100644
--- a/contrib/network-storage/heketi/roles/provision/tasks/topology.yml
+++ b/contrib/network-storage/heketi/roles/provision/tasks/topology.yml
@@ -2,7 +2,7 @@
 - name: "Get heketi topology."
   register: "heketi_topology"
   changed_when: false
-  command: "{{ bin_dir }}/kubectl exec {{ heketi_pod_name }} -- heketi-cli topology info --json"
+  command: "{{ bin_dir }}/kubectl exec {{ heketi_pod_name }} -- heketi-cli --user admin --secret {{ heketi_admin_key }} topology info --json"
 - name: "Render heketi topology template."
   become: true
   vars: { nodes: "{{ groups['heketi-node'] }}" }
diff --git a/contrib/network-storage/heketi/roles/provision/templates/glusterfs-daemonset.json.j2 b/contrib/network-storage/heketi/roles/provision/templates/glusterfs-daemonset.json.j2
index 8f46bea24d04fc54969bb587635ce6168fc5fc7b..eddd57eb8176d2d32406aab45d8dc71c0bd6dc5d 100644
--- a/contrib/network-storage/heketi/roles/provision/templates/glusterfs-daemonset.json.j2
+++ b/contrib/network-storage/heketi/roles/provision/templates/glusterfs-daemonset.json.j2
@@ -27,7 +27,7 @@
                 "containers": [
                     {
                         "image": "gluster/gluster-centos:gluster4u0_centos7",
-                        "imagePullPolicy": "Always",
+                        "imagePullPolicy": "IfNotPresent",
                         "name": "glusterfs",
                         "volumeMounts": [
                             {