فهرست منبع

Issue #176: AWX GUI changes for collecting dynamic inventory, execute job with node

Signed-off-by: sakshiarora13 <sakshi_arora1@dell.com>
John Lockman 4 سال پیش
والد
کامیت
8353195c73
30فایلهای تغییر یافته به همراه800 افزوده شده و 354 حذف شده
  1. 4 8
      appliance/inventory.yml
  2. 43 0
      appliance/roles/inventory/files/add_host.yml
  3. 93 0
      appliance/roles/inventory/files/create_inventory.yml
  4. 3 0
      appliance/roles/inventory/files/inventory
  5. 73 0
      appliance/roles/inventory/tasks/main.yml
  6. 16 0
      appliance/roles/inventory/vars/main.yml
  7. 0 153
      appliance/roles/web_ui/files/awx_configuration.yml
  8. 187 0
      appliance/roles/web_ui/tasks/awx_configuration.yml
  9. 0 118
      appliance/roles/web_ui/tasks/awx_password.yml
  10. 0 8
      appliance/roles/web_ui/tasks/check_prerequisites.yml
  11. 22 0
      appliance/roles/web_ui/tasks/clone_awx.yml
  12. 25 8
      appliance/roles/web_ui/tasks/install_awx.yml
  13. 4 2
      appliance/roles/web_ui/tasks/install_awx_cli.yml
  14. 45 8
      appliance/roles/web_ui/tasks/main.yml
  15. 13 19
      appliance/roles/web_ui/vars/main.yml
  16. 5 5
      omnia.yml
  17. 36 0
      roles/cluster_preperation/tasks/main.yml
  18. 65 0
      roles/cluster_preperation/tasks/passwordless_ssh.yml
  19. 19 0
      roles/cluster_preperation/vars/main.yml
  20. 34 0
      roles/cluster_validation/tasks/fetch_password.yml
  21. 6 14
      roles/compute_gpu/vars/main.yml
  22. 36 0
      roles/cluster_validation/tasks/validations.yml
  23. 22 0
      roles/cluster_validation/vars/main.yml
  24. 0 0
      roles/common/files/daemon.json
  25. 18 0
      roles/common/files/inventory.fact
  26. 18 0
      roles/common/tasks/main.yml
  27. 0 0
      roles/common/tasks/nvidia.yml
  28. 13 0
      roles/common/vars/main.yml
  29. 0 3
      roles/compute_gpu/files/k8s.conf
  30. 0 8
      roles/compute_gpu/files/kubernetes.repo

+ 4 - 8
appliance/inventory.yml

@@ -1,4 +1,4 @@
-# Copyright 2020 Dell Inc. or its subsidiaries. All Rights Reserved.
+# Copyright 2020 Dell Inc. or its subsidiaries. All Rights Reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -12,13 +12,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ---
-
-# inventory playbook. Will be updated later
-- name: omnia
+- name: Dynamic Inventory
   hosts: localhost
   connection: local
   gather_facts: no
-  tasks:
-    - name: Hello
-      debug:
-        msg: "Hello inventory.yml"
+  roles:
+    - inventory

+ 43 - 0
appliance/roles/inventory/files/add_host.yml

@@ -0,0 +1,43 @@
+# Copyright 2020 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+---
+
+- name: Check if host already exists
+  command: awk "{{ '/'+ item + '/' }}" inventory
+  register: check_host
+  changed_when: no
+
+- name: Initialise host description
+  set_fact:
+    host_description: "Description Unavailable"
+
+- name: Fetch description
+  set_fact:
+    host_description: "CPU:{{ hostvars[item]['ansible_processor_count'] }}
+    Cores:{{ hostvars[item]['ansible_processor_cores'] }}
+    Memory:{{ hostvars[item]['ansible_memtotal_mb'] }}MB
+    BIOS:{{ hostvars[item]['ansible_bios_version']}}"
+  changed_when: no
+  ignore_errors: yes
+
+- name: Add host
+  lineinfile:
+    path:  "inventory"
+    line: "    {{ item }}:\n      _awx_description: {{ host_description }}"
+  when: not check_host.stdout | regex_search(item)
+
+- name: Host added msg
+  debug:
+    msg: "{{ host_added_msg + item }}"
+  when: not check_host.stdout | regex_search(item)

+ 93 - 0
appliance/roles/inventory/files/create_inventory.yml

