diff --git a/contrib/network-storage/heketi/roles/provision/tasks/setup.yml b/contrib/network-storage/heketi/roles/provision/tasks/bootstrap.yml similarity index 89% rename from contrib/network-storage/heketi/roles/provision/tasks/setup.yml rename to contrib/network-storage/heketi/roles/provision/tasks/bootstrap.yml index 96462dd11..a21cfadd6 100644 --- a/contrib/network-storage/heketi/roles/provision/tasks/setup.yml +++ b/contrib/network-storage/heketi/roles/provision/tasks/bootstrap.yml @@ -1,4 +1,3 @@ ---- # Bootstrap heketi - name: "Get state of heketi service, deployment and pods." register: "initial_heketi_state" @@ -9,7 +8,7 @@ - "(initial_heketi_state.stdout|from_json|json_query(\"items[?kind=='Service']\"))|length == 0" - "(initial_heketi_state.stdout|from_json|json_query(\"items[?kind=='Deployment']\"))|length == 0" - "(initial_heketi_state.stdout|from_json|json_query(\"items[?kind=='Pod']\"))|length == 0" - include_tasks: "setup/boot.yml" + include_tasks: "bootstrap/deploy.yml" # Prepare heketi topology - name: "Get heketi initial pod state." @@ -27,11 +26,11 @@ command: "{{ bin_dir }}/kubectl exec {{ initial_heketi_pod_name }} -- heketi-cli topology info --json" - name: "Load heketi topology." when: "heketi_topology.stdout|from_json|json_query(\"clusters[*].nodes[*]\")|flatten|length == 0" - include_tasks: "setup/topology.yml" + include_tasks: "bootstrap/topology.yml" # Provision heketi database volume - name: "Prepare heketi volumes." - include_tasks: "setup/volumes.yml" + include_tasks: "bootstrap/volumes.yml" # Prepare heketi storage - name: "Test heketi storage." @@ -41,7 +40,7 @@ - command: "{{ bin_dir }}/kubectl get secrets,endpoints,services,jobs --output=json" register: "job" - name: "Create heketi storage." - include_tasks: "setup/storage.yml" + include_tasks: "bootstrap/storage.yml" vars: secret_query: "items[?metadata.name=='heketi-storage-secret' && kind=='Secret']" endpoints_query: "items[?metadata.name=='heketi-storage-endpoints' && kind=='Endpoints']" @@ -52,8 +51,7 @@ - "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" -# Finalize setup + +# Remove bootstrap heketi - name: "Tear down bootstrap." - include_tasks: "setup/tear-down-bootstrap.yml" -- name: "Setup final heketi instance." - include_tasks: "setup/heketi.yml" + 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 new file mode 100644 index 000000000..3580707d5 --- /dev/null +++ b/contrib/network-storage/heketi/roles/provision/tasks/bootstrap/deploy.yml @@ -0,0 +1,23 @@ +--- +- name: "Kubernetes Apps | Lay Down Heketi Bootstrap" + become: true + template: { src: "heketi-bootstrap.json.j2", dest: "{{ kube_config_dir }}/heketi-bootstrap.json" } + register: "rendering" +- name: "Kubernetes Apps | Install and configure Heketi Bootstrap" + kube: + name: "GlusterFS" + filename: "{{ kube_config_dir }}/heketi-bootstrap.json" + state: "{{ rendering.changed | ternary('latest', 'present') }}" +- name: "Wait for heketi bootstrap to complete." + changed_when: false + register: "initial_heketi_state" + vars: + initial_heketi_state: { stdout: "{}" } + pods_query: "items[?kind=='Pod'].status.conditions|[0][?type=='Ready'].status|[0]" + deployments_query: "items[?kind=='Deployment'].status.conditions|[0][?type=='Available'].status|[0]" + command: "{{ bin_dir }}/kubectl get services,deployments,pods --selector=deploy-heketi --output=json" + until: + - "initial_heketi_state.stdout|from_json|json_query(pods_query) == 'True'" + - "initial_heketi_state.stdout|from_json|json_query(deployments_query) == 'True'" + retries: 60 + delay: 5 diff --git a/contrib/network-storage/heketi/roles/provision/tasks/setup/storage.yml b/contrib/network-storage/heketi/roles/provision/tasks/bootstrap/storage.yml similarity index 81% rename from contrib/network-storage/heketi/roles/provision/tasks/setup/storage.yml rename to contrib/network-storage/heketi/roles/provision/tasks/bootstrap/storage.yml index 7c49a2258..1daa72ac1 100644 --- a/contrib/network-storage/heketi/roles/provision/tasks/setup/storage.yml +++ b/contrib/network-storage/heketi/roles/provision/tasks/bootstrap/storage.yml @@ -4,7 +4,10 @@ changed_when: false register: "heketi_storage_state" - name: "Create heketi storage." - command: "{{ bin_dir }}/kubectl create -f {{ kube_config_dir }}/heketi-storage.json" + kube: + name: "GlusterFS" + filename: "{{ kube_config_dir }}/heketi-storage.json" + state: "present" vars: secret_query: "items[?metadata.name=='heketi-storage-secret' && kind=='Secret']" endpoints_query: "items[?metadata.name=='heketi-storage-endpoints' && kind=='Endpoints']" @@ -16,17 +19,17 @@ - "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" -- command: "{{ bin_dir }}/kubectl get secrets,endpoints,services,jobs --output=json" - register: "heketi_storage_state" + - name: "Get state of heketi storage service, endpoint, secret and job." command: "{{ bin_dir }}/kubectl get secrets,endpoints,services,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.conditions[?type=='Complete'].status=='True']" + 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" @@ -34,5 +37,3 @@ - "heketi_storage_state.stdout|from_json|json_query(job_query)|length == 1" retries: 60 delay: 5 -# looks like there is some race condition that leads to "Database file did not appear, exiting.", can't figure out where -- command: "sleep 10" diff --git a/contrib/network-storage/heketi/roles/provision/tasks/setup/tear-down-bootstrap.yml b/contrib/network-storage/heketi/roles/provision/tasks/bootstrap/tear-down.yml similarity index 100% rename from contrib/network-storage/heketi/roles/provision/tasks/setup/tear-down-bootstrap.yml rename to contrib/network-storage/heketi/roles/provision/tasks/bootstrap/tear-down.yml diff --git a/contrib/network-storage/heketi/roles/provision/tasks/setup/topology.yml b/contrib/network-storage/heketi/roles/provision/tasks/bootstrap/topology.yml similarity index 97% rename from contrib/network-storage/heketi/roles/provision/tasks/setup/topology.yml rename to contrib/network-storage/heketi/roles/provision/tasks/bootstrap/topology.yml index fd148d8d9..8c29aa1a6 100644 --- a/contrib/network-storage/heketi/roles/provision/tasks/setup/topology.yml +++ b/contrib/network-storage/heketi/roles/provision/tasks/bootstrap/topology.yml @@ -13,6 +13,7 @@ - name: "Load heketi topology." when: "heketi_topology.stdout|from_json|json_query(\"clusters[*].nodes[*]\")|flatten|length == 0" command: "{{ bin_dir }}/kubectl exec {{ initial_heketi_pod_name }} -- heketi-cli topology load --json=/tmp/topology.json" + register: "load_heketi" - name: "Get heketi topology." register: "heketi_topology" command: "{{ bin_dir }}/kubectl exec {{ initial_heketi_pod_name }} -- heketi-cli topology info --json" diff --git a/contrib/network-storage/heketi/roles/provision/tasks/setup/volumes.yml b/contrib/network-storage/heketi/roles/provision/tasks/bootstrap/volumes.yml similarity index 89% rename from contrib/network-storage/heketi/roles/provision/tasks/setup/volumes.yml rename to contrib/network-storage/heketi/roles/provision/tasks/bootstrap/volumes.yml index 0d24a3a0b..e6226a7c3 100644 --- a/contrib/network-storage/heketi/roles/provision/tasks/setup/volumes.yml +++ b/contrib/network-storage/heketi/roles/provision/tasks/bootstrap/volumes.yml @@ -31,12 +31,6 @@ with_items: "{{ heketi_volumes.stdout|from_json|json_query(\"volumes[*]\") }}" loop_control: { loop_var: "volume_id" } register: "volumes_information" -- name: "debug heketi db vol." - with_items: "{{ volumes_information.results }}" - loop_control: { loop_var: "volume_information" } - vars: { volume: "{{ volume_information.stdout|from_json }}" } - when: "volume.name == 'heketidbstorage'" - debug: { var: "volume" } - name: "Test heketi database volume." set_fact: { heketi_database_volume_created: true } with_items: "{{ volumes_information.results }}" diff --git a/contrib/network-storage/heketi/roles/provision/tasks/glusterfs.yml b/contrib/network-storage/heketi/roles/provision/tasks/glusterfs.yml new file mode 100644 index 000000000..e9650276a --- /dev/null +++ b/contrib/network-storage/heketi/roles/provision/tasks/glusterfs.yml @@ -0,0 +1,37 @@ +--- +- name: "Kubernetes Apps | Lay Down GlusterFS Daemonset" + template: { src: "glusterfs-daemonset.json.j2", dest: "{{ kube_config_dir }}/glusterfs-daemonset.json" } + become: true + register: "rendering" +- name: "Kubernetes Apps | Install and configure GlusterFS daemonset" + kube: + name: "GlusterFS" + filename: "{{ kube_config_dir }}/glusterfs-daemonset.json" + state: "{{ rendering.changed | ternary('latest', 'present') }}" +- 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" + changed_when: false + vars: + 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" + 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 + register: "rendering" +- name: "Kubernetes Apps | Install and configure Heketi Service Account" + kube: + name: "GlusterFS" + filename: "{{ kube_config_dir }}/heketi-service-account.json" + state: "{{ rendering.changed | ternary('latest', 'present') }}" diff --git a/contrib/network-storage/heketi/roles/provision/tasks/kubernetes/label.yml b/contrib/network-storage/heketi/roles/provision/tasks/glusterfs/label.yml similarity index 100% rename from contrib/network-storage/heketi/roles/provision/tasks/kubernetes/label.yml rename to contrib/network-storage/heketi/roles/provision/tasks/glusterfs/label.yml diff --git a/contrib/network-storage/heketi/roles/provision/tasks/heketi.yml b/contrib/network-storage/heketi/roles/provision/tasks/heketi.yml new file mode 100644 index 000000000..44016df5e --- /dev/null +++ b/contrib/network-storage/heketi/roles/provision/tasks/heketi.yml @@ -0,0 +1,25 @@ +--- +- name: "Kubernetes Apps | Lay Down Heketi" + become: true + template: { src: "heketi-deployment.json.j2", dest: "{{ kube_config_dir }}/heketi-deployment.json" } + register: "rendering" +- name: "Kubernetes Apps | Install and configure Heketi" + kube: + name: "GlusterFS" + filename: "{{ kube_config_dir }}/heketi-deployment.json" + state: "{{ rendering.changed | ternary('latest', 'present') }}" +- name: "Ensure heketi is up and running." + changed_when: false + register: "heketi_state" + vars: + heketi_state: { stdout: "{}" } + pods_query: "items[?kind=='Pod'].status.conditions|[0][?type=='Ready'].status|[0]" + deployments_query: "items[?kind=='Deployment'].status.conditions|[0][?type=='Available'].status|[0]" + command: "{{ bin_dir }}/kubectl get deployments,pods --selector=glusterfs --output=json" + until: + - "heketi_state.stdout|from_json|json_query(pods_query) == 'True'" + - "heketi_state.stdout|from_json|json_query(deployments_query) == 'True'" + retries: 60 + delay: 5 +- set_fact: + heketi_pod_name: "{{ heketi_state.stdout|from_json|json_query(\"items[?kind=='Pod'].metadata.name|[0]\") }}" diff --git a/contrib/network-storage/heketi/roles/provision/tasks/kubernetes.yml b/contrib/network-storage/heketi/roles/provision/tasks/kubernetes.yml deleted file mode 100644 index 6ab92713b..000000000 --- a/contrib/network-storage/heketi/roles/provision/tasks/kubernetes.yml +++ /dev/null @@ -1,64 +0,0 @@ ---- -- register: "daemonset_state" - command: "{{ bin_dir }}/kubectl get daemonset glusterfs -o=name --ignore-not-found=true" - changed_when: false -- name: "Deploy the GlusterFS DaemonSet" - when: "daemonset_state.stdout == \"\"" - command: "{{ bin_dir }}/kubectl create -f {{ kube_config_dir }}/glusterfs-daemonset.json" -- register: "daemonset_state" - command: "{{ bin_dir }}/kubectl get daemonset glusterfs --output=json --ignore-not-found=true" - changed_when: false -- name: "Wait for daemonset to become available." - register: "daemonset_state" - command: "{{ bin_dir }}/kubectl get daemonset glusterfs --output=json --ignore-not-found=true" - changed_when: false - vars: - ready: "{{ daemonset_state.stdout|from_json|json_query(\"status.numberReady\") }}" - desired: "{{ daemonset_state.stdout|from_json|json_query(\"status.desiredNumberScheduled\") }}" - until: "ready == desired" - retries: 60 - delay: 5 - -- name: "Label Gluster nodes" - with_items: "{{ groups['heketi-node'] }}" - loop_control: - loop_var: "node" - include_tasks: "kubernetes/label.yml" - -- register: "service_account_state" - command: "{{ bin_dir }}/kubectl get serviceaccount heketi-service-account -o=name --ignore-not-found=true" - changed_when: false -- name: "Deploy the Heketi service account" - when: "service_account_state.stdout == \"\"" - command: "{{ bin_dir }}/kubectl create -f {{ kube_config_dir }}/heketi-service-account.json" -- register: "service_account_state" - command: "{{ bin_dir }}/kubectl get serviceaccount heketi-service-account -o=name --ignore-not-found=true" - changed_when: false -- assert: { that: "service_account_state.stdout != \"\"", message: "Heketi service account is not present." } - -- register: "clusterrolebinding_state" - command: "{{ bin_dir }}/kubectl get clusterrolebinding heketi-gluster-admin -o=name --ignore-not-found=true" - changed_when: false -- name: "Deploy cluster role binding." - when: "clusterrolebinding_state.stdout == \"\"" - command: "{{ bin_dir }}/kubectl create clusterrolebinding heketi-gluster-admin --clusterrole=edit --serviceaccount=default:heketi-service-account" -- register: "clusterrolebinding_state" - command: "{{ bin_dir }}/kubectl get clusterrolebinding heketi-gluster-admin -o=name --ignore-not-found=true" - changed_when: false -- assert: { that: "clusterrolebinding_state.stdout != \"\"", message: "Cluster role binding is not present." } - -- register: "secret_state" - command: "{{ bin_dir }}/kubectl get secret heketi-config-secret -o=name --ignore-not-found=true" - changed_when: false -- name: "Render Heketi secret configuration." - become: true - template: - src: "heketi.json.j2" - dest: "{{ kube_config_dir }}/heketi.json" -- name: "Deploy Heketi config secret" - when: "secret_state.stdout == \"\"" - command: "{{ bin_dir }}/kubectl create secret generic heketi-config-secret --from-file={{ kube_config_dir }}/heketi.json" -- register: "secret_state" - command: "{{ bin_dir }}/kubectl get secret heketi-config-secret -o=name --ignore-not-found=true" - changed_when: false -- assert: { that: "secret_state.stdout != \"\"", message: "Heketi config secret is not present." } diff --git a/contrib/network-storage/heketi/roles/provision/tasks/main.yml b/contrib/network-storage/heketi/roles/provision/tasks/main.yml index c247929a7..cae035893 100644 --- a/contrib/network-storage/heketi/roles/provision/tasks/main.yml +++ b/contrib/network-storage/heketi/roles/provision/tasks/main.yml @@ -1,34 +1,27 @@ --- -- name: "Render configuration." - become: true - template: { src: "{{ item.file }}.j2", dest: "{{ kube_config_dir }}/{{ item.file }}" } - with_items: - - { file: "glusterfs-daemonset.json" } - - { file: "heketi-bootstrap.json" } - - { file: "heketi-deployment.json" } - - { file: "heketi-service-account.json" } -- name: "Prepare kubernetes." - include_tasks: "kubernetes.yml" +- name: "Kubernetes Apps | GlusterFS" + include_tasks: "glusterfs.yml" -- name: "Test heketi setup." +- name: "Kubernetes Apps | Heketi Secrets" + include_tasks: "secret.yml" + +- name: "Kubernetes Apps | Test Heketi" register: "heketi_service_state" - command: "{{ bin_dir }}/kubectl get service heketi -o=name --ignore-not-found=true" + command: "kubectl get service heketi-storage-endpoints -o=name --ignore-not-found=true" changed_when: false -- name: "Setup heketi." +- name: "Kubernetes Apps | Bootstrap Heketi" when: "heketi_service_state.stdout == \"\"" - include_tasks: "setup.yml" + include_tasks: "bootstrap.yml" -- name: "Test storage class." - changed_when: false - command: "{{ bin_dir }}/kubectl get storageclass gluster --ignore-not-found=true --output=json" - register: "storageclass" -- name: "Setup storage class." - when: "storageclass.stdout == \"\"" +- name: "Kubernetes Apps | Heketi" + include_tasks: "heketi.yml" + +- name: "Kubernetes Apps | Heketi Topology" + include_tasks: "topology.yml" + +- name: "Kubernetes Apps | Heketi Storage" + include_tasks: "storage.yml" + +- name: "Kubernetes Apps | Storage Class" include_tasks: "storageclass.yml" -- name: "Test storage class." - changed_when: false - command: "{{ bin_dir }}/kubectl get storageclass gluster --ignore-not-found=true --output=json" - register: "storageclass" -- name: "Ensure storage class is up." - assert: { that: "storageclass.stdout != \"\"" } diff --git a/contrib/network-storage/heketi/roles/provision/tasks/secret.yml b/contrib/network-storage/heketi/roles/provision/tasks/secret.yml new file mode 100644 index 000000000..699eaf34b --- /dev/null +++ b/contrib/network-storage/heketi/roles/provision/tasks/secret.yml @@ -0,0 +1,27 @@ +--- +- register: "clusterrolebinding_state" + command: "kubectl get clusterrolebinding heketi-gluster-admin -o=name --ignore-not-found=true" + changed_when: false +- name: "Kubernetes Apps | Deploy cluster role binding." + when: "clusterrolebinding_state.stdout == \"\"" + command: "kubectl create clusterrolebinding heketi-gluster-admin --clusterrole=edit --serviceaccount=default:heketi-service-account" +- register: "clusterrolebinding_state" + command: "kubectl get clusterrolebinding heketi-gluster-admin -o=name --ignore-not-found=true" + changed_when: false +- assert: { that: "clusterrolebinding_state.stdout != \"\"", message: "Cluster role binding is not present." } + +- register: "secret_state" + command: "kubectl get secret heketi-config-secret -o=name --ignore-not-found=true" + changed_when: false +- name: "Render Heketi secret configuration." + become: true + template: + src: "heketi.json.j2" + dest: "{{ kube_config_dir }}/heketi.json" +- name: "Deploy Heketi config secret" + when: "secret_state.stdout == \"\"" + command: "kubectl create secret generic heketi-config-secret --from-file={{ kube_config_dir }}/heketi.json" +- register: "secret_state" + command: "kubectl get secret heketi-config-secret -o=name --ignore-not-found=true" + changed_when: false +- assert: { that: "secret_state.stdout != \"\"", message: "Heketi config secret is not present." } diff --git a/contrib/network-storage/heketi/roles/provision/tasks/setup/boot.yml b/contrib/network-storage/heketi/roles/provision/tasks/setup/boot.yml deleted file mode 100644 index 806e91570..000000000 --- a/contrib/network-storage/heketi/roles/provision/tasks/setup/boot.yml +++ /dev/null @@ -1,27 +0,0 @@ ---- -- name: "Get state of heketi service, deployment and pods." - register: "initial_heketi_state" - changed_when: false - command: "{{ bin_dir }}/kubectl get services,deployments,pods --selector=deploy-heketi --output=json" -- name: "Create Heketi initial service and deployment" - command: "{{ bin_dir }}/kubectl create -f {{ kube_config_dir }}/heketi-bootstrap.json" - when: - - "(initial_heketi_state.stdout|from_json|json_query(\"items[?kind=='Service']\"))|length == 0" - - "(initial_heketi_state.stdout|from_json|json_query(\"items[?kind=='Deployment']\"))|length == 0" - - "(initial_heketi_state.stdout|from_json|json_query(\"items[?kind=='Pod']\"))|length == 0" -- name: "Get state of heketi service, deployment and pods." - register: "initial_heketi_state" - changed_when: false - command: "{{ bin_dir }}/kubectl get services,deployments,pods --selector=deploy-heketi --output=json" -- name: "Wait for heketi bootstrap to complete." - changed_when: false - register: "initial_heketi_state" - vars: - pods_query: "items[?kind=='Pod'].status.conditions|[0][?type=='Ready'].status|[0]" - deployments_query: "items[?kind=='Deployment'].status.conditions|[0][?type=='Available'].status|[0]" - command: "{{ bin_dir }}/kubectl get services,deployments,pods --selector=deploy-heketi --output=json" - until: - - "initial_heketi_state.stdout|from_json|json_query(pods_query) == 'True'" - - "initial_heketi_state.stdout|from_json|json_query(deployments_query) == 'True'" - retries: 60 - delay: 5 diff --git a/contrib/network-storage/heketi/roles/provision/tasks/setup/heketi.yml b/contrib/network-storage/heketi/roles/provision/tasks/setup/heketi.yml deleted file mode 100644 index c38b151ac..000000000 --- a/contrib/network-storage/heketi/roles/provision/tasks/setup/heketi.yml +++ /dev/null @@ -1,10 +0,0 @@ ---- -- name: "Create long term Heketi instance." - command: "{{ bin_dir }}/kubectl create -f {{ kube_config_dir }}/heketi-deployment.json" -- name: "Get heketi deployment state." - register: "heketi_deployment_state" - command: "{{ bin_dir }}/kubectl get deployment heketi -o=name --ignore-not-found=true" - changed_when: false -- name: "Ensure heketi is up and running." - assert: { that: "heketi_deployment_state.stdout != \"\"", message: "Heketi deployment did not succeed." } - diff --git a/contrib/network-storage/heketi/roles/provision/tasks/storage.yml b/contrib/network-storage/heketi/roles/provision/tasks/storage.yml new file mode 100644 index 000000000..881084bbe --- /dev/null +++ b/contrib/network-storage/heketi/roles/provision/tasks/storage.yml @@ -0,0 +1,11 @@ +--- +- name: "Kubernetes Apps | Lay Down Heketi Storage" + become: true + vars: { nodes: "{{ groups['heketi-node'] }}" } + template: { src: "heketi-storage.json.j2", dest: "{{ kube_config_dir }}/heketi-storage.json" } + register: "rendering" +- name: "Kubernetes Apps | Install and configure Heketi Storage" + kube: + name: "GlusterFS" + filename: "{{ kube_config_dir }}/heketi-storage.json" + state: "{{ rendering.changed | ternary('latest', 'present') }}" diff --git a/contrib/network-storage/heketi/roles/provision/tasks/storageclass.yml b/contrib/network-storage/heketi/roles/provision/tasks/storageclass.yml index 393d76e64..835dc78b2 100644 --- a/contrib/network-storage/heketi/roles/provision/tasks/storageclass.yml +++ b/contrib/network-storage/heketi/roles/provision/tasks/storageclass.yml @@ -16,6 +16,9 @@ template: src: "storageclass.yml.j2" dest: "{{ kube_config_dir }}/storageclass.yml" -- name: "Setup storage class." - when: "storageclass.stdout == \"\"" - command: "{{ bin_dir }}/kubectl create -f {{ kube_config_dir }}/storageclass.yml" + register: "rendering" +- name: "Kubernetes Apps | Install and configure Storace Class" + kube: + name: "GlusterFS" + filename: "{{ kube_config_dir }}/storageclass.yml" + state: "{{ rendering.changed | ternary('latest', 'present') }}" diff --git a/contrib/network-storage/heketi/roles/provision/tasks/topology.yml b/contrib/network-storage/heketi/roles/provision/tasks/topology.yml new file mode 100644 index 000000000..52c709f37 --- /dev/null +++ b/contrib/network-storage/heketi/roles/provision/tasks/topology.yml @@ -0,0 +1,25 @@ +--- +- name: "Get heketi topology." + register: "heketi_topology" + changed_when: false + command: "{{ bin_dir }}/kubectl exec {{ heketi_pod_name }} -- heketi-cli topology info --json" +- name: "Render heketi topology template." + become: true + vars: { nodes: "{{ groups['heketi-node'] }}" } + register: "rendering" + template: + src: "topology.json.j2" + dest: "{{ kube_config_dir }}/topology.json" +- name: "Copy topology configuration into container." + when: "rendering.changed" + command: "{{ bin_dir }}/kubectl cp {{ kube_config_dir }}/topology.json {{ heketi_pod_name }}:/tmp/topology.json" +- name: "Load heketi topology." + when: "rendering.changed" + command: "{{ bin_dir }}/kubectl exec {{ heketi_pod_name }} -- heketi-cli topology load --json=/tmp/topology.json" +- name: "Get heketi topology." + register: "heketi_topology" + changed_when: false + command: "{{ bin_dir }}/kubectl exec {{ heketi_pod_name }} -- heketi-cli topology info --json" + until: "heketi_topology.stdout|from_json|json_query(\"clusters[*].nodes[*].devices[?state=='online'].id\")|flatten|length == groups['heketi-node']|length" + retries: 60 + delay: 5 diff --git a/contrib/network-storage/heketi/roles/provision/templates/heketi-storage.json.j2 b/contrib/network-storage/heketi/roles/provision/templates/heketi-storage.json.j2 new file mode 100644 index 000000000..3089256c9 --- /dev/null +++ b/contrib/network-storage/heketi/roles/provision/templates/heketi-storage.json.j2 @@ -0,0 +1,54 @@ +{ + "apiVersion": "v1", + "kind": "List", + "items": [ + { + "kind": "Endpoints", + "apiVersion": "v1", + "metadata": { + "name": "heketi-storage-endpoints", + "creationTimestamp": null + }, + "subsets": [ +{% set nodeblocks = [] %} +{% for node in nodes %} +{% set nodeblock %} + { + "addresses": [ + { + "ip": "{{ hostvars[node]['ansible_facts']['default_ipv4']['address'] }}" + } + ], + "ports": [ + { + "port": 1 + } + ] + } +{% endset %} +{% if nodeblocks.append(nodeblock) %}{% endif %} +{% endfor %} +{{ nodeblocks|join(',') }} + ] + }, + { + "kind": "Service", + "apiVersion": "v1", + "metadata": { + "name": "heketi-storage-endpoints", + "creationTimestamp": null + }, + "spec": { + "ports": [ + { + "port": 1, + "targetPort": 0 + } + ] + }, + "status": { + "loadBalancer": {} + } + } + ] +}