{"id":7745,"sha1":"db2c8026323b7e5b1440401136381085a8114b8c","playbook":{"id":5586,"items":{"plays":7,"tasks":3,"results":3,"hosts":2,"files":1,"records":0},"arguments":{"version":null,"verbosity":0,"private_key_file":"/home/ssh-gateway/.ssh/id_rsa","remote_user":"root","connection":"ssh","timeout":null,"ssh_common_args":null,"sftp_extra_args":null,"scp_extra_args":null,"ssh_extra_args":null,"ask_pass":false,"connection_password_file":null,"force_handlers":false,"flush_cache":false,"become":false,"become_method":"sudo","become_user":null,"become_ask_pass":false,"become_password_file":null,"tags":["stage2_1"],"skip_tags":[],"check":false,"diff":false,"inventory":["/home/ssh-gateway/ansible/kuly/kvm_node_install/kvm-install-inv.ini"],"listhosts":false,"subset":null,"extra_vars":"Not saved by ARA as configured by 'ignored_arguments'","vault_ids":[],"ask_vault_pass":false,"vault_password_files":[],"forks":20,"module_path":null,"syntax":false,"listtasks":false,"listtags":false,"step":false,"start_at_task":null,"args":["setup_new_node.yaml"]},"labels":[{"id":1,"name":"remote_user:root"},{"id":2,"name":"check:False"},{"id":302,"name":"tags:stage2_1"}],"started":"2026-04-23T13:53:25.615210+01:00","ended":"2026-04-23T13:53:27.755167+01:00","duration":"00:00:02.139957","name":null,"ansible_version":"2.16.13","client_version":"1.7.5","python_version":"3.10.10","server_version":"1.7.5","status":"failed","path":"/home/ssh-gateway/ansible/kuly/kvm_node_install/setup_new_node.yaml","controller":"ssh-gw-4.layershift.com","user":"root"},"content":"---\n- name: New KVM server provisioning scripts\n  hosts: kvm_node\n  gather_facts: true\n  vars:\n    agent360_api_key: \"6225dd3b2c8afd50166ae988\"\n    firewall_mode: \"HARDWARE_NODE\"\n    timezone: \"UTC\"\n    swap_file_path: \"/var/lib/libvirt/swapfile\"\n    swap_file_size: \"64G\"\n    main_server_ip: \"{{ ansible_default_ipv4.address }}\"\n    monitoring_script_url: \"https://monitoring.platform360.io/agent360.sh\"\n    kernelcare_installer_url: \"https://kernelcare.com/installer\"\n    firewall360_install_url: \"https://tgz.thecode.casa/firewall360/install.sh\"\n    firewall360_reset_url: \"https://deploy.thecode.casa/firewall360/reset_firewall.sh\"\n    agent360_plugins_tgz_url: \"https://tgz.thecode.casa/agent360_plugins/install.sh\"\n    agent360_plugins_deploy_url: \"https://deploy.thecode.casa/agent360_plugins/install.sh\"\n    virtnbdbackup_install_url: \"https://tgz.thecode.casa/virtnbdbackup/install.sh\"\n    backup_manager_install_url: \"https://backup-manager.vm.plesk-server.com/agents/install\"\n    ls_tests_install_url: \"https://deploy.thecode.casa/ls-tests/installer.sh\"\n    requisites:\n      - wget\n      - curl\n      - vim\n      - nano\n      - net-tools\n      - lsof\n      - mc\n      - bash-completion\n      - fuse-sshfs\n\n  tasks:\n    # ========================================================================\n    # install prerequisite packages\n    # ========================================================================\n    - name: Install prerequisite packages\n      ansible.builtin.dnf:\n        name: \"{{ requisites }}\"\n        state: present\n        update_cache: true\n      tags: [packages, prep, system, stage1]\n\n    # ========================================================================\n    # SWAP FILE SETUP\n    # ========================================================================\n    - name: Create swap file directory if missing\n      ansible.builtin.file:\n        path: \"{{ swap_file_path | dirname }}\"\n        state: directory\n        mode: '0755'\n      tags: [swap, stage1]\n\n    - name: Create swap file\n      ansible.builtin.command: \"fallocate -l {{ swap_file_size }} {{ swap_file_path }}\"\n      args:\n        creates: \"{{ swap_file_path }}\"\n      tags: [swap, stage1]\n\n    - name: Set secure permissions (600) on swap file\n      ansible.builtin.file:\n        path: \"{{ swap_file_path }}\"\n        mode: '0600'\n      tags: [swap, stage1]\n\n    - name: Initialize swap area\n      ansible.builtin.command: \"mkswap {{ swap_file_path }}\"\n      args:\n        creates: \"{{ swap_file_path }}.initialized\"\n      notify: Mark swap as initialized\n      tags: [swap, stage1]\n\n    - name: Enable swap file immediately\n      ansible.builtin.command: \"swapon {{ swap_file_path }}\"\n      register: swapon_result\n      changed_when: \"'already active' not in swapon_result.stderr\"\n      failed_when: swapon_result.rc != 0 and 'already active' not in swapon_result.stderr\n      tags: [swap, stage1]\n\n    - name: Enable all swaps from /etc/fstab (swapon -av)\n      ansible.builtin.command: \"swapon -av\"\n      register: swapon_av\n      changed_when: false\n      tags: [swap, stage1]\n\n    - name: Ensure swap entry exists in /etc/fstab\n      ansible.builtin.lineinfile:\n        path: /etc/fstab\n        line: \"{{ swap_file_path }} none swap sw 0 0\"\n        regexp: \"^{{ swap_file_path }}\\\\s+none\\\\s+swap\"\n        state: present\n        validate: 'findmnt -T %s'\n      tags: [swap, fstab, stage1]\n\n    # ========================================================================\n    # TIMEZONE CONFIGURATION\n    # ========================================================================\n    - name: Set system timezone to {{ timezone }}\n      community.general.timezone:\n        name: \"{{ timezone }}\"\n      tags: [config, timezone, stage1]\n\n    # ========================================================================\n    # KERNELCARE INSTALLATION\n    # ========================================================================\n    - name: Install KernelCare\n      ansible.builtin.shell: |\n        set -o pipefail\n        curl -s -L {{ kernelcare_installer_url }} | bash\n      args:\n        executable: /bin/bash\n        creates: /usr/bin/kcare\n      register: kernelcare_install\n      changed_when: kernelcare_install.rc == 0\n      tags: [kernelcare, stage1]\n\n    - name: Enable and start KernelCare service\n      ansible.builtin.systemd:\n        name: kcare\n        enabled: true\n        state: started\n        daemon_reload: true\n      tags: [kernelcare, stage1]\n\n    - name: Display KernelCare licensing reminder\n      ansible.builtin.debug:\n        msg: |\n          \u26a0\ufe0f  KERNELCARE LICENSE REMINDER \u26a0\ufe0f\n          Please license this IP in your KernelCare portal:\n          \u2192 {{ main_server_ip }}\n          Visit: https://cln.cloudlinux.com/console\n      tags: [kernelcare, stage1]\n\n    # ========================================================================\n    # AGENT360 MONITORING INSTALLATION\n    # ========================================================================\n    - name: Download Agent360 installation script\n      ansible.builtin.get_url:\n        url: \"{{ monitoring_script_url }}\"\n        dest: /tmp/agent360.sh\n        mode: '0755'\n        timeout: 30\n      tags: [monitoring, agent360, stage1]\n\n    - name: Install Agent360 monitoring agent\n      ansible.builtin.shell: |\n        set -o pipefail\n        bash /tmp/agent360.sh {{ agent360_api_key }}\n      args:\n        chdir: /tmp\n      register: agent360_install\n      changed_when: agent360_install.rc == 0\n      tags: [monitoring, agent360, stage1]\n\n    # ========================================================================\n    # FIREWALL360 INSTALLATION\n    # ========================================================================\n    - name: Install Firewall360\n      ansible.builtin.shell: \"bash <(curl -sL {{ firewall360_install_url }}) <<< '{{ firewall_mode }}'\"\n      args:\n        executable: /bin/bash\n      register: firewall_install\n      changed_when: firewall_install.rc == 0\n      tags: [firewall, stage1]\n\n    # ========================================================================\n    # FIREWALL360 RESET\n    # ========================================================================\n    - name: Reset Firewall360 configuration\n      ansible.builtin.shell: \"bash <(curl -sL {{ firewall360_reset_url }})\"\n      args:\n        executable: /bin/bash\n      register: firewall_reset\n      changed_when: firewall_reset.rc == 0\n      tags: [firewall, stage1]\n\n    # ========================================================================\n    # AGENT360 CUSTOM PLUGINS\n    # ========================================================================\n    - name: Install plugin internal_server_metrics\n      ansible.builtin.shell: |\n        set -o pipefail\n        curl -Ls {{ agent360_plugins_tgz_url }} | bash -s internal_server_metrics\n      args:\n        executable: /bin/bash\n      register: plugin_internal\n      changed_when: plugin_internal.rc == 0\n      tags: [monitoring, plugins, stage1]\n\n    - name: Install plugin vrrp_mon_cr\n      ansible.builtin.shell: |\n        set -o pipefail\n        curl -Ls {{ agent360_plugins_deploy_url }} | bash -s vrrp_mon_cr\n      args:\n        executable: /bin/bash\n      register: plugin_vrrp\n      changed_when: plugin_vrrp.rc == 0\n      tags: [monitoring, plugins, stage1]\n\n    - name: Ensure pip3 is available\n      ansible.builtin.package:\n        name: python3-pip\n        state: present\n      tags: [monitoring, plugins, stage1]\n\n    - name: Install mdjson Python package\n      ansible.builtin.pip:\n        name: mdjson\n        executable: pip3\n        state: present\n      tags: [monitoring, plugins, stage1]\n\n    - name: Install plugin mdstat_ls\n      ansible.builtin.shell: |\n        set -o pipefail\n        curl -Ls {{ agent360_plugins_deploy_url }} | bash -s mdstat_ls\n      args:\n        executable: /bin/bash\n      register: plugin_mdstat\n      changed_when: plugin_mdstat.rc == 0\n      tags: [monitoring, plugins, stage1]\n\n    # ========================================================================\n    # NBD MODULE + VIRTNBDBACKUP\n    # ========================================================================\n    - name: Ensure NBD module loads at boot\n      ansible.builtin.copy:\n        content: \"nbd\\n\"\n        dest: /etc/modules-load.d/nbd.conf\n        mode: '0644'\n      tags: [backup, nbd, prep, stage1]\n\n    - name: Load NBD kernel module immediately\n      community.general.modprobe:\n        name: nbd\n        state: present\n      tags: [backup, nbd, prep, stage1]\n\n    - name: Install virtnbdbackup\n      ansible.builtin.shell: |\n        set -o pipefail\n        curl -s {{ virtnbdbackup_install_url }} | bash\n      args:\n        executable: /bin/bash\n      register: virtnbd_install\n      changed_when: virtnbd_install.rc == 0\n      tags: [backup, virtnbd, stage1]\n  handlers:\n    - name: Mark swap as initialized\n      ansible.builtin.file:\n        path: \"{{ swap_file_path }}.initialized\"\n        state: touch\n        mode: '0644'\n\n# ----------------------------------------------------------------------------------------------------------------------------------------------------------\n- name: Install backup agent\n  hosts: kvm_node\n  gather_facts: true\n  vars:\n    backup_manager_install_url: \"https://backup-manager.stage.town/agents/install\"\n    backup_manager_add_node_url: \"https://backup-manager.stage.town/hardwarenodes/\"\n  tasks:\n    - name: Add hw node to backup manager\n      ansible.builtin.uri:\n        url: \"{{ backup_manager_add_node_url }}\"\n        method: POST\n        body_format: json\n        body:\n          name: \"{{ inventory_hostname }}\"\n          ip: \"{{ ansible_default_ipv4.address }}\"\n        headers:\n          Content-Type: \"application/json\"\n        status_code: 200\n      tags: [backup, stage2]\n\n    - name: Download backup-manager installer\n      ansible.builtin.get_url:\n        url: \"{{ backup_manager_install_url }}\"\n        dest: /tmp/installer.sh\n        mode: '0755'\n        timeout: 30\n      tags: [backup, backup-manager, stage2]\n\n    - name: Run backup-manager installer (pass 1)\n      ansible.builtin.shell: |\n        set -o pipefail\n        /tmp/installer.sh\n      args:\n        chdir: /tmp\n      register: backup_install_1\n      changed_when: backup_install_1.rc == 0\n      tags: [backup, backup-manager, stage2]\n\n- name: Generate ssh key\n  hosts: kvm_node\n  gather_facts: true\n  vars:\n    target_user: root\n    local_tmp_path: \"/tmp/id_rsa_host1.pub\"\n  tasks:\n    - name: Generate SSH key pair\n      community.crypto.openssh_keypair:\n        path: \"/{{ target_user }}/.ssh/id_rsa\"\n        type: rsa\n        size: 2048\n        comment: \"ansible-generated-on-{{ ansible_fqdn }}\"\n      register: ssh_key_result\n      tags: [stage2]\n    - name: Fetch public key\n      ansible.builtin.fetch:\n        src: \"/{{ target_user }}/.ssh/id_rsa.pub\"\n        dest: \"{{ local_tmp_path }}\"\n        flat: true\n      tags: [stage2]\n\n- name: Upload key to storage server\n  hosts: backup_node\n  gather_facts: false\n  vars:\n    target_user: root\n    local_tmp_path: \"/tmp/id_rsa_host1.pub\"\n  tasks:\n    - name: Install public key from local temp file\n      ansible.posix.authorized_key:\n        user: root\n        state: present\n        key: \"{{ lookup('file', local_tmp_path) }}\"\n      tags: [stage2]\n    - name: Remove temp file\n      delegate_to: localhost\n      run_once: true\n      ansible.builtin.file:\n        path: \"{{ local_tmp_path }}\"\n        state: absent\n      tags: [stage2]\n\n- name: Create folder and file on backup node\n  hosts: backup_node\n  gather_facts: false\n  vars:\n    kvm_host: \"{{ hostvars[groups['kvm_node'][0]]['inventory_hostname'] }}\"\n  tasks:\n    - name: Create folder\n      ansible.builtin.file:\n        force: true\n        path: \"/vz/vmprivate/backups/{{ kvm_host }}\"\n        state: directory\n        mode: '0755'\n      tags: [stage2]\n    - name: Create file\n      ansible.builtin.file:\n        force: true\n        path: \"/vz/vmprivate/backups/{{ kvm_host }}/mount-check-production.txt\"\n        state: touch\n        mode: '0644'\n      tags: [stage2]\n\n- name: Get backups private ip\n  hosts: backup_node\n  gather_facts: true\n  tasks:\n    - name: Find the IP in the 10.10.10.0/21 range\n      ansible.builtin.set_fact:\n        private_ip: \"{{ ansible_all_ipv4_addresses | select('match', '^10\\\\.10\\\\.10\\\\.') | first }}\"\n      tags: [stage2_1]\n\n- name: Finish setup on kvm node\n  hosts: kvm_node\n  gather_facts: false\n  vars:\n    st_ip: \"{{ hostvars['kvm_node']['private_ip'] }}\"\n  tasks:\n    - name: Create folder on kvm node\n      ansible.builtin.file:\n        force: true\n        path: \"/vz/vmprivate/backups/{{ inventory_hostname }}\"\n        state: directory\n        mode: '0755'\n      tags: [stage2_1]\n    - name: Add to fstab\n      ansible.builtin.lineinfile:\n        path: /etc/fstab\n        line: \"root@{{ st_ip }}/vz/vmprivate/backups/{{ inventory_hostname }} fuse.sshfs rw,nosuid,reconnect,ServerAliveInterval=15,nodev,port=22,uid=0,gid=0 0 0\"\n        state: present\n        validate: 'findmnt -T %s'\n      tags: [stage2_1]\n\n        #    - name: Run backup-manager installer (pass 2)\n        #      ansible.builtin.shell: |\n        #        set -o pipefail\n        #        /tmp/installer.sh\n        #      args:\n        #        chdir: /tmp\n        #      register: backup_install_2\n        #      changed_when: backup_install_2.rc == 0\n        #      tags: [backup, backup-manager, stage2_1]\n\n        #    - name: Run backup-manager mount script\n        #      ansible.builtin.shell: |\n        #        set -o pipefail\n        #        /tmp/mount.sh\n        #      args:\n        #        chdir: /tmp\n        #      register: backup_mount\n        #      changed_when: backup_mount.rc == 0\n        #      tags: [backup, backup-manager, stage2_1]\n\n- name: Run final tests and report\n  hosts: all\n  gather_facts: true\n  tasks:\n    # ========================================================================\n    # 10. goss ls tests\n    # ========================================================================\n    - name: Install ls-tests suite\n      ansible.builtin.shell: |\n        set -o pipefail\n        curl -s {{ ls_tests_install_url }} | bash\n      args:\n        executable: /bin/bash\n        creates: /opt/ls_tools/ls-tests/run_tests.sh\n      register: ls_tests_install\n      changed_when: ls_tests_install.rc == 0\n      tags: [tests, ls-tests, stage3]\n\n    - name: Run goss tests\n      ansible.builtin.shell: |\n        set -o pipefail\n        /opt/ls_tools/ls-tests/run_tests.sh\n      args:\n        executable: /bin/bash\n      register: ls_tests_run\n      changed_when: ls_tests_run.rc == 0\n      tags: [tests, ls-tests, stage3]\n\n    # ========================================================================\n    # 11. POST-INSTALL SUMMARY\n    # ========================================================================\n    - name: Display provisioning completion summary\n      ansible.builtin.debug:\n        msg: |\n          \u2705 SERVER PROVISIONING COMPLETE \u2705\n          Configuration applied:\n          \u2022 Swap: {{ swap_file_path }} ({{ swap_file_size }}) \u2192 active\n          \u2022 Timezone: {{ timezone }}\n          \u2022 KernelCare: installed (license IP: {{ main_server_ip }})\n          \u2022 Firewall360: {{ firewall_mode }} mode + reset\n          \u2022 Agent360: monitoring + 3 plugins installed\n          \u2022 NBD/virtnbdbackup: ready\n          \u2022 backup-manager: installed + mounted\n          Quick verification commands:\n            swapon --show\n            timedatectl\n            systemctl status kcare\n            firewall360 status\n            agent360 status\n            lsmod | grep nbd\n      tags: [verify, always, stage3]\n","created":"2026-04-23T13:53:25.634411+01:00","updated":"2026-04-23T13:53:25.634431+01:00","path":"/home/ssh-gateway/ansible/kuly/kvm_node_install/setup_new_node.yaml"}