@@ -0,0 +1,93 @@
+# Copyright 2020 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+---
+
+- name: Find reachable hosts
+  hosts: all
+  gather_facts: false
+  ignore_unreachable: true
+  ignore_errors: true
+  tasks:
+    - name: Check for reachable nodes
+      command: ping -c1 {{ inventory_hostname }}
+      delegate_to: localhost
+      register: ping_result
+      ignore_errors: yes
+      changed_when: false
+
+    - name: Group reachable hosts
+      group_by:
+        key: "reachable"
+      when: "'100% packet loss' not in ping_result.stdout"
+
+- name: Get provision password
+  hosts: localhost
+  connection: local
+  gather_facts: false
+  tasks:
+    - name: Include vars file of inventory role
+      include_vars: ../vars/main.yml
+
+- name: Set hostname on reachable nodes and gather facts
+  hosts: reachable
+  gather_facts: False
+  remote_user: "{{ cobbler_username }}"
+  vars:
+    ansible_password: "{{ cobbler_password }}"
+    ansible_become_pass: "{{ cobbler_password }}"
+  tasks:
+    - name: Setup
+      setup:
+       filter: ansible_*
+
+    - name: Set the system hostname
+      hostname:
+        name: "compute{{ inventory_hostname.split('.')[-2] + '.' + inventory_hostname.split('.')[-1] }}"
+      register: result_name
+
+    - name: Add new hostname to /etc/hosts
+      lineinfile:
+        dest: /etc/hosts
+        regexp: '^127\.0\.0\.1[ \t]+localhost'
+        line: "127.0.0.1 localhost 'compute{{ inventory_hostname.split('.')[-1] }}'"
+        state: present
+
+    - name: Ensure networking connection
+      command: nmcli networking off
+      changed_when: false
+
+    - name: Ensure networking connection
+      command: nmcli networking on
+      changed_when: false
+
+    - name: Ensure networking connection
+      command: nmcli networking on
+      changed_when: false
+
+- name: Update inventory
+  hosts: localhost
+  connection: local
+  gather_facts: false
+  tasks:
+    - name: Update inventory file
+      block:
+        - name: Fetch facts and add new hosts
+          include_tasks: add_host.yml
+          with_items: "{{ groups['reachable'] }}"
+      when: "'reachable' in groups"
+
+    - name: Show unreachable hosts
+      debug:
+        msg: "{{ host_unreachable_msg }} + {{ groups['ungrouped'] }}"
+      when: "'ungrouped' in groups"

+ 3 - 0
appliance/roles/inventory/files/inventory

@@ -0,0 +1,3 @@
+---
+all:
+  hosts:

+ 73 - 0
appliance/roles/inventory/tasks/main.yml

@@ -0,0 +1,73 @@
+# Copyright 2020 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+---
+- name: Set Facts
+  set_fact:
+    ansible_ssh_common_args: '-o StrictHostKeyChecking=no'
+
+- name: Disable key host checking
+  replace:
+    path: /etc/ansible/ansible.cfg
+    regexp: '#host_key_checking = False'
+    replace: 'host_key_checking = False'
+
+- name: Disable host key checking
+  replace:
+    path: /etc/ssh/ssh_config
+    regexp: '#   StrictHostKeyChecking ask'
+    replace: 'StrictHostKeyChecking no'
+
+- name: Check if provisioned host file exists
+  stat:
+    path: "{{ role_path }}/files/provisioned_hosts.yml"
+  register: provisioned_file_result
+
+- name: Include vars file of common role
+  include_vars: "{{ role_path }}/../common/vars/main.yml"
+
+- name: Include vars file of web_ui role
+  include_vars: "{{ role_path }}/../web_ui/vars/main.yml"
+
+- name: Update inventory file
+  block:
+    - name: Decrpyt input_config.yml
+      command: >-
+        ansible-vault decrypt {{ input_config_filename }}
+        --vault-password-file roles/common/files/{{ vault_filename }}
+      changed_when: false
+
+    - name: Include variable file input_config.yml
+      include_vars: "{{ input_config_filename }}"
+
+    - name: Save input variables from file
+      set_fact:
+        cobbler_password: "{{ provision_password }}"
+
+    - name: Encrypt input config file
+      command: >-
+        ansible-vault encrypt {{ input_config_filename }}
+        --vault-password-file roles/common/files/{{ vault_filename }}
+
+    - name: add hosts with description to inventory file
+      command: >-
+        ansible-playbook -i {{ role_path }}/files/provisioned_hosts.yml
+        {{ role_path }}/files/create_inventory.yml
+        --extra-vars "cobbler_username={{ cobbler_username }} cobbler_password={{ cobbler_password }}"
+      ignore_errors: yes
+
+  when: provisioned_file_result.stat.exists
+
+- name: push inventory to AWX
+  command: awx-manage inventory_import --inventory-name {{ omnia_inventory_name }} --source {{ role_path }}/files/inventory
+  changed_when: no

+ 16 - 0
appliance/roles/inventory/vars/main.yml

@@ -0,0 +1,16 @@
+# Copyright 2020 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+---
+host_added_msg: "Added host to inventory: "
+host_unreachable_msg: "Following hosts are unreachable: "

+ 0 - 153
appliance/roles/web_ui/files/awx_configuration.yml

