diff --git a/.gitignore b/.gitignore index eb58c89d0..163ec6ea5 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ ansible.log # Ignore user defined playbooks and inventory playbooks/* !playbooks/README.adoc +!playbooks/cephadm_preflight.yaml !playbooks/cluster_setup_*.yaml !playbooks/ci_*.yaml !playbooks/replace_machine_*.yaml diff --git a/DISCONNECTED_DEPLOYMENT.adoc b/DISCONNECTED_DEPLOYMENT.adoc new file mode 100644 index 000000000..22cfd94ab --- /dev/null +++ b/DISCONNECTED_DEPLOYMENT.adoc @@ -0,0 +1,270 @@ +// Copyright (C) 2025 RTE +// SPDX-License-Identifier: Apache-2.0 + += SEAPATH Disconnected Deployment Guide + +This guide explains how to deploy SEAPATH in disconnected environments where the control machine and cluster nodes have no internet access. + +== Overview + +The disconnected deployment uses a control machine that hosts a local container registry containing all necessary images. This registry serves the cluster nodes during deployment, eliminating the need for internet connectivity. + +The implementation uses native `cephadm` commands for Ceph cluster management and registry authentication. When the official `cephadm-ansible` collection becomes available on Ansible Galaxy, it can be integrated for enhanced functionality. + +== Architecture + +[plantuml, architecture-diagram, svg] +.... +┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ +│ Control Node │ │ Hypervisor 1 │ │ Hypervisor 2 │ +│ │ │ │ │ │ +│ ┌─────────────┐ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ +│ │ Registry │ │◄───┤ │ Cephadm │ │ │ │ Cephadm │ │ +│ │ (Port 5000) │ │ │ │ │ │ │ │ │ │ +│ └─────────────┘ │ │ └─────────────┘ │ │ └─────────────┘ │ +│ │ │ │ │ │ +│ ┌─────────────┐ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ +│ │ Images │ │ │ │ OSD │ │ │ │ OSD │ │ +│ │ Storage │ │ │ │ │ │ │ │ │ │ +│ └─────────────┘ │ │ └─────────────┘ │ │ └─────────────┘ │ +└─────────────────┘ └─────────────────┘ └─────────────────┘ +.... + +== Prerequisites + +=== Control Machine Requirements + +* Ansible 2.10+ +* Podman or Docker +* Python modules: `netaddr`, `six` +* `rsync` package +* SSH access to cluster nodes +* Sufficient disk space for container images (~2-3 GB) + +=== Cluster Node Requirements + +* SSH access enabled +* User accounts: `ansible` (Debian) or `admin` (Yocto) +* Network connectivity to control machine +* Pre-installed SEAPATH images + +== Security Configuration + +The disconnected deployment supports several security features: + +=== Registry Authentication + +Enable HTTP Basic Authentication for the registry: + +[source,yaml] +---- +registry_auth_enabled: true +registry_username: "admin" +registry_password: "secure_password" +---- + +=== TLS Encryption + +TLS is enabled by default (`registry_tls_enabled: true`). When no certificate paths are provided, the registry role automatically generates a self-signed CA and server certificate. The CA certificate is then distributed to all cluster nodes so they trust the registry without insecure flags. + +To use auto-generated certificates (default): + +[source,yaml] +---- +registry_tls_enabled: true +---- + +To use your own certificates: + +[source,yaml] +---- +registry_tls_enabled: true +registry_tls_cert: "/path/to/server.crt" +registry_tls_key: "/path/to/server.key" +registry_tls_ca: "/path/to/ca.crt" +---- + +To disable TLS and use plain HTTP (not recommended): + +[source,yaml] +---- +registry_tls_enabled: false +---- + +== Deployment Steps + +=== Phase 1: Prepare Control Machine + +. **Setup Control Registry** ++ +[source,bash] +---- +ansible-playbook -i inventories/examples/seapath-cluster-disconnected.yaml \ + playbooks/setup_control_registry.yaml +---- + +. **Export Images for Offline Use** ++ +[source,bash] +---- +# Images will be exported to /opt/seapath/registry/images/ +/opt/seapath/registry/export_images.sh +---- + +=== Phase 2: Deploy SEAPATH Cluster + +. **Deploy SEAPATH with Disconnected Cephadm** ++ +[source,bash] +---- +ansible-playbook -i inventories/examples/seapath-cluster-disconnected.yaml \ + playbooks/seapath_setup_disconnected.yaml +---- + +== Configuration + +=== Inventory Variables + +Key variables for disconnected deployment: + +[source,yaml] +---- +# Registry configuration +registry_url: "192.168.200.100:5000" # Control machine IP +registry_host: "192.168.200.100" # Control machine IP +disconnected_mode: true # Enable offline mode + +# Force cephadm usage +force_cephadm: true +---- + +=== Registry Management + +The control registry provides several management scripts: + +* **`export_images.sh`**: Export images as tar files for offline use +* **`import_images.sh`**: Import images from tar files +* **`backup_registry.sh`**: Backup registry data and images +* **`restore_registry.sh`**: Restore registry from backup + +== Offline Image Management + +=== Pre-staging Images + +For completely offline environments, pre-stage images on the control machine: + +[source,bash] +---- +# On a machine with internet access +podman pull docker.io/library/registry:2 +podman pull quay.io/ceph/ceph:v20.2.0 + +# Save images to tar files +podman save -o registry-2.tar registry:2 +podman save -o ceph-v20.2.0.tar quay.io/ceph/ceph:v20.2.0 + +# Transfer to control machine +scp *.tar control-machine:/opt/seapath/registry/images/ +---- + +=== Loading Pre-staged Images + +[source,bash] +---- +# On control machine +/opt/seapath/registry/import_images.sh +---- + +== Registry Persistence + +The registry data is stored in `/opt/seapath/registry/data/` and persists across reboots. The registry container is configured with `restart_policy: always`. + +=== Backup and Restore + +[source,bash] +---- +# Create backup +/opt/seapath/registry/backup_registry.sh + +# Restore from backup +/opt/seapath/registry/restore_registry.sh backup_20250101_120000 +---- + +== Troubleshooting + +=== Registry Not Accessible + +. Check if registry container is running: ++ +[source,bash] +---- +podman ps | grep seapath-registry +---- + +. Check registry logs: ++ +[source,bash] +---- +podman logs seapath-registry +---- + +. Verify registry connectivity (use `https` if TLS is enabled, `http` otherwise): ++ +[source,bash] +---- +curl -k https://localhost:5000/v2/ +---- + +=== Image Pull Failures + +. Verify images are available in registry: ++ +[source,bash] +---- +curl -k https://localhost:5000/v2/_catalog +---- + +. Check image tags: ++ +[source,bash] +---- +curl -k https://localhost:5000/v2/ceph/tags/list +---- + +=== Network Connectivity Issues + +. Ensure cluster nodes can reach control machine on port 5000 +. Check firewall rules +. Verify DNS resolution + +== Security Considerations + +* The registry runs in privileged mode for simplicity +* TLS is enabled by default with auto-generated self-signed certificates +* For production deployments, provide your own CA-signed certificates via `registry_tls_cert`, `registry_tls_key`, and `registry_tls_ca` +* Implement proper authentication if needed +* Regular backup of registry data + +== Performance Optimization + +* Use SSD storage for registry data directory +* Consider registry caching for large deployments +* Monitor disk space usage +* Implement registry garbage collection + +== Migration from Online to Offline + +To migrate an existing online deployment to offline: + +. Export current images from online registry +. Setup control registry with exported images +. Update inventory to use control registry +. Redeploy with disconnected playbook + +== Support + +For issues with disconnected deployment: + +* Check SEAPATH Wiki: https://lf-energy.atlassian.net/wiki/spaces/SEAP/ +* Create issue in GitHub repository +* Contact SEAPATH team diff --git a/ansible-requirements.yaml b/ansible-requirements.yaml index 7c366aa74..9b73e3936 100644 --- a/ansible-requirements.yaml +++ b/ansible-requirements.yaml @@ -14,3 +14,7 @@ collections: source: https://opendev.org/openstack/ansible-config_template type: git version: 2.1.1 + - name: ceph.cephadm + source: https://github.com/ceph/cephadm-ansible.git + type: git + version: devel diff --git a/inventories/examples/seapath-cluster-disconnected.yaml b/inventories/examples/seapath-cluster-disconnected.yaml new file mode 100644 index 000000000..3ea8f3103 --- /dev/null +++ b/inventories/examples/seapath-cluster-disconnected.yaml @@ -0,0 +1,213 @@ +# This inventory describes a SEAPATH cluster for disconnected environments +# The control machine hosts the registry and all container images +# Replace all the TODOs to fit your physical machines. + +--- +cluster_machines: + children: + hypervisors: + hosts: + hypervisor1: + # TODO : Replace the variable by your IP or interfaces + + # Admin network settings + ansible_host: 192.168.200.125 + network_interface: eno1 + + # Cluster network settings + team0_0: "eno2" + team0_1: "eno3" + cluster_next_ip_addr : "192.168.55.2" + cluster_previous_ip_addr : "192.168.55.3" + cluster_ip_addr: "192.168.55.1" + + # PTP configuration. + # Optional, remove if the machine is not synchronised with PTP + ptp_interface: "eno12419" + + hypervisor2: + # TODO : Replace the variables by your IP or interfaces + + # Admin network settings + ansible_host: 192.168.200.126 + network_interface: eno1 + + # Cluster network settings + team0_0: "eno2" + team0_1: "eno3" + cluster_next_ip_addr : "192.168.55.3" + cluster_previous_ip_addr : "192.168.55.1" + cluster_ip_addr: "192.168.55.2" + + # PTP configuration. + # Optional, remove if the machine is not synchronised with PTP + ptp_interface: "eno12419" + + vars: + livemigration_user: livemigration + isolcpus: "4-N" # TODO : Put the list of cpus to isolate. + # This variable is only used on Debian. + # On Yocto, it is configured in yocto-bsp + + observers: + hosts: + observer: + # TODO : Replace the variables by your IP or interfaces + + # Admin network settings + ansible_host: 192.168.200.10 + network_interface: enp0s20f0u3u2 + + # Cluster network settings + team0_0: "enp2s0" + team0_1: "enp3s0" + cluster_next_ip_addr : "192.168.55.1" + cluster_previous_ip_addr : "192.168.55.2" + cluster_ip_addr: "192.168.55.3" + br_rstp_priority: 12288 # Do not modify + # This value is needed only on third machine for the RSTP to work + + # PTP configuration. + ptp_interface: "eno12419" + + vars: + # Ansible vars + ansible_connection: ssh + ansible_python_interpreter: /usr/bin/python3 + ansible_remote_tmp: /tmp/.ansible/tmp + ansible_user: ansible # TODO: Put the name of your ansible user + # By default, this user is "ansible" on Debian and "admin" on Yocto + + # Debian specific, remove if you use Yocto + admin_user: admin + + # Main network configuration + gateway_addr: "192.168.200.1" # TODO : Put your gatway address + dns_servers: "192.168.200.1" # TODO : Put your dns address + ip_addr: "{{ ansible_host }}" + hostname: "{{ inventory_hostname }}" + subnet: 24 # TODO : Put your subnet mask in CIDR notation + apply_network_config: true + + # NTP time synchronisation + ntp_servers: + - "185.254.101.25" # public ntp server + - "51.145.123.29" # public ntp server + + # Hardening (Debian only) + # TODO : Put the password hash for the grub password + # It can be generated with the following command: grub-mkpasswd-pbkdf2 + grub_password: grub.pbkdf2.sha512.10000.666FF16D5587509B2B3340B2388CB798BEF9553A9666CECA6282E0D822C1529F94AF693CC6738C1F757B868D8090F24FD48D8F56486C70C545D559CB4BAAAA3E.9718E767036BDB71CC1B82BCFC906610F8772DD4757F6F075D82A23E70DA46FBED372A3E5143E5C2D40AA888C6B884E4AA437488D82008383C54ED79D68A42CF + +# ------------------------------------------------------------------------------ +# ------------------- Disconnected Environment Configuration ------------------ +# ------------------------------------------------------------------------------ + +# Registry configuration +registry_url: "{{ ansible_default_ipv4.address }}" +registry_host: "{{ ansible_default_ipv4.address }}" +registry_mirror_url: "{{ ansible_default_ipv4.address }}" +disconnected_mode: true + +# Registry security (uncomment and configure as needed) +# registry_insecure: false +# registry_username: "admin" +# registry_password: "secure_password" +# registry_ca_cert: "/path/to/registry-ca.crt" + +# Registry TLS (enabled by default with auto-generated certificates) +registry_tls_enabled: true +# To use your own certificates instead of auto-generated: +# registry_tls_cert: "/path/to/server.crt" +# registry_tls_key: "/path/to/server.key" +# registry_tls_ca: "/path/to/ca.crt" + +# Registry authentication (uncomment and configure as needed) +# registry_auth_enabled: true +# registry_auth_htpasswd: "/opt/seapath/registry/htpasswd" + +# ------------------------------------------------------------------------------ +# ------------------- Ceph configuration part ---------------------------------- +# ------------------------------------------------------------------------------ + +# This part contains SEAPATH default ceph configuration for disconnected environments +# Change only the TODOs, Do not change the other variables, unless you know +# exactly what you are doing. + force_cephadm: true # Use cephadm for disconnected environments + ceph_origin: distro + cluster_network: "192.168.55.0/24" # TODO : Replace by the IP range of your cluster + #no_cluster_network: true # if this variable is defined, whatever its value, seapath won't configure the cluster network (neither with RSTP nor HSR) + public_network: "{{ cluster_network }}" + monitor_address: "{{ cluster_ip_addr }}" + configure_firewall: false + ntp_service_enabled: false + dashboard_enabled: false + ceph_conf_overrides: + global: + osd_pool_default_size: "{{ groups['hypervisors'] | length }}" + osd_pool_default_min_size: 2 # TODO + # Set to the minimum number of osd needed to run the cluster + # You probably want 2 in case of a three hypervisors configuration + # And 1 in case of a two hypervisors and one observer + osd_pool_default_pg_num: 128 + osd_pool_default_pgp_num: 128 + osd_crush_chooseleaf_type: 1 + mon_osd_min_down_reporters: 1 + mon: + auth_allow_insecure_global_id_reclaim: false + osd: + osd memory target: 8076326604 + +# Ceph monitor. All machines in the cluster must be part of mons groups +mons: + hosts: + hypervisor1: + hypervisor2: + observer: + +# Ceph OSD. Machines that will be used as OSDs (which will store data) +osds: + hosts: + hypervisor1: + hypervisor2: + vars: + ceph_osd_disk: "/dev/disk/by-path/pci-0000:03:00.0-scsi-0:2:1:0" # TODO + # Set this to the path of the disk that will contains ceph data. + # The path can be found in "/dev/disk/by-path/" + devices: "{{ ceph_osd_disk }}" + +# Ceph clients. All machines in the cluster must be part of clients groups +clients: + hosts: + hypervisor1: + hypervisor2: + observer: + vars: + user_config: true + rbd: + name: "rbd" + application: "rbd" + pg_autoscale_mode: on + target_size_ratio: 1 + pools: + - "{{ rbd }}" + keys: + - name: client.libvirt + caps: + mon: 'profile rbd, allow command "osd blacklist"' + osd: "allow class-read object_prefix rbd_children, profile rbd pool=rbd" + mode: "{{ ceph_keyring_permissions }}" + +# ------------------------------------------------------------------------------ +# ----------------------- Empty groups, prevent warnings ----------------------- +# ------------------------------------------------------------------------------ +grafana-server: +iscsigws: +iscsi-gws: +mdss: +mgrs: +nfss: +rbdmirrors: +rgwloadbalancers: +rgws: +standalone_machine: diff --git a/inventories/examples/seapath-cluster.yaml b/inventories/examples/seapath-cluster.yaml index 121790cf0..f81f59ed2 100644 --- a/inventories/examples/seapath-cluster.yaml +++ b/inventories/examples/seapath-cluster.yaml @@ -96,6 +96,11 @@ mons: node2: node3: vars: + # For external registry (disconnected mode), uncomment these: + # disconnected_mode: true + # registry_url: "192.168.200.100" # Control machine IP + # registry_host: "192.168.200.100" # Control machine IP + # registry_tls_enabled: true # TLS with auto-generated certs (port 443) ceph_origin: distro cluster_network: "192.168.55.0/24" # IP range of your cluster. TODO public_network: "{{ cluster_network }}" diff --git a/playbooks/cephadm_preflight.yaml b/playbooks/cephadm_preflight.yaml new file mode 100644 index 000000000..0809f8684 --- /dev/null +++ b/playbooks/cephadm_preflight.yaml @@ -0,0 +1,118 @@ +# Copyright (C) 2025, RTE (http://www.rte-france.com) +# SPDX-License-Identifier: Apache-2.0 + +# SEAPATH-specific cephadm preflight playbook. +# Prepares hosts for Ceph deployment: installs cephadm, ceph-common, +# and prerequisites. Supports Debian, CentOS/OracleLinux, and Yocto. + +--- +- name: Cephadm preflight + hosts: cluster_machines + become: true + gather_facts: yes + vars: + cephadm_release: "20.2.0" + cephadm_release_name: "tentacle" + cephadm_downloadbinary: false + cephadm_installbinary: false + cephadm_installrepo: false + cephadm_installpackage: false + cephadm_installcommon: false + tasks: + - name: Include distro detection + include_role: + name: detect_seapath_distro + + # === RedHat / CentOS / OracleLinux === + - name: Install Ceph packages (RedHat family) + block: + - name: Add Ceph repository + command: > + {{ '/tmp/cephadm' if not cephadm_installbinary else 'cephadm' }} + add-repo --release {{ cephadm_release_name }} + changed_when: true + when: cephadm_installrepo | bool + + - name: Install cephadm package + command: /tmp/cephadm install + changed_when: true + when: cephadm_installpackage | bool + + - name: Install ceph-common package + command: cephadm install ceph-common + changed_when: true + when: cephadm_installcommon | bool + + - name: Install prerequisite packages (RedHat family) + dnf: + name: + - podman + - lvm2 + - chrony + state: present + when: ansible_os_family == "RedHat" + + # === Debian === + - name: Install Ceph packages (Debian) + block: + - name: Install prerequisite packages (Debian) + apt: + name: + - podman + - lvm2 + - chrony + - gpg + state: present + update_cache: yes + + - name: Ensure keyrings directory exists + file: + path: /etc/apt/keyrings + state: directory + mode: '0755' + + - name: Download Ceph GPG key + get_url: + url: "https://download.ceph.com/keys/release.asc" + dest: /etc/apt/keyrings/ceph-release.asc + mode: '0644' + when: cephadm_installrepo | bool + + - name: Add Ceph repository (Debian) + apt_repository: + repo: "deb [signed-by=/etc/apt/keyrings/ceph-release.asc] https://download.ceph.com/debian-{{ cephadm_release_name }}/ {{ ansible_distribution_release }} main" + state: present + filename: ceph + when: cephadm_installrepo | bool + + - name: Install cephadm (Debian) + apt: + name: cephadm + state: present + when: cephadm_installpackage | bool + + - name: Install ceph-common (Debian) + apt: + name: ceph-common + state: present + when: cephadm_installcommon | bool + when: seapath_distro == "Debian" + + # === Yocto === + - name: Install cephadm binary (Yocto) + block: + - name: Download cephadm binary + get_url: + url: "https://download.ceph.com/rpm-{{ cephadm_release }}/el9/noarch/cephadm" + dest: "/tmp/cephadm" + mode: '0755' + when: cephadm_downloadbinary | bool + + - name: Copy cephadm to /usr/local/bin + copy: + src: "/tmp/cephadm" + dest: "/usr/local/bin/cephadm" + mode: '0755' + remote_src: yes + when: cephadm_installbinary | bool + when: seapath_distro == "Yocto" diff --git a/playbooks/ci_configure.yaml b/playbooks/ci_configure.yaml index 6d646ce95..4cf2519f1 100644 --- a/playbooks/ci_configure.yaml +++ b/playbooks/ci_configure.yaml @@ -17,9 +17,9 @@ - role: ci_reinstalliso when: seapath_distro == "Debian" - role: ci_restoredd - when: seapath_distro == "OracleLinux" + when: ansible_os_family == "RedHat" - role: ci_restore_snapshot - when: seapath_distro != "Debian" and seapath_distro != "OracleLinux" + when: seapath_distro != "Debian" and ansible_os_family != "RedHat" - name: CI configure skip reboot hosts: @@ -30,7 +30,7 @@ ansible.builtin.set_fact: skip_reboot_setup: true skip_reboot_setup_network: true - when: seapath_distro != "CentOS" + when: ansible_os_family != "RedHat" - name: Import seapath_setup_main playbook import_playbook: ./seapath_setup_main.yaml diff --git a/playbooks/cluster_setup_cephadm.yaml b/playbooks/cluster_setup_cephadm.yaml index deb3ed49a..f02a6313c 100644 --- a/playbooks/cluster_setup_cephadm.yaml +++ b/playbooks/cluster_setup_cephadm.yaml @@ -33,6 +33,9 @@ - role: ceph_expansion_lv when: lvm_volumes is defined +- name: Cephadm preflight + import_playbook: cephadm_preflight.yaml + - name: Cephadm hosts: cluster_machines @@ -41,3 +44,7 @@ - detect_seapath_distro - cephadm - deploy_cephfs + vars: + cephadm_registry_url: "{{ registry_url | default('') }}" + cephadm_registry_username: "{{ registry_username | default('') }}" + cephadm_registry_password: "{{ registry_password | default('') }}" diff --git a/playbooks/replace_machine_cephadm.yaml b/playbooks/replace_machine_cephadm.yaml new file mode 100644 index 000000000..2de747e34 --- /dev/null +++ b/playbooks/replace_machine_cephadm.yaml @@ -0,0 +1,159 @@ +# Copyright (C) 2025, RTE (http://www.rte-france.com) +# SPDX-License-Identifier: Apache-2.0 + +# Complete machine replacement workflow using cephadm-ansible modules. +# Drains all Ceph daemons from the old host, removes it, adds the new host, +# and applies OSD specs. +# +# Required extra vars: +# machine_to_remove: inventory name of the host to remove +# machine_to_add: inventory name of the new host to add + +--- +- name: Sanity check + hosts: localhost + tasks: + - name: Exit playbook if no machine_to_remove was given + fail: + msg: "machine_to_remove must be declared" + when: machine_to_remove is undefined + + - name: Exit playbook if no machine_to_add was given + fail: + msg: "machine_to_add must be declared" + when: machine_to_add is undefined + +- name: Prepare new machine + hosts: "{{ machine_to_add }}" + become: true + gather_facts: yes + roles: + - detect_seapath_distro + tasks: + - name: Set up cephadm user on new host + include_role: + name: cephadm + tasks_from: setup_user.yml + +- name: Replace machine in Ceph cluster + hosts: cluster_machines + become: true + vars: + cephadm_release: "20.2.0" + cephadm_image: "{{ (cephadm_registry_url + '/ceph:v' + cephadm_release) if cephadm_registry_url | default('') != '' else 'quay.io/ceph/ceph:v' + cephadm_release }}" + cephadm_registry_url: "" + tasks: + - name: Set facts for replacement + set_fact: + machine_to_remove_hostname: "{{ hostvars[machine_to_remove]['hostname'] }}" + machine_to_add_hostname: "{{ hostvars[machine_to_add]['hostname'] }}" + cephadm_online_node: "{{ (groups['cluster_machines'] | difference([machine_to_remove]))[0] }}" + run_once: true + + # === Phase 1: Drain old host === + - name: Drain host gracefully + ceph.cephadm.ceph_orch_host: + name: "{{ machine_to_remove_hostname }}" + state: drain + delegate_to: "{{ cephadm_online_node }}" + run_once: true + + - name: Wait for all daemons to be drained + command: ceph orch ps {{ machine_to_remove_hostname }} --format json + register: drain_ps_check + until: (drain_ps_check.stdout | from_json | length) == 0 + retries: 60 + delay: 10 + delegate_to: "{{ cephadm_online_node }}" + run_once: true + changed_when: false + + # === Phase 2: Remove old host === + - name: Remove host from Ceph orchestrator + ceph.cephadm.ceph_orch_host: + name: "{{ machine_to_remove_hostname }}" + state: absent + delegate_to: "{{ cephadm_online_node }}" + run_once: true + + - name: Remove node from pacemaker # noqa: run-once[task] + command: "crm_node -R {{ machine_to_remove }} --force" + delegate_to: "{{ cephadm_online_node }}" + run_once: true + changed_when: true + + # === Phase 3: SSH key distribution to new host === + - name: Get ceph public key from cluster + command: cephadm shell -- ceph cephadm get-pub-key + register: cephadm_pub_key_result + delegate_to: "{{ cephadm_online_node }}" + run_once: true + changed_when: false + + - name: Add ceph pubkey to new host + ansible.posix.authorized_key: + user: cephadm + state: present + key: "{{ cephadm_pub_key_result.stdout }}" + delegate_to: "{{ machine_to_add }}" + run_once: true + + # === Phase 4: Add new host to cluster === + - name: Add new host to Ceph orchestrator + ceph.cephadm.ceph_orch_host: + name: "{{ machine_to_add_hostname }}" + address: "{{ hostvars[machine_to_add]['cluster_ip_addr'] }}" + set_admin_label: true + state: present + delegate_to: "{{ cephadm_online_node }}" + run_once: true + + # === Phase 5: Apply OSD spec for new host === + - name: Find cephadm location on new host + command: which cephadm + register: cephadm_path + failed_when: false + changed_when: false + delegate_to: "{{ machine_to_add }}" + run_once: true + environment: + PATH: "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + + - name: Set cephadm binary path + set_fact: + cephadm_bin: "{{ cephadm_path.stdout if cephadm_path.rc == 0 else '/usr/local/bin/cephadm' }}" + run_once: true + + - name: Zap volumes on new host + command: "{{ cephadm_bin }} --image {{ cephadm_image }} ceph-volume lvm zap vg_ceph/lv_ceph" + delegate_to: "{{ machine_to_add }}" + run_once: true + changed_when: true + when: machine_to_add in groups['osds'] + + - name: Determine OSD index for new host + set_fact: + new_osd_index: "{{ groups['osds'].index(machine_to_add) + 1 }}" + run_once: true + when: machine_to_add in groups['osds'] + + - name: Apply OSD service spec for new host + ceph.cephadm.ceph_orch_apply: + spec: "{{ lookup('template', '../roles/cephadm/templates/spec_osd.yaml.j2') }}" + vars: + osd_host: "{{ machine_to_add }}" + osd_index: "{{ new_osd_index }}" + delegate_to: "{{ cephadm_online_node }}" + run_once: true + when: machine_to_add in groups['osds'] + + # === Phase 6: Wait for cluster health === + - name: Confirm cluster is ok + command: ceph status --format=json + register: cephadm_cephs + retries: 60 + delay: 10 + changed_when: false + run_once: true + delegate_to: "{{ cephadm_online_node }}" + until: cephadm_cephs.stdout | from_json | community.general.json_query('health.status') == "HEALTH_OK" diff --git a/playbooks/replace_machine_remove_machine_cephadm.yaml b/playbooks/replace_machine_remove_machine_cephadm.yaml index 23a2b6c9c..89c2d5ca4 100644 --- a/playbooks/replace_machine_remove_machine_cephadm.yaml +++ b/playbooks/replace_machine_remove_machine_cephadm.yaml @@ -1,5 +1,12 @@ # Copyright (C) 2025, RTE (http://www.rte-france.com) # SPDX-License-Identifier: Apache-2.0 + +# Removes a machine from the Ceph cluster using cephadm-ansible modules. +# Uses graceful drain when the machine is online, forced removal otherwise. +# +# Required extra vars: +# machine_to_remove: inventory name of the host to remove + --- - name: Sanity check hosts: localhost @@ -16,18 +23,63 @@ - name: Set fact with hostname of machine_to_remove set_fact: machine_to_remove_hostname: "{{ hostvars[machine_to_remove]['hostname'] }}" + - name: Define first_node excluding machine_to_remove set_fact: first_node: "{{ (groups['cluster_machines'] | difference([machine_to_remove]))[0] }}" - - name: Remove machine from pacemaker-corosync cluster # noqa: run-once[task] - command: "crm_node -R {{ machine_to_remove }} --force" + - name: Check if machine_to_remove is reachable + command: ping -c 1 -W 2 {{ machine_to_remove }} + register: machine_ping + failed_when: false + changed_when: false delegate_to: "{{ first_node }}" run_once: true - changed_when: true - - name: Remove machine from ceph cluster # noqa: run-once[task] + - name: Set machine online status + set_fact: + machine_is_online: "{{ machine_ping.rc == 0 }}" + run_once: true + + # === Graceful drain (if machine is online) === + - name: Drain host gracefully (if online) # noqa: run-once[task] + ceph.cephadm.ceph_orch_host: + name: "{{ machine_to_remove_hostname }}" + state: drain + delegate_to: "{{ first_node }}" + run_once: true + when: machine_is_online | bool + + - name: Wait for all daemons to be drained # noqa: run-once[task] + command: ceph orch ps {{ machine_to_remove_hostname }} --format json + register: drain_ps_check + until: (drain_ps_check.stdout | from_json | length) == 0 + retries: 60 + delay: 10 + delegate_to: "{{ first_node }}" + run_once: true + changed_when: false + when: machine_is_online | bool + + # === Remove host from Ceph === + - name: Remove host from Ceph orchestrator (graceful) # noqa: run-once[task] + ceph.cephadm.ceph_orch_host: + name: "{{ machine_to_remove_hostname }}" + state: absent + delegate_to: "{{ first_node }}" + run_once: true + when: machine_is_online | bool + + - name: Remove host from Ceph orchestrator (forced, offline) # noqa: run-once[task] command: "ceph orch host rm {{ machine_to_remove_hostname }} --force --offline" delegate_to: "{{ first_node }}" run_once: true changed_when: true + when: not (machine_is_online | bool) + + # === Remove from pacemaker === + - name: Remove machine from pacemaker-corosync cluster # noqa: run-once[task] + command: "crm_node -R {{ machine_to_remove }} --force" + delegate_to: "{{ first_node }}" + run_once: true + changed_when: true diff --git a/playbooks/seapath_setup_disconnected.yaml b/playbooks/seapath_setup_disconnected.yaml new file mode 100644 index 000000000..2a5b262cc --- /dev/null +++ b/playbooks/seapath_setup_disconnected.yaml @@ -0,0 +1,94 @@ +# Copyright (C) 2025 RTE +# SPDX-License-Identifier: Apache-2.0 + +# This playbook setup SEAPATH in disconnected environments +# The control machine must have the registry and images pre-staged + +--- +- name: Setup registry for disconnected deployment + hosts: localhost + become: true + gather_facts: true + roles: + - registry + vars: + registry_offline_mode: "{{ disconnected_mode | default(false) }}" + registry_images: + - name: "ceph" + tag: "v{{ cephadm_release }}" + source: "quay.io/ceph/ceph" + tar_file: "ceph-v{{ cephadm_release }}.tar" + - name: "registry" + tag: "2" + source: "docker.io/library/registry" + tar_file: "registry-2.tar" + +- name: Detect Seapath distribution + hosts: + - cluster_machines + - standalone_machine + - VMs + roles: + - detect_seapath_distro + +- name: Import seapath_setup_prerequisredhat playbook + import_playbook: seapath_setup_prerequisredhat.yaml + when: ansible_os_family == "RedHat" + +- name: Import seapath_setup_prerequisdebian playbook + import_playbook: seapath_setup_prerequisdebian.yaml + when: seapath_distro == "Debian" + +- name: Import seapath_setup_cockpit_plugins playbook + import_playbook: seapath_setup_cockpit_plugins.yaml + when: seapath_distro != "Yocto" + +- name: Import seapath_setup_prerequisyocto playbook + import_playbook: seapath_setup_prerequisyocto.yaml + when: seapath_distro == "Yocto" + +- name: Import seapath_setup_network playbook + import_playbook: seapath_setup_network.yaml + +- name: Import seapath_setup_timemaster playbook + import_playbook: seapath_setup_timemaster.yaml + +- name: Import seapath_setup_libvirt playbook + import_playbook: seapath_setup_libvirt.yaml + +- name: Import seapath_setup_snmp playbook + import_playbook: seapath_setup_snmp.yaml + +- name: Import cluster_setup_ceph playbook + import_playbook: cluster_setup_ceph.yaml + when: not is_using_cephadm | bool + +- name: Import cluster_setup_cephadm playbook + import_playbook: cluster_setup_cephadm.yaml + when: is_using_cephadm | bool + +- name: Import cluster_setup_libvirt playbook + import_playbook: cluster_setup_libvirt.yaml + +- name: Import cluster_setup_users playbook + import_playbook: cluster_setup_users.yaml + +- name: Import cluster_setup_ha playbook + import_playbook: cluster_setup_ha.yaml + +- name: Import seapath_setup_vmmgrapi playbook + import_playbook: seapath_setup_vmmgrapi.yaml + +- name: Restart all hosts + hosts: + - cluster_machines + - standalone_machine + become: true + tasks: + - name: Restart to configure SEAPATH + reboot: + when: + - skip_reboot_setup is not defined or not skip_reboot_setup + - name: Wait for host to be online + wait_for_connection: + timeout: 300 diff --git a/playbooks/seapath_setup_main.yaml b/playbooks/seapath_setup_main.yaml index 63340fa0d..ddb7976cd 100644 --- a/playbooks/seapath_setup_main.yaml +++ b/playbooks/seapath_setup_main.yaml @@ -17,13 +17,9 @@ roles: - detect_seapath_distro -- name: Import seapath_setup_prerequiscentos playbook - import_playbook: seapath_setup_prerequiscentos.yaml - when: seapath_distro == "CentOS" - -- name: Import seapath_setup_prerequisoraclelinux playbook - import_playbook: seapath_setup_prerequisoraclelinux.yaml - when: seapath_distro == "OracleLinux" +- name: Import seapath_setup_prerequisredhat playbook + import_playbook: seapath_setup_prerequisredhat.yaml + when: ansible_os_family == "RedHat" - name: Import seapath_setup_prerequisdebian playbook import_playbook: seapath_setup_prerequisdebian.yaml diff --git a/playbooks/seapath_setup_prerequiscentos.yaml b/playbooks/seapath_setup_prerequiscentos.yaml deleted file mode 100644 index 7bc369582..000000000 --- a/playbooks/seapath_setup_prerequiscentos.yaml +++ /dev/null @@ -1,79 +0,0 @@ -# Copyright (C) 2024 Red Hat, Inc. -# SPDX-License-Identifier: Apache-2.0 - -- name: Prerequis machine centos - gather_facts: true - hosts: - - cluster_machines - - standalone_machine - - VMs - become: true - roles: - - centos -- name: Prerequis physical machine centos - hosts: - - cluster_machines - - standalone_machine - become: true - roles: - - centos_physical_machine -- name: Prerequis hypervisor centos - hosts: - - hypervisors - - standalone_machine - become: true - roles: - - centos_hypervisor - -- name: Add admin user to haclient group - hosts: - - cluster_machines - become: true - tasks: - - name: Add admin user to haclient group - user: - name: "{{ admin_user }}" - groups: haclient - append: yes - -- name: Disable libvirt-guests.service - hosts: - - cluster_machines - become: true - tasks: - - name: Disable libvirt-guests.service - ansible.builtin.systemd: - name: libvirt-guests.service - enabled: no - state: stopped - -- name: Upload extra files - hosts: - - cluster_machines - - standalone_machine - - VMs - become: true - tasks: - - name: Upload extra files - copy: - src: "{{ item.src }}" - dest: "{{ item.dest }}" - owner: "{{ item.owner | default('root') }}" - group: "{{ item.group | default('root') }}" - mode: "{{ item.mode | default('0644') }}" - backup: yes - with_items: "{{ upload_files }}" - when: - - upload_files is defined - - item.extract is not defined or item.extract is false - - name: Upload extra files and extract them - unarchive: - src: "{{ item.src }}" - dest: "{{ item.dest }}" - owner: "{{ item.owner | default('root') }}" - group: "{{ item.group | default('root') }}" - mode: "{{ item.mode | default('0644') }}" - with_items: "{{ upload_files }}" - when: - - upload_files is defined - - item.extract is defined and item.extract is true diff --git a/playbooks/seapath_setup_prerequisoraclelinux.yaml b/playbooks/seapath_setup_prerequisredhat.yaml similarity index 85% rename from playbooks/seapath_setup_prerequisoraclelinux.yaml rename to playbooks/seapath_setup_prerequisredhat.yaml index d8ac8d13f..b64c4d5e0 100644 --- a/playbooks/seapath_setup_prerequisoraclelinux.yaml +++ b/playbooks/seapath_setup_prerequisredhat.yaml @@ -1,7 +1,8 @@ +# Copyright (C) 2024 Red Hat, Inc. # Copyright (C) 2025 RTE # SPDX-License-Identifier: Apache-2.0 -- name: Prerequis machine oraclelinux +- name: Prerequis machine redhat gather_facts: true hosts: - cluster_machines @@ -9,27 +10,27 @@ - VMs become: true roles: - - oraclelinux -- name: Prerequis physical machine oraclelinux + - redhat +- name: Prerequis physical machine redhat hosts: - cluster_machines - standalone_machine become: true roles: - - oraclelinux_physical_machine -- name: Prerequis physical machine oraclelinux + - redhat_physical_machine +- name: Prerequis physical machine backup/restore hosts: - cluster_machines become: true roles: - backup_restore -#- name: Prerequis hypervisor oraclelinux -# hosts: -# - hypervisors -# - standalone_machine -# become: true -# roles: -# - oraclelinux_hypervisor +- name: Prerequis hypervisor redhat + hosts: + - hypervisors + - standalone_machine + become: true + roles: + - redhat_hypervisor - name: Add admin user to haclient group hosts: diff --git a/playbooks/test_deploy_cukinia_tests.yaml b/playbooks/test_deploy_cukinia_tests.yaml index 031468699..c75802415 100644 --- a/playbooks/test_deploy_cukinia_tests.yaml +++ b/playbooks/test_deploy_cukinia_tests.yaml @@ -23,5 +23,5 @@ roles: - role: debian_tests when: seapath_distro == "Debian" - - role: oraclelinux_tests - when: seapath_distro == "OracleLinux" + - role: redhat_tests + when: ansible_os_family == "RedHat" diff --git a/playbooks/test_run_cukinia.yaml b/playbooks/test_run_cukinia.yaml index 4667452c1..031f2d3d2 100644 --- a/playbooks/test_run_cukinia.yaml +++ b/playbooks/test_run_cukinia.yaml @@ -13,7 +13,7 @@ roles: - detect_seapath_distro tasks: - - include_vars: "../vars/{{ seapath_distro }}_paths.yml" + - include_vars: "../vars/{{ ansible_os_family }}_paths.yml" - name: Cukinia tests hosts: diff --git a/roles/centos/README.md b/roles/centos/README.md deleted file mode 100644 index 83d05b626..000000000 --- a/roles/centos/README.md +++ /dev/null @@ -1,28 +0,0 @@ -# centos Role - -This role apply the basic SEAPATH prerequisites for any CentOS machine - -## Requirements - -no requirement. - -## Role Variables - -| Variable | Required | Type | Comments | -|----------------------|----------|-------------|--------------------------------------------------------------------| -| syslog_tls_ca | No | String | Syslog TLS public key | -| syslog_tls_key | No | String | Syslog TLS private key | -| syslog_tls_server_ca | No | String | Syslog TLS CA | -| admin_user | Yes | String | User to use for administration | -| admin_passwd | No | String | Optional user password | -| admin_ssh_keys | No | String list | List of SSH public keys used to connect to the administration user | -| grub_append | No | String list | List of extra kernel parameters | -| syslog_server_ip | No | String | IP address of the Syslog server to send logs | - -## Example Playbook - -```yaml -- hosts: cluster_machines - roles: - - { role: seapath_ansible.centos } -``` diff --git a/roles/centos/handlers/main.yml b/roles/centos/handlers/main.yml deleted file mode 100644 index 97db5c8f8..000000000 --- a/roles/centos/handlers/main.yml +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (C) 2024 Red Hat, Inc. -# SPDX-License-Identifier: Apache-2.0 - -- name: Daemon-reload - ansible.builtin.service: - daemon_reload: yes - -- name: Restart syslog-ng - ansible.builtin.systemd: - name: syslog-ng - state: restarted - -- name: Restart systemd-journald - ansible.builtin.systemd: - name: systemd-journald - state: restarted - -- name: Update Grub - command: grub2-mkconfig -o /boot/grub2/grub.cfg - changed_when: true diff --git a/roles/centos/tasks/main.yml b/roles/centos/tasks/main.yml deleted file mode 100644 index ea24418ca..000000000 --- a/roles/centos/tasks/main.yml +++ /dev/null @@ -1,200 +0,0 @@ -# Copyright (C) 2024 RTE -# Copyright (C) 2024 Red Hat, Inc. -# SPDX-License-Identifier: Apache-2.0 - ---- -- name: Disable vim defaults - lineinfile: - dest: /etc/vimrc - regexp: '^"? *let g:skip_defaults_vim = 1$' - line: "let g:skip_defaults_vim = 1" - state: present -- name: Vim color syntax - lineinfile: - dest: /etc/vimrc - regexp: '^"? *syntax on$' - line: "syntax on" - state: present -- name: Remove vimrc.local file - file: - path: /etc/vimrc.local - state: absent - -- name: Create /var/log/syslog-ng folder on hosts - file: - path: /var/log/syslog-ng - state: directory - mode: '0755' -- name: Copy syslog-ng conf file - template: - src: syslog-ng.conf.j2 - dest: /etc/syslog-ng/syslog-ng.conf - mode: '0644' - notify: Restart syslog-ng -- when: - - syslog_tls_ca is defined - - syslog_tls_key is defined - - syslog_tls_server_ca is defined - block: - - name: Create /etc/syslog-ng/cert.d - file: - path: /etc/syslog-ng/cert.d - state: directory - mode: '0755' - notify: Restart syslog-ng - - name: Create /etc/syslog-ng/ca.d - file: - path: /etc/syslog-ng/ca.d/ - state: directory - mode: '0755' - notify: Restart syslog-ng - - name: Copy syslog client certificate - ansible.builtin.copy: - src: "{{ syslog_tls_ca }}" - dest: /etc/syslog-ng/cert.d/clientcert.pem - mode: '0644' - notify: Restart syslog-ng - - name: Copy syslog key - ansible.builtin.copy: - src: "{{ syslog_tls_key }}" - dest: /etc/syslog-ng/cert.d/clientkey.pem - mode: '0400' - notify: Restart syslog-ng - - name: Copy syslog server ca - ansible.builtin.copy: - src: "{{ syslog_tls_server_ca }}" - dest: /etc/syslog-ng/ca.d/serverca.pem - mode: '0644' - notify: Restart syslog-ng - -- name: Copy journald conf file - ansible.builtin.copy: - src: journald.conf - dest: /etc/systemd/journald.conf - mode: '0644' - notify: Restart systemd-journald - -- name: Ensure admin group exists - ansible.builtin.group: - name: "{{ admin_user }}" - state: present - gid: 1000 -- name: Adding admin user - user: - name: "{{ admin_user }}" - shell: /bin/bash - group: "{{ admin_user }}" - uid: 1000 - password: "{{ admin_passwd | default(omit) }}" - append: no -- name: Add authorized keys to admin user - ansible.posix.authorized_key: - user: "{{ admin_user }}" - key: "{{ item }}" - with_items: "{{ admin_ssh_keys }}" - when: admin_ssh_keys is defined and admin_ssh_keys is iterable -- name: Install sudo admin user rules - copy: - content: | - {{ admin_user }} ALL=NOPASSWD:EXEC: ALL - dest: "/etc/sudoers.d/{{ admin_user }}" - owner: root - group: root - mode: '0440' -- name: Remove admin sudoers line created by build_debian_iso - lineinfile: - dest: /etc/sudoers - state: absent - regexp: '^{{ admin_user }}' - validate: visudo -cf %s - -- name: Copy sysctl rules - ansible.builtin.copy: - src: sysctl/{{ item }} - dest: /etc/sysctl.d/{{ item }} - mode: '0644' - with_items: - - 00-panicreboot.conf - -- name: Customize /etc/environment - ansible.builtin.lineinfile: - dest: "/etc/environment" - state: present - regexp: "^{{ item.key }}=" - line: "{{ item.key }}={{ item.value }}" - vars: - env_list: - HISTSIZE: 2000000 - HISTFILESIZE: 2000000 - LIBVIRT_DEFAULT_URI: "qemu:///system" - HISTTIMEFORMAT: '"%F %T "' - EDITOR: 'vim' - SYSTEMD_EDITOR: 'vim' - with_items: "{{ env_list | dict2items }}" - -- name: "PATH for admin user" - lineinfile: - dest: "/home/{{ admin_user }}/.bash_profile" - regexp: '^export PATH' - line: "export PATH=$PATH:/usr/sbin:/usr/local/sbin:/sbin" - state: present - create: yes - owner: "{{ admin_user }}" - group: "{{ admin_user }}" - mode: '0644' - -- name: Remove GRUB_CMDLINE_LINUX_DEFAULT option in grub conf - lineinfile: - dest: /etc/default/grub - regexp: "^GRUB_CMDLINE_LINUX_DEFAULT=" - state: absent - -- name: Make sure GRUB_CMDLINE_LINUX starts with a space - lineinfile: - dest: /etc/default/grub - regexp: "^(GRUB_CMDLINE_LINUX=)\"([ ]*)(.*)\"" - line: '\1" \3"' - state: present - backrefs: yes - -- name: Grub conf - lineinfile: - dest: /etc/default/grub - regexp: "^(GRUB_CMDLINE_LINUX=(?!.* {{ item }})\"[^\"]*)(\".*)" - line: '\1 {{ item }}\2' - state: present - backrefs: yes - notify: Update Grub - with_items: - - ipv6.disable=1 - - efi=runtime - - fsck.mode=force - - fsck.repair=yes - - "{{ grub_append | default([]) }}" - -- name: Grub conf osprober - lineinfile: - dest: /etc/default/grub - regexp: '^#?GRUB_DISABLE_OS_PROBER=.*$' - line: 'GRUB_DISABLE_OS_PROBER=true' - state: present - notify: Update Grub - -- name: Stop and Disable NetworkManager - service: - name: NetworkManager - state: stopped - enabled: no - register: centos_nm_stop - -- name: Start and Enable systemd-networkd - service: - name: systemd-networkd - state: started - enabled: yes - register: centos_sd_start - -- name: Set need_reboot to true if any change was made - set_fact: - need_reboot: true # noqa: var-naming[no-role-prefix] - when: centos_nm_stop is changed or centos_sd_start is changed diff --git a/roles/centos/templates/sources.list.j2 b/roles/centos/templates/sources.list.j2 deleted file mode 100644 index 7ed5626e2..000000000 --- a/roles/centos/templates/sources.list.j2 +++ /dev/null @@ -1,3 +0,0 @@ -{% for repo in apt_repo %} -deb {{ repo }} -{% endfor %} diff --git a/roles/centos/templates/syslog-ng.conf.j2 b/roles/centos/templates/syslog-ng.conf.j2 deleted file mode 100644 index 23cb14a05..000000000 --- a/roles/centos/templates/syslog-ng.conf.j2 +++ /dev/null @@ -1,86 +0,0 @@ -@version: 3.27 -# Copyright (C) 2022, RTE (http://www.rte-france.com) -# SPDX-License-Identifier: Apache-2.0 - -# First, set some global options. -options { - chain_hostnames(off); - flush_lines(0); - use_dns(no); - dns_cache(no); - use_fqdn(no); - owner("root"); - group("adm"); - perm(0640); - stats_freq(0); - bad_hostname("^gconfd$"); -}; - -######################## -# Sources -######################## -# This is the default behavior of sysklogd package -# Logs may come from unix stream, but not from another machine. -# -source s_src { - systemd_journal(); - internal(); - file("/proc/kmsg" program_override("kernel")); -}; - -######################## -# Destinations -######################## -destination d_syslog { file("/var/log/syslog-ng/syslog.local"); }; - -{% if syslog_server_ip is defined %} -# Network destination -# mem-buff-size is set to 163840000 ~= 156MB (default value) -# disk-buf-size is set to 1073741824 = 1GB -destination d_net { - network( - "{{ syslog_server_ip }}" -{% if syslog_tls_ca is defined and syslog_tls_key is defined %} - port({{ syslog_tls_port | default(6514) }}) - transport("tls") - tls( - key-file("/etc/syslog-ng/cert.d/clientkey.pem") - cert-file("/etc/syslog-ng/cert.d/clientcert.pem") - ca-dir("/etc/syslog-ng/ca.d") - ) -{% else %} - port({{ syslog_tcp_port | default(601) }}) - transport("tcp") -{% endif %} - time_zone("UTC") - disk-buffer( - mem-buf-size(16384000) - disk-buf-size(107374182) - reliable(yes) - dir("/var/log/syslog-ng") - ) - ); - }; -{% endif %} - -######################## -# Log paths -######################## -{% if syslog_local is defined %} -log { - source(s_src); - destination(d_syslog); -}; -{% endif %} -{% if syslog_server_ip is defined %} -log { - source(s_src); -{% if ansible_distribution == 'Debian' and ansible_distribution_version | int < 12 %} - if (program("libvirtd")) { - rewrite { set-facility("daemon"); }; - }; -{% endif %} - destination(d_net); -}; -{% endif %} - diff --git a/roles/centos_physical_machine/README.md b/roles/centos_physical_machine/README.md deleted file mode 100644 index bdbce508a..000000000 --- a/roles/centos_physical_machine/README.md +++ /dev/null @@ -1,28 +0,0 @@ -# CentOS Physical Machine Role - -This role applies the SEAPATH prerequisites for any Debian physical machine (hypervisor, observer, or standalone). - -## Requirements - -No requirement. - -## Role Variables - -| Variable | Required | Type | Default | Comments | -|--------------------------------|-----------|-------------|---------|---------------------------------------------------------------------------------------------------------------------------| -| extra_sysctl_physical_machines | No | String | | Custom systctl configuration separate by new spaces | -| extra_kernel_modules | No | String list | | List of Kernel modules to load when booting | -| admin_user | Yes | String | | Administrator Unix username | -| logstash_server_ip | No | String | | Address IP of the logstash server | -| pacemaker_shutdown_timeout | No | String | 2min | Custom timeout for stopping the systemd Pacemaker service. Time is in seconds, but support the min suffix to use minutes. | -| chrony_wait_timeout_sec | No | String | 180 | Custom timeout for stopping the systemd Chrony service. Time is in seconds, but support the min suffix to use minutes. | -| | | | | | -| unbind_pci_address | no | String list | | List of PCI addresses to "unbind". | - -## Example Playbook - -```yaml -- hosts: cluster_machines - roles: - - { role: seapath_ansible.centos_physical_machine } -``` diff --git a/roles/centos_physical_machine/files/69-lvm.rules b/roles/centos_physical_machine/files/69-lvm.rules deleted file mode 100644 index 6544dccf9..000000000 --- a/roles/centos_physical_machine/files/69-lvm.rules +++ /dev/null @@ -1,94 +0,0 @@ -# Copyright (C) 2012,2021 Red Hat, Inc. All rights reserved. -# -# This file is part of LVM. -# -# This rule requires blkid to be called on block devices before so only devices -# used as LVM PVs are processed (ID_FS_TYPE="LVM2_member"). - -SUBSYSTEM!="block", GOTO="lvm_end" - - -ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", GOTO="lvm_end" - -# Only process devices already marked as a PV - this requires blkid to be called before. -ENV{ID_FS_TYPE}!="LVM2_member", GOTO="lvm_end" -ENV{DM_MULTIPATH_DEVICE_PATH}=="1", GOTO="lvm_end" -ACTION=="remove", GOTO="lvm_end" - -# Create /dev/disk/by-id/lvm-pv-uuid- symlink for each PV -ENV{ID_FS_UUID_ENC}=="?*", SYMLINK+="disk/by-id/lvm-pv-uuid-$env{ID_FS_UUID_ENC}" - -# If the PV is a special device listed below, scan only if the device is -# properly activated. These devices are not usable after an ADD event, -# but they require an extra setup and they are ready after a CHANGE event. -# Also support coldplugging with ADD event but only if the device is already -# properly activated. -# This logic should be eventually moved to rules where those particular -# devices are processed primarily (MD and loop). - -# DM device: -KERNEL!="dm-[0-9]*", GOTO="next" -ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}=="1", ENV{DM_ACTIVATION}=="1", GOTO="lvm_scan" -GOTO="lvm_end" - -# MD device: -LABEL="next" -KERNEL!="md[0-9]*", GOTO="next" -IMPORT{db}="LVM_MD_PV_ACTIVATED" -ACTION=="add", ENV{LVM_MD_PV_ACTIVATED}=="1", GOTO="lvm_scan" -ACTION=="change", ENV{LVM_MD_PV_ACTIVATED}!="1", TEST=="md/array_state", ENV{LVM_MD_PV_ACTIVATED}="1", GOTO="lvm_scan" -ACTION=="add", KERNEL=="md[0-9]*p[0-9]*", GOTO="lvm_scan" -ENV{LVM_MD_PV_ACTIVATED}!="1", ENV{SYSTEMD_READY}="0" -GOTO="lvm_end" - -# Loop device: -LABEL="next" -KERNEL!="loop[0-9]*", GOTO="next" -ACTION=="add", ENV{LVM_LOOP_PV_ACTIVATED}=="1", GOTO="lvm_scan" -ACTION=="change", ENV{LVM_LOOP_PV_ACTIVATED}!="1", TEST=="loop/backing_file", ENV{LVM_LOOP_PV_ACTIVATED}="1", GOTO="lvm_scan" -ENV{LVM_LOOP_PV_ACTIVATED}!="1", ENV{SYSTEMD_READY}="0" -GOTO="lvm_end" - -LABEL="next" -ACTION!="add", GOTO="lvm_end" - -LABEL="lvm_scan" - -ENV{SYSTEMD_READY}="1" - -# pvscan will check if this device completes a VG, -# i.e. all PVs in the VG are now present with the -# arrival of this PV. If so, it prints to stdout: -# LVM_VG_NAME_COMPLETE='foo' -# -# When the VG is complete it can be activated, so -# vgchange -aay is run. It is run via -# systemd since it can take longer to run than -# udev wants to block when processing rules. -# (if there are hundreds of LVs to activate, -# the vgchange can take many seconds.) -# -# pvscan only reads the single device specified, -# and uses temp files under /run/lvm to check if -# other PVs in the VG are present. -# -# If event_activation=0 in lvm.conf, this pvscan -# (using checkcomplete) will do nothing, so that -# no event-based autoactivation will be happen. -# -# TODO: adjust the output of vgchange -aay so that -# it's better suited to appearing in the journal. - -IMPORT{program}="/sbin/lvm pvscan --cache --listvg --checkcomplete --vgonline --autoactivation event --udevoutput --journal=output $env{DEVNAME}" -TEST!="/run/systemd/system", GOTO="lvm_direct_vgchange" - -ENV{LVM_VG_NAME_COMPLETE}=="?*", RUN+="/usr/bin/systemd-run --no-block --property DefaultDependencies=no --unit lvm-activate-$env{LVM_VG_NAME_COMPLETE} /sbin/lvm vgchange -aay --autoactivation event $env{LVM_VG_NAME_COMPLETE}" -GOTO="lvm_end" - -LABEL="lvm_direct_vgchange" -ENV{LVM_VG_NAME_COMPLETE}=="?*", RUN+="/sbin/lvm vgchange -aay --autoactivation event $env{LVM_VG_NAME_COMPLETE}" -TEST!="/run/initramfs", GOTO="lvm_end" -ENV{LVM_VG_NAME_INCOMPLETE}=="?*", RUN+="/sbin/lvm vgchange --sysinit -aay --activation degraded $env{LVM_VG_NAME_INCOMPLETE}" -GOTO="lvm_end" - -LABEL="lvm_end" diff --git a/roles/centos_physical_machine/files/modules/netfilter.conf b/roles/centos_physical_machine/files/modules/netfilter.conf deleted file mode 100644 index 26d1e93c2..000000000 --- a/roles/centos_physical_machine/files/modules/netfilter.conf +++ /dev/null @@ -1,2 +0,0 @@ -br_netfilter -raid6_pq diff --git a/roles/centos_physical_machine/files/pacemaker_ra/VirtualDomain b/roles/centos_physical_machine/files/pacemaker_ra/VirtualDomain deleted file mode 100755 index 3bbdc56f5..000000000 --- a/roles/centos_physical_machine/files/pacemaker_ra/VirtualDomain +++ /dev/null @@ -1,1201 +0,0 @@ -#!/bin/sh -# -# Support: users@clusterlabs.org -# License: GNU General Public License (GPL) -# -# Resource Agent for domains managed by the libvirt API. -# Requires a running libvirt daemon (libvirtd). -# -# (c) 2008-2010 Florian Haas, Dejan Muhamedagic, -# and Linux-HA contributors -# -# usage: $0 {start|stop|status|monitor|migrate_to|migrate_from|meta-data|validate-all} -# -####################################################################### -# Initialization: -: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat} -. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs - -# Defaults -OCF_RESKEY_config_default="" -OCF_RESKEY_migration_transport_default="" -OCF_RESKEY_migration_downtime_default=0 -OCF_RESKEY_migration_speed_default=0 -OCF_RESKEY_migration_network_suffix_default="" -OCF_RESKEY_force_stop_default=0 -OCF_RESKEY_monitor_scripts_default="" -OCF_RESKEY_autoset_utilization_cpu_default="true" -OCF_RESKEY_autoset_utilization_host_memory_default="true" -OCF_RESKEY_autoset_utilization_hv_memory_default="true" -OCF_RESKEY_unset_utilization_cpu_default="false" -OCF_RESKEY_unset_utilization_host_memory_default="false" -OCF_RESKEY_unset_utilization_hv_memory_default="false" -OCF_RESKEY_migrateport_default=$(( 49152 + $(ocf_maybe_random) % 64 )) -OCF_RESKEY_CRM_meta_timeout_default=90000 -OCF_RESKEY_save_config_on_stop_default=false -OCF_RESKEY_sync_config_on_stop_default=false -OCF_RESKEY_snapshot_default="" -OCF_RESKEY_backingfile_default="" -OCF_RESKEY_stateless_default="false" -OCF_RESKEY_copyindirs_default="" -OCF_RESKEY_shutdown_mode_default="" -OCF_RESKEY_start_resources_default="false" -OCF_RESKEY_seapath_default="false" - -: ${OCF_RESKEY_config=${OCF_RESKEY_config_default}} -: ${OCF_RESKEY_migration_transport=${OCF_RESKEY_migration_transport_default}} -: ${OCF_RESKEY_migration_downtime=${OCF_RESKEY_migration_downtime_default}} -: ${OCF_RESKEY_migration_speed=${OCF_RESKEY_migration_speed_default}} -: ${OCF_RESKEY_migration_network_suffix=${OCF_RESKEY_migration_network_suffix_default}} -: ${OCF_RESKEY_force_stop=${OCF_RESKEY_force_stop_default}} -: ${OCF_RESKEY_monitor_scripts=${OCF_RESKEY_monitor_scripts_default}} -: ${OCF_RESKEY_autoset_utilization_cpu=${OCF_RESKEY_autoset_utilization_cpu_default}} -: ${OCF_RESKEY_autoset_utilization_host_memory=${OCF_RESKEY_autoset_utilization_host_memory_default}} -: ${OCF_RESKEY_autoset_utilization_hv_memory=${OCF_RESKEY_autoset_utilization_hv_memory_default}} -: ${OCF_RESKEY_unset_utilization_cpu=${OCF_RESKEY_unset_utilization_cpu_default}} -: ${OCF_RESKEY_unset_utilization_host_memory=${OCF_RESKEY_unset_utilization_host_memory_default}} -: ${OCF_RESKEY_unset_utilization_hv_memory=${OCF_RESKEY_unset_utilization_hv_memory_default}} -: ${OCF_RESKEY_migrateport=${OCF_RESKEY_migrateport_default}} -: ${OCF_RESKEY_CRM_meta_timeout=${OCF_RESKEY_CRM_meta_timeout_default}} -: ${OCF_RESKEY_save_config_on_stop=${OCF_RESKEY_save_config_on_stop_default}} -: ${OCF_RESKEY_sync_config_on_stop=${OCF_RESKEY_sync_config_on_stop_default}} -: ${OCF_RESKEY_snapshot=${OCF_RESKEY_snapshot_default}} -: ${OCF_RESKEY_backingfile=${OCF_RESKEY_backingfile_default}} -: ${OCF_RESKEY_stateless=${OCF_RESKEY_stateless_default}} -: ${OCF_RESKEY_copyindirs=${OCF_RESKEY_copyindirs_default}} -: ${OCF_RESKEY_shutdown_mode=${OCF_RESKEY_shutdown_mode_default}} -: ${OCF_RESKEY_start_resources=${OCF_RESKEY_start_resources_default}} -: ${OCF_RESKEY_seapath=${OCF_RESKEY_seapath_default}} - -if ocf_is_true ${OCF_RESKEY_sync_config_on_stop}; then - OCF_RESKEY_save_config_on_stop="true" -fi -####################################################################### - -## I'd very much suggest to make this RA use bash, -## and then use magic $SECONDS. -## But for now: -NOW=$(date +%s) - -usage() { - echo "usage: $0 {start|stop|status|monitor|migrate_to|migrate_from|meta-data|validate-all}" -} - -VirtualDomain_meta_data() { - cat < - - -1.0 - - -Resource agent for a virtual domain (a.k.a. domU, virtual machine, -virtual environment etc., depending on context) managed by libvirtd. - -Manages virtual domains through the libvirt virtualization framework - - - - - -Absolute path to the libvirt configuration file, -for this virtual domain. - -Virtual domain configuration file - - - - - -Hypervisor URI to connect to. See the libvirt documentation for -details on supported URI formats. The default is system dependent. -Determine the system's default uri by running 'virsh --quiet uri'. - -Hypervisor URI - - - - - -Always forcefully shut down ("destroy") the domain on stop. The default -behavior is to resort to a forceful shutdown only after a graceful -shutdown attempt has failed. You should only set this to true if -your virtual domain (or your virtualization backend) does not support -graceful shutdown. - -Always force shutdown on stop - - - - - -Transport used to connect to the remote hypervisor while -migrating. Please refer to the libvirt documentation for details on -transports available. If this parameter is omitted, the resource will -use libvirt's default transport to connect to the remote hypervisor. - -Remote hypervisor transport - - - - - -The username will be used in the remote libvirt remoteuri/migrateuri. No user will be -given (which means root) in the username if omitted - -If remoteuri is set, migration_user will be ignored. - -Remote username for the remoteuri - - - - - -Define max downtime during live migration in milliseconds - -Live migration downtime - - - - - -Define live migration speed per resource in MiB/s - -Live migration speed - - - - - -Use a dedicated migration network. The migration URI is composed by -adding this parameters value to the end of the node name. If the node -name happens to be an FQDN (as opposed to an unqualified host name), -insert the suffix immediately prior to the first period (.) in the FQDN. -At the moment Qemu/KVM and Xen migration via a dedicated network is supported. - -Note: Be sure this composed host name is locally resolvable and the -associated IP is reachable through the favored network. This suffix will -be added to the remoteuri and migrateuri parameters. - -See also the migrate_options parameter below. - -Migration network host name suffix - - - - - -You can also specify here if the calculated migrate URI is unsuitable for your -environment. - -If migrateuri is set then migration_network_suffix, migrateport and ---migrateuri in migrate_options are effectively ignored. Use "%n" as the -placeholder for the target node name. - -Please refer to the libvirt documentation for details on guest -migration. - -Custom migrateuri for migration state transfer - - - - - -Extra virsh options for the guest live migration. You can also specify -here --migrateuri if the calculated migrate URI is unsuitable for your -environment. If --migrateuri is set then migration_network_suffix -and migrateport are effectively ignored. Use "%n" as the placeholder -for the target node name. - -Please refer to the libvirt documentation for details on guest -migration. - -live migrate options - - - - - -To additionally monitor services within the virtual domain, add this -parameter with a list of scripts to monitor. - -Note: when monitor scripts are used, the start and migrate_from operations -will complete only when all monitor scripts have completed successfully. -Be sure to set the timeout of these operations to accommodate this delay. - -space-separated list of monitor scripts - - - - - -If set true, the agent will detect the number of domainU's vCPUs from virsh, and put it -into the CPU utilization of the resource when the monitor is executed. - -Enable auto-setting the CPU utilization of the resource - - - - - -If set true, the agent will detect the number of *Max memory* from virsh, and put it -into the host_memory utilization of the resource when the monitor is executed. - -Enable auto-setting the host_memory utilization of the resource - - - - - -If set true, the agent will detect the number of *Max memory* from virsh, and put it -into the hv_memory utilization of the resource when the monitor is executed. - -Enable auto-setting the hv_memory utilization of the resource - - - - - -If set true then the agent will remove the cpu utilization resource when the monitor -is executed. - -Enable auto-removing the CPU utilization of the resource - - - - - -If set true then the agent will remove the host_memory utilization resource when the monitor -is executed. - -Enable auto-removing the host_memory utilization of the resource - - - - - -If set true then the agent will remove the hv_memory utilization resource when the monitor -is executed. - -Enable auto-removing the hv_memory utilization of the resource - - - - - -This port will be used in the qemu migrateuri. If unset, the port will be a random highport. - -Port for migrateuri - - - - - -Use this URI as virsh connection URI to commuicate with a remote hypervisor. - -If remoteuri is set then migration_user and migration_network_suffix are -effectively ignored. Use "%n" as the placeholder for the target node name. - -Please refer to the libvirt documentation for details on guest -migration. - -Custom remoteuri to communicate with a remote hypervisor - - - - - -Changes to a running VM's config are normally lost on stop. -This parameter instructs the RA to save the configuration back to the xml file provided in the "config" parameter. - -Save running VM's config back to its config file - - - - - -Setting this automatically enables save_config_on_stop. -When enabled this parameter instructs the RA to -call csync2 -x to synchronize the file to all nodes. -csync2 must be properly set up for this to work. - -Save running VM's config back to its config file - - - - - -Path to the snapshot directory where the virtual machine image will be stored. When this -parameter is set, the virtual machine's RAM state will be saved to a file in the snapshot -directory when stopped. If on start a state file is present for the domain, the domain -will be restored to the same state it was in right before it stopped last. This option -is incompatible with the 'force_stop' option. - - -Restore state on start/stop - - - - - - -When the VM is used in Copy-On-Write mode, this is the backing file to use (with its full path). -The VMs image will be created based on this backing file. -This backing file will never be changed during the life of the VM. - -If the VM is wanted to work with Copy-On-Write mode, this is the backing file to use (with its full path) - - - - - -If set to true and backingfile is defined, the start of the VM will systematically create a new qcow2 based on -the backing file, therefore the VM will always be stateless. If set to false, the start of the VM will use the -COW (<vmname>.qcow2) file if it exists, otherwise the first start will create a new qcow2 based on the backing -file given as backingfile. - -If set to true, the (<vmname>.qcow2) file will be re-created at each start, based on the backing file (if defined) - - - - - -List of directories for the virt-copy-in before booting the VM. Used only in stateless mode. - -List of directories for the virt-copy-in before booting the VM stateless mode. - - - - - -virsh shutdown method to use. Please verify that it is supported by your virsh toolsed with 'virsh help shutdown' -When this parameter is set --mode shutdown_mode is passed as an additional argument to the 'virsh shutdown' command. -One can use this option in case default acpi method does not work. Verify that this mode is supported -by your VM. By default --mode is not passed. - - -Instruct virsh to use specific shutdown mode - - - - - - -Start the virtual storage pools and networks used by the virtual machine before starting it or before live migrating it. - - -Ensure the needed virtual storage pools and networks are started - - - - - - -Work on Seapath cluster. - -Enable seapath cluster support - - - - - - - - - - - - - - - - -EOF -} - -set_util_attr() { - local attr=$1 val=$2 - local cval outp - - cval=$(crm_resource -Q -r $OCF_RESOURCE_INSTANCE -z -g $attr 2>/dev/null) - if [ $? -ne 0 ] && [ -z "$cval" ]; then - crm_resource -Q -r $OCF_RESOURCE_INSTANCE -z -g $attr 2>&1 | grep -e "not connected" > /dev/null 2>&1 - if [ $? -eq 0 ]; then - ocf_log debug "Unable to set utilization attribute, cib is not available" - return - fi - fi - - if [ "$cval" != "$val" ]; then - outp=$(crm_resource -r $OCF_RESOURCE_INSTANCE -z -p $attr -v $val 2>&1) || - ocf_log warn "crm_resource failed to set utilization attribute $attr: $outp" - fi -} - -unset_util_attr() { - local attr=$1 - local cval outp - - outp=$(crm_resource --resource=$OCF_RESOURCE_INSTANCE --utilization --delete-parameter=$attr 2>&1) || - ocf_log warn "crm_resource failed to unset utilization attribute $attr: $outp" -} - -update_utilization() { - local dom_cpu dom_mem - - if ocf_is_true "$OCF_RESKEY_autoset_utilization_cpu"; then - dom_cpu=$(LANG=C virsh $VIRSH_OPTIONS dominfo ${DOMAIN_NAME} 2>/dev/null | awk '/CPU\(s\)/{print $2}') - test -n "$dom_cpu" && set_util_attr cpu $dom_cpu - elif ocf_is_true "$OCF_RESKEY_unset_utilization_cpu"; then - unset_util_attr cpu - fi - - if ocf_is_true "$OCF_RESKEY_autoset_utilization_host_memory"; then - dom_mem=$(LANG=C virsh $VIRSH_OPTIONS dominfo ${DOMAIN_NAME} 2>/dev/null | awk '/Max memory/{printf("%d", $3/1024)}') - test -n "$dom_mem" && set_util_attr host_memory "$dom_mem" - elif ocf_is_true "$OCF_RESKEY_unset_utilization_host_memory"; then - unset_util_attr host_memory - fi - - if ocf_is_true "$OCF_RESKEY_autoset_utilization_hv_memory"; then - dom_mem=$(LANG=C virsh $VIRSH_OPTIONS dominfo ${DOMAIN_NAME} 2>/dev/null | awk '/Max memory/{printf("%d", $3/1024)}') - test -n "$dom_mem" && set_util_attr hv_memory "$dom_mem" - elif ocf_is_true "$OCF_RESKEY_unset_utilization_hv_memory"; then - unset_util_attr hv_memory - fi -} - -get_emulator() -{ - local emulator="" - - emulator=$(virsh $VIRSH_OPTIONS dumpxml $DOMAIN_NAME 2>/dev/null | sed -n -e 's/^.*\(.*\)<\/emulator>.*$/\1/p') - if [ -z "$emulator" ] && [ -e "$EMULATOR_STATE" ]; then - emulator=$(cat $EMULATOR_STATE) - fi - if [ -z "$emulator" ]; then - emulator=$(cat ${OCF_RESKEY_config} | sed -n -e 's/^.*\(.*\)<\/emulator>.*$/\1/p') - fi - - if [ -n "$emulator" ]; then - basename $emulator - fi -} - -update_emulator_cache() -{ - local emulator - - emulator=$(get_emulator) - if [ -n "$emulator" ]; then - echo $emulator > $EMULATOR_STATE - fi -} - -# attempt to check domain status outside of libvirt using the emulator process -pid_status() -{ - local rc=$OCF_ERR_GENERIC - local emulator=$(get_emulator) - # An emulator is not required, so only report message in debug mode - local loglevel="debug" - - if ocf_is_probe; then - loglevel="notice" - fi - - case "$emulator" in - qemu-kvm|qemu-dm|qemu-system-*) - rc=$OCF_NOT_RUNNING - ps awx | grep -E "[q]emu-(kvm|dm|system).*-name ($DOMAIN_NAME|[^ ]*guest=$DOMAIN_NAME(,[^ ]*)?) " > /dev/null 2>&1 - if [ $? -eq 0 ]; then - rc=$OCF_SUCCESS - fi - ;; - libvirt_lxc) - rc=$OCF_NOT_RUNNING - ps awx | grep -E "[l]ibvirt_lxc.*-name ($DOMAIN_NAME|[^ ]*guest=$DOMAIN_NAME(,[^ ]*)?) " > /dev/null 2>&1 - if [ $? -eq 0 ]; then - rc=$OCF_SUCCESS - fi - ;; - # This can be expanded to check for additional emulators - *) - # We may be running xen with PV domains, they don't - # have an emulator set. try xl list or xen-lists - if have_binary xl; then - rc=$OCF_NOT_RUNNING - xl list $DOMAIN_NAME >/dev/null 2>&1 - if [ $? -eq 0 ]; then - rc=$OCF_SUCCESS - fi - elif have_binary xen-list; then - rc=$OCF_NOT_RUNNING - xen-list $DOMAIN_NAME 2>/dev/null | grep -qs "State.*[-r][-b][-p]--" 2>/dev/null - if [ $? -eq 0 ]; then - rc=$OCF_SUCCESS - fi - else - ocf_log $loglevel "Unable to determine emulator for $DOMAIN_NAME" - fi - ;; - esac - - if [ $rc -eq $OCF_SUCCESS ]; then - ocf_log debug "Virtual domain $DOMAIN_NAME is currently running." - elif [ $rc -eq $OCF_NOT_RUNNING ]; then - ocf_log debug "Virtual domain $DOMAIN_NAME is currently not running." - fi - - return $rc -} - -VirtualDomain_status() { - local try=0 - rc=$OCF_ERR_GENERIC - status="no state" - while [ "$status" = "no state" ]; do - try=$(($try + 1 )) - status=$(LANG=C virsh $VIRSH_OPTIONS domstate $DOMAIN_NAME 2>&1 | tr 'A-Z' 'a-z') - case "$status" in - *"error:"*"domain not found"|*"error:"*"failed to get domain"*|"shut off") - # shut off: domain is defined, but not started, will not happen if - # domain is created but not defined - # "Domain not found" or "failed to get domain": domain is not defined - # and thus not started - ocf_log debug "Virtual domain $DOMAIN_NAME is not running: $(echo $status | sed s/error://g)" - rc=$OCF_NOT_RUNNING - ;; - running|paused|idle|blocked|"in shutdown") - # running: domain is currently actively consuming cycles - # paused: domain is paused (suspended) - # idle: domain is running but idle - # blocked: synonym for idle used by legacy Xen versions - # in shutdown: the domain is in process of shutting down, but has not completely shutdown or crashed. - ocf_log debug "Virtual domain $DOMAIN_NAME is currently $status." - rc=$OCF_SUCCESS - ;; - ""|*"failed to "*"connect to the hypervisor"*|"no state") - # Empty string may be returned when virsh does not - # receive a reply from libvirtd. - # "no state" may occur when the domain is currently - # being migrated (on the migration target only), or - # whenever virsh can't reliably obtain the domain - # state. - status="no state" - if [ "$__OCF_ACTION" = "stop" ] && [ $try -ge 3 ]; then - # During the stop operation, we want to bail out - # quickly, so as to be able to force-stop (destroy) - # the domain if necessary. - ocf_exit_reason "Virtual domain $DOMAIN_NAME has no state during stop operation, bailing out." - return $OCF_ERR_GENERIC; - elif [ "$__OCF_ACTION" = "monitor" ]; then - pid_status - rc=$? - if [ $rc -ne $OCF_ERR_GENERIC ]; then - # we've successfully determined the domains status outside of libvirt - return $rc - fi - - else - # During all other actions, we just wait and try - # again, relying on the CRM/LRM to time us out if - # this takes too long. - ocf_log info "Virtual domain $DOMAIN_NAME currently has no state, retrying." - fi - sleep 1 - ;; - *) - # any other output is unexpected. - ocf_log error "Virtual domain $DOMAIN_NAME has unknown status \"$status\"!" - sleep 1 - ;; - esac - done - return $rc -} - -# virsh undefine removes configuration files if they are in -# directories which are managed by libvirt. such directories -# include also subdirectories of /etc (for instance -# /etc/libvirt/*) which may be surprising. VirtualDomain didn't -# include the undefine call before, hence this wasn't an issue -# before. -# -# There seems to be no way to find out which directories are -# managed by libvirt. -# -verify_undefined() { - local tmpf - if virsh --connect=${OCF_RESKEY_hypervisor} list --all --name 2>/dev/null | grep -wqs "$DOMAIN_NAME" - then - tmpf=$(mktemp -t vmcfgsave.XXXXXX) - if [ ! -r "$tmpf" ]; then - ocf_log warn "unable to create temp file, disk full?" - # we must undefine the domain - virsh $VIRSH_OPTIONS undefine --nvram $DOMAIN_NAME > /dev/null 2>&1 - else - cp -p $OCF_RESKEY_config $tmpf - virsh $VIRSH_OPTIONS undefine --nvram $DOMAIN_NAME > /dev/null 2>&1 - [ -f $OCF_RESKEY_config ] || cp -f $tmpf $OCF_RESKEY_config - rm -f $tmpf - fi - fi -} - -start_resources() { - local virsh_opts="--connect=$1 --quiet" - local pool_state net_state - for pool in `sed -n "s/^.*pool=['\"]\([^'\"]\+\)['\"].*\$/\1/gp" ${OCF_RESKEY_config} | sort | uniq`; do - pool_state=`LANG=C virsh ${virsh_opts} pool-info ${pool} | sed -n 's/^State: \+\(.*\)$/\1/gp'` - if [ "$pool_state" != "running" ]; then - virsh ${virsh_opts} pool-start $pool - if [ $? -ne 0 ]; then - ocf_exit_reason "Failed to start required virtual storage pool ${pool}." - return $OCF_ERR_GENERIC - fi - else - virsh ${virsh_opts} pool-refresh $pool - fi - done - - for net in `sed -n "s/^.*network=['\"]\([^'\"]\+\)['\"].*\$/\1/gp" ${OCF_RESKEY_config} | sort | uniq`; do - net_state=`LANG=C virsh ${virsh_opts} net-info ${net} | sed -n 's/^Active: \+\(.*\)$/\1/gp'` - if [ "$net_state" != "yes" ]; then - virsh ${virsh_opts} net-start $net - if [ $? -ne 0 ]; then - ocf_exit_reason "Failed to start required virtual network ${net}." - return $OCF_ERR_GENERIC - fi - fi - done - - return $OCF_SUCCESS -} - -restore_config() { - if ocf_is_true $OCF_RESKEY_seapath ; then - local disk_name=system_$DOMAIN_NAME - if rbd info $disk_name > /dev/null 2>&1 ; then - rbd image-meta get $disk_name xml > $OCF_RESKEY_config - fi - fi -} - -VirtualDomain_start() { - local snapshotimage - - if VirtualDomain_status; then - ocf_log info "Virtual domain $DOMAIN_NAME already running." - return $OCF_SUCCESS - fi - - # systemd drop-in to stop domain before libvirtd terminates services - # during shutdown/reboot - if systemd_is_running ; then - systemd_drop_in "99-VirtualDomain-libvirt" "After" "libvirtd.service" - systemd_drop_in "99-VirtualDomain-machines" "Wants" "virt-guest-shutdown.target" - systemctl start virt-guest-shutdown.target - fi - - snapshotimage="$OCF_RESKEY_snapshot/${DOMAIN_NAME}.state" - if [ -n "$OCF_RESKEY_snapshot" -a -f "$snapshotimage" ]; then - virsh restore $snapshotimage - if [ $? -eq 0 ]; then - rm -f $snapshotimage - return $OCF_SUCCESS - fi - ocf_exit_reason "Failed to restore ${DOMAIN_NAME} from state file in ${OCF_RESKEY_snapshot} directory." - return $OCF_ERR_GENERIC - fi - - restore_config - # Make sure domain is undefined before creating. - # The 'create' command guarantees that the domain will be - # undefined on shutdown, but requires the domain to be undefined. - # if a user defines the domain - # outside of this agent, we have to ensure that the domain - # is restored to an 'undefined' state before creating. - verify_undefined - - if ocf_is_true "${OCF_RESKEY_start_resources}"; then - start_resources ${OCF_RESKEY_hypervisor} - rc=$? - if [ $rc -eq $OCF_ERR_GENERIC ]; then - return $rc - fi - fi - - if [ -z "${OCF_RESKEY_backingfile}" ]; then - virsh $VIRSH_OPTIONS create ${OCF_RESKEY_config} - if [ $? -ne 0 ]; then - ocf_exit_reason "Failed to start virtual domain ${DOMAIN_NAME}." - return $OCF_ERR_GENERIC - fi - else - if ocf_is_true "${OCF_RESKEY_stateless}" || [ ! -s "${OCF_RESKEY_config%%.*}.qcow2" ]; then - # Create the Stateless image - dirconfig=`dirname ${OCF_RESKEY_config}` - qemu-img create -f qcow2 -b ${OCF_RESKEY_backingfile} ${OCF_RESKEY_config%%.*}.qcow2 - if [ $? -ne 0 ]; then - ocf_exit_reason "Failed qemu-img create ${DOMAIN_NAME} with backing file ${OCF_RESKEY_backingfile}." - return $OCF_ERR_GENERIC - fi - - virsh define ${OCF_RESKEY_config} - if [ $? -ne 0 ]; then - ocf_exit_reason "Failed to define virtual domain ${DOMAIN_NAME}." - return $OCF_ERR_GENERIC - fi - - if [ -n "${OCF_RESKEY_copyindirs}" ]; then - # Inject copyindirs directories and files - virt-copy-in -d ${DOMAIN_NAME} ${OCF_RESKEY_copyindirs} / - if [ $? -ne 0 ]; then - ocf_exit_reason "Failed on virt-copy-in command ${DOMAIN_NAME}." - return $OCF_ERR_GENERIC - fi - fi - else - virsh define ${OCF_RESKEY_config} - if [ $? -ne 0 ]; then - ocf_exit_reason "Failed to define virtual domain ${DOMAIN_NAME}." - return $OCF_ERR_GENERIC - fi - fi - - virsh $VIRSH_OPTIONS start ${DOMAIN_NAME} - if [ $? -ne 0 ]; then - ocf_exit_reason "Failed to start virtual domain ${DOMAIN_NAME}." - return $OCF_ERR_GENERIC - fi - fi - - while ! VirtualDomain_monitor; do - sleep 1 - done - - return $OCF_SUCCESS -} - -force_stop() -{ - local out ex translate - local status=0 - - ocf_log info "Issuing forced shutdown (destroy) request for domain ${DOMAIN_NAME}." - out=$(LANG=C virsh $VIRSH_OPTIONS destroy ${DOMAIN_NAME} 2>&1) - ex=$? - translate=$(echo $out|tr 'A-Z' 'a-z') - echo >&2 "$translate" - case $ex$translate in - *"error:"*"domain is not running"*|*"error:"*"domain not found"*|\ - *"error:"*"failed to get domain"*) - : ;; # unexpected path to the intended outcome, all is well - [!0]*) - ocf_exit_reason "forced stop failed" - return $OCF_ERR_GENERIC ;; - 0*) - while [ $status != $OCF_NOT_RUNNING ]; do - VirtualDomain_status - status=$? - done ;; - esac - return $OCF_SUCCESS -} - -sync_config(){ - ocf_log info "Syncing $DOMAIN_NAME config file with csync2 -x ${OCF_RESKEY_config}" - if ! csync2 -x ${OCF_RESKEY_config}; then - ocf_log warn "Syncing ${OCF_RESKEY_config} failed."; - fi -} - -save_config(){ - CFGTMP=$(mktemp -t vmcfgsave.XXX) - virsh $VIRSH_OPTIONS dumpxml --inactive --security-info ${DOMAIN_NAME} > ${CFGTMP} - if [ -s ${CFGTMP} ]; then - if ! cmp -s ${CFGTMP} ${OCF_RESKEY_config}; then - if virt-xml-validate ${CFGTMP} domain 2>/dev/null ; then - ocf_log info "Saving domain $DOMAIN_NAME to ${OCF_RESKEY_config}. Please make sure it's present on all nodes or sync_config_on_stop is on." - if cat ${CFGTMP} > ${OCF_RESKEY_config} ; then - ocf_log info "Saved $DOMAIN_NAME domain's configuration to ${OCF_RESKEY_config}." - if ocf_is_true "$OCF_RESKEY_sync_config_on_stop"; then - sync_config - fi - else - ocf_log warn "Moving ${CFGTMP} to ${OCF_RESKEY_config} failed." - fi - else - ocf_log warn "Domain $DOMAIN_NAME config failed to validate after dump. Skipping config update." - fi - fi - else - ocf_log warn "Domain $DOMAIN_NAME config has 0 size. Skipping config update." - fi - rm -f ${CFGTMP} -} - -VirtualDomain_stop() { - local i - local status - local shutdown_timeout - local needshutdown=1 - - VirtualDomain_status - status=$? - - case $status in - $OCF_SUCCESS) - if ocf_is_true $OCF_RESKEY_force_stop; then - # if force stop, don't bother attempting graceful shutdown. - force_stop - return $? - fi - - ocf_log info "Issuing graceful shutdown request for domain ${DOMAIN_NAME}." - - if [ -n "$OCF_RESKEY_snapshot" ]; then - virsh save $DOMAIN_NAME "$OCF_RESKEY_snapshot/${DOMAIN_NAME}.state" - if [ $? -eq 0 ]; then - needshutdown=0 - else - ocf_log error "Failed to save snapshot state of ${DOMAIN_NAME} on stop" - fi - fi - - # save config if needed - if ocf_is_true "$OCF_RESKEY_save_config_on_stop"; then - save_config - fi - - # issue the shutdown if save state didn't shutdown for us - if [ $needshutdown -eq 1 ]; then - # Issue a graceful shutdown request - if [ -n "${OCF_RESKEY_CRM_shutdown_mode}" ]; then - shutdown_opts="--mode ${OCF_RESKEY_CRM_shutdown_mode}" - fi - ocf_log info "virsh $VIRSH_OPTIONS shutdown ${DOMAIN_NAME} $shutdown_opts" - timeout 1s virsh $VIRSH_OPTIONS shutdown ${DOMAIN_NAME} $shutdown_opts - virsh_timeout_status=$? - if [ $virsh_timeout_status -eq 124 ] #timeout, there's something wrong with the guest - then - # Something went wrong, break from switch case, and resort to forced stop (destroy). - ocf_log info "${DOMAIN_NAME} shutdown problem, force_stop" - force=1 - else - force=0 - fi - fi - - # The "shutdown_timeout" we use here is the operation - # timeout specified in the CIB, minus 17 seconds (because it has been seen cases where the destroy operation takes more than 15s) - shutdown_timeout=$(( $NOW + ($OCF_RESKEY_CRM_meta_timeout/1000) -17 )) - # Loop on status until we reach $shutdown_timeout - ocf_log info "${DOMAIN_NAME} shutdown_timeout=$shutdown_timeout, NOW=$NOW" - while [ $NOW -lt $shutdown_timeout -a $force -ne 1 ]; do - VirtualDomain_status - status=$? - ocf_log info "${DOMAIN_NAME} VirtualDomain_status $status" - case $status in - $OCF_NOT_RUNNING) - # This was a graceful shutdown. - ocf_log info "${DOMAIN_NAME} This was a graceful shutdown." - return $OCF_SUCCESS - ;; - $OCF_SUCCESS) - # Domain is still running, keep - # waiting (until shutdown_timeout - # expires) - ocf_log info "${DOMAIN_NAME} sleep 1." - sleep 1 - ;; - *) - # Something went wrong. Bail out and - # resort to forced stop (destroy). - break; - esac - NOW=$(date +%s) - done - ;; - $OCF_NOT_RUNNING) - ocf_log info "Domain $DOMAIN_NAME already stopped." - return $OCF_SUCCESS - esac - - # OK. Now if the above graceful shutdown hasn't worked, kill - # off the domain with destroy. If that too does not work, - # have the LRM time us out. - ocf_log info "${DOMAIN_NAME} force_stop" - force_stop -} - -mk_migrateuri() { - local target_node - local migrate_target - local hypervisor - - target_node="$OCF_RESKEY_CRM_meta_migrate_target" - - # A typical migration URI via a special migration network looks - # like "tcp://bar-mig:49152". The port would be randomly chosen - # by libvirt from the range 49152-49215 if omitted, at least since - # version 0.7.4 ... - if [ -n "${OCF_RESKEY_migration_network_suffix}" ]; then - hypervisor="${OCF_RESKEY_hypervisor%%[+:]*}" - # Hostname might be a FQDN - migrate_target=$(echo ${target_node} | sed -e "s,^\([^.]\+\),\1${OCF_RESKEY_migration_network_suffix},") - case $hypervisor in - qemu) - # For quiet ancient libvirt versions a migration port is needed - # and the URI must not contain the "//". Newer versions can handle - # the "bad" URI. - echo "tcp:${migrate_target}:${OCF_RESKEY_migrateport}" - ;; - xen) - echo "${migrate_target}" - ;; - *) - ocf_log warn "$DOMAIN_NAME: Migration via dedicated network currently not supported for ${hypervisor}." - ;; - esac - fi -} - -VirtualDomain_migrate_to() { - local rc - local target_node - local remoteuri - local transport_suffix - local migrateuri - local migrate_opts - local migrate_pid - - target_node="$OCF_RESKEY_CRM_meta_migrate_target" - - if VirtualDomain_status; then - # Find out the remote hypervisor to connect to. That is, turn - # something like "qemu://foo:9999/system" into - # "qemu+tcp://bar:9999/system" - - if [ -n "${OCF_RESKEY_remoteuri}" ]; then - remoteuri=`echo "${OCF_RESKEY_remoteuri}" | - sed "s/%n/$target_node/g"` - else - if [ -n "${OCF_RESKEY_migration_transport}" ]; then - transport_suffix="+${OCF_RESKEY_migration_transport}" - fi - - # append user defined suffix if virsh target should differ from cluster node name - if [ -n "${OCF_RESKEY_migration_network_suffix}" ]; then - # Hostname might be a FQDN - target_node=$(echo ${target_node} | sed -e "s,^\([^.]\+\),\1${OCF_RESKEY_migration_network_suffix},") - fi - - # a remote user has been defined to connect to target_node - if echo ${OCF_RESKEY_migration_user} | grep -q "^[a-z][-a-z0-9]*$" ; then - target_node="${OCF_RESKEY_migration_user}@${target_node}" - fi - - # Scared of that sed expression? So am I. :-) - remoteuri=$(echo ${OCF_RESKEY_hypervisor} | sed -e "s,\(.*\)://[^/:]*\(:\?[0-9]*\)/\(.*\),\1${transport_suffix}://${target_node}\2/\3,") - fi - - # User defined migrateuri or do we make one? - migrate_opts="$OCF_RESKEY_migrate_options" - - # migration_uri is directly set - if [ -n "${OCF_RESKEY_migrateuri}" ]; then - migrateuri=`echo "${OCF_RESKEY_migrateuri}" | - sed "s/%n/$target_node/g"` - - # extract migrationuri from options - elif echo "$migrate_opts" | fgrep -qs -- "--migrateuri="; then - migrateuri=`echo "$migrate_opts" | - sed "s/.*--migrateuri=\([^ ]*\).*/\1/;s/%n/$target_node/g"` - - # auto generate - else - migrateuri=`mk_migrateuri` - fi - - # remove --migrateuri from migration_opts - migrate_opts=`echo "$migrate_opts" | - sed "s/\(.*\)--migrateuri=[^ ]*\(.*\)/\1\2/"` - - - # save config if needed - if ocf_is_true "$OCF_RESKEY_save_config_on_stop"; then - save_config - fi - - if ocf_is_true "${OCF_RESKEY_start_resources}"; then - start_resources $remoteuri - rc=$? - if [ $rc -eq $OCF_ERR_GENERIC ]; then - return $rc - fi - fi - - # Live migration speed limit - if [ ${OCF_RESKEY_migration_speed} -ne 0 ]; then - ocf_log info "$DOMAIN_NAME: Setting live migration speed limit for $DOMAIN_NAME (using: virsh ${VIRSH_OPTIONS} migrate-setspeed $DOMAIN_NAME ${OCF_RESKEY_migration_speed})." - virsh ${VIRSH_OPTIONS} migrate-setspeed $DOMAIN_NAME ${OCF_RESKEY_migration_speed} - fi - - # OK, we know where to connect to. Now do the actual migration. - ocf_log info "$DOMAIN_NAME: Starting live migration to ${target_node} (using: virsh ${VIRSH_OPTIONS} migrate --live $migrate_opts $DOMAIN_NAME $remoteuri $migrateuri)." - virsh ${VIRSH_OPTIONS} migrate --live $migrate_opts $DOMAIN_NAME $remoteuri $migrateuri & - - migrate_pid=${!} - - # Live migration downtime interval - # Note: You can set downtime only while live migration is in progress - if [ ${OCF_RESKEY_migration_downtime} -ne 0 ]; then - sleep 2 - ocf_log info "$DOMAIN_NAME: Setting live migration downtime for $DOMAIN_NAME (using: virsh ${VIRSH_OPTIONS} migrate-setmaxdowntime $DOMAIN_NAME ${OCF_RESKEY_migration_downtime})." - virsh ${VIRSH_OPTIONS} migrate-setmaxdowntime $DOMAIN_NAME ${OCF_RESKEY_migration_downtime} - fi - - wait ${migrate_pid} - - rc=$? - if [ $rc -ne 0 ]; then - ocf_exit_reason "$DOMAIN_NAME: live migration to ${target_node} failed: $rc" - return $OCF_ERR_GENERIC - else - ocf_log info "$DOMAIN_NAME: live migration to ${target_node} succeeded." - return $OCF_SUCCESS - fi - else - ocf_exit_reason "$DOMAIN_NAME: migrate_to: Not active locally!" - return $OCF_ERR_GENERIC - fi -} - -VirtualDomain_migrate_from() { - # systemd drop-in to stop domain before libvirtd terminates services - # during shutdown/reboot - if systemd_is_running ; then - systemd_drop_in "99-VirtualDomain-libvirt" "After" "libvirtd.service" - systemd_drop_in "99-VirtualDomain-machines" "Wants" "virt-guest-shutdown.target" - systemctl start virt-guest-shutdown.target - fi - - while ! VirtualDomain_monitor; do - sleep 1 - done - ocf_log info "$DOMAIN_NAME: live migration from ${OCF_RESKEY_CRM_meta_migrate_source} succeeded." - # save config if needed - if ocf_is_true "$OCF_RESKEY_save_config_on_stop"; then - save_config - fi - return $OCF_SUCCESS -} - -VirtualDomain_monitor() { - # First, check the domain status. If that returns anything other - # than $OCF_SUCCESS, something is definitely wrong. - VirtualDomain_status - rc=$? - if [ ${rc} -eq ${OCF_SUCCESS} ]; then - # OK, the generic status check turned out fine. Now, if we - # have monitor scripts defined, run them one after another. - for script in ${OCF_RESKEY_monitor_scripts}; do - script_output="$($script 2>&1)" - script_rc=$? - if [ ${script_rc} -ne ${OCF_SUCCESS} ]; then - # A monitor script returned a non-success exit - # code. Stop iterating over the list of scripts, log a - # warning message, and propagate $OCF_ERR_GENERIC. - ocf_exit_reason "Monitor command \"${script}\" for domain ${DOMAIN_NAME} returned ${script_rc} with output: ${script_output}" - rc=$OCF_ERR_GENERIC - break - else - ocf_log debug "Monitor command \"${script}\" for domain ${DOMAIN_NAME} completed successfully with output: ${script_output}" - fi - done - fi - - update_emulator_cache - update_utilization - # Save configuration on monitor as well, so we will have a better chance of - # having fresh and up to date config files on all nodes. - if ocf_is_true "$OCF_RESKEY_save_config_on_stop"; then - save_config - fi - - return ${rc} -} - -VirtualDomain_validate_all() { - if ocf_is_true $OCF_RESKEY_force_stop && [ -n "$OCF_RESKEY_snapshot" ]; then - ocf_exit_reason "The 'force_stop' and 'snapshot' options can not be used together." - return $OCF_ERR_CONFIGURED - fi - - if [ ! -r $OCF_RESKEY_config ] ; then - restore_config - fi - - # check if we can read the config file (otherwise we're unable to - # deduce $DOMAIN_NAME from it, see below) - if [ ! -r $OCF_RESKEY_config ]; then - if ocf_is_probe; then - ocf_log info "Configuration file $OCF_RESKEY_config not readable during probe." - elif [ "$__OCF_ACTION" = "stop" ]; then - ocf_log info "Configuration file $OCF_RESKEY_config not readable, resource considered stopped." - else - ocf_exit_reason "Configuration file $OCF_RESKEY_config does not exist or not readable." - fi - return $OCF_ERR_INSTALLED - fi - - if [ -z $DOMAIN_NAME ]; then - ocf_exit_reason "Unable to determine domain name." - return $OCF_ERR_INSTALLED - fi - - # Check if csync2 is available when config tells us we might need it. - if ocf_is_true $OCF_RESKEY_sync_config_on_stop; then - check_binary csync2 - fi - - # Check if migration_speed is a decimal value - if ! ocf_is_decimal ${OCF_RESKEY_migration_speed}; then - ocf_exit_reason "migration_speed has to be a decimal value" - return $OCF_ERR_CONFIGURED - fi - - # Check if migration_downtime is a decimal value - if ! ocf_is_decimal ${OCF_RESKEY_migration_downtime}; then - ocf_exit_reason "migration_downtime has to be a decimal value" - return $OCF_ERR_CONFIGURED - fi - - if ocf_is_true "${OCF_RESKEY_stateless}" && [ -z "${OCF_RESKEY_backingfile}" ]; then - ocf_exit_reason "Stateless functionality can't be achieved without a backing file." - return $OCF_ERR_CONFIGURED - fi -} - -VirtualDomain_getconfig() { - # Grab the virsh uri default, but only if hypervisor isn't set - : ${OCF_RESKEY_hypervisor=$(virsh --quiet uri 2>/dev/null)} - - # Set options to be passed to virsh: - VIRSH_OPTIONS="--connect=${OCF_RESKEY_hypervisor} --quiet" - if ocf_is_true $OCF_RESKEY_seapath ; then - # Retrieve the domain name from xml filename - DOMAIN_NAME=`basename ${OCF_RESKEY_config} | cut -d '.' -f 1` - else - # Retrieve the domain name from the xml file. - DOMAIN_NAME=`egrep '[[:space:]]*.*[[:space:]]*$' ${OCF_RESKEY_config} 2>/dev/null | sed -e 's/[[:space:]]*\(.*\)<\/name>[[:space:]]*$/\1/'` - fi - - EMULATOR_STATE="${HA_RSCTMP}/VirtualDomain-${DOMAIN_NAME}-emu.state" -} - -OCF_REQUIRED_PARAMS="config" -OCF_REQUIRED_BINARIES="virsh sed" -ocf_rarun $* diff --git a/roles/centos_physical_machine/initramfs-tools/conf.d/rebooter.conf.j2 b/roles/centos_physical_machine/initramfs-tools/conf.d/rebooter.conf.j2 deleted file mode 100644 index d951dbc17..000000000 --- a/roles/centos_physical_machine/initramfs-tools/conf.d/rebooter.conf.j2 +++ /dev/null @@ -1,5 +0,0 @@ -# Device for /var/log storage -REBOOTER_LOG_DEVICE={{ centos_physical_machine_lvm_rebooter_log_device }} - -# Relative path from device root for /var/log -REBOOTER_LOG_PATH={{ centos_physical_machine_lvm_rebooter_log_path }} diff --git a/roles/centos_physical_machine/templates/pacemaker_override.conf.j2 b/roles/centos_physical_machine/templates/pacemaker_override.conf.j2 deleted file mode 100644 index 0979e3f3d..000000000 --- a/roles/centos_physical_machine/templates/pacemaker_override.conf.j2 +++ /dev/null @@ -1,11 +0,0 @@ -[Unit] -Wants=libvirtd.service -After=libvirtd.service - -[Install] -WantedBy=corosync.service - -[Service] -ExecStartPre=/usr/bin/virsh list -TimeoutStopSec={{ pacemaker_shutdown_timeout | default("2min") }} -TimeoutStartSec=60s diff --git a/roles/cephadm/defaults/main.yml b/roles/cephadm/defaults/main.yml index 05a027303..b199cefa9 100644 --- a/roles/cephadm/defaults/main.yml +++ b/roles/cephadm/defaults/main.yml @@ -4,8 +4,11 @@ --- cephadm_release: "20.2.0" cephadm_release_name: "tentacle" -cephadm_downloadbinary: false -cephadm_installbinary: false -cephadm_installrepo: false -cephadm_installcommon: false -cephadm_pullimages: false + +# Registry configuration (for disconnected mode) +cephadm_registry_url: "" +cephadm_registry_username: "" +cephadm_registry_password: "" + +# Container image (auto-constructed from registry_url and release) +cephadm_image: "{{ (cephadm_registry_url + '/ceph:v' + cephadm_release) if cephadm_registry_url | default('') != '' else 'quay.io/ceph/ceph:v' + cephadm_release }}" diff --git a/roles/cephadm/tasks/apply_ceph_conf_section.yml b/roles/cephadm/tasks/apply_ceph_conf_section.yml new file mode 100644 index 000000000..4fa5ece47 --- /dev/null +++ b/roles/cephadm/tasks/apply_ceph_conf_section.yml @@ -0,0 +1,18 @@ +# Copyright (C) 2025 RTE +# SPDX-License-Identifier: Apache-2.0 + +# Apply config options for a single ceph.conf section. +# Expected variable: ceph_conf_section (from dict2items, with .key and .value) + +--- +- name: "Apply config options for [{{ ceph_conf_section.key }}]" + ceph.cephadm.ceph_config: + action: set + who: "{{ ceph_conf_section.key }}" + option: "{{ item.key }}" + value: "{{ item.value | string }}" + loop: "{{ ceph_conf_section.value | dict2items }}" + loop_control: + label: "{{ ceph_conf_section.key }}/{{ item.key }}" + delegate_to: "{{ cephadm_first_node }}" + run_once: true diff --git a/roles/cephadm/tasks/main.yml b/roles/cephadm/tasks/main.yml index 2c26af075..e519063fc 100644 --- a/roles/cephadm/tasks/main.yml +++ b/roles/cephadm/tasks/main.yml @@ -2,92 +2,13 @@ # SPDX-License-Identifier: Apache-2.0 --- -- include_vars: "{{ seapath_distro }}.yml" +- include_vars: "{{ ansible_os_family }}.yml" -- name: Ensure group "cephadm" exists - group: - name: cephadm - gid: 1001 - state: present - -- name: Ensure user "cephadm" exists - user: - name: cephadm - uid: 1001 - group: cephadm - create_home: yes - -- name: Ensure group "containerized-ceph" exists - group: - name: containerized-ceph - gid: 167 - state: present - when: seapath_distro == "Debian" - -- name: Ensure user "containerized-ceph" exists with nologin (already exists on centos/oraclelinux) - user: - name: containerized-ceph - uid: 167 - group: containerized-ceph - create_home: no - shell: /sbin/nologin - when: seapath_distro == "Debian" - -- name: Set cephadm user sudo permissions - copy: - src: cephadm_sudoers - dest: /etc/sudoers.d/cephadm - -- name: Download cephadm - get_url: - url: "https://download.ceph.com/rpm-{{ cephadm_release }}/el9/noarch/cephadm" - dest: "/tmp/cephadm" - mode: '0755' - when: cephadm_downloadbinary is true - -- name: Copy cephadm to /usr/local/bin - copy: - src: "/tmp/cephadm" - dest: "/usr/local/bin/cephadm" - mode: '0755' - remote_src: yes - when: cephadm_installbinary is true - -- name: Install cephadm repository - command: "{{ '/tmp/cephadm' if not cephadm_installbinary else 'cephadm' }} add-repo --release {{ cephadm_release_name }}" - changed_when: true - when: cephadm_installrepo is true - -- name: Install cephadm - command: /tmp/cephadm install - changed_when: true - when: cephadm_installpackage is true - -- name: Install ceph-common package - command: cephadm install ceph-common - changed_when: true - when: cephadm_installcommon is true - -#- name: Disable ceph-crash non-containerized service -# ansible.builtin.systemd: -# name: ceph-crash.service -# enabled: false -# state: stopped - -#- name: Create /usr/local/bin/ceph with 755 permissions -# copy: -# dest: /usr/local/bin/ceph -# content: | -# #!/bin/bash -# if [ $# -eq 0 ]; then -# exec cephadm shell -# else -# exec cephadm shell -- ceph "$@" -# fi -# mode: '0755' -# owner: root -# group: root +# === User/Group setup (SEAPATH-specific) === +- name: Set up cephadm user and group + include_tasks: setup_user.yml +# === Cluster detection === - name: Check if host is part of a Ceph cluster command: "ceph -s" register: cephadm_ceph_status @@ -137,53 +58,17 @@ nonceph_nodes = {{ groups['nonceph_nodes'] | default([]) }} run_once: true -- name: Ensure insecure registry localhost:5000 is in /etc/containers/registries.conf - ansible.builtin.blockinfile: - path: /etc/containers/registries.conf - marker: "# {mark} ANSIBLE MANAGED BLOCK for insecure registries" - block: | - [[registry]] - insecure = true - location = "localhost" - -- name: Ensure /var/lib/registry exists - ansible.builtin.file: - path: /var/lib/registry - state: directory - owner: root - group: root - mode: '0755' - -- name: Pull needed Docker images - containers.podman.podman_image: - name: "{{ item }}" - when: cephadm_pullimages - loop: - - "docker.io/library/registry:2" - - "quay.io/ceph/ceph:v{{ cephadm_release }}" - -- name: Run local container registry using Podman - containers.podman.podman_container: - name: registry - image: registry:2 - state: started - detach: true - privileged: true - ports: - - "5000:5000" - volume: - - /var/lib/registry:/var/lib/registry - restart_policy: always - -- name: Tag ceph image for local registry - command: > - podman tag quay.io/ceph/ceph:v{{ cephadm_release }} localhost:5000/ceph:v{{ cephadm_release }} - changed_when: true - -- name: Push ceph image to local registry - command: > - podman push localhost:5000/ceph:v{{ cephadm_release }} - changed_when: true +# === Registry login === +- name: Login to container registry + ceph.cephadm.cephadm_registry_login: + registry_url: "{{ cephadm_registry_url }}" + registry_username: "{{ cephadm_registry_username }}" + registry_password: "{{ cephadm_registry_password }}" + when: + - cephadm_registry_url | default('') != '' + - cephadm_registry_username | default('') != '' + - cephadm_registry_password | default('') != '' + no_log: true # === Bootstrap if currently no ceph nodes === - name: Upload file ceph.conf needed for bootstrapping @@ -194,89 +79,42 @@ delegate_to: "{{ cephadm_first_node }}" when: cephadm_do_bootstrap | bool -- name: Find cephadm location - command: which cephadm - register: cephadm_path - failed_when: false - changed_when: false - environment: - PATH: "{{ ansible_env.PATH }}:/usr/local/bin" - -- name: Set cephadm binary path - set_fact: - cephadm_bin: "{{ cephadm_path.stdout if cephadm_path.rc == 0 else '/usr/local/bin/cephadm' }}" - -- name: Show bootstrap command - ansible.builtin.debug: - msg: >- - {{ cephadm_bin }} - --image localhost:5000/ceph:v{{ cephadm_release }} - bootstrap - --skip-monitoring-stack - --skip-dashboard - --skip-firewalld - --config /tmp/ceph.conf - --ssh-user cephadm - --mon-ip {{ hostvars[cephadm_first_node]['cluster_ip_addr'] }} - - name: Bootstrap Ceph cluster - command: >- - {{ cephadm_bin }} - --image localhost:5000/ceph:v{{ cephadm_release }} - bootstrap - --skip-monitoring-stack - --skip-dashboard - --skip-firewalld - --config /tmp/ceph.conf - --ssh-user cephadm - --mon-ip {{ hostvars[cephadm_first_node]['cluster_ip_addr'] }} - changed_when: true - failed_when: false - run_once: true - delegate_to: "{{ cephadm_first_node }}" - register: cephadm_ceph_bootstrap_result - when: cephadm_do_bootstrap | bool - -- name: Show bootstrap result - ansible.builtin.debug: - var: cephadm_ceph_bootstrap_result - -# === adding cephadm key on other nodes === -- name: Check if /etc/ceph/ceph.pub exists on first_node - stat: - path: /etc/ceph/ceph.pub - register: cephadm_ceph_pub_stat - run_once: true - delegate_to: "{{ cephadm_first_node }}" - when: cephadm_mon_nodes_to_add | length > 0 - -- name: Get cephadm user entry - getent: - database: passwd - key: cephadm + ceph.cephadm.cephadm_bootstrap: + mon_ip: "{{ hostvars[cephadm_first_node]['cluster_ip_addr'] }}" + image: "{{ cephadm_image }}" + skip_dashboard: true + skip_monitoring_stack: true + skip_firewalld: true + config: /tmp/ceph.conf + ssh_user: cephadm + cluster_network: "{{ cluster_network | default(omit) }}" + allow_overwrite: false delegate_to: "{{ cephadm_first_node }}" run_once: true + when: cephadm_do_bootstrap | bool -- name: Fetch the ceph keyfile if it exists, otherwise fetch authorized_keys - fetch: - src: >- - {{ - cephadm_ceph_pub_stat.stat.exists - | ternary( - '/etc/ceph/ceph.pub', - getent_passwd['cephadm'][4] ~ '/.ssh/authorized_keys' - ) - }} - dest: "/tmp/ceph.pub" - flat: true +# === Apply ceph_conf_overrides === +- name: Apply ceph_conf_overrides + include_tasks: apply_ceph_conf_section.yml + loop: "{{ ceph_conf_overrides | dict2items }}" + loop_control: + loop_var: ceph_conf_section + label: "{{ ceph_conf_section.key }}" + when: ceph_conf_overrides is defined + +# === SSH key distribution === +- name: Get ceph public key from cluster + command: cephadm shell -- ceph cephadm get-pub-key + register: cephadm_pub_key_result delegate_to: "{{ cephadm_first_node }}" run_once: true + changed_when: false when: cephadm_mon_nodes_to_add | length > 0 -- name: Read the key from the local file +- name: Set ceph public key fact set_fact: - cephadm_ceph_pubkey: "{{ lookup('file', '/tmp/ceph.pub') }}" - delegate_to: localhost + cephadm_ceph_pubkey: "{{ cephadm_pub_key_result.stdout }}" run_once: true when: cephadm_mon_nodes_to_add | length > 0 @@ -292,14 +130,16 @@ run_once: true when: cephadm_mon_nodes_to_add | length > 0 -# === adding monitor on other nodes === -- name: Add hosts to Ceph orchestrator with _admin label - command: "ceph orch host add {{ hostvars[item]['hostname'] }} --labels _admin" +# === Add hosts to Ceph orchestrator === +- name: Add hosts to Ceph orchestrator + ceph.cephadm.ceph_orch_host: + name: "{{ hostvars[item]['hostname'] }}" + address: "{{ hostvars[item]['cluster_ip_addr'] }}" + set_admin_label: true + state: present loop: "{{ cephadm_mon_nodes_to_add }}" - changed_when: true - failed_when: false - run_once: true delegate_to: "{{ cephadm_first_node }}" + run_once: true when: cephadm_mon_nodes_to_add | length > 0 - name: Confirm monitors are in monmap @@ -314,53 +154,79 @@ loop: "{{ cephadm_mon_nodes_to_add }}" when: cephadm_mon_nodes_to_add | length > 0 -# === OSDs now === +# === OSDs === - name: Get list of current OSD daemons and their hosts command: ceph orch ps --daemon-type=osd --format json register: cephadm_osd_ps delegate_to: "{{ cephadm_first_node }}" run_once: true changed_when: false + - name: Set fact for existing OSD hosts set_fact: cephadm_existing_osd_hosts: "{{ cephadm_osd_ps.stdout | from_json | map(attribute='hostname') | list | unique }}" run_once: true + - name: Debug cephadm_existing_osd_hosts debug: msg: "Nodes with existing OSDs: {{ cephadm_existing_osd_hosts }}" run_once: true + - name: Set list of nodes that need OSDs set_fact: cephadm_nodes_needing_osds: "{{ groups['cluster_machines'] | map('extract', hostvars, 'hostname') | difference(cephadm_existing_osd_hosts) }}" run_once: true + - name: Debug nodes needing OSDs debug: msg: "Nodes that need OSDs: {{ cephadm_nodes_needing_osds }}" run_once: true +- name: Find cephadm location + command: which cephadm + register: cephadm_path + failed_when: false + changed_when: false + environment: + PATH: "{{ ansible_env.PATH }}:/usr/local/bin" + +- name: Set cephadm binary path + set_fact: + cephadm_bin: "{{ cephadm_path.stdout if cephadm_path.rc == 0 else '/usr/local/bin/cephadm' }}" + - name: Zap the volume on nodes that need OSDs - command: "{{ cephadm_bin }} --image localhost:5000/ceph:v{{ cephadm_release }} ceph-volume lvm zap vg_ceph/lv_ceph" + command: "{{ cephadm_bin }} --image {{ cephadm_image }} ceph-volume lvm zap vg_ceph/lv_ceph" delegate_to: "{{ item }}" run_once: true when: hostvars[item]['hostname'] in cephadm_nodes_needing_osds loop: "{{ groups['cluster_machines'] }}" changed_when: true -- name: Copy ceph orch spec file - template: - src: "{{ cephadm_spec_path | default('spec.yaml.j2') }}" - dest: /tmp/t.yaml - mode: 0644 - run_once: true +# === Apply service specs === +- name: Apply service specs + ceph.cephadm.ceph_orch_apply: + spec: "{{ lookup('template', item) }}" + loop: + - spec_crash.yaml.j2 + - spec_mgr.yaml.j2 + - spec_mon.yaml.j2 delegate_to: "{{ cephadm_first_node }}" + run_once: true -- name: Add OSD daemon on nodes that need OSDs - command: "{{ cephadm_bin }} --image localhost:5000/ceph:v{{ cephadm_release }} shell -v /tmp/t.yaml:/tmp/t.yaml:ro -- ceph orch apply -i /tmp/t.yaml" +- name: Apply OSD service specs + ceph.cephadm.ceph_orch_apply: + spec: "{{ lookup('template', 'spec_osd.yaml.j2') }}" + vars: + osd_host: "{{ item }}" + osd_index: "{{ idx + 1 }}" + loop: "{{ groups['osds'] }}" + loop_control: + index_var: idx delegate_to: "{{ cephadm_first_node }}" run_once: true - changed_when: true - failed_when: false + when: hostvars[item]['hostname'] in cephadm_nodes_needing_osds +# === Health check === - name: Confirm cluster is ok command: ceph status --format=json register: cephadm_cephs @@ -371,6 +237,7 @@ delegate_to: "{{ cephadm_first_node }}" until: cephadm_cephs.stdout | from_json | community.general.json_query('health.status') == "HEALTH_OK" +# === RBD pool and CephX user (SEAPATH-specific) === - name: Check if RBD pool exists shell: cmd: set -o pipefail && ceph osd lspools | grep -w rbd @@ -414,14 +281,3 @@ osd 'allow class-read object_prefix rbd_children, profile rbd pool=rbd' when: cephadm_cephx_user_check.rc == 0 changed_when: true - -#- name: Update logrotate configuration for Ceph -# replace: -# path: "{{ cephadm_logrorateceph_path }}" -# regexp: '^/var/log/ceph/\*.log' -# replace: '/var/log/ceph/!(cephadm).log' - -- name: Stop and remove Podman registry container - containers.podman.podman_container: - name: registry - state: absent diff --git a/roles/cephadm/tasks/setup_user.yml b/roles/cephadm/tasks/setup_user.yml new file mode 100644 index 000000000..a4742847c --- /dev/null +++ b/roles/cephadm/tasks/setup_user.yml @@ -0,0 +1,40 @@ +# Copyright (C) 2025 RTE +# SPDX-License-Identifier: Apache-2.0 + +# Sets up the cephadm user, group, and sudoers entry. +# Can be included independently from the full cephadm role. + +--- +- name: Ensure group "cephadm" exists + group: + name: cephadm + gid: 1001 + state: present + +- name: Ensure user "cephadm" exists + user: + name: cephadm + uid: 1001 + group: cephadm + create_home: yes + +- name: Ensure group "containerized-ceph" exists + group: + name: containerized-ceph + gid: 167 + state: present + when: seapath_distro | default('') == "Debian" + +- name: Ensure user "containerized-ceph" exists with nologin (already exists on centos/oraclelinux) + user: + name: containerized-ceph + uid: 167 + group: containerized-ceph + create_home: no + shell: /sbin/nologin + when: seapath_distro | default('') == "Debian" + +- name: Set cephadm user sudo permissions + copy: + src: cephadm_sudoers + dest: /etc/sudoers.d/cephadm diff --git a/roles/cephadm/templates/ceph.conf.j2 b/roles/cephadm/templates/ceph.conf.j2 index ec0473817..6d2ede38e 100644 --- a/roles/cephadm/templates/ceph.conf.j2 +++ b/roles/cephadm/templates/ceph.conf.j2 @@ -1,3 +1,3 @@ [global] -public_network = {{ cephadm_network }} -cluster_network = {{ cephadm_network }} +public_network = {{ public_network }} +cluster_network = {{ cluster_network | default(public_network) }} diff --git a/roles/cephadm/templates/spec.yaml.j2 b/roles/cephadm/templates/spec.yaml.j2 deleted file mode 100644 index b17e085ed..000000000 --- a/roles/cephadm/templates/spec.yaml.j2 +++ /dev/null @@ -1,29 +0,0 @@ -service_type: crash -service_name: crash -placement: - host_pattern: '*' ---- -service_type: mgr -service_name: mgr -placement: - host_pattern: '*' ---- -service_type: mon -service_name: mon -placement: - host_pattern: '*' ---- -{% for host in groups['osds'] %} -service_type: osd -service_id: {{ 'osd' ~ (groups['osds'].index(host) + 1) }} -service_name: osd.{{ 'osd' ~ (groups['osds'].index(host) + 1) }} -placement: - host_pattern: {{ hostvars[host]['hostname'] }} -spec: - data_devices: - paths: - - /dev/vg_ceph/lv_ceph - filter_logic: AND - objectstore: bluestore ---- -{% endfor %} diff --git a/roles/cephadm/templates/spec_crash.yaml.j2 b/roles/cephadm/templates/spec_crash.yaml.j2 new file mode 100644 index 000000000..39b5bff06 --- /dev/null +++ b/roles/cephadm/templates/spec_crash.yaml.j2 @@ -0,0 +1,4 @@ +service_type: crash +service_name: crash +placement: + host_pattern: '*' diff --git a/roles/cephadm/templates/spec_mgr.yaml.j2 b/roles/cephadm/templates/spec_mgr.yaml.j2 new file mode 100644 index 000000000..90bf6dd2b --- /dev/null +++ b/roles/cephadm/templates/spec_mgr.yaml.j2 @@ -0,0 +1,4 @@ +service_type: mgr +service_name: mgr +placement: + host_pattern: '*' diff --git a/roles/cephadm/templates/spec_mon.yaml.j2 b/roles/cephadm/templates/spec_mon.yaml.j2 new file mode 100644 index 000000000..b62951a3f --- /dev/null +++ b/roles/cephadm/templates/spec_mon.yaml.j2 @@ -0,0 +1,4 @@ +service_type: mon +service_name: mon +placement: + host_pattern: '*' diff --git a/roles/cephadm/templates/spec_osd.yaml.j2 b/roles/cephadm/templates/spec_osd.yaml.j2 new file mode 100644 index 000000000..4220b545a --- /dev/null +++ b/roles/cephadm/templates/spec_osd.yaml.j2 @@ -0,0 +1,11 @@ +service_type: osd +service_id: {{ 'osd' ~ (osd_index | string) }} +service_name: osd.{{ 'osd' ~ (osd_index | string) }} +placement: + host_pattern: {{ hostvars[osd_host]['hostname'] }} +spec: + data_devices: + paths: + - /dev/vg_ceph/lv_ceph + filter_logic: AND + objectstore: bluestore diff --git a/roles/cephadm/vars/OracleLinux.yml b/roles/cephadm/vars/OracleLinux.yml deleted file mode 100644 index fcce39ed2..000000000 --- a/roles/cephadm/vars/OracleLinux.yml +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (C) 2025 RTE -# SPDX-License-Identifier: Apache-2.0 - ---- -cephadm_logrorateceph_path: "/etc/logrotate.d/ceph" diff --git a/roles/cephadm/vars/CentOS.yml b/roles/cephadm/vars/RedHat.yml similarity index 100% rename from roles/cephadm/vars/CentOS.yml rename to roles/cephadm/vars/RedHat.yml diff --git a/roles/ci_restore_snapshot/tasks/main.yml b/roles/ci_restore_snapshot/tasks/main.yml index 66c0bb972..85152786e 100644 --- a/roles/ci_restore_snapshot/tasks/main.yml +++ b/roles/ci_restore_snapshot/tasks/main.yml @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 --- -- include_vars: "{{ seapath_distro }}.yml" +- include_vars: "{{ ansible_os_family }}.yml" - name: Grub conf lineinfile: diff --git a/roles/ci_restore_snapshot/vars/OracleLinux.yml b/roles/ci_restore_snapshot/vars/OracleLinux.yml deleted file mode 100644 index 17a87461c..000000000 --- a/roles/ci_restore_snapshot/vars/OracleLinux.yml +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (C) 2025, RTE -# SPDX-License-Identifier: Apache-2.0 - ---- -ci_restore_snapshot_grub_update_command: "grub2-mkconfig -o /boot/grub2/grub.cfg" diff --git a/roles/ci_restore_snapshot/vars/CentOS.yml b/roles/ci_restore_snapshot/vars/RedHat.yml similarity index 100% rename from roles/ci_restore_snapshot/vars/CentOS.yml rename to roles/ci_restore_snapshot/vars/RedHat.yml diff --git a/roles/configure_ha/tasks/main.yml b/roles/configure_ha/tasks/main.yml index b64ae2d75..5a46b79a8 100644 --- a/roles/configure_ha/tasks/main.yml +++ b/roles/configure_ha/tasks/main.yml @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 --- -- include_vars: "{{ seapath_distro }}.yml" +- include_vars: "{{ ansible_os_family }}.yml" - name: Save cluster machine informations template: diff --git a/roles/configure_ha/vars/OracleLinux.yml b/roles/configure_ha/vars/OracleLinux.yml deleted file mode 100644 index 00eaaf8b2..000000000 --- a/roles/configure_ha/vars/OracleLinux.yml +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (C) 2025, RTE -# SPDX-License-Identifier: Apache-2.0 - ---- -configure_ha_crm_command_path: "/usr/local/bin/crm" diff --git a/roles/configure_ha/vars/CentOS.yml b/roles/configure_ha/vars/RedHat.yml similarity index 100% rename from roles/configure_ha/vars/CentOS.yml rename to roles/configure_ha/vars/RedHat.yml diff --git a/roles/configure_libvirt/tasks/main.yml b/roles/configure_libvirt/tasks/main.yml index a8d205417..a1a90dd36 100644 --- a/roles/configure_libvirt/tasks/main.yml +++ b/roles/configure_libvirt/tasks/main.yml @@ -20,22 +20,22 @@ state: restarted when: configure_libvirt_libvirtd_conf.changed # noqa: no-handler -# OracleLinux specific +# RedHat-family specific - name: Enable and start virtsecretd.socket ansible.builtin.systemd: name: virtsecretd.socket state: started enabled: true - when: seapath_distro == "OracleLinux" + when: ansible_os_family == "RedHat" - name: Enable and start virtqemud.socket ansible.builtin.systemd: name: virtqemud.socket state: started enabled: true - when: seapath_distro == "OracleLinux" + when: ansible_os_family == "RedHat" - name: Enable and start virtstoraged.socket ansible.builtin.systemd: name: virtstoraged.socket state: started enabled: true - when: seapath_distro == "OracleLinux" + when: ansible_os_family == "RedHat" diff --git a/roles/debian_physical_machine/tasks/main.yml b/roles/debian_physical_machine/tasks/main.yml index 3c32a5749..b788395cd 100644 --- a/roles/debian_physical_machine/tasks/main.yml +++ b/roles/debian_physical_machine/tasks/main.yml @@ -240,6 +240,65 @@ line: " types = [ \"rbd\", 1024 ]" state: present +- name: Configure registry mirroring + when: registry_mirror_url is defined and registry_mirror_url != '' + block: + - name: Create podman certs.d directory for registry + ansible.builtin.file: + path: "/etc/containers/certs.d/{{ registry_mirror_url }}" + state: directory + mode: '0755' + when: registry_tls_enabled | default(false) + + - name: Copy registry CA certificate for podman + ansible.builtin.copy: + src: /tmp/registry-ca.crt + dest: "/etc/containers/certs.d/{{ registry_mirror_url }}/ca.crt" + mode: '0644' + when: registry_tls_enabled | default(false) + + - name: Create docker certs.d directory for registry + ansible.builtin.file: + path: "/etc/docker/certs.d/{{ registry_mirror_url }}" + state: directory + mode: '0755' + when: registry_tls_enabled | default(false) + + - name: Copy registry CA certificate for docker + ansible.builtin.copy: + src: /tmp/registry-ca.crt + dest: "/etc/docker/certs.d/{{ registry_mirror_url }}/ca.crt" + mode: '0644' + when: registry_tls_enabled | default(false) + + - name: Configure podman registry mirroring + ansible.builtin.blockinfile: + path: /etc/containers/registries.conf + marker: "# {mark} ANSIBLE MANAGED BLOCK for registry mirroring" + block: | + [[registry]] + location = "docker.io" + insecure = {{ 'false' if registry_tls_enabled | default(false) else 'true' }} + [[registry.mirror]] + location = "{{ registry_mirror_url }}" + insecure = {{ 'false' if registry_tls_enabled | default(false) else 'true' }} + + [[registry]] + location = "quay.io" + insecure = {{ 'false' if registry_tls_enabled | default(false) else 'true' }} + [[registry.mirror]] + location = "{{ registry_mirror_url }}" + insecure = {{ 'false' if registry_tls_enabled | default(false) else 'true' }} + + - name: Configure docker registry mirroring + ansible.builtin.copy: + content: | + { + "registry-mirrors": ["{{ 'https' if registry_tls_enabled | default(false) else 'http' }}://{{ registry_mirror_url }}"] + } + dest: /etc/docker/daemon.json + mode: '0644' + - name: Create ovs-vswitchd.service.d directory file: path: /etc/systemd/system/ovs-vswitchd.service.d/ diff --git a/roles/deploy_python3_setup_ovs/tasks/main.yml b/roles/deploy_python3_setup_ovs/tasks/main.yml index 769e8873a..20ecfec60 100644 --- a/roles/deploy_python3_setup_ovs/tasks/main.yml +++ b/roles/deploy_python3_setup_ovs/tasks/main.yml @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 --- -- include_vars: "{{ seapath_distro }}.yml" +- include_vars: "{{ ansible_os_family }}.yml" - name: Synchronization of src python3-setup-ovs on the control machine to dest on the remote hosts ansible.posix.synchronize: diff --git a/roles/deploy_python3_setup_ovs/vars/OracleLinux.yml b/roles/deploy_python3_setup_ovs/vars/OracleLinux.yml deleted file mode 100644 index 94f0ea66d..000000000 --- a/roles/deploy_python3_setup_ovs/vars/OracleLinux.yml +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (C) 2025 RTE -# SPDX-License-Identifier: Apache-2.0 - ---- -deploy_python3_setup_ovs_pip_options: "--prefix=/usr/local/" diff --git a/roles/deploy_python3_setup_ovs/vars/CentOS.yml b/roles/deploy_python3_setup_ovs/vars/RedHat.yml similarity index 100% rename from roles/deploy_python3_setup_ovs/vars/CentOS.yml rename to roles/deploy_python3_setup_ovs/vars/RedHat.yml diff --git a/roles/deploy_vm_manager/tasks/main.yml b/roles/deploy_vm_manager/tasks/main.yml index cf7759abe..f8426e1a5 100644 --- a/roles/deploy_vm_manager/tasks/main.yml +++ b/roles/deploy_vm_manager/tasks/main.yml @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 --- -- include_vars: "{{ seapath_distro }}.yml" +- include_vars: "{{ ansible_os_family }}.yml" - name: Synchronization of src vm_manager on the control machine to dest on the remote hosts ansible.posix.synchronize: diff --git a/roles/deploy_vm_manager/vars/OracleLinux.yml b/roles/deploy_vm_manager/vars/OracleLinux.yml deleted file mode 100644 index 85ed76f7c..000000000 --- a/roles/deploy_vm_manager/vars/OracleLinux.yml +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (C) 2025 RTE -# SPDX-License-Identifier: Apache-2.0 - ---- -deploy_vm_manager_pip_options: "--prefix=/usr/local/" diff --git a/roles/deploy_vm_manager/vars/CentOS.yml b/roles/deploy_vm_manager/vars/RedHat.yml similarity index 100% rename from roles/deploy_vm_manager/vars/CentOS.yml rename to roles/deploy_vm_manager/vars/RedHat.yml diff --git a/roles/detect_seapath_distro/tasks/main.yaml b/roles/detect_seapath_distro/tasks/main.yaml index 11f512f08..f2ed98627 100644 --- a/roles/detect_seapath_distro/tasks/main.yaml +++ b/roles/detect_seapath_distro/tasks/main.yaml @@ -2,9 +2,11 @@ # SPDX-License-Identifier: Apache-2.0 --- -- name: Gather only ansible_distribution facts +- name: Gather distribution and os_family facts ansible.builtin.setup: - filter: ansible_distribution* + filter: + - ansible_distribution* + - ansible_os_family - name: Set detect_seapath_distro_distro from seapath_distro if it exists set_fact: @@ -30,6 +32,16 @@ detect_seapath_distro_distro: OracleLinux when: ansible_distribution | regex_search("Oracle") != None +- name: Detect Rocky distribution + set_fact: + detect_seapath_distro_distro: Rocky + when: ansible_distribution | regex_search("Rocky") != None + +- name: Detect AlmaLinux distribution + set_fact: + detect_seapath_distro_distro: AlmaLinux + when: ansible_distribution | regex_search("Alma") != None + - name: Show detect_seapath_distro_distro debug: var: detect_seapath_distro_distro @@ -57,8 +69,13 @@ seapath_distro: "{{ detect_seapath_distro_distro }}" # noqa: var-naming[no-role-prefix] when: detect_seapath_distro_distro is defined +- name: Set ansible_os_family for Yocto + set_fact: + ansible_os_family: Yocto + when: seapath_distro == 'Yocto' + - name: Set is_using_cephadm depending on distro and option set_fact: - is_using_cephadm: "{{ seapath_distro == 'OracleLinux' or seapath_distro == 'Debian' or (force_cephadm | default(false)) }}" # noqa: var-naming[no-role-prefix] + is_using_cephadm: "{{ ansible_os_family in ['RedHat', 'Debian'] or (force_cephadm | default(false)) }}" # noqa: var-naming[no-role-prefix] ... diff --git a/roles/network_configovs/tasks/main.yml b/roles/network_configovs/tasks/main.yml index e0dde9c2b..c2daf2dd1 100644 --- a/roles/network_configovs/tasks/main.yml +++ b/roles/network_configovs/tasks/main.yml @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 --- -- include_vars: "{{ seapath_distro }}.yml" +- include_vars: "{{ ansible_os_family }}.yml" - name: Create OVS configuration template: diff --git a/roles/network_configovs/vars/OracleLinux.yml b/roles/network_configovs/vars/OracleLinux.yml deleted file mode 100644 index 491758ce3..000000000 --- a/roles/network_configovs/vars/OracleLinux.yml +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (C) 2024 RTE -# SPDX-License-Identifier: Apache-2.0 - ---- -network_configovs_setup_ovs_command_path: "/usr/local/bin/setup_ovs" diff --git a/roles/network_configovs/vars/CentOS.yml b/roles/network_configovs/vars/RedHat.yml similarity index 100% rename from roles/network_configovs/vars/CentOS.yml rename to roles/network_configovs/vars/RedHat.yml diff --git a/roles/oraclelinux/README.md b/roles/oraclelinux/README.md deleted file mode 100644 index e50541285..000000000 --- a/roles/oraclelinux/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# OracleLinux Role - -This role apply the basic SEAPATH prerequisites for any OracleLinux machine - -## Requirements - -no requirement. - -## Role Variables - -| Variable | Required | Type | Comments | -|----------------------|----------|-------------|--------------------------------------------------------------------| -| syslog_tls_ca | No | String | Syslog TLS public key | -| syslog_tls_key | No | String | Syslog TLS private key | -| syslog_tls_server_ca | No | String | Syslog TLS CA | -| admin_user | Yes | String | User to use for administration | -| admin_passwd | No | String | Optional user password | -| admin_ssh_keys | No | String list | List of SSH public keys used to connect to the administration user | -| grub_append | No | String list | List of extra kernel parameters | -| syslog_server_ip | No | String | IP address of the Syslog server to send logs | -| apt_repo | No | String list | List of apt repositories | - -## Example Playbook - -```yaml -- hosts: cluster_machines - roles: - - { role: seapath_ansible.oraclelinux } -``` diff --git a/roles/oraclelinux/files/00-panicreboot.conf b/roles/oraclelinux/files/00-panicreboot.conf deleted file mode 100644 index 56730a77e..000000000 --- a/roles/oraclelinux/files/00-panicreboot.conf +++ /dev/null @@ -1 +0,0 @@ -kernel.panic = 20 diff --git a/roles/oraclelinux/files/journald.conf b/roles/oraclelinux/files/journald.conf deleted file mode 100644 index 6e1f321f0..000000000 --- a/roles/oraclelinux/files/journald.conf +++ /dev/null @@ -1,44 +0,0 @@ -# This file is part of systemd. -# -# systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. -# -# Entries in this file show the compile time defaults. -# You can change settings by editing this file. -# Defaults can be restored by simply deleting this file. -# -# See journald.conf(5) for details. - -[Journal] -Storage=persistent -#Compress=yes -#Seal=yes -#SplitMode=uid -#SyncIntervalSec=5m -#RateLimitIntervalSec=30s -#RateLimitBurst=10000 -#SystemMaxUse= -#SystemKeepFree= -#SystemMaxFileSize= -#SystemMaxFiles=100 -#RuntimeMaxUse= -#RuntimeKeepFree= -#RuntimeMaxFileSize= -#RuntimeMaxFiles=100 -#MaxRetentionSec= -#MaxFileSec=1month -#ForwardToSyslog=yes -#ForwardToKMsg=no -#ForwardToConsole=no -#ForwardToWall=yes -#TTYPath=/dev/console -#MaxLevelStore=debug -#MaxLevelSyslog=debug -#MaxLevelKMsg=notice -#MaxLevelConsole=info -#MaxLevelWall=emerg -#LineMax=48K -#ReadKMsg=yes -#Audit=no diff --git a/roles/oraclelinux/meta/main.yml b/roles/oraclelinux/meta/main.yml deleted file mode 100644 index b677f1e56..000000000 --- a/roles/oraclelinux/meta/main.yml +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (C) 2024 RTE -# SPDX-License-Identifier: Apache-2.0 ---- -galaxy_info: - author: "Seapath" - description: Prerequisite for all debian machine - min_ansible_version: 2.9.10 - license: Apache-2.0 - platforms: - - name: Debian - versions: - - all -dependencies: [] - diff --git a/roles/oraclelinux_physical_machine/README.md b/roles/oraclelinux_physical_machine/README.md deleted file mode 100644 index 1e3baa6bc..000000000 --- a/roles/oraclelinux_physical_machine/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# OracleLinux Physical Machine Role - -This role apply the SEAPATH prerequisites for any OracleLinux physical machine (hypervisor, observer, or standalone). - -## Requirements - -No requirement. - -## Role Variables - -| Variable | Type | Comments | -|--------------------------------|-------------|--------------------------------------------------------------------------------------------------------------------------------------| -| extra_sysctl_physical_machines | String | Custom systctl configuration separate by new spaces | -| extra_kernel_modules | String list | List of Kernel modules to load when booting | -| admin_user | String | Administrator Unix username | -| logstash_server_ip | String | Address IP of the logstash server | -| pacemaker_shutdown_timeout | String | Custom timeout for stopping the systemd Pacemaker service. Time is a seconds, but support the min suffix to use minutes.Default 2min | -| chrony_wait_timeout_sec | String | Custom timeout for stopping the systemd Chrony service. Time is a seconds, but support the min suffix to use minutes.Default 180 | - - -## Example Playbook - -```yaml -- hosts: cluster_machines - roles: - - { role: seapath_ansible.oraclelinux_physical_machine } -``` diff --git a/roles/oraclelinux_physical_machine/files/00-bridge_nf_call.conf b/roles/oraclelinux_physical_machine/files/00-bridge_nf_call.conf deleted file mode 100644 index 3fe3e5277..000000000 --- a/roles/oraclelinux_physical_machine/files/00-bridge_nf_call.conf +++ /dev/null @@ -1,3 +0,0 @@ -net.bridge.bridge-nf-call-arptables = 0 -net.bridge.bridge-nf-call-ip6tables = 0 -net.bridge.bridge-nf-call-iptables = 0 diff --git a/roles/oraclelinux_physical_machine/files/69-lvm.rules b/roles/oraclelinux_physical_machine/files/69-lvm.rules deleted file mode 100644 index 6544dccf9..000000000 --- a/roles/oraclelinux_physical_machine/files/69-lvm.rules +++ /dev/null @@ -1,94 +0,0 @@ -# Copyright (C) 2012,2021 Red Hat, Inc. All rights reserved. -# -# This file is part of LVM. -# -# This rule requires blkid to be called on block devices before so only devices -# used as LVM PVs are processed (ID_FS_TYPE="LVM2_member"). - -SUBSYSTEM!="block", GOTO="lvm_end" - - -ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", GOTO="lvm_end" - -# Only process devices already marked as a PV - this requires blkid to be called before. -ENV{ID_FS_TYPE}!="LVM2_member", GOTO="lvm_end" -ENV{DM_MULTIPATH_DEVICE_PATH}=="1", GOTO="lvm_end" -ACTION=="remove", GOTO="lvm_end" - -# Create /dev/disk/by-id/lvm-pv-uuid- symlink for each PV -ENV{ID_FS_UUID_ENC}=="?*", SYMLINK+="disk/by-id/lvm-pv-uuid-$env{ID_FS_UUID_ENC}" - -# If the PV is a special device listed below, scan only if the device is -# properly activated. These devices are not usable after an ADD event, -# but they require an extra setup and they are ready after a CHANGE event. -# Also support coldplugging with ADD event but only if the device is already -# properly activated. -# This logic should be eventually moved to rules where those particular -# devices are processed primarily (MD and loop). - -# DM device: -KERNEL!="dm-[0-9]*", GOTO="next" -ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}=="1", ENV{DM_ACTIVATION}=="1", GOTO="lvm_scan" -GOTO="lvm_end" - -# MD device: -LABEL="next" -KERNEL!="md[0-9]*", GOTO="next" -IMPORT{db}="LVM_MD_PV_ACTIVATED" -ACTION=="add", ENV{LVM_MD_PV_ACTIVATED}=="1", GOTO="lvm_scan" -ACTION=="change", ENV{LVM_MD_PV_ACTIVATED}!="1", TEST=="md/array_state", ENV{LVM_MD_PV_ACTIVATED}="1", GOTO="lvm_scan" -ACTION=="add", KERNEL=="md[0-9]*p[0-9]*", GOTO="lvm_scan" -ENV{LVM_MD_PV_ACTIVATED}!="1", ENV{SYSTEMD_READY}="0" -GOTO="lvm_end" - -# Loop device: -LABEL="next" -KERNEL!="loop[0-9]*", GOTO="next" -ACTION=="add", ENV{LVM_LOOP_PV_ACTIVATED}=="1", GOTO="lvm_scan" -ACTION=="change", ENV{LVM_LOOP_PV_ACTIVATED}!="1", TEST=="loop/backing_file", ENV{LVM_LOOP_PV_ACTIVATED}="1", GOTO="lvm_scan" -ENV{LVM_LOOP_PV_ACTIVATED}!="1", ENV{SYSTEMD_READY}="0" -GOTO="lvm_end" - -LABEL="next" -ACTION!="add", GOTO="lvm_end" - -LABEL="lvm_scan" - -ENV{SYSTEMD_READY}="1" - -# pvscan will check if this device completes a VG, -# i.e. all PVs in the VG are now present with the -# arrival of this PV. If so, it prints to stdout: -# LVM_VG_NAME_COMPLETE='foo' -# -# When the VG is complete it can be activated, so -# vgchange -aay is run. It is run via -# systemd since it can take longer to run than -# udev wants to block when processing rules. -# (if there are hundreds of LVs to activate, -# the vgchange can take many seconds.) -# -# pvscan only reads the single device specified, -# and uses temp files under /run/lvm to check if -# other PVs in the VG are present. -# -# If event_activation=0 in lvm.conf, this pvscan -# (using checkcomplete) will do nothing, so that -# no event-based autoactivation will be happen. -# -# TODO: adjust the output of vgchange -aay so that -# it's better suited to appearing in the journal. - -IMPORT{program}="/sbin/lvm pvscan --cache --listvg --checkcomplete --vgonline --autoactivation event --udevoutput --journal=output $env{DEVNAME}" -TEST!="/run/systemd/system", GOTO="lvm_direct_vgchange" - -ENV{LVM_VG_NAME_COMPLETE}=="?*", RUN+="/usr/bin/systemd-run --no-block --property DefaultDependencies=no --unit lvm-activate-$env{LVM_VG_NAME_COMPLETE} /sbin/lvm vgchange -aay --autoactivation event $env{LVM_VG_NAME_COMPLETE}" -GOTO="lvm_end" - -LABEL="lvm_direct_vgchange" -ENV{LVM_VG_NAME_COMPLETE}=="?*", RUN+="/sbin/lvm vgchange -aay --autoactivation event $env{LVM_VG_NAME_COMPLETE}" -TEST!="/run/initramfs", GOTO="lvm_end" -ENV{LVM_VG_NAME_INCOMPLETE}=="?*", RUN+="/sbin/lvm vgchange --sysinit -aay --activation degraded $env{LVM_VG_NAME_INCOMPLETE}" -GOTO="lvm_end" - -LABEL="lvm_end" diff --git a/roles/oraclelinux_physical_machine/files/etc_apparmor.d_abstractions_libvirt-qemu.conf b/roles/oraclelinux_physical_machine/files/etc_apparmor.d_abstractions_libvirt-qemu.conf deleted file mode 100644 index 34af51204..000000000 --- a/roles/oraclelinux_physical_machine/files/etc_apparmor.d_abstractions_libvirt-qemu.conf +++ /dev/null @@ -1,252 +0,0 @@ - #include - #include - #include - - # required for reading disk images - capability dac_override, - capability dac_read_search, - capability chown, - - # needed to drop privileges - capability setgid, - capability setuid, - - network inet stream, - network inet6 stream, - - ptrace (readby, tracedby) peer=libvirtd, - ptrace (readby, tracedby) peer=/usr/sbin/libvirtd, - - signal (receive) peer=libvirtd, - signal (receive) peer=/usr/sbin/libvirtd, - - /dev/kvm rw, - /dev/net/tun rw, - /dev/ptmx rw, - @{PROC}/*/status r, - # When qemu is signaled to terminate, it will read cmdline of signaling - # process for reporting purposes. Allowing read access to a process - # cmdline may leak sensitive information embedded in the cmdline. - @{PROC}/@{pid}/cmdline r, - # Per man(5) proc, the kernel enforces that a thread may - # only modify its comm value or those in its thread group. - owner @{PROC}/@{pid}/task/@{tid}/comm rw, - @{PROC}/sys/kernel/cap_last_cap r, - @{PROC}/sys/vm/overcommit_memory r, - # detect hardware capabilities via qemu_getauxval - owner @{PROC}/*/auxv r, - - # For hostdev access. The actual devices will be added dynamically - /sys/bus/usb/devices/ r, - /sys/devices/**/usb[0-9]*/** r, - # libusb needs udev data about usb devices (~equal to content of lsusb -v) - /run/udev/data/+usb* r, - /run/udev/data/c16[6,7]* r, - /run/udev/data/c18[0,8,9]* r, - - # WARNING: this gives the guest direct access to host hardware and specific - # portions of shared memory. This is required for sound using ALSA with kvm, - # but may constitute a security risk. If your environment does not require - # the use of sound in your VMs, feel free to comment out or prepend 'deny' to - # the rules for files in /dev. - /dev/snd/* rw, - /{dev,run}/shm r, - /{dev,run}/shmpulse-shm* r, - /{dev,run}/shmpulse-shm* rwk, - capability ipc_lock, - # spice - owner /{dev,run}/shm/spice.* rw, - # 'kill' is not required for sound and is a security risk. Do not enable - # unless you absolutely need it. - deny capability kill, - - # Uncomment the following if you need access to /dev/fb* - #/dev/fb* rw, - - /etc/pulse/client.conf r, - @{HOME}/.pulse-cookie rwk, - owner /root/.pulse-cookie rwk, - owner /root/.pulse/ rw, - owner /root/.pulse/* rw, - /usr/share/alsa/** r, - owner /tmp/pulse-*/ rw, - owner /tmp/pulse-*/* rw, - /var/lib/dbus/machine-id r, - - # access to firmware's etc - /usr/share/AAVMF/** r, - /usr/share/bochs/** r, - /usr/share/edk2-ovmf/** rk, - /usr/share/kvm/** r, - /usr/share/misc/sgabios.bin r, - /usr/share/openbios/** r, - /usr/share/openhackware/** r, - /usr/share/OVMF/** rk, - /usr/share/ovmf/** rk, - /usr/share/proll/** r, - /usr/share/qemu-efi/** r, - /usr/share/qemu-kvm/** r, - /usr/share/qemu/** r, - /usr/share/seabios/** r, - /usr/share/sgabios/** r, - /usr/share/slof/** r, - /usr/share/vgabios/** r, - - # pki for libvirt-vnc and libvirt-spice (LP: #901272, #1690140) - /etc/pki/CA/ r, - /etc/pki/CA/* r, - /etc/pki/libvirt{,-spice,-vnc}/ r, - /etc/pki/libvirt{,-spice,-vnc}/** r, - /etc/pki/qemu/ r, - /etc/pki/qemu/** r, - - # the various binaries - /usr/bin/kvm rmix, - /usr/bin/kvm-spice rmix, - /usr/bin/qemu rmix, - /usr/bin/qemu-aarch64 rmix, - /usr/bin/qemu-alpha rmix, - /usr/bin/qemu-arm rmix, - /usr/bin/qemu-armeb rmix, - /usr/bin/qemu-cris rmix, - /usr/bin/qemu-i386 rmix, - /usr/bin/qemu-kvm rmix, - /usr/bin/qemu-m68k rmix, - /usr/bin/qemu-microblaze rmix, - /usr/bin/qemu-microblazeel rmix, - /usr/bin/qemu-mips rmix, - /usr/bin/qemu-mips64 rmix, - /usr/bin/qemu-mips64el rmix, - /usr/bin/qemu-mipsel rmix, - /usr/bin/qemu-mipsn32 rmix, - /usr/bin/qemu-mipsn32el rmix, - /usr/bin/qemu-or32 rmix, - /usr/bin/qemu-ppc rmix, - /usr/bin/qemu-ppc64 rmix, - /usr/bin/qemu-ppc64abi32 rmix, - /usr/bin/qemu-ppc64le rmix, - /usr/bin/qemu-s390x rmix, - /usr/bin/qemu-sh4 rmix, - /usr/bin/qemu-sh4eb rmix, - /usr/bin/qemu-sparc rmix, - /usr/bin/qemu-sparc32plus rmix, - /usr/bin/qemu-sparc64 rmix, - /usr/bin/qemu-system-aarch64 rmix, - /usr/bin/qemu-system-alpha rmix, - /usr/bin/qemu-system-arm rmix, - /usr/bin/qemu-system-cris rmix, - /usr/bin/qemu-system-hppa rmix, - /usr/bin/qemu-system-i386 rmix, - /usr/bin/qemu-system-lm32 rmix, - /usr/bin/qemu-system-m68k rmix, - /usr/bin/qemu-system-microblaze rmix, - /usr/bin/qemu-system-microblazeel rmix, - /usr/bin/qemu-system-mips rmix, - /usr/bin/qemu-system-mips64 rmix, - /usr/bin/qemu-system-mips64el rmix, - /usr/bin/qemu-system-mipsel rmix, - /usr/bin/qemu-system-moxie rmix, - /usr/bin/qemu-system-nios2 rmix, - /usr/bin/qemu-system-or1k rmix, - /usr/bin/qemu-system-or32 rmix, - /usr/bin/qemu-system-ppc rmix, - /usr/bin/qemu-system-ppc64 rmix, - /usr/bin/qemu-system-ppcemb rmix, - /usr/bin/qemu-system-riscv32 rmix, - /usr/bin/qemu-system-riscv64 rmix, - /usr/bin/qemu-system-s390x rmix, - /usr/bin/qemu-system-sh4 rmix, - /usr/bin/qemu-system-sh4eb rmix, - /usr/bin/qemu-system-sparc rmix, - /usr/bin/qemu-system-sparc64 rmix, - /usr/bin/qemu-system-tricore rmix, - /usr/bin/qemu-system-unicore32 rmix, - /usr/bin/qemu-system-x86_64 rmix, - /usr/bin/qemu-system-xtensa rmix, - /usr/bin/qemu-system-xtensaeb rmix, - /usr/bin/qemu-unicore32 rmix, - /usr/bin/qemu-x86_64 rmix, - # for Debian/Ubuntu qemu-block-extra / RPMs qemu-block-* (LP: #1554761) - /usr/{lib,lib64}/qemu/*.so mr, - /usr/lib/@{multiarch}/qemu/*.so mr, - - # let qemu load old shared objects after upgrades (LP: #1847361) - /{var/,}run/qemu/*/*.so mr, - # but explicitly deny writing to these files - audit deny /{var/,}run/qemu/*/*.so w, - - # swtpm - /{usr/,}bin/swtpm rmix, - /usr/{lib,lib64}/libswtpm_libtpms.so mr, - /usr/lib/@{multiarch}/libswtpm_libtpms.so mr, - - # for save and resume - /{usr/,}bin/dash rmix, - /{usr/,}bin/dd rmix, - /{usr/,}bin/cat rmix, - - # for restore - /{usr/,}bin/bash rmix, - - # for usb access - /dev/bus/usb/ r, - /etc/udev/udev.conf r, - /sys/bus/ r, - /sys/class/ r, - - # for rbd - /etc/ceph/ceph.conf r, - - # Various functions will need to enumerate /tmp (e.g. ceph), allow the base - # dir and a few known functions like samba support. - # We want to avoid to give blanket rw permission to everything under /tmp, - # users are expected to add site specific addons for more uncommon cases. - # Qemu processes usually all run as the same users, so the "owner" - # restriction prevents access to other services files, but not across - # different instances. - # This is a tradeoff between usability and security - if paths would be more - # predictable that would be preferred - at least for write rules we would - # want more unique paths per rule. - /{,var/}tmp/ r, - owner /{,var/}tmp/**/ r, - - # for file-posix getting limits since 9103f1ce - /sys/devices/**/block/*/queue/max_segments r, - - # for ppc device-tree access - @{PROC}/device-tree/ r, - @{PROC}/device-tree/** r, - /sys/firmware/devicetree/** r, - - # allow connect with openGraphicsFD to work - unix (send, receive) type=stream addr=none peer=(label=libvirtd), - unix (send, receive) type=stream addr=none peer=(label=/usr/sbin/libvirtd), - - # for gathering information about available host resources - /sys/devices/system/cpu/ r, - /sys/devices/system/node/ r, - /sys/devices/system/node/node[0-9]*/meminfo r, - /sys/module/vhost/parameters/max_mem_regions r, - - # silence refusals to open lttng files (see LP: #1432644) - deny /dev/shm/lttng-ust-wait-* r, - deny /run/shm/lttng-ust-wait-* r, - - # for vfio hotplug on systems without static vfio (LP: #1775777) - /dev/vfio/vfio rw, - - # required for sasl GSSAPI plugin - /etc/gss/mech.d/ r, - /etc/gss/mech.d/* r, - - # required by libpmem init to fts_open()/fts_read() the symlinks in - # /sys/bus/nd/devices - / r, # harmless on any lsb compliant system - /sys/bus/nd/devices/{,**/} r, - - # Site-specific additions and overrides. See local/README for details. - #include - - # required for QEMU accessing UEFI nvram variables - owner /var/lib/libvirt/qemu/nvram/*_VARS.fd rwk, - owner /var/lib/libvirt/qemu/nvram/*_VARS.ms.fd rwk, diff --git a/roles/oraclelinux_physical_machine/files/pacemaker_ra/ntpstatus b/roles/oraclelinux_physical_machine/files/pacemaker_ra/ntpstatus deleted file mode 100755 index 5ac67370b..000000000 --- a/roles/oraclelinux_physical_machine/files/pacemaker_ra/ntpstatus +++ /dev/null @@ -1,320 +0,0 @@ -#!/bin/sh -# -# ocf:seapath:ntpstatus resource agent -# -# Original copyright 2004 SUSE LINUX AG, Lars Marowsky-Bre -# Later changes copyright 2008-2019 the Pacemaker project contributors -# -# The version control history for this file may have further details. -# -# This source code is licensed under the GNU General Public License version 2 -# (GPLv2) WITHOUT ANY WARRANTY. -# -# crm config example: -#primitive ntpstatus_test ocf:seapath:ntpstatus \ -# op monitor timeout=10 interval=10 -#clone cl_ntpstatus_test ntpstatus_test \ -# meta target-role=Started -#location ntp_test_debian debian \ -# rule ntpstatus: defined ntpstatus -# -####################################################################### -# Initialization: - -: ${OCF_FUNCTIONS:="${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs"} -. "${OCF_FUNCTIONS}" -: ${__OCF_ACTION:="$1"} - -####################################################################### - -meta_data() { - cat < - - -1.0 - - -Checks the status of the connectivity to a ntp server - -Checks the status of the connectivity to a ntp server - - - - -Location to store the resource state in. - -State file - - - - - -ntpstatus - -ntpstatus - - - - - -Number of seconds to sleep during operations. This can be used to test how -the cluster reacts to operation timeouts. - -Operation sleep duration in seconds. - - - - - -Start actions will return failure if running on the host specified here, but -the resource will start successfully anyway (future monitor calls will find it -running). This can be used to test on-fail=ignore. - -Report bogus start failure on specified host - - - - - -If this is set, the environment will be dumped to this file for every call. - -Environment dump file - - - - - -The number by which to multiply the connectivity (0 or 1) by - -Value multiplier - - - - - -ip address to check the connectivity to - -Host IP - - - - - - - - - - - - - - - - -END -} - -####################################################################### - -# don't exit on TERM, to test that pacemaker-execd makes sure that we do exit -trap sigterm_handler TERM -sigterm_handler() { - ocf_log info "They use TERM to bring us down. No such luck." - - # Since we're likely going to get KILLed, clean up any monitor - # serialization in progress, so the next probe doesn't return an error. - rm -f "${VERIFY_SERIALIZED_FILE}" - return -} - -ntpstatus_usage() { - cat <> "${OCF_RESKEY_envfile}" - fi -} - -ntpstatus_update() { - # get the 5th column from chrony sources output (reach), convert from octal to binary and get the last digit (last contact with server) - # 1 --> last contact fine - # 0 --> last contact problem - status=`echo $(/usr/bin/chronyc -n sources | grep -E "$OCF_RESKEY_host_ip" | awk '{print $5}') | python3 -c "print(\"{0:b}\".format(int(input() or \"0\",8))[-1])"` - case "${status#[+]}" in - ''|*[!0-9]*) - status=0 - ;; - esac - status=$(expr $status \* $OCF_RESKEY_multiplier) - if [ "$__OCF_ACTION" = "start" ] ; then - attrd_updater -n "$OCF_RESKEY_ntpstatus" -B "$status" -d "$OCF_RESKEY_dampen" $attrd_options - else - attrd_updater -n "$OCF_RESKEY_ntpstatus" -v "$status" -d "$OCF_RESKEY_dampen" $attrd_options - fi - rc=$? - case $rc in - 0) #ocf_log info "Updated $OCF_RESKEY_ntpstatus = $status" - ;; - *) ocf_log warn "Could not update $OCF_RESKEY_ntpstatus = $status: rc=$rc";; - esac - if [ $rc -ne 0 ]; then - return $rc - fi -} - -ntpstatus_start() { - ntpstatus_monitor - - DS_RETVAL=$? - if [ $DS_RETVAL -eq $OCF_SUCCESS ]; then - if [ "$(uname -n)" = "${OCF_RESKEY_fail_start_on}" ]; then - DS_RETVAL=$OCF_ERR_GENERIC - fi - return $DS_RETVAL - fi - - touch "${OCF_RESKEY_state}" - DS_RETVAL=$? - if [ "$(uname -n)" = "${OCF_RESKEY_fail_start_on}" ]; then - DS_RETVAL=$OCF_ERR_GENERIC - fi - ntpstatus_update - return $DS_RETVAL -} - -ntpstatus_stop() { - ntpstatus_monitor --force - attrd_updater -D -n "$OCF_RESKEY_ntpstatus" -d "$OCF_RESKEY_dampen" $attrd_options - if [ $? -eq $OCF_SUCCESS ]; then - rm "${OCF_RESKEY_state}" - fi - rm -f "${VERIFY_SERIALIZED_FILE}" - return $OCF_SUCCESS -} - -ntpstatus_monitor() { - if [ $OCF_RESKEY_op_sleep -ne 0 ]; then - if [ "$1" = "" ] && [ -f "${VERIFY_SERIALIZED_FILE}" ]; then - # two monitor ops have occurred at the same time. - # This verifies a condition in pacemaker-execd regression tests. - ocf_log err "$VERIFY_SERIALIZED_FILE exists already" - ocf_exit_reason "alternate universe collision" - return $OCF_ERR_GENERIC - fi - - touch "${VERIFY_SERIALIZED_FILE}" - sleep ${OCF_RESKEY_op_sleep} - rm "${VERIFY_SERIALIZED_FILE}" - fi - - if [ -f "${OCF_RESKEY_state}" ]; then - ntpstatus_update - # Multiple monitor levels are defined to support various tests - case "$OCF_CHECK_LEVEL" in - 10) - # monitor level with delay, useful for testing timeouts - sleep 30 - ;; - - 20) - # monitor level that fails intermittently - n=$(expr "$(dd if=/dev/urandom bs=1 count=1 2>/dev/null | od | head -1 | cut -f2 -d' ')" % 5) - if [ $n -eq 1 ]; then - ocf_exit_reason "smoke detected near CPU fan" - return $OCF_ERR_GENERIC - fi - ;; - - 30) - # monitor level that always fails - ocf_exit_reason "hyperdrive quota reached" - return $OCF_ERR_GENERIC - ;; - - 40) - # monitor level that returns error code from state file - rc=$(cat ${OCF_RESKEY_state}) - [ -n "$rc" ] && ocf_exit_reason "CPU ejected. Observed leaving the Kronosnet galaxy at $rc times the speed of light." && return $rc - ;; - - *) - ;; - esac - return $OCF_SUCCESS - fi - return $OCF_NOT_RUNNING -} - -ntpstatus_validate() { - # Is the state directory writable? - state_dir=$(dirname "$OCF_RESKEY_state") - [ -d "$state_dir" ] && [ -w "$state_dir" ] && [ -x "$state_dir" ] - if [ $? -ne 0 ]; then - return $OCF_ERR_ARGS - fi - - # Check the host ip - if [ -z "$OCF_RESKEY_host_ip" ]; then - ocf_log err "Empty host_ip. Please specify a host to check" - exit $OCF_ERR_CONFIGURED - fi - return $OCF_SUCCESS -} - -: ${OCF_RESKEY_op_sleep:=0} -: ${OCF_RESKEY_CRM_meta_interval:=0} -: ${OCF_RESKEY_CRM_meta_globally_unique:="false"} -: ${OCF_RESKEY_ntpstatus:="ntpstatus"} -: ${OCF_RESKEY_dampen:=75} -: ${OCF_RESKEY_multiplier:=1000} - -if [ -z "$OCF_RESKEY_state" ]; then - OCF_RESKEY_state="${HA_VARRUN%%/}/ntpstatus-${OCF_RESOURCE_INSTANCE}.state" - - if [ "${OCF_RESKEY_CRM_meta_globally_unique}" = "false" ]; then - # Strip off the trailing clone marker (note + is not portable in sed) - OCF_RESKEY_state=$(echo $OCF_RESKEY_state | sed s/:[0-9][0-9]*\.state/.state/) - fi -fi -VERIFY_SERIALIZED_FILE="${OCF_RESKEY_state}.serialized" - -dump_env - -case "$__OCF_ACTION" in -meta-data) meta_data - exit $OCF_SUCCESS - ;; -start) ntpstatus_start;; -stop) ntpstatus_stop;; -monitor) ntpstatus_monitor;; -migrate_to) ocf_log info "Migrating ${OCF_RESOURCE_INSTANCE} to ${OCF_RESKEY_CRM_meta_migrate_target}." - ntpstatus_stop - ;; -migrate_from) ocf_log info "Migrating ${OCF_RESOURCE_INSTANCE} from ${OCF_RESKEY_CRM_meta_migrate_source}." - ntpstatus_start - ;; -reload) ocf_log err "Reloading..." - ntpstatus_start - ;; -validate-all) ntpstatus_validate;; -usage|help) ntpstatus_usage - exit $OCF_SUCCESS - ;; -*) ntpstatus_usage - exit $OCF_ERR_UNIMPLEMENTED - ;; -esac -rc=$? -ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc" -exit $rc - -# vim: set filetype=sh expandtab tabstop=4 softtabstop=4 shiftwidth=4 textwidth=80: diff --git a/roles/oraclelinux_physical_machine/files/pacemaker_ra/ptpstatus b/roles/oraclelinux_physical_machine/files/pacemaker_ra/ptpstatus deleted file mode 100755 index d3d42ab1e..000000000 --- a/roles/oraclelinux_physical_machine/files/pacemaker_ra/ptpstatus +++ /dev/null @@ -1,303 +0,0 @@ -#!/bin/sh -# -# ocf:seapath:ptpstatus resource agent -# -# Original copyright 2004 SUSE LINUX AG, Lars Marowsky-Bre -# Later changes copyright 2008-2019 the Pacemaker project contributors -# -# The version control history for this file may have further details. -# -# This source code is licensed under the GNU General Public License version 2 -# (GPLv2) WITHOUT ANY WARRANTY. -# -# crm config example: -#primitive ptpstatus_test ocf:seapath:ptpstatus \ -# op monitor timeout=10 interval=10 -#clone cl_ptpstatus_test ptpstatus_test \ -# meta target-role=Started -#location ptp_test_debian debian \ -# rule ptpstatus: defined ptpstatus -# -####################################################################### -# Initialization: - -: ${OCF_FUNCTIONS:="${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs"} -. "${OCF_FUNCTIONS}" -: ${__OCF_ACTION:="$1"} - -####################################################################### - -meta_data() { - cat < - - -1.0 - - -Checks the status of the PTP synchronization - -Checks the status of the PTP synchronization - - - - -Location to store the resource state in. - -State file - - - - - -ptpstatus - -ptpstatus - - - - - -Number of seconds to sleep during operations. This can be used to test how -the cluster reacts to operation timeouts. - -Operation sleep duration in seconds. - - - - - -Start actions will return failure if running on the host specified here, but -the resource will start successfully anyway (future monitor calls will find it -running). This can be used to test on-fail=ignore. - -Report bogus start failure on specified host - - - - - -If this is set, the environment will be dumped to this file for every call. - -Environment dump file - - - - - -The number by which to multiply the connectivity (0 or 1) by - -Value multiplier - - - - - - - - - - - - - - - - -END -} - -####################################################################### - -# don't exit on TERM, to test that pacemaker-execd makes sure that we do exit -trap sigterm_handler TERM -sigterm_handler() { - ocf_log info "They use TERM to bring us down. No such luck." - - # Since we're likely going to get KILLed, clean up any monitor - # serialization in progress, so the next probe doesn't return an error. - rm -f "${VERIFY_SERIALIZED_FILE}" - return -} - -ptpstatus_usage() { - cat <> "${OCF_RESKEY_envfile}" - fi -} - -ptpstatus_update() { - status=`/usr/bin/chronyc -n sources | grep -E "#[*+] PTP0" | wc -l` - case "${status#[+]}" in - ''|*[!0-9]*) - status=0 - ;; - esac - status=$(expr $status \* $OCF_RESKEY_multiplier) - if [ "$__OCF_ACTION" = "start" ] ; then - attrd_updater -n "$OCF_RESKEY_ptpstatus" -B "$status" -d "$OCF_RESKEY_dampen" $attrd_options - else - attrd_updater -n "$OCF_RESKEY_ptpstatus" -v "$status" -d "$OCF_RESKEY_dampen" $attrd_options - fi - rc=$? - case $rc in - 0) #ocf_log info "Updated $OCF_RESKEY_ptpstatus = $status" - ;; - *) ocf_log warn "Could not update $OCF_RESKEY_ptpstatus = $status: rc=$rc";; - esac - if [ $rc -ne 0 ]; then - return $rc - fi -} - -ptpstatus_start() { - ptpstatus_monitor - - DS_RETVAL=$? - if [ $DS_RETVAL -eq $OCF_SUCCESS ]; then - if [ "$(uname -n)" = "${OCF_RESKEY_fail_start_on}" ]; then - DS_RETVAL=$OCF_ERR_GENERIC - fi - return $DS_RETVAL - fi - - touch "${OCF_RESKEY_state}" - DS_RETVAL=$? - if [ "$(uname -n)" = "${OCF_RESKEY_fail_start_on}" ]; then - DS_RETVAL=$OCF_ERR_GENERIC - fi - ptpstatus_update - return $DS_RETVAL -} - -ptpstatus_stop() { - ptpstatus_monitor --force - attrd_updater -D -n "$OCF_RESKEY_ptpstatus" -d "$OCF_RESKEY_dampen" $attrd_options - if [ $? -eq $OCF_SUCCESS ]; then - rm "${OCF_RESKEY_state}" - fi - rm -f "${VERIFY_SERIALIZED_FILE}" - return $OCF_SUCCESS -} - -ptpstatus_monitor() { - if [ $OCF_RESKEY_op_sleep -ne 0 ]; then - if [ "$1" = "" ] && [ -f "${VERIFY_SERIALIZED_FILE}" ]; then - # two monitor ops have occurred at the same time. - # This verifies a condition in pacemaker-execd regression tests. - ocf_log err "$VERIFY_SERIALIZED_FILE exists already" - ocf_exit_reason "alternate universe collision" - return $OCF_ERR_GENERIC - fi - - touch "${VERIFY_SERIALIZED_FILE}" - sleep ${OCF_RESKEY_op_sleep} - rm "${VERIFY_SERIALIZED_FILE}" - fi - - if [ -f "${OCF_RESKEY_state}" ]; then - ptpstatus_update - # Multiple monitor levels are defined to support various tests - case "$OCF_CHECK_LEVEL" in - 10) - # monitor level with delay, useful for testing timeouts - sleep 30 - ;; - - 20) - # monitor level that fails intermittently - n=$(expr "$(dd if=/dev/urandom bs=1 count=1 2>/dev/null | od | head -1 | cut -f2 -d' ')" % 5) - if [ $n -eq 1 ]; then - ocf_exit_reason "smoke detected near CPU fan" - return $OCF_ERR_GENERIC - fi - ;; - - 30) - # monitor level that always fails - ocf_exit_reason "hyperdrive quota reached" - return $OCF_ERR_GENERIC - ;; - - 40) - # monitor level that returns error code from state file - rc=$(cat ${OCF_RESKEY_state}) - [ -n "$rc" ] && ocf_exit_reason "CPU ejected. Observed leaving the Kronosnet galaxy at $rc times the speed of light." && return $rc - ;; - - *) - ;; - esac - return $OCF_SUCCESS - fi - return $OCF_NOT_RUNNING -} - -ptpstatus_validate() { - # Is the state directory writable? - state_dir=$(dirname "$OCF_RESKEY_state") - [ -d "$state_dir" ] && [ -w "$state_dir" ] && [ -x "$state_dir" ] - if [ $? -ne 0 ]; then - return $OCF_ERR_ARGS - fi - return $OCF_SUCCESS -} - -: ${OCF_RESKEY_op_sleep:=0} -: ${OCF_RESKEY_CRM_meta_interval:=0} -: ${OCF_RESKEY_CRM_meta_globally_unique:="false"} -: ${OCF_RESKEY_ptpstatus:="ptpstatus"} -: ${OCF_RESKEY_dampen:=75} -: ${OCF_RESKEY_multiplier:=1000} - -if [ -z "$OCF_RESKEY_state" ]; then - OCF_RESKEY_state="${HA_VARRUN%%/}/ptpstatus-${OCF_RESOURCE_INSTANCE}.state" - - if [ "${OCF_RESKEY_CRM_meta_globally_unique}" = "false" ]; then - # Strip off the trailing clone marker (note + is not portable in sed) - OCF_RESKEY_state=$(echo $OCF_RESKEY_state | sed s/:[0-9][0-9]*\.state/.state/) - fi -fi -VERIFY_SERIALIZED_FILE="${OCF_RESKEY_state}.serialized" - -dump_env - -case "$__OCF_ACTION" in -meta-data) meta_data - exit $OCF_SUCCESS - ;; -start) ptpstatus_start;; -stop) ptpstatus_stop;; -monitor) ptpstatus_monitor;; -migrate_to) ocf_log info "Migrating ${OCF_RESOURCE_INSTANCE} to ${OCF_RESKEY_CRM_meta_migrate_target}." - ptpstatus_stop - ;; -migrate_from) ocf_log info "Migrating ${OCF_RESOURCE_INSTANCE} from ${OCF_RESKEY_CRM_meta_migrate_source}." - ptpstatus_start - ;; -reload) ocf_log err "Reloading..." - ptpstatus_start - ;; -validate-all) ptpstatus_validate;; -usage|help) ptpstatus_usage - exit $OCF_SUCCESS - ;; -*) ptpstatus_usage - exit $OCF_ERR_UNIMPLEMENTED - ;; -esac -rc=$? -ocf_log debug "${OCF_RESOURCE_INSTANCE} $__OCF_ACTION : $rc" -exit $rc - -# vim: set filetype=sh expandtab tabstop=4 softtabstop=4 shiftwidth=4 textwidth=80: diff --git a/roles/oraclelinux_physical_machine/handlers/main.yml b/roles/oraclelinux_physical_machine/handlers/main.yml deleted file mode 100644 index dbf8fa089..000000000 --- a/roles/oraclelinux_physical_machine/handlers/main.yml +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (C) 2025 RTE -# SPDX-License-Identifier: Apache-2.0 - -- name: Trigger daemon-reload - ansible.builtin.service: - daemon_reload: yes - -- name: Restart systemd-sysctl - ansible.builtin.systemd: - name: systemd-sysctl.service - state: restarted - -- name: Rebuild initramfs if necessary - command: - cmd: /usr/sbin/update-initramfs -u - changed_when: true diff --git a/roles/oraclelinux_physical_machine/initramfs-tools/conf.d/rebooter.conf.j2 b/roles/oraclelinux_physical_machine/initramfs-tools/conf.d/rebooter.conf.j2 deleted file mode 100644 index 5741d2d16..000000000 --- a/roles/oraclelinux_physical_machine/initramfs-tools/conf.d/rebooter.conf.j2 +++ /dev/null @@ -1,5 +0,0 @@ -# Device for /var/log storage -REBOOTER_LOG_DEVICE={{ lvm_rebooter_log_device }} - -# Relative path from device root for /var/log -REBOOTER_LOG_PATH={{ lvm_rebooter_log_path }} diff --git a/roles/oraclelinux_physical_machine/initramfs-tools/scripts/init-bottom/rebooter b/roles/oraclelinux_physical_machine/initramfs-tools/scripts/init-bottom/rebooter deleted file mode 100755 index fa1934f90..000000000 --- a/roles/oraclelinux_physical_machine/initramfs-tools/scripts/init-bottom/rebooter +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/sh - -PREREQ="lvm" - -prereqs() -{ - echo "$PREREQ" -} - -case $1 in -prereqs) - prereqs - exit 0 - ;; -esac - -. /scripts/functions - -# Get REBOOTER_LOG_DEVICE and REBOOTER_LOG_PATH from config -# Default to SEAPATH default (a dedicated LV called vg1-varlog) -REBOOTER_LOG_DEVICE=/dev/mapper/vg1-varlog -REBOOTER_LOG_PATH=. -if [ -e /conf/conf.d/rebooter.conf ]; then - . /conf/conf.d/rebooter.conf -fi - -log_begin_msg "Rebooter starting" -if [ -e /run/initramfs/do_reboot ]; then - _log_msg "Rebooting...\n" - MOUNT_POINT="/run/mnt" - mkdir -p $MOUNT_POINT - mount -o sync,rw $REBOOTER_LOG_DEVICE $MOUNT_POINT - LOG_PATH="$MOUNT_POINT/$REBOOTER_LOG_PATH/initramfs.log" - echo "== $(date) ==" >> $LOG_PATH - dmesg >> $LOG_PATH - echo >> $LOG_PATH - umount $MOUNT_POINT - reboot -f -d 1 # No init to handle reboot => -f -else - _log_msg "(no reboot needed) " -fi -log_end_msg - -exit 0 diff --git a/roles/oraclelinux_physical_machine/initramfs-tools/scripts/init-premount/lvm_snapshot_rebooter b/roles/oraclelinux_physical_machine/initramfs-tools/scripts/init-premount/lvm_snapshot_rebooter deleted file mode 100755 index 4a1d8e7fb..000000000 --- a/roles/oraclelinux_physical_machine/initramfs-tools/scripts/init-premount/lvm_snapshot_rebooter +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/sh -# LVM snapshot rebooter : wait for any merging LV and reboot once done -# Use this it to workaround GRUB limitation : it does not handle LV with merging snapshot - -PREREQ="lvm" -prereqs() -{ - echo "$PREREQ" -} - -case $1 in -prereqs) - prereqs - exit 0 - ;; -esac - -. /scripts/functions - -if [ ! -x "/sbin/lvm" ]; then - panic "lvs executable not found" -fi - -get_lv_snapshot_merging() { - # This will print a list of "vg/lv" marked for merging - /sbin/lvm lvs --select 'lv_merging!=0' --noheadings --separator '/' -o vg_name,lv_name -} - -log_begin_msg "Starting LVM Snapshot rebooter" - -# Wait for LVM elements to appear and be activated by udev -wait_for_udev 10 - -lv_merging=$(get_lv_snapshot_merging) -if [ -n "$lv_merging" ] ; then - log_end_msg - for lv in $lv_merging; do - log_begin_msg " Merging $lv" - /sbin/lvm lvchange --sysinit -ay "$lv" # lvmpolld/dmeventd no yet available - /sbin/lvm lvpoll --polloperation merge --interval 1 --config activation/monitoring=0 "$lv" - log_end_msg - done - log_success_msg "Snapshot merging complete, will reboot..." - touch /run/initramfs/do_reboot -else - log_success_msg "Done. (No LVM snapshot need merging)" -fi - -exit 0 diff --git a/roles/oraclelinux_physical_machine/initramfs-tools/scripts/init-top/init_log b/roles/oraclelinux_physical_machine/initramfs-tools/scripts/init-top/init_log deleted file mode 100755 index 297e8e3d0..000000000 --- a/roles/oraclelinux_physical_machine/initramfs-tools/scripts/init-top/init_log +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh - -prereqs() -{ - echo "$PREREQ" -} - -case $1 in -prereqs) - prereqs - exit 0 - ;; -esac - -. /scripts/functions - -cat >> /conf/param.conf <init: " \$0}' > /dev/kmsg /run/initramfs/tempfifo 2>&1 - rm /run/initramfs/tempfifo - - INIT_LOG_DONE=done -fi -EOF -exit 0 diff --git a/roles/oraclelinux_physical_machine/meta/main.yml b/roles/oraclelinux_physical_machine/meta/main.yml deleted file mode 100644 index 94fb5c38c..000000000 --- a/roles/oraclelinux_physical_machine/meta/main.yml +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (C) 2024 RTE -# SPDX-License-Identifier: Apache-2.0 ---- -galaxy_info: - author: "Seapath" - description: Debian prerequisites for a physical machine - license: Apache-2.0 - min_ansible_version: 2.9.10 - platforms: - - name: Debian - versions: - - all -dependencies: [] - diff --git a/roles/oraclelinux_physical_machine/tasks/main.yml b/roles/oraclelinux_physical_machine/tasks/main.yml deleted file mode 100644 index b0dc261f9..000000000 --- a/roles/oraclelinux_physical_machine/tasks/main.yml +++ /dev/null @@ -1,194 +0,0 @@ -# Copyright (C) 2024 RTE -# SPDX-License-Identifier: Apache-2.0 - ---- -- name: Populate service facts - service_facts: - -- name: Copy sysctl rules - ansible.builtin.copy: - src: "{{ item }}" - dest: /etc/sysctl.d/{{ item }} - mode: '0644' - with_items: - - 00-bridge_nf_call.conf - notify: Restart systemd-sysctl - -- name: Add sysctl conf from inventory (extra_sysctl_physical_machines) - ansible.builtin.copy: - dest: /etc/sysctl.d/00-seapathextra_physicalmachines.conf - mode: '0644' - content: "{{ extra_sysctl_physical_machines }}" - when: extra_sysctl_physical_machines is defined - notify: Restart systemd-sysctl - -- name: Create src folder on hosts - file: - path: /tmp/src - state: directory - mode: '0755' - -- name: Temp fix for synchronize to force evaluate variables - set_fact: - ansible_host: "{{ ansible_host }}" - -- name: Deploy vm_manager - include_role: - name: deploy_vm_manager - -- name: Deploy python3-setup-ovs - include_role: - name: deploy_python3_setup_ovs - -- name: Create /usr/lib/ocf/resource.d/seapath on hosts - file: - path: /usr/lib/ocf/resource.d/seapath - state: directory - mode: '0755' - -- name: Copy Pacemaker Seapath Resource-Agent files - ansible.posix.synchronize: - src: pacemaker_ra/ - dest: /usr/lib/ocf/resource.d/seapath/ - rsync_opts: - - "--chmod=F755" - - "--chown=root:root" - when: - - "'cluster_machines' in group_names" - -- name: Copy chrony-wait.service - template: - src: chrony-wait.service.j2 - dest: /etc/systemd/system/chrony-wait.service - owner: root - group: root - mode: '0644' - notify: Trigger daemon-reload -- name: Enable chrony-wait.service - ansible.builtin.systemd: - name: chrony-wait.service - enabled: yes - -- when: - - services['pacemaker.service'] is defined - block: - - name: Create pacemaker.service.d directory - file: - path: /etc/systemd/system/pacemaker.service.d/ - state: directory - owner: root - group: root - mode: 0755 - - name: Copy pacemaker.service drop-in - template: - src: pacemaker_override.conf.j2 - dest: /etc/systemd/system/pacemaker.service.d/override.conf - owner: root - group: root - mode: 0644 - notify: Trigger daemon-reload - register: oraclelinux_physical_machine_pacemaker_corosync - - name: Get Pacemaker service Status - ansible.builtin.systemd: - name: "pacemaker.service" - register: oraclelinux_physical_machine_pacemaker_service_status - - name: Disable pacemaker (reinstall step 1/2) - ansible.builtin.systemd: - name: pacemaker.service - enabled: no - when: oraclelinux_physical_machine_pacemaker_corosync.changed and oraclelinux_physical_machine_pacemaker_service_status.status.UnitFileState == "enabled" - - name: Enable pacemaker (reinstall step 2/2) - ansible.builtin.systemd: - name: pacemaker.service - enabled: yes - when: oraclelinux_physical_machine_pacemaker_corosync.changed and oraclelinux_physical_machine_pacemaker_service_status.status.UnitFileState == "enabled" - -- name: Add extra modules to the kernel - lineinfile: - dest: /etc/modules - state: present - regexp: "^{{ item }}$" - line: "{{ item }}" - with_items: "{{ extra_kernel_modules | default([]) }}" - -- name: Add br_netfilter to /etc/modules-load.d - ansible.builtin.copy: - src: modules/netfilter.conf - dest: /etc/modules-load.d/netfilter.conf - owner: root - group: root - mode: 0751 -- name: Add raid6_pq to /etc/modules-load.d - ansible.builtin.copy: - src: modules/raid6_pq.conf - dest: /etc/modules-load.d/raid6_pq.conf - owner: root - group: root - mode: 0751 - -- name: Lineinfile in hosts file for logstash-seapath - lineinfile: - dest: /etc/hosts - regexp: '.* logstash-seapath$' - line: "{{ logstash_server_ip }} logstash-seapath" - state: present - when: logstash_server_ip is defined - -- name: Make libvirt use the "machine-id" way to determine host UUID - lineinfile: - dest: /etc/libvirt/libvirtd.conf - regexp: "^#?host_uuid_source =" - line: "host_uuid_source = \"machine-id\"" - state: present -- name: Restart libvirtd - ansible.builtin.systemd: - name: libvirtd.service - state: restarted - -- name: Add rbd type to lvm.conf - ansible.builtin.lineinfile: - path: /etc/lvm/lvm.conf - insertafter: 'devices {' - line: " types = [ \"rbd\", 1024 ]" - state: present -- name: Disable lvm use_devicesfile - ansible.builtin.lineinfile: - path: /etc/lvm/lvm.conf - regexp: "^\\s*#?\\s*use_devicesfile\\s*=\\s*" - line: " use_devicesfile = 0" - state: present - -- name: Create a symbolic link for qemu-kvm/x86-64 - ansible.builtin.file: - src: /usr/libexec/qemu-kvm - dest: /usr/bin/qemu-system-x86_64 - state: link - -- name: Enable and start virtsecretd.socket - ansible.builtin.systemd: - name: virtsecretd.socket - state: started - enabled: true -- name: Enable and start virtqemud.socket - ansible.builtin.systemd: - name: virtqemud.socket - state: started - enabled: true -- name: Enable and start virtstoraged.socket - ansible.builtin.systemd: - name: virtstoraged.socket - state: started - enabled: true - -- name: Ensure group www-data exists with GID 1033 - group: - name: www-data - gid: 1033 - state: present - -- name: Ensure user www-data exists with UID 1033 and GID 1033 - user: - name: www-data - uid: 1033 - group: www-data - shell: /bin/bash diff --git a/roles/oraclelinux_physical_machine/templates/chrony-wait.service.j2 b/roles/oraclelinux_physical_machine/templates/chrony-wait.service.j2 deleted file mode 100644 index ecc1edf2a..000000000 --- a/roles/oraclelinux_physical_machine/templates/chrony-wait.service.j2 +++ /dev/null @@ -1,46 +0,0 @@ -[Unit] -Description=Wait for chrony to synchronize system clock -Documentation=man:chronyc(1) -After=timemaster.service -Requires=timemaster.service -Before=time-sync.target -Wants=time-sync.target - -[Service] -Type=oneshot -# Wait for chronyd to update the clock and the remaining -# correction to be less than 0.1 seconds -ExecStart=/usr/bin/chronyc -h 127.0.0.1,::1 waitsync 0 0.1 0.0 1 -# Wait for at most chrony_wait_timeout_sec seconds -TimeoutStartSec={{ chrony_wait_timeout_sec | default(180) }} -RemainAfterExit=yes -StandardOutput=null - -CapabilityBoundingSet= -DevicePolicy=closed -DynamicUser=yes -IPAddressAllow=localhost -IPAddressDeny=any -LockPersonality=yes -MemoryDenyWriteExecute=yes -PrivateDevices=yes -PrivateUsers=yes -ProtectClock=yes -ProtectControlGroups=yes -ProtectHome=yes -ProtectHostname=yes -ProtectKernelLogs=yes -ProtectKernelModules=yes -ProtectKernelTunables=yes -ProtectProc=invisible -ProtectSystem=strict -RestrictAddressFamilies=AF_INET AF_INET6 -RestrictNamespaces=yes -RestrictRealtime=yes -SystemCallArchitectures=native -SystemCallFilter=@system-service -SystemCallFilter=~@privileged @resources -UMask=0777 - -[Install] -WantedBy=multi-user.target diff --git a/roles/oraclelinux_tests/README.md b/roles/oraclelinux_tests/README.md deleted file mode 100644 index 94371e9cb..000000000 --- a/roles/oraclelinux_tests/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# Oracle Linux cukinia tests - -This role the tests specific to OracleLinux machines - -## Requirements - -No requirement. - -## Role Variables - -## Example Playbook - -```yaml -- hosts: cluster_machines - roles: - - { role: seapath_ansible.oraclelinux_tests } -``` diff --git a/roles/centos/files/sysctl/00-panicreboot.conf b/roles/redhat/files/00-panicreboot.conf similarity index 100% rename from roles/centos/files/sysctl/00-panicreboot.conf rename to roles/redhat/files/00-panicreboot.conf diff --git a/roles/centos/files/journald.conf b/roles/redhat/files/journald.conf similarity index 100% rename from roles/centos/files/journald.conf rename to roles/redhat/files/journald.conf diff --git a/roles/oraclelinux/handlers/main.yml b/roles/redhat/handlers/main.yml similarity index 86% rename from roles/oraclelinux/handlers/main.yml rename to roles/redhat/handlers/main.yml index 833c2f4e3..5d6e15b81 100644 --- a/roles/oraclelinux/handlers/main.yml +++ b/roles/redhat/handlers/main.yml @@ -1,18 +1,19 @@ +# Copyright (C) 2024 Red Hat, Inc. # Copyright (C) 2025 RTE # SPDX-License-Identifier: Apache-2.0 --- -- name: Restart systemd-journald - ansible.builtin.systemd: - name: systemd-journald - state: restarted - - name: Restart syslog-ng ansible.builtin.systemd: name: syslog-ng state: restarted enabled: yes -- name: Update-grub +- name: Restart systemd-journald + ansible.builtin.systemd: + name: systemd-journald + state: restarted + +- name: Update Grub command: grub2-mkconfig -o /boot/grub2/grub.cfg changed_when: true diff --git a/roles/centos/meta/main.yml b/roles/redhat/meta/main.yml similarity index 69% rename from roles/centos/meta/main.yml rename to roles/redhat/meta/main.yml index 142b40192..d090fc9b5 100644 --- a/roles/centos/meta/main.yml +++ b/roles/redhat/meta/main.yml @@ -1,9 +1,10 @@ # Copyright (C) 2024 RTE +# Copyright (C) 2024 Red Hat, Inc. # SPDX-License-Identifier: Apache-2.0 --- galaxy_info: author: "Seapath" - description: Prerequisite for all centos machine + description: Prerequisite for all RedHat-family machines min_ansible_version: 2.9.10 license: Apache-2.0 platforms: @@ -11,4 +12,3 @@ galaxy_info: versions: - all dependencies: [] - diff --git a/roles/oraclelinux/tasks/main.yml b/roles/redhat/tasks/main.yml similarity index 89% rename from roles/oraclelinux/tasks/main.yml rename to roles/redhat/tasks/main.yml index d4efaad5c..868abb2df 100644 --- a/roles/oraclelinux/tasks/main.yml +++ b/roles/redhat/tasks/main.yml @@ -1,14 +1,8 @@ -# Copyright (C) 2025 RTE +# Copyright (C) 2024 RTE +# Copyright (C) 2024 Red Hat, Inc. # SPDX-License-Identifier: Apache-2.0 --- - -- name: Stop and Disable firewalld - service: - name: firewalld - state: stopped - enabled: no - - name: Disable vim defaults lineinfile: dest: /etc/vimrc @@ -75,29 +69,33 @@ - name: Retrieve user information for UID 1000 ansible.builtin.command: getent passwd 1000 - register: oraclelinux_user_info + register: redhat_user_info changed_when: false + when: seapath_distro == 'OracleLinux' - name: Extract username from the result ansible.builtin.set_fact: - oraclelinux_old_admin_user: "{{ oraclelinux_user_info.stdout.split(':')[0] }}" + redhat_old_admin_user: "{{ redhat_user_info.stdout.split(':')[0] }}" + when: seapath_distro == 'OracleLinux' - name: Removing or not the old admin user created by the iso - when: admin_user != oraclelinux_old_admin_user + when: + - seapath_distro == 'OracleLinux' + - admin_user != redhat_old_admin_user block: - name: Remove old admin user from sudoers file lineinfile: dest: /etc/sudoers state: absent - regexp: "^{{ oraclelinux_old_admin_user }}" + regexp: "^{{ redhat_old_admin_user }}" validate: visudo -cf %s - name: Remove the old admin user ansible.builtin.user: - name: "{{ oraclelinux_old_admin_user }}" + name: "{{ redhat_old_admin_user }}" state: absent remove: yes - name: Remove the old admin group ansible.builtin.group: - name: "{{ oraclelinux_old_admin_user }}" + name: "{{ redhat_old_admin_user }}" state: absent - name: Copy journald conf file @@ -182,7 +180,7 @@ regexp: "^(GRUB_CMDLINE_LINUX_DEFAULT=\")(.*?[ ])?quiet([ ].*)?(\")$" line: '\1\2\3\4' backrefs: yes - notify: Update-grub + notify: Update Grub - name: Make sure GRUB_CMDLINE_LINUX_DEFAULT has no double space lineinfile: @@ -191,8 +189,8 @@ line: '\1 \2' state: present backrefs: yes - register: oraclelinux_doublespace - until: not oraclelinux_doublespace.changed + register: redhat_doublespace + until: not redhat_doublespace.changed delay: 1 retries: 10 @@ -203,14 +201,14 @@ state: absent check_mode: true changed_when: false - register: oraclelinux_check_grub_cmdline_linux + register: redhat_check_grub_cmdline_linux - name: Make sure GRUB_CMDLINE_LINUX exists 2/2 lineinfile: path: /etc/default/grub state: present line: "GRUB_CMDLINE_LINUX=\" \"" - when: oraclelinux_check_grub_cmdline_linux.found == 0 + when: redhat_check_grub_cmdline_linux.found == 0 - name: Make sure GRUB_CMDLINE_LINUX starts with a space lineinfile: @@ -227,7 +225,7 @@ line: '\1 {{ item }}\2' state: present backrefs: yes - notify: Update-grub + notify: Update Grub with_items: - ipv6.disable=1 - efi=runtime @@ -241,7 +239,7 @@ regexp: '^#?GRUB_DISABLE_OS_PROBER=.*$' line: 'GRUB_DISABLE_OS_PROBER=true' state: present - notify: Update-grub + notify: Update Grub - name: Stop and Disable NetworkManager service: diff --git a/roles/oraclelinux/templates/syslog-ng.conf.j2 b/roles/redhat/templates/syslog-ng.conf.j2 similarity index 100% rename from roles/oraclelinux/templates/syslog-ng.conf.j2 rename to roles/redhat/templates/syslog-ng.conf.j2 diff --git a/roles/centos_hypervisor/README.md b/roles/redhat_hypervisor/README.md similarity index 95% rename from roles/centos_hypervisor/README.md rename to roles/redhat_hypervisor/README.md index 77e7e1460..3d5bf2369 100644 --- a/roles/centos_hypervisor/README.md +++ b/roles/redhat_hypervisor/README.md @@ -1,6 +1,6 @@ -# CentOS Hypervisor Role +# RedHat Hypervisor Role -This role applies the hypervisor specific configurations (virtualisation, realtime...) for Centos machines +This role applies the hypervisor specific configurations (virtualisation, realtime...) for RedHat-family machines ## Requirements @@ -28,5 +28,5 @@ All variables are optional. ```yaml - hosts: cluster_machines roles: - - { role: seapath_ansible.centos_hypervisor } + - { role: seapath_ansible.redhat_hypervisor } ``` diff --git a/roles/centos_hypervisor/files/modules/sriov_driver.conf b/roles/redhat_hypervisor/files/modules/sriov_driver.conf similarity index 100% rename from roles/centos_hypervisor/files/modules/sriov_driver.conf rename to roles/redhat_hypervisor/files/modules/sriov_driver.conf diff --git a/roles/centos_hypervisor/files/modules/vhost_vsock.conf b/roles/redhat_hypervisor/files/modules/vhost_vsock.conf similarity index 100% rename from roles/centos_hypervisor/files/modules/vhost_vsock.conf rename to roles/redhat_hypervisor/files/modules/vhost_vsock.conf diff --git a/roles/centos_hypervisor/files/ovs-vswitchd_override.conf b/roles/redhat_hypervisor/files/ovs-vswitchd_override.conf similarity index 100% rename from roles/centos_hypervisor/files/ovs-vswitchd_override.conf rename to roles/redhat_hypervisor/files/ovs-vswitchd_override.conf diff --git a/roles/centos_hypervisor/handlers/main.yml b/roles/redhat_hypervisor/handlers/main.yml similarity index 100% rename from roles/centos_hypervisor/handlers/main.yml rename to roles/redhat_hypervisor/handlers/main.yml diff --git a/roles/centos_hypervisor/meta/main.yml b/roles/redhat_hypervisor/meta/main.yml similarity index 83% rename from roles/centos_hypervisor/meta/main.yml rename to roles/redhat_hypervisor/meta/main.yml index 87845c296..93ce6067c 100644 --- a/roles/centos_hypervisor/meta/main.yml +++ b/roles/redhat_hypervisor/meta/main.yml @@ -3,7 +3,7 @@ --- galaxy_info: author: "Seapath" - description: applies the hypervisor specific configurations (virtualisation, realtime...) for Centos machines + description: applies the hypervisor specific configurations (virtualisation, realtime...) for RedHat-family machines license: Apache-2.0 min_ansible_version: 2.9.10 platforms: diff --git a/roles/centos_hypervisor/tasks/main.yml b/roles/redhat_hypervisor/tasks/main.yml similarity index 100% rename from roles/centos_hypervisor/tasks/main.yml rename to roles/redhat_hypervisor/tasks/main.yml diff --git a/roles/centos_hypervisor/templates/sriov.conf.j2 b/roles/redhat_hypervisor/templates/sriov.conf.j2 similarity index 100% rename from roles/centos_hypervisor/templates/sriov.conf.j2 rename to roles/redhat_hypervisor/templates/sriov.conf.j2 diff --git a/roles/centos_hypervisor/templates/sriov_network_pool.xml.j2 b/roles/redhat_hypervisor/templates/sriov_network_pool.xml.j2 similarity index 100% rename from roles/centos_hypervisor/templates/sriov_network_pool.xml.j2 rename to roles/redhat_hypervisor/templates/sriov_network_pool.xml.j2 diff --git a/roles/centos_hypervisor/templates/systemd_slice.j2 b/roles/redhat_hypervisor/templates/systemd_slice.j2 similarity index 100% rename from roles/centos_hypervisor/templates/systemd_slice.j2 rename to roles/redhat_hypervisor/templates/systemd_slice.j2 diff --git a/roles/centos_hypervisor/templates/systemd_slice_override.j2 b/roles/redhat_hypervisor/templates/systemd_slice_override.j2 similarity index 100% rename from roles/centos_hypervisor/templates/systemd_slice_override.j2 rename to roles/redhat_hypervisor/templates/systemd_slice_override.j2 diff --git a/roles/centos_hypervisor/templates/tmpfiles-workqueue_cpumask.conf.j2 b/roles/redhat_hypervisor/templates/tmpfiles-workqueue_cpumask.conf.j2 similarity index 100% rename from roles/centos_hypervisor/templates/tmpfiles-workqueue_cpumask.conf.j2 rename to roles/redhat_hypervisor/templates/tmpfiles-workqueue_cpumask.conf.j2 diff --git a/roles/centos_hypervisor/templates/tuned.conf.j2 b/roles/redhat_hypervisor/templates/tuned.conf.j2 similarity index 100% rename from roles/centos_hypervisor/templates/tuned.conf.j2 rename to roles/redhat_hypervisor/templates/tuned.conf.j2 diff --git a/roles/centos_physical_machine/files/00-bridge_nf_call.conf b/roles/redhat_physical_machine/files/00-bridge_nf_call.conf similarity index 100% rename from roles/centos_physical_machine/files/00-bridge_nf_call.conf rename to roles/redhat_physical_machine/files/00-bridge_nf_call.conf diff --git a/roles/oraclelinux_physical_machine/files/modules/netfilter.conf b/roles/redhat_physical_machine/files/modules/netfilter.conf similarity index 100% rename from roles/oraclelinux_physical_machine/files/modules/netfilter.conf rename to roles/redhat_physical_machine/files/modules/netfilter.conf diff --git a/roles/oraclelinux_physical_machine/files/modules/raid6_pq.conf b/roles/redhat_physical_machine/files/modules/raid6_pq.conf similarity index 100% rename from roles/oraclelinux_physical_machine/files/modules/raid6_pq.conf rename to roles/redhat_physical_machine/files/modules/raid6_pq.conf diff --git a/roles/oraclelinux_physical_machine/files/pacemaker_ra/VirtualDomain b/roles/redhat_physical_machine/files/pacemaker_ra/VirtualDomain similarity index 100% rename from roles/oraclelinux_physical_machine/files/pacemaker_ra/VirtualDomain rename to roles/redhat_physical_machine/files/pacemaker_ra/VirtualDomain diff --git a/roles/centos_physical_machine/files/pacemaker_ra/ntpstatus b/roles/redhat_physical_machine/files/pacemaker_ra/ntpstatus similarity index 100% rename from roles/centos_physical_machine/files/pacemaker_ra/ntpstatus rename to roles/redhat_physical_machine/files/pacemaker_ra/ntpstatus diff --git a/roles/centos_physical_machine/files/pacemaker_ra/ptpstatus b/roles/redhat_physical_machine/files/pacemaker_ra/ptpstatus similarity index 100% rename from roles/centos_physical_machine/files/pacemaker_ra/ptpstatus rename to roles/redhat_physical_machine/files/pacemaker_ra/ptpstatus diff --git a/roles/centos_physical_machine/files/team0_x@.service b/roles/redhat_physical_machine/files/team0_x@.service similarity index 100% rename from roles/centos_physical_machine/files/team0_x@.service rename to roles/redhat_physical_machine/files/team0_x@.service diff --git a/roles/centos_physical_machine/handlers/main.yml b/roles/redhat_physical_machine/handlers/main.yml similarity index 95% rename from roles/centos_physical_machine/handlers/main.yml rename to roles/redhat_physical_machine/handlers/main.yml index fefb3bbcb..c1d94d595 100644 --- a/roles/centos_physical_machine/handlers/main.yml +++ b/roles/redhat_physical_machine/handlers/main.yml @@ -1,4 +1,5 @@ # Copyright (C) 2024 Red Hat, Inc. +# Copyright (C) 2025 RTE # SPDX-License-Identifier: Apache-2.0 - name: Trigger daemon-reload diff --git a/roles/redhat_physical_machine/initramfs-tools/conf.d/rebooter.conf.j2 b/roles/redhat_physical_machine/initramfs-tools/conf.d/rebooter.conf.j2 new file mode 100644 index 000000000..9132a0096 --- /dev/null +++ b/roles/redhat_physical_machine/initramfs-tools/conf.d/rebooter.conf.j2 @@ -0,0 +1,5 @@ +# Device for /var/log storage +REBOOTER_LOG_DEVICE={{ redhat_physical_machine_lvm_rebooter_log_device }} + +# Relative path from device root for /var/log +REBOOTER_LOG_PATH={{ redhat_physical_machine_lvm_rebooter_log_path }} diff --git a/roles/centos_physical_machine/initramfs-tools/scripts/init-bottom/rebooter b/roles/redhat_physical_machine/initramfs-tools/scripts/init-bottom/rebooter similarity index 100% rename from roles/centos_physical_machine/initramfs-tools/scripts/init-bottom/rebooter rename to roles/redhat_physical_machine/initramfs-tools/scripts/init-bottom/rebooter diff --git a/roles/centos_physical_machine/initramfs-tools/scripts/init-premount/lvm_snapshot_rebooter b/roles/redhat_physical_machine/initramfs-tools/scripts/init-premount/lvm_snapshot_rebooter similarity index 100% rename from roles/centos_physical_machine/initramfs-tools/scripts/init-premount/lvm_snapshot_rebooter rename to roles/redhat_physical_machine/initramfs-tools/scripts/init-premount/lvm_snapshot_rebooter diff --git a/roles/centos_physical_machine/initramfs-tools/scripts/init-top/init_log b/roles/redhat_physical_machine/initramfs-tools/scripts/init-top/init_log similarity index 100% rename from roles/centos_physical_machine/initramfs-tools/scripts/init-top/init_log rename to roles/redhat_physical_machine/initramfs-tools/scripts/init-top/init_log diff --git a/roles/centos_physical_machine/meta/main.yml b/roles/redhat_physical_machine/meta/main.yml similarity index 57% rename from roles/centos_physical_machine/meta/main.yml rename to roles/redhat_physical_machine/meta/main.yml index cdb45b2a6..11bdcdf77 100644 --- a/roles/centos_physical_machine/meta/main.yml +++ b/roles/redhat_physical_machine/meta/main.yml @@ -1,9 +1,10 @@ # Copyright (C) 2024 RTE +# Copyright (C) 2024 Red Hat, Inc. # SPDX-License-Identifier: Apache-2.0 --- galaxy_info: author: "Seapath" - description: applies the SEAPATH prerequisites for any Debian physical machine (hypervisor, observer, or standalone) + description: applies the SEAPATH prerequisites for any RedHat-family physical machine (hypervisor, observer, or standalone) license: Apache-2.0 min_ansible_version: 2.9.10 platforms: @@ -11,4 +12,3 @@ galaxy_info: versions: - all dependencies: [] - diff --git a/roles/centos_physical_machine/tasks/main.yml b/roles/redhat_physical_machine/tasks/main.yml similarity index 53% rename from roles/centos_physical_machine/tasks/main.yml rename to roles/redhat_physical_machine/tasks/main.yml index 7f35a5be4..accec3c89 100644 --- a/roles/centos_physical_machine/tasks/main.yml +++ b/roles/redhat_physical_machine/tasks/main.yml @@ -2,6 +2,10 @@ # Copyright (C) 2024 Red Hat, Inc. # SPDX-License-Identifier: Apache-2.0 +--- +- name: Populate service facts + service_facts: + - name: Copy sysctl rules ansible.builtin.copy: src: "{{ item }}" @@ -50,6 +54,8 @@ rsync_opts: - "--chmod=F755" - "--chown=root:root" + when: + - "'cluster_machines' in group_names" - name: Copy chrony-wait.service template: @@ -64,36 +70,39 @@ name: chrony-wait.service enabled: yes -- name: Create pacemaker.service.d directory - file: - path: /etc/systemd/system/pacemaker.service.d/ - state: directory - owner: root - group: root - mode: 0755 -- name: Copy pacemaker.service drop-in - template: - src: pacemaker_override.conf.j2 - dest: /etc/systemd/system/pacemaker.service.d/override.conf - owner: root - group: root - mode: 0644 - notify: Trigger daemon-reload - register: centos_physical_machine_pacemaker_corosync -- name: Get Pacemaker service Status - ansible.builtin.systemd: - name: "pacemaker.service" - register: centos_physical_machine_pacemaker_service_status -- name: Disable pacemaker (reinstall step 1/2) - ansible.builtin.systemd: - name: pacemaker.service - enabled: no - when: centos_physical_machine_pacemaker_corosync.changed and centos_physical_machine_pacemaker_service_status.status.UnitFileState == "enabled" -- name: Enable pacemaker (reinstall step 2/2) - ansible.builtin.systemd: - name: pacemaker.service - enabled: yes - when: centos_physical_machine_pacemaker_corosync.changed and centos_physical_machine_pacemaker_service_status.status.UnitFileState == "enabled" +- when: + - services['pacemaker.service'] is defined + block: + - name: Create pacemaker.service.d directory + file: + path: /etc/systemd/system/pacemaker.service.d/ + state: directory + owner: root + group: root + mode: 0755 + - name: Copy pacemaker.service drop-in + template: + src: pacemaker_override.conf.j2 + dest: /etc/systemd/system/pacemaker.service.d/override.conf + owner: root + group: root + mode: 0644 + notify: Trigger daemon-reload + register: redhat_physical_machine_pacemaker_corosync + - name: Get Pacemaker service Status + ansible.builtin.systemd: + name: "pacemaker.service" + register: redhat_physical_machine_pacemaker_service_status + - name: Disable pacemaker (reinstall step 1/2) + ansible.builtin.systemd: + name: pacemaker.service + enabled: no + when: redhat_physical_machine_pacemaker_corosync.changed and redhat_physical_machine_pacemaker_service_status.status.UnitFileState == "enabled" + - name: Enable pacemaker (reinstall step 2/2) + ansible.builtin.systemd: + name: pacemaker.service + enabled: yes + when: redhat_physical_machine_pacemaker_corosync.changed and redhat_physical_machine_pacemaker_service_status.status.UnitFileState == "enabled" - name: Add extra modules to the kernel block: @@ -119,6 +128,13 @@ owner: root group: root mode: 0751 +- name: Add raid6_pq to /etc/modules-load.d + ansible.builtin.copy: + src: modules/raid6_pq.conf + dest: /etc/modules-load.d/raid6_pq.conf + owner: root + group: root + mode: 0751 - name: Lineinfile in hosts file for logstash-seapath lineinfile: @@ -139,15 +155,6 @@ name: libvirtd.service state: restarted -- name: Enable virtsecretd - ansible.builtin.systemd: - name: virtsecretd.service - enabled: yes - state: started - -- name: Enable docker.service - ansible.builtin.systemd: - name: docker.service - name: "Add initramfs-tools scripts: script file (LVM rebooter and log handling)" ansible.builtin.copy: src: initramfs-tools/scripts/ @@ -157,21 +164,21 @@ - name: Get the /var/log/ device command: "findmnt -n -o SOURCE --target /var/log" - register: centos_physical_machine_varlog_dev + register: redhat_physical_machine_varlog_dev changed_when: false - name: Set_fact /var/log/ device set_fact: - centos_physical_machine_lvm_rebooter_log_device: "{{ centos_physical_machine_varlog_dev.stdout }}" + redhat_physical_machine_lvm_rebooter_log_device: "{{ redhat_physical_machine_varlog_dev.stdout }}" - name: Get the /var/log/ relative path shell: "realpath --relative-to=$(findmnt -n -o TARGET --target /var/log/) /var/log" - register: centos_physical_machine_varlog_path + register: redhat_physical_machine_varlog_path changed_when: false - name: Set_fact /var/log/ relative path set_fact: - centos_physical_machine_lvm_rebooter_log_path: "{{ centos_physical_machine_varlog_path.stdout }}" + redhat_physical_machine_lvm_rebooter_log_path: "{{ redhat_physical_machine_varlog_path.stdout }}" - name: Copy rebooter.conf template: @@ -192,6 +199,12 @@ insertafter: 'devices {' line: " types = [ \"rbd\", 1024 ]" state: present +- name: Disable lvm use_devicesfile + ansible.builtin.lineinfile: + path: /etc/lvm/lvm.conf + regexp: "^\\s*#?\\s*use_devicesfile\\s*=\\s*" + line: " use_devicesfile = 0" + state: present - name: Configure firewalld for ceph block: @@ -217,6 +230,100 @@ permanent: true state: enabled +- name: Configure registry mirroring + when: registry_mirror_url is defined and registry_mirror_url != '' + block: + - name: Create podman certs.d directory for registry + ansible.builtin.file: + path: "/etc/containers/certs.d/{{ registry_mirror_url }}" + state: directory + mode: '0755' + when: registry_tls_enabled | default(false) + + - name: Copy registry CA certificate for podman + ansible.builtin.copy: + src: /tmp/registry-ca.crt + dest: "/etc/containers/certs.d/{{ registry_mirror_url }}/ca.crt" + mode: '0644' + when: registry_tls_enabled | default(false) + + - name: Create docker certs.d directory for registry + ansible.builtin.file: + path: "/etc/docker/certs.d/{{ registry_mirror_url }}" + state: directory + mode: '0755' + when: registry_tls_enabled | default(false) + + - name: Copy registry CA certificate for docker + ansible.builtin.copy: + src: /tmp/registry-ca.crt + dest: "/etc/docker/certs.d/{{ registry_mirror_url }}/ca.crt" + mode: '0644' + when: registry_tls_enabled | default(false) + + - name: Configure podman registry mirroring + ansible.builtin.blockinfile: + path: /etc/containers/registries.conf + marker: "# {mark} ANSIBLE MANAGED BLOCK for registry mirroring" + block: | + [[registry]] + location = "docker.io" + insecure = {{ 'false' if registry_tls_enabled | default(false) else 'true' }} + [[registry.mirror]] + location = "{{ registry_mirror_url }}" + insecure = {{ 'false' if registry_tls_enabled | default(false) else 'true' }} + + [[registry]] + location = "quay.io" + insecure = {{ 'false' if registry_tls_enabled | default(false) else 'true' }} + [[registry.mirror]] + location = "{{ registry_mirror_url }}" + insecure = {{ 'false' if registry_tls_enabled | default(false) else 'true' }} + + - name: Configure docker registry mirroring + ansible.builtin.copy: + content: | + { + "registry-mirrors": ["{{ 'https' if registry_tls_enabled | default(false) else 'http' }}://{{ registry_mirror_url }}"] + } + dest: /etc/docker/daemon.json + mode: '0644' + +- name: Create a symbolic link for qemu-kvm/x86-64 + ansible.builtin.file: + src: /usr/libexec/qemu-kvm + dest: /usr/bin/qemu-system-x86_64 + state: link + +- name: Enable and start virtsecretd.socket + ansible.builtin.systemd: + name: virtsecretd.socket + state: started + enabled: true +- name: Enable and start virtqemud.socket + ansible.builtin.systemd: + name: virtqemud.socket + state: started + enabled: true +- name: Enable and start virtstoraged.socket + ansible.builtin.systemd: + name: virtstoraged.socket + state: started + enabled: true + +- name: Ensure group www-data exists with GID 1033 + group: + name: www-data + gid: 1033 + state: present + +- name: Ensure user www-data exists with UID 1033 and GID 1033 + user: + name: www-data + uid: 1033 + group: www-data + shell: /bin/bash + - name: Create ovs-vswitchd.service.d directory file: path: /etc/systemd/system/ovs-vswitchd.service.d/ diff --git a/roles/centos_physical_machine/templates/chrony-wait.service.j2 b/roles/redhat_physical_machine/templates/chrony-wait.service.j2 similarity index 100% rename from roles/centos_physical_machine/templates/chrony-wait.service.j2 rename to roles/redhat_physical_machine/templates/chrony-wait.service.j2 diff --git a/roles/centos_physical_machine/templates/ovs-vswitchd_override.conf.j2 b/roles/redhat_physical_machine/templates/ovs-vswitchd_override.conf.j2 similarity index 100% rename from roles/centos_physical_machine/templates/ovs-vswitchd_override.conf.j2 rename to roles/redhat_physical_machine/templates/ovs-vswitchd_override.conf.j2 diff --git a/roles/oraclelinux_physical_machine/templates/pacemaker_override.conf.j2 b/roles/redhat_physical_machine/templates/pacemaker_override.conf.j2 similarity index 100% rename from roles/oraclelinux_physical_machine/templates/pacemaker_override.conf.j2 rename to roles/redhat_physical_machine/templates/pacemaker_override.conf.j2 diff --git a/roles/redhat_tests/README.md b/roles/redhat_tests/README.md new file mode 100644 index 000000000..13299d450 --- /dev/null +++ b/roles/redhat_tests/README.md @@ -0,0 +1,17 @@ +# RedHat cukinia tests + +This role deploys the tests specific to RedHat-family machines + +## Requirements + +No requirement. + +## Role Variables + +## Example Playbook + +```yaml +- hosts: cluster_machines + roles: + - { role: seapath_ansible.redhat_tests } +``` diff --git a/roles/oraclelinux_tests/files/cukinia-cluster.conf b/roles/redhat_tests/files/cukinia-cluster.conf similarity index 100% rename from roles/oraclelinux_tests/files/cukinia-cluster.conf rename to roles/redhat_tests/files/cukinia-cluster.conf diff --git a/roles/oraclelinux_tests/files/cukinia.conf b/roles/redhat_tests/files/cukinia.conf similarity index 100% rename from roles/oraclelinux_tests/files/cukinia.conf rename to roles/redhat_tests/files/cukinia.conf diff --git a/roles/oraclelinux_tests/meta/main.yml b/roles/redhat_tests/meta/main.yml similarity index 80% rename from roles/oraclelinux_tests/meta/main.yml rename to roles/redhat_tests/meta/main.yml index 05280e748..248caa79c 100644 --- a/roles/oraclelinux_tests/meta/main.yml +++ b/roles/redhat_tests/meta/main.yml @@ -3,7 +3,7 @@ --- galaxy_info: author: "Seapath" - description: Cukinia tests for OracleLinux + description: Cukinia tests for RedHat-family distros min_ansible_version: 2.9.10 license: Apache-2.0 platforms: diff --git a/roles/oraclelinux_tests/tasks/main.yml b/roles/redhat_tests/tasks/main.yml similarity index 81% rename from roles/oraclelinux_tests/tasks/main.yml rename to roles/redhat_tests/tasks/main.yml index 9c9a9f9f1..4280c60b0 100644 --- a/roles/oraclelinux_tests/tasks/main.yml +++ b/roles/redhat_tests/tasks/main.yml @@ -8,12 +8,12 @@ state: directory mode: '0755' -- name: Copy OracleLinux cukinia tests +- name: Copy RedHat cukinia tests ansible.builtin.copy: src: cukinia.conf dest: /etc/cukinia/cukinia.conf mode: '0644' -- name: Copy OracleLinux cukinia cluster tests +- name: Copy RedHat cukinia cluster tests ansible.builtin.copy: src: cukinia-cluster.conf dest: /etc/cukinia/cukinia-cluster.conf diff --git a/roles/registry/defaults/main.yml b/roles/registry/defaults/main.yml new file mode 100644 index 000000000..ed98e16d2 --- /dev/null +++ b/roles/registry/defaults/main.yml @@ -0,0 +1,24 @@ +# Copyright (C) 2025 RTE +# SPDX-License-Identifier: Apache-2.0 + +--- +registry_path: "/opt/seapath/registry" +registry_data_path: "{{ registry_path }}/data" +registry_images_path: "{{ registry_path }}/images" +registry_port: 443 +registry_container_name: "seapath-registry" +registry_offline_mode: false +registry_backup_path: "{{ registry_path }}/backups" + +# TLS and Authentication +registry_tls_enabled: true +registry_tls_cert: "" +registry_tls_key: "" +registry_tls_ca: "" +registry_auth_enabled: false +registry_auth_htpasswd: "" +registry_username: "" +registry_password: "" + +# Container images to manage (empty by default - users provide their own list) +registry_images: [] diff --git a/roles/registry/meta/main.yml b/roles/registry/meta/main.yml new file mode 100644 index 000000000..0786176da --- /dev/null +++ b/roles/registry/meta/main.yml @@ -0,0 +1,31 @@ +# Copyright (C) 2025 RTE +# SPDX-License-Identifier: Apache-2.0 + +--- +galaxy_info: + author: SEAPATH Team + description: Control node registry management for disconnected environments + company: RTE + license: Apache-2.0 + min_ansible_version: "2.10" + platforms: + - name: EL + versions: + - 8 + - 9 + - name: Ubuntu + versions: + - 20.04 + - 22.04 + - name: Debian + versions: + - 11 + - 12 + galaxy_tags: + - seapath + - registry + - containers + - offline + - disconnected + +dependencies: [] diff --git a/roles/registry/tasks/main.yml b/roles/registry/tasks/main.yml new file mode 100644 index 000000000..4e4760a02 --- /dev/null +++ b/roles/registry/tasks/main.yml @@ -0,0 +1,364 @@ +# Copyright (C) 2025 RTE +# SPDX-License-Identifier: Apache-2.0 + +--- +- name: Ensure registry directory exists + ansible.builtin.file: + path: "{{ registry_path }}" + state: directory + owner: root + group: root + mode: '0755' + +- name: Ensure registry data directory exists + ansible.builtin.file: + path: "{{ registry_data_path }}" + state: directory + owner: root + group: root + mode: '0755' + +- name: Ensure registry images directory exists + ansible.builtin.file: + path: "{{ registry_images_path }}" + state: directory + owner: root + group: root + mode: '0755' + +- name: Check if registry images already exist + ansible.builtin.stat: + path: "{{ registry_data_path }}/docker/registry/v2/repositories" + register: registry_images_exist + +- name: Pull images from public registries if not in offline mode + containers.podman.podman_image: + name: "{{ item.source }}:{{ item.tag }}" + state: present + loop: "{{ registry_images }}" + when: + - not registry_offline_mode | default(false) + - not registry_images_exist.stat.exists + - registry_images | length > 0 + +- name: Check for offline image tar files + ansible.builtin.stat: + path: "{{ registry_images_path }}/{{ item.tar_file }}" + loop: "{{ registry_images }}" + register: registry_offline_tar_files + when: + - registry_offline_mode | default(false) + - registry_images | length > 0 + +- name: Load images from tar files if in offline mode + containers.podman.podman_image: + name: "{{ item.item.source }}:{{ item.item.tag }}" + load: "{{ registry_images_path }}/{{ item.item.tar_file }}" + state: present + loop: "{{ registry_offline_tar_files.results }}" + when: + - registry_offline_mode | default(false) + - registry_images | length > 0 + - item.stat is defined + - item.stat.exists + +- name: Generate htpasswd file for registry authentication + ansible.builtin.command: htpasswd -Bbn "{{ registry_username }}" "{{ registry_password }}" + register: htpasswd_output + changed_when: true + when: registry_auth_enabled | default(false) + +- name: Create htpasswd file + ansible.builtin.copy: + content: "{{ htpasswd_output.stdout }}" + dest: "{{ registry_path }}/htpasswd" + mode: '0600' + when: registry_auth_enabled | default(false) + +- name: TLS certificate setup + when: registry_tls_enabled | default(false) + block: + - name: Create registry certs directory + ansible.builtin.file: + path: "{{ registry_path }}/certs" + state: directory + owner: root + group: root + mode: '0755' + + - name: Generate self-signed CA and server certificate + when: registry_tls_cert == '' or registry_tls_key == '' + block: + - name: Generate CA private key + ansible.builtin.command: + cmd: openssl genrsa -out {{ registry_path }}/certs/ca.key 4096 + creates: "{{ registry_path }}/certs/ca.key" + + - name: Generate CA certificate + ansible.builtin.command: + cmd: > + openssl req -x509 -new -nodes + -key {{ registry_path }}/certs/ca.key + -sha256 -days 3650 + -out {{ registry_path }}/certs/ca.crt + -subj "/CN=SEAPATH Registry CA" + creates: "{{ registry_path }}/certs/ca.crt" + + - name: Generate server private key + ansible.builtin.command: + cmd: openssl genrsa -out {{ registry_path }}/certs/server.key 4096 + creates: "{{ registry_path }}/certs/server.key" + + - name: Create OpenSSL config for SAN + ansible.builtin.copy: + content: | + [req] + distinguished_name = req_dn + req_extensions = v3_req + prompt = no + [req_dn] + CN = {{ inventory_hostname }} + [v3_req] + subjectAltName = IP:{{ ansible_default_ipv4.address }},DNS:{{ inventory_hostname }},IP:127.0.0.1 + dest: "{{ registry_path }}/certs/openssl.cnf" + mode: '0644' + + - name: Generate server CSR + ansible.builtin.command: + cmd: > + openssl req -new + -key {{ registry_path }}/certs/server.key + -out {{ registry_path }}/certs/server.csr + -config {{ registry_path }}/certs/openssl.cnf + creates: "{{ registry_path }}/certs/server.csr" + + - name: Sign server certificate with CA + ansible.builtin.command: + cmd: > + openssl x509 -req + -in {{ registry_path }}/certs/server.csr + -CA {{ registry_path }}/certs/ca.crt + -CAkey {{ registry_path }}/certs/ca.key + -CAcreateserial + -out {{ registry_path }}/certs/server.crt + -days 3650 -sha256 + -extensions v3_req + -extfile {{ registry_path }}/certs/openssl.cnf + creates: "{{ registry_path }}/certs/server.crt" + + - name: Set generated cert paths + ansible.builtin.set_fact: + registry_tls_cert: "{{ registry_path }}/certs/server.crt" + registry_tls_key: "{{ registry_path }}/certs/server.key" + registry_tls_ca: "{{ registry_path }}/certs/ca.crt" + + - name: Copy user-provided certificates + when: registry_tls_cert != '' and registry_tls_key != '' + block: + - name: Copy TLS certificate + ansible.builtin.copy: + src: "{{ registry_tls_cert }}" + dest: "{{ registry_path }}/certs/server.crt" + mode: '0644' + + - name: Copy TLS private key + ansible.builtin.copy: + src: "{{ registry_tls_key }}" + dest: "{{ registry_path }}/certs/server.key" + mode: '0600' + + - name: Copy CA certificate + ansible.builtin.copy: + src: "{{ registry_tls_ca }}" + dest: "{{ registry_path }}/certs/ca.crt" + mode: '0644' + when: registry_tls_ca != '' + + - name: Set key file permissions + ansible.builtin.file: + path: "{{ registry_path }}/certs/{{ item }}" + mode: '0600' + loop: + - server.key + - ca.key + failed_when: false + + - name: Fetch CA certificate to Ansible controller + ansible.builtin.fetch: + src: "{{ registry_path }}/certs/ca.crt" + dest: /tmp/registry-ca.crt + flat: true + + - name: Create local podman certs.d directory + ansible.builtin.file: + path: "/etc/containers/certs.d/{{ ansible_default_ipv4.address }}:{{ registry_port }}" + state: directory + mode: '0755' + + - name: Install CA certificate for local podman + ansible.builtin.copy: + src: "{{ registry_path }}/certs/ca.crt" + dest: "/etc/containers/certs.d/{{ ansible_default_ipv4.address }}:{{ registry_port }}/ca.crt" + remote_src: true + mode: '0644' + +- name: Create registry configuration + ansible.builtin.template: + src: registry_config.yml.j2 + dest: "{{ registry_path }}/config.yml" + mode: '0644' + +- name: Start registry container + containers.podman.podman_container: + name: "{{ registry_container_name }}" + image: registry:2 + state: started + detach: true + privileged: true + ports: + - "{{ registry_port }}:5000" + volume: "{{ _base_volumes + _tls_volumes }}" + restart_policy: always + vars: + _base_volumes: + - "{{ registry_data_path }}:/var/lib/registry" + - "{{ registry_path }}/config.yml:/etc/docker/registry/config.yml:ro" + - "{{ registry_path }}/htpasswd:/auth/htpasswd:ro" + _tls_volumes: "{{ [registry_path + '/certs:/certs:ro'] if registry_tls_enabled | default(false) else [] }}" + +- name: Wait for registry to be ready + ansible.builtin.uri: + url: "{{ 'https' if registry_tls_enabled | default(false) else 'http' }}://localhost:{{ registry_port }}/v2/" + validate_certs: false + method: GET + status_code: 200 + retries: 30 + delay: 2 + register: registry_ready + until: registry_ready.status == 200 + +- name: Set registry push address + ansible.builtin.set_fact: + _registry_push_address: >- + {{ (ansible_default_ipv4.address + ':' + (registry_port | string)) + if registry_tls_enabled | default(false) + else 'localhost:' + (registry_port | string) }} + +- name: Tag images for local registry + ansible.builtin.command: > + podman tag {{ item.source }}:{{ item.tag }} + {{ _registry_push_address }}/{{ item.name }}:{{ item.tag }} + loop: "{{ registry_images }}" + when: registry_images | length > 0 + changed_when: true + +- name: Push images to local registry + ansible.builtin.command: > + podman push {{ _registry_push_address }}/{{ item.name }}:{{ item.tag }} + loop: "{{ registry_images }}" + when: registry_images | length > 0 + changed_when: true + +- name: Create registry backup script + ansible.builtin.template: + src: backup_registry.sh.j2 + dest: "{{ registry_path }}/backup_registry.sh" + mode: '0755' + owner: root + group: root + +- name: Create registry restore script + ansible.builtin.template: + src: restore_registry.sh.j2 + dest: "{{ registry_path }}/restore_registry.sh" + mode: '0755' + owner: root + group: root + +- name: Create image export script + ansible.builtin.template: + src: export_images.sh.j2 + dest: "{{ registry_path }}/export_images.sh" + mode: '0755' + owner: root + group: root + +- name: Create image import script + ansible.builtin.template: + src: import_images.sh.j2 + dest: "{{ registry_path }}/import_images.sh" + mode: '0755' + owner: root + group: root + +# ============================================================================= +# Image Export Tasks (Ansible-based) +# ============================================================================= +- name: Export images to tar files + ansible.builtin.command: > + podman save -o {{ registry_images_path }}/{{ item.tar_file }} + {{ item.source }}:{{ item.tag }} + loop: "{{ registry_images }}" + when: registry_images | length > 0 + changed_when: true + +- name: Create export manifest + ansible.builtin.copy: + content: | + { + "export_timestamp": "{{ ansible_date_time.iso8601 }}", + "registry_url": "{{ _registry_push_address }}", + "images": [ + {% for item in registry_images %} + { + "name": "{{ item.name }}:{{ item.tag }}", + "file": "{{ item.tar_file }}", + "source": "{{ item.source }}:{{ item.tag }}" + }{% if not loop.last %},{% endif %} + {% endfor %} + ] + } + dest: "{{ registry_images_path }}/export_manifest.json" + mode: '0644' + when: registry_images | length > 0 + +# ============================================================================= +# Image Import Tasks (Ansible-based) +# ============================================================================= +- name: Validate image tar files exist + ansible.builtin.stat: + path: "{{ registry_images_path }}/{{ item.tar_file }}" + loop: "{{ registry_images }}" + register: image_files + when: registry_images | length > 0 + +- name: Fail if required images are missing + ansible.builtin.fail: + msg: "Missing required image: {{ item.item.tar_file }}" + loop: "{{ image_files.results }}" + when: + - registry_images | length > 0 + - not item.stat.exists + +- name: Load images from tar files + containers.podman.podman_image: + name: "{{ item.source }}:{{ item.tag }}" + load: "{{ registry_images_path }}/{{ item.tar_file }}" + state: present + loop: "{{ registry_images }}" + when: registry_images | length > 0 + +- name: Tag imported images for local registry + ansible.builtin.command: > + podman tag {{ item.source }}:{{ item.tag }} + {{ _registry_push_address }}/{{ item.name }}:{{ item.tag }} + loop: "{{ registry_images }}" + when: registry_images | length > 0 + changed_when: true + +- name: Push imported images to registry + ansible.builtin.command: > + podman push {{ _registry_push_address }}/{{ item.name }}:{{ item.tag }} + loop: "{{ registry_images }}" + when: registry_images | length > 0 + changed_when: true diff --git a/roles/registry/templates/backup_registry.sh.j2 b/roles/registry/templates/backup_registry.sh.j2 new file mode 100644 index 000000000..fd631fea1 --- /dev/null +++ b/roles/registry/templates/backup_registry.sh.j2 @@ -0,0 +1,58 @@ +#!/bin/bash +# Copyright (C) 2025 RTE +# SPDX-License-Identifier: Apache-2.0 + +# Backup script for control registry +# This script creates a backup of the registry data and exports images as tar files + +set -euo pipefail + +REGISTRY_PATH="{{ registry_path }}" +BACKUP_PATH="{{ registry_backup_path }}" +TIMESTAMP=$(date +%Y%m%d_%H%M%S) +BACKUP_DIR="${BACKUP_PATH}/backup_${TIMESTAMP}" + +echo "Starting registry backup at $(date)" + +# Create backup directory +mkdir -p "${BACKUP_DIR}" + +# Stop registry container +echo "Stopping registry container..." +podman stop {{ registry_container_name }} || true + +# Backup registry data +echo "Backing up registry data..." +tar -czf "${BACKUP_DIR}/registry_data.tar.gz" -C "${REGISTRY_PATH}/data" . + +# Export images +echo "Exporting images..." +mkdir -p "${BACKUP_DIR}/images" + +# Export registry image +podman save -o "${BACKUP_DIR}/images/registry-2.tar" registry:2 + +# Export Ceph image +podman save -o "${BACKUP_DIR}/images/ceph-v{{ cephadm_release }}.tar" quay.io/ceph/ceph:v{{ cephadm_release }} + +# Create backup manifest +cat > "${BACKUP_DIR}/backup_manifest.json" << EOF +{ + "timestamp": "${TIMESTAMP}", + "ceph_version": "{{ cephadm_release }}", + "registry_version": "2", + "backup_type": "full", + "files": [ + "registry_data.tar.gz", + "images/registry-2.tar", + "images/ceph-v{{ cephadm_release }}.tar" + ] +} +EOF + +# Restart registry container +echo "Restarting registry container..." +podman start {{ registry_container_name }} + +echo "Backup completed successfully at $(date)" +echo "Backup location: ${BACKUP_DIR}" diff --git a/roles/registry/templates/export_images.sh.j2 b/roles/registry/templates/export_images.sh.j2 new file mode 100644 index 000000000..438cd1531 --- /dev/null +++ b/roles/registry/templates/export_images.sh.j2 @@ -0,0 +1,56 @@ +#!/bin/bash +# Copyright (C) 2025 RTE +# SPDX-License-Identifier: Apache-2.0 + +# Export script for registry images +# This script exports all images from the registry as tar files for offline deployment + +set -euo pipefail + +REGISTRY_PATH="{{ registry_path }}" +IMAGES_PATH="{{ registry_images_path }}" +{% if registry_tls_enabled | default(false) %} +REGISTRY_URL="{{ ansible_default_ipv4.address }}:{{ registry_port }}" +{% else %} +REGISTRY_URL="localhost:{{ registry_port }}" +{% endif %} + +echo "Starting image export at $(date)" + +# Create images directory +mkdir -p "${IMAGES_PATH}" + +# Export registry image +echo "Exporting registry image..." +podman save -o "${IMAGES_PATH}/registry-2.tar" registry:2 + +# Export Ceph image +echo "Exporting Ceph image..." +podman save -o "${IMAGES_PATH}/ceph-v{{ cephadm_release }}.tar" quay.io/ceph/ceph:v{{ cephadm_release }} + +# Create export manifest +cat > "${IMAGES_PATH}/export_manifest.json" << EOF +{ + "export_timestamp": "$(date -Iseconds)", + "ceph_version": "{{ cephadm_release }}", + "registry_version": "2", + "registry_url": "${REGISTRY_URL}", + "images": [ + { + "name": "registry:2", + "file": "registry-2.tar", + "source": "docker.io/library/registry:2" + }, + { + "name": "ceph:v{{ cephadm_release }}", + "file": "ceph-v{{ cephadm_release }}.tar", + "source": "quay.io/ceph/ceph:v{{ cephadm_release }}" + } + ] +} +EOF + +echo "Image export completed successfully at $(date)" +echo "Images exported to: ${IMAGES_PATH}" +echo "Files created:" +ls -la "${IMAGES_PATH}" diff --git a/roles/registry/templates/import_images.sh.j2 b/roles/registry/templates/import_images.sh.j2 new file mode 100644 index 000000000..f0990b0ff --- /dev/null +++ b/roles/registry/templates/import_images.sh.j2 @@ -0,0 +1,56 @@ +#!/bin/bash +# Copyright (C) 2025 RTE +# SPDX-License-Identifier: Apache-2.0 + +# Import script for registry images +# This script imports images from tar files for offline deployment + +set -euo pipefail + +IMAGES_PATH="{{ registry_images_path }}" +{% if registry_tls_enabled | default(false) %} +REGISTRY_URL="{{ ansible_default_ipv4.address }}:{{ registry_port }}" +{% else %} +REGISTRY_URL="localhost:{{ registry_port }}" +{% endif %} + +echo "Starting image import at $(date)" + +if [ ! -d "${IMAGES_PATH}" ]; then + echo "Error: Images directory ${IMAGES_PATH} does not exist" + exit 1 +fi + +# Check if manifest exists +if [ ! -f "${IMAGES_PATH}/export_manifest.json" ]; then + echo "Warning: No export manifest found, proceeding with available files" +fi + +# Import registry image +if [ -f "${IMAGES_PATH}/registry-2.tar" ]; then + echo "Importing registry image..." + podman load -i "${IMAGES_PATH}/registry-2.tar" +else + echo "Warning: registry-2.tar not found" +fi + +# Import Ceph image +if [ -f "${IMAGES_PATH}/ceph-v{{ cephadm_release }}.tar" ]; then + echo "Importing Ceph image..." + podman load -i "${IMAGES_PATH}/ceph-v{{ cephadm_release }}.tar" +else + echo "Error: ceph-v{{ cephadm_release }}.tar not found" + exit 1 +fi + +# Tag images for local registry +echo "Tagging images for local registry..." +podman tag registry:2 "${REGISTRY_URL}/registry:2" +podman tag quay.io/ceph/ceph:v{{ cephadm_release }} "${REGISTRY_URL}/ceph:v{{ cephadm_release }}" + +# Push images to registry +echo "Pushing images to registry..." +podman push "${REGISTRY_URL}/registry:2" +podman push "${REGISTRY_URL}/ceph:v{{ cephadm_release }}" + +echo "Image import completed successfully at $(date)" diff --git a/roles/registry/templates/registry_config.yml.j2 b/roles/registry/templates/registry_config.yml.j2 new file mode 100644 index 000000000..14f0ca4e6 --- /dev/null +++ b/roles/registry/templates/registry_config.yml.j2 @@ -0,0 +1,34 @@ +version: 0.1 +log: + level: info + fields: + service: registry +storage: + filesystem: + rootdirectory: /var/lib/registry + cache: + blobdescriptor: inmemory + delete: + enabled: true +http: + addr: 0.0.0.0:5000 + headers: + X-Content-Type-Options: [nosniff] + X-Frame-Options: [DENY] + X-XSS-Protection: [1; mode=block] +{% if registry_tls_enabled | default(false) %} + tls: + certificate: /certs/server.crt + key: /certs/server.key +{% endif %} +{% if registry_auth_enabled | default(false) %} +auth: + htpasswd: + realm: Registry Realm + path: /auth/htpasswd +{% endif %} +health: + storagedriver: + enabled: true + interval: 10s + threshold: 3 diff --git a/roles/registry/templates/restore_registry.sh.j2 b/roles/registry/templates/restore_registry.sh.j2 new file mode 100644 index 000000000..9da12a2c9 --- /dev/null +++ b/roles/registry/templates/restore_registry.sh.j2 @@ -0,0 +1,70 @@ +#!/bin/bash +# Copyright (C) 2025 RTE +# SPDX-License-Identifier: Apache-2.0 + +# Restore script for registry +# This script restores registry data and imports images from tar files + +set -euo pipefail + +REGISTRY_PATH="{{ registry_path }}" +BACKUP_PATH="{{ registry_backup_path }}" + +if [ $# -ne 1 ]; then + echo "Usage: $0 " + echo "Available backups:" + ls -la "${BACKUP_PATH}" | grep backup_ || echo "No backups found" + exit 1 +fi + +BACKUP_DIR="${BACKUP_PATH}/$1" + +if [ ! -d "${BACKUP_DIR}" ]; then + echo "Error: Backup directory ${BACKUP_DIR} does not exist" + exit 1 +fi + +echo "Starting registry restore from ${BACKUP_DIR} at $(date)" + +# Stop registry container +echo "Stopping registry container..." +podman stop {{ registry_container_name }} || true + +# Clean existing data +echo "Cleaning existing registry data..." +rm -rf "${REGISTRY_PATH}/data"/* + +# Restore registry data +echo "Restoring registry data..." +tar -xzf "${BACKUP_DIR}/registry_data.tar.gz" -C "${REGISTRY_PATH}/data" + +# Load images +echo "Loading images..." +if [ -f "${BACKUP_DIR}/images/registry-2.tar" ]; then + podman load -i "${BACKUP_DIR}/images/registry-2.tar" +fi + +if [ -f "${BACKUP_DIR}/images/ceph-v{{ cephadm_release }}.tar" ]; then + podman load -i "${BACKUP_DIR}/images/ceph-v{{ cephadm_release }}.tar" +fi + +# Restart registry container +echo "Restarting registry container..." +podman start {{ registry_container_name }} + +# Wait for registry to be ready +echo "Waiting for registry to be ready..." +for i in {1..30}; do +{% if registry_tls_enabled | default(false) %} + if curl -sk https://localhost:{{ registry_port }}/v2/ > /dev/null; then +{% else %} + if curl -s http://localhost:{{ registry_port }}/v2/ > /dev/null; then +{% endif %} + echo "Registry is ready" + break + fi + echo "Waiting for registry... (${i}/30)" + sleep 2 +done + +echo "Restore completed successfully at $(date)" diff --git a/roles/snmp/tasks/main.yml b/roles/snmp/tasks/main.yml index 976a1fccd..36555808c 100644 --- a/roles/snmp/tasks/main.yml +++ b/roles/snmp/tasks/main.yml @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 --- -- include_vars: "{{ seapath_distro }}.yml" +- include_vars: "{{ ansible_os_family }}.yml" - name: Configure snmp when: diff --git a/roles/snmp/vars/CentOS.yml b/roles/snmp/vars/CentOS.yml deleted file mode 100644 index c878b8f59..000000000 --- a/roles/snmp/vars/CentOS.yml +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (C) 2024 RTE -# SPDX-License-Identifier: Apache-2.0 - ---- -snmp_user_name: "Centos-snmp" diff --git a/roles/snmp/vars/OracleLinux.yml b/roles/snmp/vars/OracleLinux.yml deleted file mode 100644 index 1f8c7daeb..000000000 --- a/roles/snmp/vars/OracleLinux.yml +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (C) 2024 RTE -# SPDX-License-Identifier: Apache-2.0 - ---- -snmp_user_name: "oraclelinux-snmp" diff --git a/roles/snmp/vars/RedHat.yml b/roles/snmp/vars/RedHat.yml new file mode 100644 index 000000000..62d7aa6f7 --- /dev/null +++ b/roles/snmp/vars/RedHat.yml @@ -0,0 +1,5 @@ +# Copyright (C) 2024 RTE +# SPDX-License-Identifier: Apache-2.0 + +--- +snmp_user_name: "{{ {'CentOS': 'Centos-snmp', 'OracleLinux': 'oraclelinux-snmp'}.get(seapath_distro, seapath_distro | lower ~ '-snmp') }}" diff --git a/roles/timemaster/tasks/main.yml b/roles/timemaster/tasks/main.yml index 2477a4b57..673a24e78 100644 --- a/roles/timemaster/tasks/main.yml +++ b/roles/timemaster/tasks/main.yml @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 --- -- include_vars: "{{ seapath_distro }}.yml" +- include_vars: "{{ ansible_os_family }}.yml" - name: Populate service facts service_facts: diff --git a/roles/timemaster/vars/OracleLinux.yml b/roles/timemaster/vars/OracleLinux.yml deleted file mode 100644 index 2052b8975..000000000 --- a/roles/timemaster/vars/OracleLinux.yml +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright (C) 2024 RTE -# SPDX-License-Identifier: Apache-2.0 - ---- -timemaster_path_timemaster_conf: "/etc/timemaster.conf" -timemaster_path_chrony_conf: "/etc/chrony.conf" -timemaster_service_name_chrony: "chronyd" diff --git a/roles/timemaster/vars/CentOS.yml b/roles/timemaster/vars/RedHat.yml similarity index 100% rename from roles/timemaster/vars/CentOS.yml rename to roles/timemaster/vars/RedHat.yml diff --git a/vars/OracleLinux_paths.yml b/vars/OracleLinux_paths.yml deleted file mode 100644 index 50f3dc223..000000000 --- a/vars/OracleLinux_paths.yml +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (C) 2024, Red Hat -# SPDX-License-Identifier: Apache-2.0 - ---- -cukinia_command_path: "/usr/local/bin/cukinia" diff --git a/vars/CentOS_paths.yml b/vars/RedHat_paths.yml similarity index 100% rename from vars/CentOS_paths.yml rename to vars/RedHat_paths.yml