diff --git a/docs/dictionary/en-custom.txt b/docs/dictionary/en-custom.txt index c84c7dec04..e3c22e1e15 100644 --- a/docs/dictionary/en-custom.txt +++ b/docs/dictionary/en-custom.txt @@ -8,6 +8,8 @@ ansibleuser ansiblevars apiversion apivips +appcreds +applicationcredential aqc args arx @@ -24,6 +26,7 @@ basedomain baseimg baseurl bashrc +bd blockquote bmaas bmc @@ -99,6 +102,7 @@ dataplanenodeset dataplanenodesets dd'd ddr +ddthh deepscrub delorean deployer @@ -108,6 +112,7 @@ dev devscripts devsetup dfb +dfce dfg dhcp dib @@ -125,6 +130,7 @@ dnsmasq dockerfile dryrun ecdsa +edecb edploy edpm ee @@ -169,6 +175,7 @@ gzwu haproxy hbmfnzwqkcltnbg hci +hfu hostkey hostname hostnames @@ -207,6 +214,7 @@ jira jmespath jq json +jxe jzxbol kcgpby keepalived @@ -230,6 +238,7 @@ kustomized kuttl kvm lacp +lajly ldp libguestfs libvirt @@ -243,6 +252,7 @@ lkid lmxpynzpcnrdcmfkbwluihnvy localhost localnet +logfile logserver loopback losetup @@ -306,6 +316,7 @@ ntp num nvme nwy +nzgdh oauth oc ocp @@ -328,6 +339,7 @@ openstackdataplane openstackdataplanenodeset openstackdataplanenodesets openstackprovisioner +openstacksdk operatorgroup opn orchestrator @@ -409,8 +421,10 @@ rsa rsync runtime scp +sdk selinux sha +sig skbg skiplist specificities @@ -514,6 +528,7 @@ yml ytm yxivcnvul yyoje +yyyy zlcbwcm zm zpbgugcmjkihbvb diff --git a/docs/source/build-docs.sh b/docs/source/build-docs.sh index 51e83a0be4..4c7df187b9 100755 --- a/docs/source/build-docs.sh +++ b/docs/source/build-docs.sh @@ -13,7 +13,7 @@ cd ${DOCS_DIR}/source SITE_PACKAGES=$(python -c 'import site; print(site.getsitepackages()[0])') # install the cifmw collection from source without dependencies (removes the # need for any symlink) -ansible-galaxy collection install -U -n ../.. -p "${SITE_PACKAGES}" +ansible-galaxy collection install -U ../.. -p "${SITE_PACKAGES}" make clean make html diff --git a/docs/source/usage/01_usage.md b/docs/source/usage/01_usage.md index 1fb8030598..234477773d 100644 --- a/docs/source/usage/01_usage.md +++ b/docs/source/usage/01_usage.md @@ -42,6 +42,8 @@ are shared among multiple roles: - `cifmw_arch_automation_file`: (String) Name of the workflow automation file in the architecture repository. Defaults to `default.yaml` - `cifmw_architecture_scenario`: (String) The selected VA scenario to deploy. +- `cifmw_architecture_wait_condition`: (Dict) Structure defining custom wait_conditions for the automation. +- `cifmw_architecture_user_kustomize`: (Dict) Structure defining user provided kustomization for automation. - `cifmw_ceph_target`: (String) The Ansible inventory group where ceph is deployed. Defaults to `computes`. - `cifmw_run_tests`: (Bool) Specifies whether tests should be executed. Defaults to false. diff --git a/playbooks/nfs.yml b/playbooks/nfs.yml index cd4fd42518..5efd03677b 100644 --- a/playbooks/nfs.yml +++ b/playbooks/nfs.yml @@ -23,9 +23,11 @@ - not cifmw_edpm_deploy_nfs | default('false') | bool ansible.builtin.meta: end_play tasks: - - name: Install nfs-utils package + - name: Install required packages ansible.builtin.package: - name: "nfs-utils" + name: + - nfs-utils + - iptables - name: Configure nfs to use v4 only community.general.ini_file: diff --git a/plugins/doc_fragments/openstack.py b/plugins/doc_fragments/openstack.py deleted file mode 100644 index 038de34a1a..0000000000 --- a/plugins/doc_fragments/openstack.py +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2014, Hewlett-Packard Development Company, L.P. -# GNU General Public License v3.0+ (see COPYING or -# https://www.gnu.org/licenses/gpl-3.0.txt) - - -class ModuleDocFragment(object): - - # Standard openstack documentation fragment - DOCUMENTATION = r""" -options: - cloud: - description: - - Named cloud or cloud config to operate against. - If I(cloud) is a string, it references a named cloud config as defined - in an OpenStack clouds.yaml file. Provides default values for I(auth) - and I(auth_type). This parameter is not needed if I(auth) is provided - or if OpenStack OS_* environment variables are present. - If I(cloud) is a dict, it contains a complete cloud configuration like - would be in a section of clouds.yaml. - type: raw - auth: - description: - - Dictionary containing auth information as needed by the cloud's auth - plugin strategy. For the default I(password) plugin, this would contain - I(auth_url), I(username), I(password), I(project_name) and any - information about domains (for example, I(user_domain_name) or - I(project_domain_name)) if the cloud supports them. - For other plugins, - this param will need to contain whatever parameters that auth plugin - requires. This parameter is not needed if a named cloud is provided or - OpenStack OS_* environment variables are present. - type: dict - auth_type: - description: - - Name of the auth plugin to use. If the cloud uses something other than - password authentication, the name of the plugin should be indicated here - and the contents of the I(auth) parameter should be updated accordingly. - type: str - region_name: - description: - - Name of the region. - type: str - wait: - description: - - Should ansible wait until the requested resource is complete. - type: bool - default: true - timeout: - description: - - How long should ansible wait for the requested resource. - type: int - default: 180 - api_timeout: - description: - - How long should the socket layer wait before timing out for API calls. - If this is omitted, nothing will be passed to the requests library. - type: int - validate_certs: - description: - - Whether or not SSL API requests should be verified. - - Before Ansible 2.3 this defaulted to C(true). - type: bool - aliases: [ verify ] - ca_cert: - description: - - A path to a CA Cert bundle that can be used as part of verifying - SSL API requests. - type: str - aliases: [ cacert ] - client_cert: - description: - - A path to a client certificate to use as part of the SSL transaction. - type: str - aliases: [ cert ] - client_key: - description: - - A path to a client key to use as part of the SSL transaction. - type: str - aliases: [ key ] - interface: - description: - - Endpoint URL type to fetch from the service catalog. - type: str - choices: [ admin, internal, public ] - default: public - aliases: [ endpoint_type ] - sdk_log_path: - description: - - Path to the logfile of the OpenStackSDK. If empty no log is written - type: str - sdk_log_level: - description: Log level of the OpenStackSDK - type: str - default: INFO - choices: [INFO, DEBUG] -requirements: - - "python >= 3.6" - - "openstacksdk >= 1.0.0" -notes: - - The standard OpenStack environment variables, such as C(OS_USERNAME) - may be used instead of providing explicit values. - - Auth information is driven by openstacksdk, which means that values - can come from a yaml config file in /etc/ansible/openstack.yaml, - /etc/openstack/clouds.yaml or ~/.config/openstack/clouds.yaml, then from - standard environment variables, then finally by explicit parameters in - plays. More information can be found at - U(https://docs.openstack.org/openstacksdk/) -""" diff --git a/roles/kustomize_deploy/tasks/execute_step.yml b/roles/kustomize_deploy/tasks/execute_step.yml index c0a0769cf5..7541237991 100644 --- a/roles/kustomize_deploy/tasks/execute_step.yml +++ b/roles/kustomize_deploy/tasks/execute_step.yml @@ -185,18 +185,32 @@ ansible.builtin.command: cmd: "oc apply -f {{ _cr }}" - - name: "Run Wait Conditions for {{ stage.path }}" + - name: "Build Wait Conditions for {{ stage.path }}" when: - not cifmw_kustomize_deploy_generate_crs_only | bool + vars: + _stage_name: "stage_{{ stage_id }}" + _custom_conditions: >- + {{ + cifmw_architecture_wait_condition[_stage_name] | + default([]) + }} + ## TODO: remove "validations" once architecture is up-to-date + _commands: >- + {{ + (stage['wait_conditions'] | + default(stage['validations'])) + _custom_conditions + }} environment: KUBECONFIG: "{{ cifmw_openshift_kubeconfig }}" PATH: "{{ cifmw_path }}" - ansible.builtin.command: - cmd: "{{ wait_condition }}" - ## TODO: remove "validations" once architecture is up-to-date - loop: "{{ stage['wait_conditions'] | default(stage['validations']) }}" - loop_control: - loop_var: wait_condition + block: + - name: "Run Wait Conditions for {{ stage.path }}" + ansible.builtin.command: + cmd: "{{ wait_condition }}" + loop: "{{ _commands }}" + loop_control: + loop_var: wait_condition - name: Stop after applying CRs if requested when: diff --git a/roles/libvirt_manager/molecule/deploy_layout/converge.yml b/roles/libvirt_manager/molecule/deploy_layout/converge.yml index da1094673d..4439b60b46 100644 --- a/roles/libvirt_manager/molecule/deploy_layout/converge.yml +++ b/roles/libvirt_manager/molecule/deploy_layout/converge.yml @@ -14,7 +14,7 @@ # License for the specific language governing permissions and limitations # under the License. -- name: Converge +- name: One hypervisor hosts: instance gather_facts: true vars: @@ -243,7 +243,7 @@ - expected_count == found_count loop: "{{ volume_count.results }}" -- name: Cleanup +- name: Cleanup one hypervisor hosts: instance tasks: - name: Clean layout @@ -251,23 +251,34 @@ name: libvirt_manager tasks_from: clean_layout.yml + - name: Reload clean inventory + ansible.builtin.meta: refresh_inventory + + - name: Expose current hosts + ansible.builtin.debug: + msg: "{{ hostvars.keys() }}" + - name: Inject fake hosts in inventory hosts: instance tasks: - - name: Inject compute-0 in inventory + - name: Inject hypervisor-0 in inventory ansible.builtin.add_host: - name: compute-0 + name: hypervisor-0 + groups: + - hypervisors ansible_host: localhost ansible_connection: local - - name: Inject compute-1 in inventory + - name: Inject hypervisor-1 in inventory ansible.builtin.add_host: - name: compute-1 + name: hypervisor-1 + groups: + - hypervisors ansible_host: localhost ansible_connection: local -- name: Converge - hosts: all +- name: Multiple hypervisors + hosts: hypervisors vars: ansible_user_dir: "{{ lookup('env', 'HOME') }}" cifmw_basedir: "/opt/basedir" @@ -287,7 +298,7 @@ cifmw_libvirt_manager_configuration: vms: computecp0: - target: compute-0 + target: hypervisor-0 amount: 1 disk_file_name: "blank" disksize: 20 @@ -297,7 +308,7 @@ - public - osp_trunk computecp1: - target: compute-1 + target: hypervisor-1 amount: 1 disk_file_name: "blank" disksize: 20 diff --git a/roles/libvirt_manager/tasks/deploy_layout.yml b/roles/libvirt_manager/tasks/deploy_layout.yml index f51f586135..eb9e1af0c8 100644 --- a/roles/libvirt_manager/tasks/deploy_layout.yml +++ b/roles/libvirt_manager/tasks/deploy_layout.yml @@ -84,22 +84,32 @@ loop_control: label: "{{ item.key }}" -- name: Create temporary ssh keypair - community.crypto.openssh_keypair: - path: "{{ ansible_user_dir }}/.ssh/cifmw_reproducer_key" - type: "{{ cifmw_libvirt_manager_reproducer_key_type }}" - size: "{{ cifmw_libvirt_manager_reproducer_key_size }}" - regenerate: full_idempotence +- name: Manage SSH key + vars: + _sshkey: "{{ ansible_user_dir }}/.ssh/cifmw_reproducer_key" + block: + - name: Get ssh key state + register: _keystat + ansible.builtin.stat: + path: "{{ _sshkey }}" + + - name: Create temporary ssh keypair + when: + - not _keystat.stat.exists + community.crypto.openssh_keypair: + path: "{{ _sshkey }}" + type: "{{ cifmw_libvirt_manager_reproducer_key_type }}" + size: "{{ cifmw_libvirt_manager_reproducer_key_size }}" -- name: Slurp public key for later use - register: pub_ssh_key - ansible.builtin.slurp: - path: "{{ ansible_user_dir }}/.ssh/cifmw_reproducer_key.pub" + - name: Slurp public key for later use + register: pub_ssh_key + ansible.builtin.slurp: + path: "{{ _sshkey }}.pub" -- name: Slurp private key for later use - register: priv_ssh_key - ansible.builtin.slurp: - path: "{{ ansible_user_dir }}/.ssh/cifmw_reproducer_key" + - name: Slurp private key for later use + register: priv_ssh_key + ansible.builtin.slurp: + path: "{{ _sshkey }}" - name: Inject cifmw_reproducer_key.pub in hypervisor authorized_keys ansible.posix.authorized_key: @@ -222,6 +232,52 @@ dest: "{{ cifmw_libvirt_manager_basedir }}/artifacts/interfaces-info.yml" content: "{{ cifmw_libvirt_manager_mac_map | to_nice_yaml }}" +- name: Extract VM UUIDs from libvirt + block: + - name: Get all XMLs + register: _all_xmls + community.libvirt.virt: + command: get_xml + name: "{{ item }}" + loop: "{{ _vms.list_vms }}" + + - name: Extract UUIDs from all XMLs + register: _extracted_uuids + community.general.xml: + xmlstring: "{{ vm.get_xml }}" + xpath: "/domain/uuid" + content: text + loop: "{{ _all_xmls.results }}" + loop_control: + label: "{{ vm.item }}" + loop_var: vm + + - name: Build UUIDs fact + vars: + vm_uuid: "{{ xml.matches | first }}" + ansible.builtin.set_fact: + cifmw_libvirt_manager_uuids: >- + {{ + cifmw_libvirt_manager_uuids | default({}) | + combine({xml.vm.item: vm_uuid.uuid}) + }} + loop: "{{ _extracted_uuids.results }}" + loop_control: + label: "{{ xml.vm.item }}" + loop_var: xml + + - name: Dump UUIDs + when: + - cifmw_libvirt_manager_uuids is defined + - cifmw_libvirt_manager_uuids | length > 0 + vars: + _content: + libvirt_uuid: "{{ cifmw_libvirt_manager_uuids }}" + ansible.builtin.copy: + dest: "{{ cifmw_libvirt_manager_basedir }}/artifacts/libvirt-uuids.yml" + content: "{{ _content | to_nice_yaml }}" + mode: "0644" + - name: Refresh and dump vbmc hosts when: - _vbmc_host is defined @@ -232,21 +288,34 @@ name: virtualbmc tasks_from: list_hosts.yml - - name: Dump vbmc known hosts + - name: Update vbmc related fact vars: _auth: username: "{{ cifmw_virtualbmc_ipmi_user | default('admin') }}" password: "{{ cifmw_virtualbmc_ipmi_password | default('password') }}" - _mapped: >- + _map_auth: >- {{ cifmw_virtualbmc_known_hosts | map('combine', _auth) }} + _map_uuid: >- + {% set ns = namespace(output=[]) -%} + {% for host in _map_auth -%} + {% set _uuid = {'uuid': cifmw_libvirt_manager_uuids[host['Domain name']]} -%} + {% set _host = host | combine(_uuid) -%} + {% set _ = ns.output.append(_host) -%} + {% endfor -%} + {{ ns.output }} + ansible.builtin.set_fact: + cifmw_virtualbmc_known_hosts: "{{ _map_uuid }}" + + - name: Dump vbmc known hosts + vars: content: - cifmw_virtualbmc_known_hosts: "{{ _mapped }}" + cifmw_virtualbmc_known_hosts: "{{ cifmw_virtualbmc_known_hosts }}" ansible.builtin.copy: dest: >- - {{ cifmw_libvirt_manager_basedir }}/artifacts/virtualbmc-nodes.yml + {{ cifmw_libvirt_manager_basedir }}/artifacts/virtual-nodes.yml content: "{{ content | to_nice_yaml }}" - name: Ensure we get proper access to CRC diff --git a/roles/reproducer/tasks/configure_controller.yml b/roles/reproducer/tasks/configure_controller.yml index d53224fee7..034e4af6d8 100644 --- a/roles/reproducer/tasks/configure_controller.yml +++ b/roles/reproducer/tasks/configure_controller.yml @@ -106,6 +106,54 @@ dest: "{{ _ctl_reproducer_basedir }}/parameters/interfaces-info.yml" content: "{{ cifmw_libvirt_manager_mac_map | to_nice_yaml }}" + # Here, we update the existing cifmw_virtualbmc_known_hosts fact + # to inject networking information such as provisioning MAC (if any), + # and fixed Boot mode + - name: Generate IPMI information + block: + - name: Convert VBMC list into a dict for better usage + vars: + keys: "{{ item.keys() | difference(['Domain name']) }}" + vals: "{{ keys | map('extract', item) | list }}" + value: "{{ dict(keys | map('lower') | zip(vals)) }}" + _host: "{{ item['Domain name'] | regex_replace('^cifmw-', '') }}" + _nics: >- + {{ + cifmw_libvirt_manager_mac_map[_host] + }} + _uefi: >- + {% set _type = _host | regex_replace('-[0-9]+$', '') -%} + {{ _layout.vms[_type].uefi | default(false) | bool }} + _boot_mode: "{{ _uefi | ternary('UEFI', 'legacy') }}" + ## TODO: add sushy driver address once we get sushy in + ## TODO: create new parameter to allow chosing which connection + # to expose in the generated file + _connections: + ipmi: "ipmi://{{ value.address }}:{{ value.port }}" + ansible.builtin.set_fact: + _ipmi_dict: >- + {{ + _ipmi_dict | default({}) | + combine({_host: value}, recursive=true) | + combine({_host: { + 'boot_mode': _boot_mode, + 'nics': _nics, + 'connection': _connections['ipmi'] + } + }, recursive=true) + }} + cacheable: false + loop: "{{ cifmw_virtualbmc_known_hosts }}" + + - name: Output IPMI data in a file + vars: + _content: + baremetal_nodes: "{{ _ipmi_dict }}" + ansible.builtin.copy: + dest: "{{ _ctl_reproducer_basedir }}/parameters/baremetal-info.yml" + content: "{{ _content | to_nice_yaml }}" + mode: "0644" + - name: Inject other Hypervisor SSH keys when: - hostvars[host]['priv_ssh_key'] is defined