@@ -1,153 +0,0 @@
-# Copyright 2020 Dell Inc. or its subsidiaries. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
----
-
-# Playbook to configure AWX
-- name: Configure AWX
-  hosts: localhost
-  connection: local
-  gather_facts: no
-  tasks:
-    - name: Include vars file
-      include_vars: ../vars/main.yml
-
-    # Get Current AWX configuration
-    - name: Get organization list
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        organizations list -f human
-      register: organizations_list
-
-    - name: Get project list
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        projects list -f human
-      register: projects_list
-
-    - name: Get inventory list
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        inventory list -f human
-      register: inventory_list
-
-    - name: Get template list
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        job_templates list -f human
-      register: job_templates_list
-
-    - name: If omnia-inventory exists, fetch group names in the inventory
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        groups list --inventory "{{ omnia_inventory_name }}" -f human
-      register: groups_list
-      when: omnia_inventory_name in inventory_list.stdout
-
-    - name: Get schedules list
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        schedules list -f human
-      register: schedules_list
-
-    # Delete Default Configurations
-    - name: Delete default organization
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        organizations delete "{{ default_org }}"
-      when: default_org in organizations_list.stdout
-
-    - name: Delete default job template
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        job_templates delete "{{ default_template }}"
-      when: default_template in job_templates_list.stdout
-
-    - name: Delete default project
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        projects delete "{{ default_projects }}"
-      when: default_projects in projects_list.stdout
-
-    # Create required configuration if not present
-    - name: Create organisation
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        organizations create --name "{{ organization_name }}"
-      when: organization_name not in organizations_list.stdout
-
-    - name: Create new project
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        projects create --name "{{ project_name }}" --organization "{{ organization_name }}"
-        --local_path "{{ dir_name }}"
-      when: project_name not in projects_list.stdout
-
-    - name: Create new omnia inventory
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        inventory create --name "{{ omnia_inventory_name }}" --organization "{{ organization_name }}"
-      when: omnia_inventory_name not in inventory_list.stdout
-
-    - name: Create groups in omnia inventory
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        groups create --name "{{ item }}" --inventory "{{ omnia_inventory_name }}"
-      when: omnia_inventory_name not in inventory_list.stdout or item not in groups_list.stdout
-      loop: "{{ group_names }}"
-
-    - name: Create template to deploy omnia
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        job_templates create
-        --name "{{ omnia_template_name }}"
-        --job_type run
-        --inventory "{{ omnia_inventory_name }}"
-        --project "{{ project_name }}"
-        --playbook "{{ omnia_playbook }}"
-        --verbosity "{{ playbooks_verbosity }}"
-        --ask_skip_tags_on_launch true
-      when: omnia_template_name not in job_templates_list.stdout
-
-    - name: Create template to fetch dynamic inventory
-      command: >-
-        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-        job_templates create
-        --name "{{ inventory_template_name }}"
-        --job_type run
-        --inventory "{{ omnia_inventory_name }}"
-        --project "{{ project_name }}"
-        --playbook "{{ inventory_playbook }}"
-        --verbosity "{{ playbooks_verbosity }}"
-        --use_fact_cache true
-      when: inventory_template_name not in job_templates_list.stdout
-
-    - name: Schedule dynamic inventory template
-      block:
-        - name: Get unified job template list
-          command: >-
-            awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-            unified_job_templates list --name "{{ inventory_template_name }}" -f human
-          register: unified_job_template_list
-
-        - name: Get job ID
-          set_fact:
-            job_id: "{{ unified_job_template_list.stdout | regex_search('[0-9]+') }}"
-
-        - name: Schedule dynamic inventory job
-          command: >-
-            awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
-            schedules create --name "{{ schedule_name }}"
-            --unified_job_template="{{ job_id }}" --rrule="{{ schedule_rule }}"
-
-      when: schedule_name not in schedules_list.stdout

+ 187 - 0
appliance/roles/web_ui/tasks/awx_configuration.yml

