diff --git a/linux/deploy_vm/templates/photon-ova-user-data.j2 b/linux/deploy_vm/templates/photon-ova-user-data.j2 index ca12c54fb..5ae08c055 100644 --- a/linux/deploy_vm/templates/photon-ova-user-data.j2 +++ b/linux/deploy_vm/templates/photon-ova-user-data.j2 @@ -5,7 +5,6 @@ ssh_authorized_keys: packages: - sudo - sg3_utils - - chrony - tar - ndctl - python3-rpm diff --git a/linux/guest_customization/check_gosc_log.yml b/linux/guest_customization/check_gosc_log.yml index 99dfb6b6d..7253685cb 100644 --- a/linux/guest_customization/check_gosc_log.yml +++ b/linux/guest_customization/check_gosc_log.yml @@ -4,57 +4,41 @@ # Fetch gosc log file to local and check the log content - name: "Set guest customization plugin log location on localhost" ansible.builtin.set_fact: - deploypkg_log_path: "{{ current_test_log_folder }}{{ gosc_deploypkg_log_file }}" gosc_log_success: true -- include_tasks: ../../common/vm_guest_file_operation.yml +- name: "Fetch GOSC log file {{ gosc_deploypkg_log_file }}" + include_tasks: ../../common/vm_guest_file_operation.yml vars: operation: "fetch_file" src_path: "{{ gosc_deploypkg_log_file }}" - dest_path: "{{ deploypkg_log_path }}" + dest_path: "{{ gosc_deploypkg_log_local }}" -# Check perl GOSC log file -- block: - # Check below message exists - - include_tasks: check_log_msg.yml - vars: - check_log_file: "{{ deploypkg_log_path }}" - check_msg_state: "present" - with_items: - - "Executing traditional GOSC workflow" - - "Deployment succeeded" - - "Ran DeployPkg_DeployPackageFromFile successfully" - loop_control: - loop_var: "check_msg_regexp" +- name: "Check traditional GOSC log in {{ gosc_deploypkg_log_local }}" when: gosc_workflow == "perl" + include_tasks: check_log_msg.yml + vars: + check_log_file: "{{ gosc_deploypkg_log_local }}" + check_msg_state: "present" + with_items: + - "Executing traditional GOSC workflow" + - "Deployment succeeded" + - "Ran DeployPkg_DeployPackageFromFile successfully" + loop_control: + loop_var: "check_msg_regexp" -# Check cloud-init GOSC log file -- block: - # Collect /var/log/cloud-init.log and /etc/cloud/cloud.cfg - - include_tasks: ../../common/vm_guest_file_operation.yml - vars: - operation: "fetch_file" - src_path: "{{ gosc_cloudinit_log_file }}" - dest_path: "{{ current_test_log_folder }}{{ gosc_cloudinit_log_file }}" - - # Check below message exists - - include_tasks: check_log_msg.yml - vars: - check_log_file: "{{ deploypkg_log_path }}" - check_msg_state: "present" - with_items: - - "Executing cloud-init workflow" - - "Deployment for cloud-init succeeded" - - "Ran DeployPkg_DeployPackageFromFile successfully" - loop_control: - loop_var: "check_msg_regexp" +- name: "Check cloud-init GOSC log in {{ gosc_deploypkg_log_local }}" when: gosc_workflow == "cloud-init" + include_tasks: check_log_msg.yml + vars: + check_log_file: "{{ gosc_deploypkg_log_local }}" + check_msg_state: "present" + with_items: + - "Executing cloud-init workflow" + - "Deployment for cloud-init succeeded" + - "Ran DeployPkg_DeployPackageFromFile successfully" + loop_control: + loop_var: "check_msg_regexp" -# Collect all cloud-init logs and userdata for cloud-init GOSC or VMware Photon OS -- include_tasks: ../utils/collect_cloudinit_logs.yml - when: > - (gosc_workflow == "cloud-init") or - (guest_os_ansible_distribution == "VMware Photon OS") - -- name: "Print GOSC log file check result" - ansible.builtin.debug: var=gosc_log_success +- name: "Print result of checking GOSC log" + ansible.builtin.debug: + msg: "Checking GOSC log success: {{ gosc_log_success }}" diff --git a/linux/guest_customization/linux_gosc_execution.yml b/linux/guest_customization/linux_gosc_execution.yml index 95d510b4c..fdd5169a1 100644 --- a/linux/guest_customization/linux_gosc_execution.yml +++ b/linux/guest_customization/linux_gosc_execution.yml @@ -1,7 +1,7 @@ # Copyright 2021-2023 VMware, Inc. # SPDX-License-Identifier: BSD-2-Clause --- -- name: Customize Linux guest OS +- name: "Customize Linux guest OS" community.vmware.vmware_guest: hostname: "{{ vcenter_hostname }}" username: "{{ vcenter_username }}" @@ -26,9 +26,9 @@ timezone: "{{ linux_gosc_spec.timezone }}" hwclockUTC: "{{ linux_gosc_spec.hwclockUTC }}" wait_for_customization: true - wait_for_customization_timeout: "{{ timeout | default(omit) }}" + wait_for_customization_timeout: "{{ linux_gosc_timeout | default(omit) }}" register: customize_linux_result -- name: Display the Linux customization result +- name: "Display the Linux customization result" ansible.builtin.debug: var=customize_linux_result when: enable_debug diff --git a/linux/guest_customization/linux_gosc_start.yml b/linux/guest_customization/linux_gosc_start.yml index 1eb72a812..5a5fbda80 100644 --- a/linux/guest_customization/linux_gosc_start.yml +++ b/linux/guest_customization/linux_gosc_start.yml @@ -42,7 +42,7 @@ include_tasks: linux_gosc_execution.yml vars: type: "{{ ip_assignment }}" - timeout: 900 + linux_gosc_timeout: 900 # Do not fail GOSC immediately if state keyword doesn't exist - name: "Wait for GOSC state is completed" @@ -75,7 +75,9 @@ - name: "Set fact of GOSC log files" ansible.builtin.set_fact: gosc_deploypkg_log_file: "/var/log/vmware-imc/toolsDeployPkg.log" + gosc_deploypkg_log_local: "{{ current_test_log_folder }}/toolsDeployPkg.log" gosc_cloudinit_log_file: "/var/log/cloud-init.log" + gosc_cloudinit_log_local: "{{ current_test_log_folder }}/cloud-init.log" # Wait GOSC completes message in logs - name: "Wait for traditional GOSC complete message" diff --git a/linux/guest_customization/linux_gosc_workflow.yml b/linux/guest_customization/linux_gosc_workflow.yml index bdec3f24f..4ce6b0eda 100644 --- a/linux/guest_customization/linux_gosc_workflow.yml +++ b/linux/guest_customization/linux_gosc_workflow.yml @@ -13,7 +13,8 @@ ansible.builtin.set_fact: enable_cloudinit_gosc: "{% if gosc_workflow == 'cloud-init' %}True{% else %}False{% endif %}" - - include_tasks: ../setup/test_setup.yml + - name: "Test setup" + include_tasks: ../setup/test_setup.yml vars: skip_test_no_vmtools: true @@ -21,6 +22,7 @@ include_tasks: check_gosc_support_status.yml - name: "Prepare for GOSC testing on VMware Photon OS" + when: guest_os_ansible_distribution == "VMware Photon OS" block: # Traditional GOSC in VMware Photon OS is implemented with cloud-init, # so will upgrade cloud-init to the latest version in VMware Photon OS @@ -30,11 +32,12 @@ package_list: ["cloud-init"] package_state: "latest" - - include_tasks: ../utils/get_cloudinit_version.yml + - name: "Get cloud-init version" + include_tasks: ../utils/get_cloudinit_version.yml # In VMware Photon OS 4.0, open-vm-tools-gosc is provided with GOSC scripts # from open-vm-tools 11.3.5 - - name: "Install 'open-vm-tools-gosc-{{ vmtools_version }}' for GOSC" + - name: "Install GOSC required package 'open-vm-tools-gosc-{{ vmtools_version }}'" include_tasks: ../utils/install_uninstall_package.yml vars: package_list: ["open-vm-tools-gosc-{{ vmtools_version }}"] @@ -44,10 +47,12 @@ - guest_os_ansible_distribution_major_ver | int >= 4 - vmtools_version is defined - vmtools_version is version('11.3.5', '>=') - when: guest_os_ansible_distribution == "VMware Photon OS" # Install perl if guest OS doesn't have it - name: "Prepare for perl GOSC testing on {{ guest_os_ansible_distribution }}" + when: + - not enable_cloudinit_gosc | bool + - guest_os_family == "RedHat" block: - name: "Check perl existence" ansible.builtin.command: "which perl" @@ -56,6 +61,7 @@ delegate_to: "{{ vm_guest_ip }}" - name: "Install perl" + when: which_perl_result.rc is undefined or which_perl_result.rc != 0 block: - name: "Set perl package name on {{ guest_os_ansible_distribution }} {{ guest_os_ansible_distribution_ver }}" ansible.builtin.set_fact: @@ -68,12 +74,9 @@ vars: package_list: ["{{ guest_perl_package_name }}"] package_state: "latest" - when: which_perl_result.rc is undefined or which_perl_result.rc != 0 - when: - - not enable_cloudinit_gosc | bool - - guest_os_family == "RedHat" - name: "Prepare for cloud-init GOSC" + when: enable_cloudinit_gosc block: - name: "Install 'cloud-init' for cloud-init GOSC on {{ guest_os_ansible_distribution }}" include_tasks: ../utils/install_uninstall_package.yml @@ -84,6 +87,9 @@ # Need to install the latest cloud-init to Oracle Linux 8.7, 9.1 and pass the GOSC tests in Ansible - name: "Update cloud-init GOSC in OracleLinux 8.7 & 9.1" + when: + - guest_os_ansible_distribution == "OracleLinux" + - guest_os_ansible_distribution_ver in ['8.7', '9.1'] block: - name: "Known issue - failure of cloud-init GOSC in Oracle Linux 8.7 and 9.1" ansible.builtin.debug: @@ -112,9 +118,6 @@ vars: package_list: ["cloud-init"] package_state: "latest" - when: - - guest_os_ansible_distribution == "OracleLinux" - - guest_os_ansible_distribution_ver in ['8.7', '9.1'] # Check whether cloud-init version meets cloud-init GOSC requirements # Debian 10 and 11 cloud-init GOSC requires cloud-init 22.1 or later installed. @@ -126,9 +129,11 @@ gosc_required_cloudinit_version: >- {% if guest_os_ansible_distribution != 'Debian' %}18.5{% else %}22.1{% endif %} - - include_tasks: ../utils/get_cloudinit_version.yml + - name: "Get cloud-init version" + include_tasks: ../utils/get_cloudinit_version.yml - - include_tasks: ../../common/skip_test_case.yml + - name: "Skip test case due to cloud-init version doesn't meet cloud-init GOSC requirements" + include_tasks: ../../common/skip_test_case.yml vars: skip_reason: "Not Supported" skip_msg: >- @@ -137,7 +142,6 @@ when: > (not cloudinit_version) or not (cloudinit_version is version(gosc_required_cloudinit_version, '>=')) - when: enable_cloudinit_gosc - name: "Get DNS server info before GOSC" include_tasks: ../utils/get_system_dns.yml @@ -154,14 +158,14 @@ - name: "Update cloud-init config for {{ gosc_workflow }} GOSC" include_tasks: ../utils/enable_disable_cloudinit_cfg.yml - # Prepare router VM, vSwitch and portgroup - - include_tasks: ../../common/network_testbed_setup.yml + - name: "Prepare router VM, vSwitch and portgroup" + include_tasks: ../../common/network_testbed_setup.yml when: - router_vm_required | default(false) - router_vm_deployed is undefined or not router_vm_deployed | bool # Initialize the GOSC spec - - name: Initialize the GOS customization spec + - name: "Initialize the GOS customization spec" ansible.builtin.set_fact: linux_gosc_spec: {'domain': 'gosc.test.com', 'timezone': "Europe/Berlin", 'dns_suffix': ["test.com", "gosc.test.com"]} @@ -190,9 +194,38 @@ - {'hwclockUTC': true} when: ip_assignment == "dhcp" - # Execute guest customization on VM - - include_tasks: linux_gosc_start.yml - # Check guest customization results - - include_tasks: linux_gosc_verify.yml + - name: "Execute guest customization on VM" + include_tasks: linux_gosc_start.yml + + - name: "Check guest customization results" + include_tasks: linux_gosc_verify.yml rescue: - - include_tasks: ../../common/test_rescue.yml + - name: "Test case failure" + include_tasks: ../../common/test_rescue.yml + always: + - name: "Collect GOSC log" + when: + - gosc_deploypkg_log_local is defined + - gosc_deploypkg_log_local + block: + - name: "Get stat of {{ gosc_deploypkg_log_local }}" + ansible.builtin.stat: + path: "{{ gosc_deploypkg_log_local }}" + register: gosc_deploypkg_log_stat + + - name: "Fetch GOSC log file {{ gosc_deploypkg_log_file }}" + include_tasks: ../../common/vm_guest_file_operation.yml + vars: + operation: "fetch_file" + src_path: "{{ gosc_deploypkg_log_file }}" + dest_path: "{{ gosc_deploypkg_log_local }}" + when: + - not (gosc_deploypkg_log_stat.stat.exists | default(False)) + - vmtools_is_running is defined + - vmtools_is_running | bool + + - name: "Colect cloud-init logs" + include_tasks: ../utils/collect_cloudinit_logs.yml + when: > + (gosc_workflow == "cloud-init") or + (guest_os_ansible_distribution == "VMware Photon OS") diff --git a/linux/utils/collect_cloudinit_logs.yml b/linux/utils/collect_cloudinit_logs.yml index ed94ea96c..92bf1c99c 100644 --- a/linux/utils/collect_cloudinit_logs.yml +++ b/linux/utils/collect_cloudinit_logs.yml @@ -2,23 +2,48 @@ # SPDX-License-Identifier: BSD-2-Clause --- # Collect cloud-init logs at deploying OVA or guest customization -- name: "Initialize the cloud-init logs archive path in guest OS" +# +- name: "Initialize cloud-init archives in guest OS" ansible.builtin.set_fact: - cloudinit_logs_src_path: "/tmp/cloud-init_{{ lookup('pipe', 'date +%Y-%m-%d-%H-%M-%S') }}.tar.gz" + cloudinit_logs_src_path: "/tmp/cloud-init-logs_{{ lookup('pipe', 'date +%Y%m%d%H%M%S') }}.tar.gz" + cloudinit_cfgs_src_path: "/tmp/cloud-init-configs_{{ lookup('pipe', 'date +%Y%m%d%H%M%S') }}.tar.gz" -- name: "Set fact of cloud-init logs archive path at local" +- name: "Set facts of cloud-init archives at local" ansible.builtin.set_fact: cloudinit_logs_local_path: "{{ current_test_log_folder }}/{{ cloudinit_logs_src_path | basename }}" + cloudinit_cfgs_local_path: "{{ current_test_log_folder }}/{{ cloudinit_cfgs_src_path | basename }}" -- block: - # Collect cloud-init logs - - include_tasks: ../../common/vm_shell_in_guest.yml +- name: "Collect cloud-init archives when VMware Tools is running" + when: + - vmtools_is_running is defined + - vmtools_is_running | bool + block: + - name: "Create cloud-init configs archive" + include_tasks: ../../common/vm_shell_in_guest.yml + vars: + vm_shell_cmd: "/usr/bin/tar" + vm_shell_args: "-czvf {{ cloudinit_cfgs_src_path }} --exclude /etc/cloud/templates /etc/cloud" + vm_shell_out: "" + + - name: "Fetch cloud-init configs archive to local" + include_tasks: ../../common/vm_guest_file_operation.yml + vars: + operation: "fetch_file" + src_path: "{{ cloudinit_cfgs_src_path }}" + dest_path: "{{ cloudinit_cfgs_local_path }}" + when: + - vm_shell_result.exit_code is defined + - vm_shell_result.exit_code == 0 + + - name: "Create cloud-init logs archive" + include_tasks: ../../common/vm_shell_in_guest.yml vars: vm_shell_cmd: "/usr/bin/cloud-init" vm_shell_args: "collect-logs -u -t {{ cloudinit_logs_src_path }}" vm_shell_out: "" - - include_tasks: ../../common/vm_guest_file_operation.yml + - name: "Fetch cloud-init logs archive to local" + include_tasks: ../../common/vm_guest_file_operation.yml vars: operation: "fetch_file" src_path: "{{ cloudinit_logs_src_path }}" @@ -26,18 +51,36 @@ when: - vm_shell_result.exit_code is defined - vm_shell_result.exit_code == 0 + +- name: "Collect cloud-init archives when VMware Tools is not running" when: - - vmtools_is_running is defined - - vmtools_is_running | bool + - vmtools_is_running is undefined or not (vmtools_is_running | bool) + - vm_guest_ip is defined + - vm_guest_ip in groups['target_vm'] + block: + - name: "Create cloud-init configs archive" + ansible.builtin.shell: + cmd: "/usr/bin/tar -czvf {{ cloudinit_cfgs_src_path }} --exclude /etc/cloud/templates /etc/cloud" + delegate_to: "{{ vm_guest_ip }}" + ignore_errors: True + register: collect_cloudinit_cfgs_result + + - name: "Fetch cloud-init configs archive to local" + include_tasks: fetch_file.yml + vars: + fetch_file_src_path: "{{ cloudinit_cfgs_src_path }}" + fetch_file_dst_path: "{{ cloudinit_cfgs_local_path }}" + when: + - collect_cloudinit_cfgs_result.rc is defined + - collect_cloudinit_cfgs_result.rc == 0 -- block: - - name: "Collect cloud-init logs" + - name: "Create cloud-init logs archive" ansible.builtin.shell: "/usr/bin/cloud-init collect-logs -u -t {{ cloudinit_logs_src_path }}" delegate_to: "{{ vm_guest_ip }}" ignore_errors: True register: collect_cloudinit_logs_result - - name: "Fetch cloud-init logs from guest OS" + - name: "Fetch cloud-init logs archive to local" include_tasks: fetch_file.yml vars: fetch_file_src_path: "{{ cloudinit_logs_src_path }}" @@ -45,7 +88,3 @@ when: - collect_cloudinit_logs_result.rc is defined - collect_cloudinit_logs_result.rc == 0 - when: - - vmtools_is_running is undefined or not (vmtools_is_running | bool) - - vm_guest_ip is defined - - vm_guest_ip in groups['target_vm'] diff --git a/linux/utils/enable_disable_cloudinit_cfg.yml b/linux/utils/enable_disable_cloudinit_cfg.yml index 9f7bac41c..5eddfd9a4 100644 --- a/linux/utils/enable_disable_cloudinit_cfg.yml +++ b/linux/utils/enable_disable_cloudinit_cfg.yml @@ -25,6 +25,7 @@ - not guest_cloud_cfg_exists | bool - name: "Update cloud-init configs" + when: guest_cloud_cfg_exists | bool block: - name: "Set keyword for searching network config in cloud-init config files" ansible.builtin.set_fact: @@ -37,13 +38,14 @@ changed_when: false delegate_to: "{{ vm_guest_ip }}" - - name: "Enable Cloud-Init GOSC for cloud-init workflow" + - name: "Enable cloud-init GOSC for cloud-init workflow" + when: enable_cloudinit_gosc | bool block: - # Enable cloud-init services - - include_tasks: service_operation.yml + - name: "Enable cloud-init services but not start them" + include_tasks: service_operation.yml vars: service_enabled: true - service_state: "started" + service_state: "stopped" loop: - cloud-init-local - cloud-init @@ -64,15 +66,17 @@ - 'disable_vmware_customization: false' - 'ssh_pwauth: 1' - - name: Check cloud-init GOSC is enabled + - name: "Get cloud-init GOSC flag 'disable_vmware_customization'" ansible.builtin.command: "grep '^disable_vmware_customization' {{ guest_cloud_cfg_path }}" - register: result + register: enable_ci_gosc_result changed_when: false delegate_to: "{{ vm_guest_ip }}" - - name: "Save cloud-init GOSC enable flag" - ansible.builtin.set_fact: - cloudinit_gosc_enabled: "{{ result.stdout.split(': ')[1] | lower == 'false' }}" + - name: "Assert cloud-init GOSC flag 'disable_vmware_customization' is false" + ansible.builtin.assert: + that: + - "{{ enable_ci_gosc_result.stdout.split(':')[1].strip() | lower == 'false' }}" + fail_msg: "Failed to enable cloud-init GOSC by setting 'disable_vmware_customization' to true" - name: "Enable cloud-init network config" include_tasks: replace_or_add_line_in_file.yml @@ -107,19 +111,13 @@ delegate_to: "{{ vm_guest_ip }}" ignore_errors: true - - name: "Assert disable_vmware_customization is false" - ansible.builtin.assert: - that: - - cloudinit_gosc_enabled - fail_msg: "Failed to enable cloud-init GOSC" - - - name: "Clear cloud-init.log" - ansible.builtin.shell: "cat /dev/null >/var/log/cloud-init.log" + - name: "Clean cloud-init seed and logs" + ansible.builtin.shell: "cloud-init clean --log --seed" delegate_to: "{{ vm_guest_ip }}" ignore_errors: true - when: enable_cloudinit_gosc | bool - - name: "Disable Cloud-Init GOSC for perl workflow" + - name: "Disable cloud-init GOSC for perl workflow" + when: not enable_cloudinit_gosc | bool block: - name: "Disable cloud-init GOSC in {{ guest_cloud_cfg_path }}" ansible.builtin.lineinfile: @@ -178,5 +176,3 @@ that: - cloudinit_gosc_disabled fail_msg: "Failed to disable cloud-init GOSC" - when: not enable_cloudinit_gosc | bool - when: guest_cloud_cfg_exists | bool