From 5cb8111ddc24dcdbf2915c4497ec9d20504ca276 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Wed, 16 Jul 2025 09:34:54 +0000 Subject: [PATCH] Add v2 of cloud facts playbook --- etc/kayobe/ansible.cfg | 2 + etc/kayobe/ansible/filter_plugins/filters.py | 57 ++++++++++ etc/kayobe/ansible/get-cloud-facts.yml | 104 +++++++++++++------ 3 files changed, 129 insertions(+), 34 deletions(-) create mode 100644 etc/kayobe/ansible/filter_plugins/filters.py diff --git a/etc/kayobe/ansible.cfg b/etc/kayobe/ansible.cfg index e6c3e9c12d..c4bf7a0dda 100644 --- a/etc/kayobe/ansible.cfg +++ b/etc/kayobe/ansible.cfg @@ -10,6 +10,8 @@ inject_facts_as_vars = False callbacks_enabled = ansible.posix.profile_tasks # Silence warning about invalid characters found in group names force_valid_group_names = ignore +# Default value plus custom filter plugins path +filter_plugins = $ANSIBLE_HOME/plugins/filter:/usr/share/ansible/plugins/filter:$KAYOBE_CONFIG_PATH/ansible/filter_plugins/ [inventory] # Fail when any inventory source cannot be parsed. diff --git a/etc/kayobe/ansible/filter_plugins/filters.py b/etc/kayobe/ansible/filter_plugins/filters.py new file mode 100644 index 0000000000..ed6ca94a59 --- /dev/null +++ b/etc/kayobe/ansible/filter_plugins/filters.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 + +from ansible.errors import AnsibleFilterError + +class FilterModule(object): + def filters(self): + return { + 'group_hostvars_by_var': + self.group_hostvars_by_var, + 'group_hostvars_by_host': + self.group_hostvars_by_host + } + + def group_hostvars_by_var(self, hostvars, var, stdout=None): + """ + Returns a dictionary where the keys are values for the + specified var in hostvars, and the values are the hosts + that match that value. + """ + result = {} + + for host in hostvars.keys(): + try: + indiv_host_all = hostvars[host] + indiv_host_var = indiv_host_all[var] + if stdout is not None: + indiv_host_var = indiv_host_var[stdout] + result.setdefault(indiv_host_var, []).append(host) + except KeyError as e: + raise AnsibleFilterError(f"Variable {var} not found for host {host} in hostvars: {e}") + + return result + + def group_hostvars_by_host(self, hostvars, var, stdout=None, hostgroup=None): + result = {} + """ + Returns a dictionary where the keys are hosts and the values + are the values for the specified var in hostvars. If hosts is + specified, only those hosts are included. + """ + for host in hostvars.keys(): + try: + indiv_host_vars = hostvars[host][var] + for key in indiv_host_vars.keys(): + if key == "skipped": + return {} + if stdout is not None: + indiv_host_vars = indiv_host_vars[stdout] + if indiv_host_vars: + result[host] = indiv_host_vars + else: + result[host] = [] + + except KeyError as e: + raise AnsibleFilterError(f"Variable {var} not found for host {host} in hostvars: {e}") + + return result diff --git a/etc/kayobe/ansible/get-cloud-facts.yml b/etc/kayobe/ansible/get-cloud-facts.yml index e966f8acce..7be9419850 100644 --- a/etc/kayobe/ansible/get-cloud-facts.yml +++ b/etc/kayobe/ansible/get-cloud-facts.yml @@ -1,4 +1,64 @@ --- +- name: Get facts for control host + hosts: localhost + gather_facts: true + tasks: + - name: Check if ngs enabled + ansible.builtin.set_fact: + ngs_enabled: >- + {{ 'genericswitch' in kolla_neutron_ml2_mechanism_drivers | default(false) }} + when: kolla_neutron_ml2_mechanism_drivers + +- name: Get facts for seed node + hosts: seed + gather_facts: true + tasks: + - name: Is there a dedicated seed node? + ansible.builtin.set_fact: + seed_node_is_vm: "{{ ansible_facts.virtualization_role == 'guest' }}" + +- name: Get facts + hosts: all + gather_facts: true + tasks: + - name: Pinging stackhpc.com to check internet connectivity + ansible.builtin.command: "ping stackhpc.com -c 3" + register: successful_ping + timeout: 5 + ignore_errors: true + + - name: Set internet connectivity fact + ansible.builtin.set_fact: + internet_connectivity: "{{ not successful_ping.failed }}" + + - name: Get OS distribution + ansible.builtin.set_fact: + distribution: "{{ ansible_facts.distribution }}" + + - name: Get OS distribution release + ansible.builtin.set_fact: + distribution_release: "{{ ansible_facts.distribution_release }}" + + - name: Get kernel version + ansible.builtin.command: "uname -r" + register: kernel_version + + - name: Check if docker is installed + ansible.builtin.command: "which docker" + register: docker_check + failed_when: docker_check.rc not in [0] + ignore_errors: true + + - name: Get running contianers + ansible.builtin.command: "docker ps --format {% raw %}'{{.Names}}'{% endraw %}" + become: true + register: containers_list + when: not docker_check.failed + + - name: Check if hugepages enabled + ansible.builtin.set_fact: + hugepages_enabled: "{{ 'hugepages' in ansible_facts.cmdline }}" + - name: Gather Cloud Facts hosts: localhost gather_facts: true @@ -6,8 +66,12 @@ - name: Write facts to file vars: cloud_facts: - ansible_control_host_distribution: "{{ ansible_facts.distribution }}" - ansible_control_host_distribution_release: "{{ ansible_facts.distribution_release }}" + internet_connectivity: "{{ hostvars | group_hostvars_by_var('internet_connectivity') }}" + seed_node_is_vm: "{{ hostvars[groups['seed'][0]]['seed_node_is_vm'] | default('N/A') if groups ['seed'] else 'N/A' }}" + distributions: "{{ hostvars | group_hostvars_by_var('distribution') }}" + dist_releases: "{{ hostvars | group_hostvars_by_var('distribution_release') }}" + kernel_versions: "{{ hostvars | group_hostvars_by_var('kernel_version','stdout') }}" + deployed_containers: "{{ hostvars | group_hostvars_by_host('containers_list', 'stdout_lines') | default({}) }}" openstack_release: "{{ openstack_release }}" openstack_release_name: "{{ openstack_release_codename }}" ansible_control_host_is_vm: "{{ ansible_facts.virtualization_role == 'guest' }}" @@ -22,41 +86,10 @@ ceph_release: "{{ cephadm_ceph_release }}" storage_hyperconverged: "{{ groups['controllers'] | intersect(groups['osds']) | length > 0 | bool }}" wazuh_enabled: "{{ groups['wazuh-agent'] | length > 0 | bool }}" + ngs_enabled: "{{ ngs_enabled | default(false) }}" kayobe_managed_switches: "{{ groups['switches'] | length > 0 | bool }}" proxy_configured: "{{ http_proxy | bool or https_proxy | bool }}" bifrost_version: "{{ kolla_bifrost_source_version }}" - barbican_enabled: "{{ kolla_enable_barbican }}" - nova_enabled: "{{ kolla_enable_nova }}" - neutron_enabled: "{{ kolla_enable_neutron }}" - ovs_enabled: "{{ kolla_enable_openvswitch }}" - ovn_enabled: "{{ kolla_enable_ovn }}" - glance_enabled: "{{ kolla_enable_glance }}" - cinder_enabled: "{{ kolla_enable_cinder }}" - keystone_enabled: "{{ kolla_enable_keystone }}" - horizon_enabled: "{{ kolla_enable_horizon }}" - fluentd_enabled: "{{ kolla_enable_fluentd }}" - rabbitmq_enabled: "{{ kolla_enable_rabbitmq }}" - mariadb_enabled: "{{ kolla_enable_mariadb }}" - mariabackup_enabled: "{{ kolla_enable_mariabackup }}" - memcached_enabled: "{{ kolla_enable_memcached }}" - haproxy_enabled: "{{ kolla_enable_haproxy }}" - keepalived_enabled: "{{ kolla_enable_keepalived }}" - octavia_enabled: "{{ kolla_enable_octavia }}" - designate_enabled: "{{ kolla_enable_designate }}" - manila_enabled: "{{ kolla_enable_manila }}" - magnum_enabled: "{{ kolla_enable_magnum }}" - heat_enabled: "{{ kolla_enable_heat }}" - ironic_enabled: "{{ kolla_enable_ironic }}" - skyline_enabled: "{{ kolla_enable_skyline }}" - blazar_enabled: "{{ kolla_enable_blazar }}" - pulp_enabled: "{{ seed_pulp_container_enabled }}" - opensearch_enabled: "{{ kolla_enable_opensearch }}" - opensearch_dashboards_enabled: "{{ kolla_enable_opensearch_dashboards }}" - influxdb_enabled: "{{ kolla_enable_influxdb }}" - grafana_enabled: "{{ kolla_enable_grafana }}" - prometheus_enabled: "{{ kolla_enable_prometheus }}" - cloudkitty_enabled: "{{ kolla_enable_cloudkitty }}" - telegraf_enabled: "{{ kolla_enable_telegraf }}" internal_tls_enabled: "{{ kolla_enable_tls_internal }}" external_tls_enabled: "{{ kolla_enable_tls_external }}" firewalld_enabled_all: >- @@ -82,6 +115,9 @@ stackhpc_package_repos_enabled: "{{ stackhpc_repos_enabled }}" pulp_tls_enabled: "{{ pulp_enable_tls }}" kolla_image_tags: "{{ kolla_image_tags }}" + gpu_passthrough_enabled: "{{ gpu_group_map | length > 0 | bool }}" + vGPU_enabled: "{{ groups['vgpu'] | length > 0 | bool }}" + hugepages_enabled: "{{ hostvars | group_hostvars_by_var('hugepages_enabled') }}" ansible.builtin.copy: content: "{{ cloud_facts | to_nice_json(sort_keys=false) }}" dest: ~/cloud-facts.json