@@ -0,0 +1,187 @@
+# Copyright 2020 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+---
+
+# Get Current AWX configuration
+- name: Get organization list
+  command: >-
+    awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
+    organizations list -f human
+  register: organizations_list
+  changed_when: no
+
+- name: Get project list
+  command: >-
+    awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
+    projects list -f human
+  register: projects_list
+  changed_when: no
+
+- name: Get inventory list
+  command: >-
+    awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
+    inventory list -f human
+  register: inventory_list
+  changed_when: no
+
+- name: Get credentials list
+  command: >-
+    awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
+    credentials list -f human
+  register: credentials_list
+  changed_when: no
+
+- name: Get template list
+  command: >-
+    awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
+    job_templates list -f human
+  register: job_templates_list
+  changed_when: no
+
+- name: If omnia-inventory exists, fetch group names in the inventory
+  command: >-
+    awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
+    groups list --inventory "{{ omnia_inventory_name }}" -f human
+  register: groups_list
+  when: omnia_inventory_name in inventory_list.stdout
+
+- name: Get schedules list
+  command: >-
+    awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
+    schedules list -f human
+  register: schedules_list
+  changed_when: no
+
+# Delete Default Configurations
+- name: Delete default organization
+  command: >-
+    awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
+    organizations delete "{{ default_org }}"
+  when: default_org in organizations_list.stdout
+
+- name: Delete default job template
+  command: >-
+    awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
+    job_templates delete "{{ default_template }}"
+  when: default_template in job_templates_list.stdout
+
+- name: Delete default project
+  command: >-
+    awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
+    projects delete "{{ default_projects }}"
+  when: default_projects in projects_list.stdout
+
+- name: Delete default credential
+  command: >-
+    awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
+    credentials delete "{{ default_credentials }}"
+  when: default_credentials in credentials_list.stdout
+
+# Create required configuration if not present
+- name: Create organisation
+  command: >-
+    awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
+    organizations create --name "{{ organization_name }}"
+  when: organization_name not in organizations_list.stdout
+
+- name: Create new project
+  command: >-
+    awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
+    projects create --name "{{ project_name }}" --organization "{{ organization_name }}"
+    --local_path "{{ dir_name }}"
+  when: project_name not in projects_list.stdout
+
+- name: Create new omnia inventory
+  command: >-
+    awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
+    inventory create --name "{{ omnia_inventory_name }}" --organization "{{ organization_name }}"
+  when: omnia_inventory_name not in inventory_list.stdout
+
+- name: Create groups in omnia inventory
+  command: >-
+    awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
+    groups create --name "{{ item }}" --inventory "{{ omnia_inventory_name }}"
+  when: omnia_inventory_name not in inventory_list.stdout or item not in groups_list.stdout
+  loop: "{{ group_names }}"
+
+- name: Create credentials for omnia
+  command: >-
+    awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
+    credentials create --name "{{ credential_name }}" --organization "{{ organization_name }}"
+    --credential_type "{{ credential_type }}"
+    --inputs '{"username": "{{ cobbler_username }}", "password": "{{ cobbler_password }}"}'
+  when: credential_name not in credentials_list.stdout
+
+- name: DeployOmnia Template
+  block:
+    - name: Create template to deploy omnia
+      command: >-
+        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
+        job_templates create
+        --name "{{ omnia_template_name }}"
+        --job_type run
+        --inventory "{{ omnia_inventory_name }}"
+        --project "{{ project_name }}"
+        --playbook "{{ omnia_playbook }}"
+        --verbosity "{{ playbooks_verbosity }}"
+        --ask_skip_tags_on_launch true
+
+    - name: Associate credential
+      command: >-
+        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
+        job_templates associate "{{ omnia_template_name }}"
+        --credential ""{{ credential_name }}""
+
+  when: omnia_template_name not in job_templates_list.stdout
+
+- name: DynamicInventory template
+  block:
+    - name: Create template to fetch dynamic inventory
+      command: >-
+        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
+        job_templates create
+        --name "{{ inventory_template_name }}"
+        --job_type run
+        --inventory "{{ omnia_inventory_name }}"
+        --project "{{ project_name }}"
+        --playbook "{{ inventory_playbook }}"
+        --verbosity "{{ playbooks_verbosity }}"
+        --use_fact_cache true
+
+    - name: Associate credential
+      command: >-
+        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
+        job_templates associate "{{ inventory_template_name }}"
+        --credential ""{{ credential_name }}""
+  when: inventory_template_name not in job_templates_list.stdout
+
+- name: Schedule dynamic inventory template
+  block:
+    - name: Get unified job template list
+      command: >-
+        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
+        unified_job_templates list --name "{{ inventory_template_name }}" -f human
+      register: unified_job_template_list
+
+    - name: Get job ID
+      set_fact:
+        job_id: "{{ unified_job_template_list.stdout | regex_search('[0-9]+') }}"
+
+    - name: Schedule dynamic inventory job
+      command: >-
+        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
+        schedules create --name "{{ schedule_name }}"
+        --unified_job_template="{{ job_id }}" --rrule="{{ schedule_rule }}"
+
+  when: schedule_name not in schedules_list.stdout

+ 0 - 118
appliance/roles/web_ui/tasks/awx_password.yml

@@ -1,118 +0,0 @@
-# Copyright 2020 Dell Inc. or its subsidiaries. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
----
-
-#Tasks for getting and encrypting AWX Password
-- name: Clone AWX repo
-  git:
-    repo: "{{ awx_git_repo }}"
-    dest: "{{ awx_repo_path }}"
-    force: yes
-  tags: install
-
-- name: AWX password
-  block:
-    - name: Take awx password
-      pause:
-        prompt: "{{ prompt_password }}"
-        echo: no
-      register: prompt_admin_password
-      until:
-        - prompt_admin_password.user_input | length >  min_length| int  - 1
-        - '"-" not in prompt_admin_password.user_input '
-        - '"\\" not in prompt_admin_password.user_input '
-        - '"\"" not in prompt_admin_password.user_input '
-        - " \"'\" not in prompt_admin_password.user_input "
-      retries: "{{ retries }}"
-      delay: "{{ retry_delay }}"
-      when: admin_password is not defined and no_prompt is not defined
-  rescue:
-    - name: Abort if password validation fails
-      fail:
-        msg: "{{ msg_incorrect_password_format }}"
-  tags: install
-
-- name: Assert admin_password if prompt not given
-  assert:
-    that:
-        - admin_password | length >  min_length| int  - 1
-        - '"-" not in admin_password '
-        - '"\\" not in admin_password '
-        - '"\"" not in admin_password '
-        - " \"'\" not in admin_password "
-    success_msg: "{{ success_msg_pwd_format }}"
-    fail_msg: "{{ fail_msg_pwd_format }}"
-  register: msg_pwd_format
-  when: admin_password is defined and no_prompt is defined
-
-- name: Save admin password
-  set_fact:
-    admin_password: "{{ prompt_admin_password.user_input }}"
-  when: no_prompt is not defined
-
-- name: Confirmation
-  block:
-    - name: Confirm AWX password
-      pause:
-        prompt: "{{ confirm_password }}"
-        echo: no
-      register: prompt_admin_password_confirm
-      until: admin_password == prompt_admin_password_confirm.user_input
-      retries: "{{ confirm_retries }}"
-      delay: "{{ retry_delay }}"
-      when: admin_password_confirm is not defined and no_prompt is not defined
-  rescue:
-    - name: Abort if password confirmation failed
-      fail:
-        msg: "{{ msg_failed_password_confirm }}"
-  tags: install
-
-- name: Assert admin_password_confirm if prompt not given
-  assert:
-    that: admin_password == admin_password_confirm
-    success_msg: "{{ success_msg_pwd_confirm }}"
-    fail_msg: "{{ fail_msg_pwd_confirm }}"
-  register: msg_pwd_confirm
-  when: admin_password_confirm is defined and no_prompt is defined
-
-- name: Create ansible vault key
-  set_fact:
-    vault_key: "{{ lookup('password', '/dev/null chars=ascii_letters') }}"
-  tags: install
-
-- name: Save vault key
-  copy:
-    dest: "{{ awx_installer_path + vault_file }}"
-    content: |
-      {{ vault_key }}
-    owner: root
-    force: yes
-  tags: install
-
-- name: Encrypt awx password
-  command: ansible-vault encrypt_string "{{ admin_password }}" --name admin_password --vault-password-file "{{ vault_file }}"
-  register: encrypt_password
-  args:
-    chdir: "{{ awx_installer_path }}"
-  tags: install
-
-- name: Store encrypted password
-  copy:
-    dest: "{{ awx_installer_path + awx_password_file }}"
-    content: |
-      ---
-      {{ encrypt_password.stdout }}
-    force: yes
-    owner: root
-  tags: install

+ 0 - 8
appliance/roles/web_ui/tasks/check_prerequisites.yml

@@ -17,7 +17,6 @@
 - name: Initialize variables
   set_fact:
     awx_status: false
-    awx_task_status: false
   tags: install
 
 - name: Check awx_task status on the machine
@@ -26,17 +25,10 @@
   register: awx_task_result
   tags: install
 
-- name: Update awx status
-  set_fact:
-    awx_task_status: true
-  when: awx_task_result.exists
-  tags: install
-
 - name: Check awx_web status on the machine
   docker_container_info:
     name: awx_web
   register: awx_web_result
-  when: awx_task_status
   tags: install
 
 - name: Update awx status

+ 22 - 0
appliance/roles/web_ui/tasks/clone_awx.yml

@@ -0,0 +1,22 @@
+# Copyright 2020 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+---
+
+- name: Clone AWX repo
+  git:
+    repo: "{{ awx_git_repo }}"
+    dest: "{{ awx_repo_path }}"
+    force: yes
+    version: devel
+  tags: install

+ 25 - 8
appliance/roles/web_ui/tasks/install_awx.yml

@@ -14,10 +14,6 @@
 ---
 
 # Tasks for installing AWX
-- name: Store omnia parent directory path
-  set_fact:
-     dir_path:
-  tags: install
 
 - name: Change inventory file
   replace:
@@ -32,14 +28,35 @@
     label: "{{ item.name }}"
   tags: install
 
+- name: Ensure port is 8081
+  lineinfile:
+    path: "{{ awx_inventory_path }}"
+    regexp: "{{ port_old }}"
+    line: "{{ port_new }}"
+    state: present
+
 - name: Create pgdocker directory
   file:
     path: "{{ pgdocker_dir_path }}"
     state: directory
+    mode: 0775
   tags: install
 
-- name: Run AWX install.yml file
-  command: ansible-playbook -i inventory install.yml -e @"{{ awx_password_file }}" --vault-password-file "{{ vault_file }}"
-  args:
-    chdir: "{{ awx_installer_path }}"
+- name: Install AWX
+  block:
+    - name: Run AWX install.yml file
+      command: ansible-playbook -i inventory install.yml --extra-vars "admin_password={{ admin_password }}"
+      args:
+        chdir: "{{ awx_installer_path }}"
+      register: awx_installation
+
+  rescue:
+    - name: Check AWX status on machine
+      include_tasks: check_awx_status.yml
+
+    - name: Fail if container are not running
+      fail:
+        msg: "AWX installation failed."
+      when: not awx_status
+
   tags: install

+ 4 - 2
appliance/roles/web_ui/tasks/install_awx_cli.yml

@@ -16,10 +16,12 @@
 # Tasks for installing AWX-CLI
 - name: Add AWX CLI repo
   block:
-    - get_url:
+    - name: Get repo
+      get_url:
         url: "{{ awx_cli_repo }}"
         dest: "{{ awx_cli_repo_path }}"
-    - replace:
+    - name: Disable gpgcheck
+      replace:
         path: "{{ awx_cli_repo_path }}"
         regexp: 'gpgcheck=1'
         replace: 'gpgcheck=0'

+ 45 - 8
appliance/roles/web_ui/tasks/main.yml

@@ -15,7 +15,7 @@
 
 # Tasks for Deploying AWX on the system
 - name: Check AWX status on machine
-  include_tasks: check_prerequisites.yml
+  include_tasks: check_awx_status.yml
   tags: install
 
 - name: Include common variables
@@ -28,7 +28,7 @@
   tags: install
 
 - name: Get and encrypt AWX password
-  include_tasks: awx_password.yml
+  include_tasks: clone_awx.yml
   when: not awx_status
   tags: install
 
@@ -58,13 +58,50 @@
   include_tasks: ../../common/tasks/internet_validation.yml
   tags: install
 
+- name: Waiting for AWX UI to be accessible
+  wait_for:
+    timeout: 300
+  delegate_to: localhost
+  tags: install
+
+- name: Re-install if in migrating state
+  block:
+    - name: Check if AWX UI is accessible
+      command: >-
+        awx --conf.host "{{ awx_ip }}" --conf.username "{{ awx_user }}" --conf.password "{{ admin_password }}"
+        organizations list -f human
+      changed_when: no
+
+  rescue:
+    - name: Remove old containers
+      docker_container:
+        name: "{{ item }}"
+        state: absent
+      loop:
+        - awx_task
+        - awx_web
+
+    - name: Restart docker
+      service:
+        name: docker
+        state: restarted
+
+    - name: Run AWX install.yml file
+      command: ansible-playbook -i inventory install.yml --extra-vars "admin_password={{ admin_password }}"
+      args:
+        chdir: "{{ awx_installer_path }}"
+      ignore_errors: yes
+
+    - name: Waiting for AWX UI to be accessible
+      wait_for:
+        timeout: 150
+      delegate_to: localhost
+  tags: install
+
 - name: Install AWX-CLI
   include_tasks: install_awx_cli.yml
   tags: install
 
-- name: AWX configuration
-  command: >-
-    ansible-playbook "{{ role_path }}"/files/awx_configuration.yml
-    -e @"{{ awx_installer_path + awx_password_file }}"
-    --vault-password-file "{{ awx_installer_path + vault_file }}"
-  tags: install
+- name: Configure AWX
+  include_tasks: awx_configuration.yml
+  tags: install

+ 13 - 19
appliance/roles/web_ui/vars/main.yml

@@ -15,25 +15,11 @@
 
 # vars file for web_ui
 
-# Usage: awx_password.yml
+# Usage: clone_awx.yml
 awx_git_repo: "https://github.com/ansible/awx.git"
-min_length: 8
-retries: 3
-confirm_retries: 1
-retry_delay: 0.01
-prompt_password: "Enter AWX password.( Min. Length of Password should be {{ min_length| int }}. Dont use chars: - \' \\ \" )"
-confirm_password: "Confirm AWX Password"
-msg_incorrect_password_format: "Failed. Password format not correct."
-msg_failed_password_confirm: "Failed. Passwords did not match"
 docker_volume: "/var/lib/docker/volumes/{{ docker_volume_name }}"
 awx_repo_path: "{{ docker_volume }}/awx/"
 awx_installer_path: "{{ awx_repo_path }}/installer/"
-vault_file: .vault_key
-awx_password_file: .password.yml
-success_msg_pwd_format: "admin_password validated"
-fail_msg_pwd_format: "admin_password validation failed"
-success_msg_pwd_confirm: "admin_password confirmed"
-fail_msg_pwd_confirm: "admin_password confirmation failed"
 
 # Usage: install_awx.yml
 awx_inventory_path: "{{ awx_repo_path }}/installer/inventory"
@@ -44,21 +30,26 @@ awx_alternate_dns_servers_old: '#awx_alternate_dns_servers="10.1.2.3,10.2.3.4"'
 awx_alternate_dns_servers_new: 'awx_alternate_dns_servers="8.8.8.8,8.8.4.4"'
 admin_password_old: "admin_password=password"
 admin_password_new: "#admin_password=password"
+port_old: "host_port=80"
+port_new: "host_port=8081"
 
 # Usage: main.yml
 message_skipped: "Installation Skipped: AWX instance is already running on your system"
 message_installed: "Installation Successful"
+awx_ip: http://localhost:8081
+return_status: 200
+migrating_msg: "IsMigrating"
 
 # Usage: install_awx_cli.yml
-awx_cli_repo: "https://releases.ansible.com/ansible-tower/cli/ansible-tower-cli-centos8.repo"
-awx_cli_repo_path: "/etc/yum.repos.d/ansible-tower-cli-centos8.repo"
+awx_cli_repo: "https://releases.ansible.com/ansible-tower/cli/ansible-tower-cli-centos7.repo"
+awx_cli_repo_path: "/etc/yum.repos.d/ansible-tower-cli-centos7.repo"
 
 # Usage: awx_configuration.yml
-awx_ip: http://localhost
 awx_user: admin         #Don't change it. It is set as admin while installing AWX
 default_org: Default
 default_template: 'Demo Job Template'
 default_projects: 'Demo Project'
+default_credentials: 'Demo Credential'
 dir_name: omnia
 organization_name: DellEMC
 project_name: omnia
@@ -66,10 +57,13 @@ omnia_inventory_name: omnia_inventory
 group_names:
   - manager
   - compute
+credential_name: omnia_credential
+credential_type: Machine
+cobbler_username: root
 omnia_template_name: DeployOmnia
 omnia_playbook: omnia.yml
 inventory_template_name: DynamicInventory
 inventory_playbook: appliance/inventory.yml
 playbooks_verbosity: 0
 schedule_name: DynamicInventorySchedule
-schedule_rule: "DTSTART:20201201T000000Z RRULE:FREQ=MINUTELY;INTERVAL=10"
+schedule_rule: "DTSTART:20201201T000000Z RRULE:FREQ=MINUTELY;INTERVAL=10"

+ 5 - 5
omnia.yml

@@ -24,11 +24,11 @@
   roles:
     - common
  
-- name: Apply GPU node config
-  hosts: gpus
-  gather_facts: false
-  roles:
-    - compute_gpu
+#- name: Apply GPU node config
+#  hosts: gpus
+#  gather_facts: false
+#  roles:
+#    - compute_gpu
 
 - name: Apply K8s manager config
   hosts: manager

+ 36 - 0
roles/cluster_preperation/tasks/main.yml

@@ -0,0 +1,36 @@
+#  Copyright 2020 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+---
+- name: Set Facts
+  set_fact:
+    ansible_ssh_common_args: '-o StrictHostKeyChecking=no'
+
+- name: Disable host key checking
+  replace:
+    path: /etc/ssh/ssh_config
+    regexp: '#   StrictHostKeyChecking ask'
+    replace: 'StrictHostKeyChecking no'
+
+- name: Install sshpass
+  package:
+    name: sshpass
+    state: present
+
+- name: Verify and set passwordless ssh from manager to compute nodes
+  block:
+    - name: Execute on individual hosts
+      include_tasks: passwordless_ssh.yml
+      with_items: "{{ ssh_to }}"
+      loop_control:
+        pause: 5

+ 65 - 0
roles/cluster_preperation/tasks/passwordless_ssh.yml

@@ -0,0 +1,65 @@
+#  Copyright 2020 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+---
+
+- name: Initialize variables
+  set_fact:
+    ssh_status: false
+    current_host: "{{ item }}"
+
+- name: Verify whether passwordless ssh is set on the remote host
+  command: ssh -o PasswordAuthentication=no root@"{{ current_host }}" 'hostname'
+  register: ssh_output
+  ignore_errors: yes
+  changed_when: False
+
+- name: Update ssh connection status
+  set_fact:
+    ssh_status: true
+  when: "'Permission denied' not in ssh_output.stderr"
+
+- name: Verify the public key file existence
+  stat:
+    path: "{{ rsa_id_file }}"
+  register: verify_rsa_id_file
+  when: not ssh_status
+
+- name: Generate ssh key pair
+  command: ssh-keygen -t rsa -b 4096 -f "{{ rsa_id_file }}" -q -N "{{ passphrase }}"
+  when:
+    - not ssh_status
+    - not verify_rsa_id_file.stat.exists
+
+- name: Add the key identity
+  shell: |
+    eval `ssh-agent -s`
+    ssh-add "{{ rsa_id_file }}"
+  when: not ssh_status
+
+- name: Create .ssh directory
+  command: >-
+    sshpass -p "{{ hostvars['127.0.0.1']['cobbler_password'] }}"
+    ssh root@"{{ current_host }}" mkdir -p /root/.ssh
+  when: not ssh_status
+
+- name: Copy the public key to remote host
+  shell: >-
+    set -o pipefail && cat "{{ rsa_id_file }}".pub
+    | sshpass -p "{{ hostvars['127.0.0.1']['cobbler_password'] }}"
+    ssh root@"{{ current_host }}" 'cat >> "{{ auth_key_path }}"'
+  when: not ssh_status
+
+- name: Change permissions on the remote host
+  shell: sshpass -p "{{ hostvars['127.0.0.1']['cobbler_password'] }}" ssh root@"{{ current_host }}" 'chmod 700 .ssh; chmod 640 "{{ auth_key_path }}"'
+  when: not ssh_status

+ 19 - 0
roles/cluster_preperation/vars/main.yml

@@ -0,0 +1,19 @@
+#  Copyright 2020 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+---
+
+#Usage: passwordless_ssh.yml
+rsa_id_file: "/root/.ssh/id_rsa"
+passphrase: ""
+auth_key_path: "/root/.ssh/authorized_keys"

+ 34 - 0
roles/cluster_validation/tasks/fetch_password.yml

@@ -0,0 +1,34 @@
+#  Copyright 2020 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+---
+
+- name: Decrpyt input_config.yml
+  command: >-
+    ansible-vault decrypt {{ role_path }}/../../appliance/{{ input_config_filename }}
+    --vault-password-file {{ role_path }}/../../appliance/roles/common/files/{{ vault_filename }}
+  changed_when: false
+
+- name: Include variable file input_config.yml
+  include_vars: "{{ role_path }}/../../appliance/{{ input_config_filename }}"
+
+- name: Save input variables from file
+  set_fact:
+    cobbler_password: "{{ provision_password }}"
+    db_password: "{{ mariadb_password }}"
+
+- name: Encrypt input config file
+  command: >-
+    ansible-vault encrypt {{ role_path }}/../../appliance/{{ input_config_filename }}
+    --vault-password-file {{ role_path }}/../../appliance/roles/common/files/{{ vault_filename }}
+  changed_when: false

+ 6 - 14
roles/compute_gpu/vars/main.yml

@@ -12,19 +12,11 @@
 #  See the License for the specific language governing permissions and
 #  limitations under the License.
 ---
+- name: Include vars file of common role
+  include_vars: "{{ role_path }}/../../appliance/roles/common/vars/main.yml"
 
-nvidia_docker_repo_url: https://nvidia.github.io/nvidia-docker/centos7/nvidia-docker.repo
+- name: Perform validations
+  include_tasks: validations.yml
 
-nvidia_docker_repo_dest: /etc/yum.repos.d/nvidia-docker.repo
-
-nvidia_container_repo_url: https://nvidia.github.io/libnvidia-container/centos7/libnvidia-container.repo 
-
-nvidia_container_repo_dest: /etc/yum.repos.d/libnvidia-container.repo
-
-nvidia_packages:
-  - kmod-nvidia
-  - nvidia-docker2
-
-daemon_file_dest: /etc/docker/
-
-daemon_file_mode: 0644
+- name: Fetch cobbler password
+  include_tasks: fetch_password.yml

+ 36 - 0
roles/cluster_validation/tasks/validations.yml

@@ -0,0 +1,36 @@
+#  Copyright 2020 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+---
+- name: Validate skip tags
+  fail:
+    msg: "{{ skip_tag_fail_msg }}"
+  when: "'slurm' in ansible_skip_tags and 'kubernetes' in ansible_skip_tags"
+
+- name: Manager group to contain exactly 1 node
+  assert:
+    that: "groups['manager'] | length | int == 1"
+    fail_msg: "{{ manager_group_fail_msg }}"
+    success_msg: "{{ manager_group_success_msg }}"
+
+- name: Compute group to contain atleast 1 node
+  assert:
+    that: "groups['compute'] | length | int >= 1"
+    fail_msg: "{{ compute_group_fail_msg }}"
+    success_msg: "{{ compute_group_success_msg }}"
+
+- name: Manager and compute groups should be disjoint
+  assert:
+    that: "groups['manager'][0] not in groups['compute']"
+    fail_msg: "{{ disjoint_fail_msg }}"
+    success_msg: "{{ disjoint_success_msg }}"

+ 22 - 0
roles/cluster_validation/vars/main.yml

@@ -0,0 +1,22 @@
+#  Copyright 2020 Dell Inc. or its subsidiaries. All Rights Reserved.
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+---
+
+skip_tag_fail_msg: "Can't skip both slurm and kubernetes"
+manager_group_fail_msg: "manager group should contain exactly 1 node"
+manager_group_success_msg: "manager group check passed"
+compute_group_fail_msg: "compute group should contain atleast 1 node"
+compute_group_success_msg: "compute group check passed"
+disjoint_fail_msg: "manager and compute groups should be disjoint"
+disjoint_success_msg: "manager and compute groups are disjoint"

roles/compute_gpu/files/daemon.json → roles/common/files/daemon.json


+ 18 - 0
roles/common/files/inventory.fact

@@ -0,0 +1,18 @@
+#!/bin/bash
+INVENTORY=$(mktemp lspci.XXXXXXXX)
+
+lspci > $INVENTORY
+
+NVIDIA_GPU=$(cat $INVENTORY | grep -i nvidia | wc -l)
+XILINX_FPGA=$(cat $INVENTORY | grep "Processing accelerators: Xilinx Corporation Device" | wc -l)
+INTEL_A10_FPGA=$(cat $INVENTORY | grep "Processing accelerators: Intel Corporation Device" | wc -l)
+
+cat << EOF
+{
+	"xilinx_fpga" : $XILINX_FPGA,
+	"nvidia_gpu" : $NVIDIA_GPU,
+	"intel_a10_fpga" : $INTEL_A10_FPGA
+}
+EOF
+
+rm -f $INVENTORY

+ 18 - 0
roles/common/tasks/main.yml

@@ -13,6 +13,17 @@
 #  limitations under the License.
 ---
 
+- name: Create a custom fact directory on each host
+  file:
+    path: /etc/ansible/facts.d
+    state: directory
+
+- name: Install accelerator discovery script
+  copy:
+    src: inventory.fact
+    dest: /etc/ansible/facts.d/inventory.fact
+    mode: 0755
+
 - name: Add kubernetes repo
   copy:
     src: kubernetes.repo
@@ -70,6 +81,9 @@
     state: present
   tags: install
 
+- name: Collect host facts (including acclerator information)
+  setup: ~
+
 - name: Install k8s packages
   package:
     name: "{{ k8s_packages }}"
@@ -107,3 +121,7 @@
 - name: Deploy time ntp/chrony
   include_tasks: ntp.yml
   tags: install
+
+- name: Install Nvidia drivers and software components
+  include_tasks: nvidia.yml
+  when: ansible_local.inventory.nvidia_gpu > 0

roles/compute_gpu/tasks/main.yml → roles/common/tasks/nvidia.yml


+ 13 - 0
roles/common/vars/main.yml

@@ -23,6 +23,7 @@ common_packages:
   - bash-completion
   - nvidia-detect
   - chrony
+  - pciutils
 
 k8s_packages:
   - kubelet-1.16.7
@@ -61,3 +62,15 @@ ntp_servers:
   - 2.centos.pool.ntp.org
 chrony_servers:
   - 2.centos.pool.ntp.org
+
+nvidia_docker_repo_url: https://nvidia.github.io/nvidia-docker/centos7/nvidia-docker.repo
+nvidia_docker_repo_dest: /etc/yum.repos.d/nvidia-docker.repo
+nvidia_container_repo_url: https://nvidia.github.io/libnvidia-container/centos7/libnvidia-container.repo
+nvidia_container_repo_dest: /etc/yum.repos.d/libnvidia-container.repo
+
+nvidia_packages:
+  - kmod-nvidia
+  - nvidia-docker2
+
+daemon_file_dest: /etc/docker/
+daemon_file_mode: 0644

+ 0 - 3
roles/compute_gpu/files/k8s.conf

@@ -1,3 +0,0 @@
-net.bridge.bridge-nf-call-ip6tables = 1
-net.bridge.bridge-nf-call-iptables = 1
-

+ 0 - 8
roles/compute_gpu/files/kubernetes.repo

@@ -1,8 +0,0 @@
-[kubernetes]
-name=Kubernetes
-baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
-enabled=1
-gpgcheck=1
-repo_gpgcheck=1
-gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
-