From 63e75c6f33257c530ca8054b8ea3e29b0c3f3f67 Mon Sep 17 00:00:00 2001 From: "Qi (Keira) Zhang" Date: Wed, 31 Jan 2024 11:08:59 +0800 Subject: [PATCH] [Linux] Fix v3.1 regression test issues for deploy_vm, GOSC and waiting ESXi portgroup (#541) Signed-off-by: Qi Zhang --- autoinstall/FreeBSD/13/installerconfig | 2 +- autoinstall/FreeBSD/14/installerconfig | 2 +- common/esxi_wait_portgroup.yml | 7 +- linux/deploy_vm/deploy_vm_from_ova.yml | 6 +- linux/guest_customization/check_dns.yml | 141 ++++++++++++++---------- 5 files changed, 92 insertions(+), 66 deletions(-) diff --git a/autoinstall/FreeBSD/13/installerconfig b/autoinstall/FreeBSD/13/installerconfig index 702854b2c..110b2f1ef 100644 --- a/autoinstall/FreeBSD/13/installerconfig +++ b/autoinstall/FreeBSD/13/installerconfig @@ -24,7 +24,7 @@ export ZFSBOOT_BOOT_TYPE="BIOS" #!/bin/sh # Set hostname -sysrc hostname="FreeBSD-{{ hostname_timestamp }}" +sysrc hostname="FreeBSD-{{ current_test_timestamp }}" # Set Time Zone to UTC echo "Setting Time Zone to UTC ..." diff --git a/autoinstall/FreeBSD/14/installerconfig b/autoinstall/FreeBSD/14/installerconfig index 37b0ae916..31ddae4b0 100644 --- a/autoinstall/FreeBSD/14/installerconfig +++ b/autoinstall/FreeBSD/14/installerconfig @@ -24,7 +24,7 @@ export ZFSBOOT_BOOT_TYPE="BIOS" #!/bin/sh # Set hostname -sysrc hostname="FreeBSD-{{ hostname_timestamp }}" +sysrc hostname="FreeBSD-{{ current_test_timestamp }}" # Set Time Zone to UTC echo "Setting Time Zone to UTC ..." diff --git a/common/esxi_wait_portgroup.yml b/common/esxi_wait_portgroup.yml index 427658f99..b969467db 100644 --- a/common/esxi_wait_portgroup.yml +++ b/common/esxi_wait_portgroup.yml @@ -26,9 +26,10 @@ until: - portgroup_facts is defined - portgroup_facts.hosts_portgroup_info is defined - - portgroup_facts.hosts_portgroup_info[esxi_hostname] is defined - - portgroup_facts.hosts_portgroup_info[esxi_hostname] | length > 0 - - (portgroup_facts.hosts_portgroup_info[esxi_hostname] | selectattr('portgroup', 'equalto', wait_for_portgroup_name)) | length != 0 + - portgroup_facts.hosts_portgroup_info | length == 1 + - (portgroup_facts.hosts_portgroup_info | + dict2items | map(attribute='value') | flatten | + selectattr('portgroup', 'equalto', wait_for_portgroup_name)) | length != 0 ignore_errors: true register: portgroup_facts diff --git a/linux/deploy_vm/deploy_vm_from_ova.yml b/linux/deploy_vm/deploy_vm_from_ova.yml index 94800632a..e85422232 100644 --- a/linux/deploy_vm/deploy_vm_from_ova.yml +++ b/linux/deploy_vm/deploy_vm_from_ova.yml @@ -63,6 +63,9 @@ - name: "Get VM info" include_tasks: ../../common/vm_get_vm_info.yml +- name: "Get VM's primary network adapter MAC address" + include_tasks: ../../common/vm_wait_primary_nic_mac.yml + - name: "Try to get OS type from guest info" include_tasks: get_ova_guest_os_type.yml @@ -90,9 +93,6 @@ - name: "Add a serial port for VM" include_tasks: ../../common/vm_add_serial_port.yml -- name: "Get VM's primary network adapter MAC address" - include_tasks: ../../common/vm_wait_primary_nic_mac.yml - - name: "Reconfigure VM with cloud-init" include_tasks: reconfigure_vm_with_cloudinit.yml when: ova_guest_os_type in ['photon', 'ubuntu', 'amazon'] diff --git a/linux/guest_customization/check_dns.yml b/linux/guest_customization/check_dns.yml index ecb7ac9cb..f5cf03e2d 100644 --- a/linux/guest_customization/check_dns.yml +++ b/linux/guest_customization/check_dns.yml @@ -1,91 +1,105 @@ # Copyright 2021-2023 VMware, Inc. # SPDX-License-Identifier: BSD-2-Clause --- -- name: "Initilize DNS configuration check results" +- name: "Initilize facts of guest OS resolvectl command and DNS configuration check results" ansible.builtin.set_fact: + guest_resolvectl_cmd: "/usr/bin/resolvectl" dns_servers_success: false dns_suffix_success: false guest_dns_servers: [] guest_dns_search: [] -# Try to use command 'resolvectl' to get DNS status -- include_tasks: ../../common/vm_shell_in_guest.yml +- name: "Test '{{ guest_resolvectl_cmd }} status' command in guest OS" + include_tasks: ../../common/vm_shell_in_guest.yml vars: - vm_shell_cmd: "/usr/bin/resolvectl" + vm_shell_cmd: "{{ guest_resolvectl_cmd }}" vm_shell_args: "status" vm_shell_out: "/tmp/resolvectl_status.txt" -- name: "Set fact of the 'resolvectl status' command result" + +- name: "Set fact of '{{ guest_resolvectl_cmd }} status' command result" ansible.builtin.set_fact: - resolvectl_status_result: "{{ false if vm_shell_result.exit_code is undefined or vm_shell_result.exit_code != 0 else true }}" + resolvectl_status_result: "{{ vm_shell_result.exit_code is defined and vm_shell_result.exit_code == 0 }}" -# If 'resolvectl' command succeed -- block: - - include_tasks: ../../common/vm_guest_file_operation.yml +# Guest OS has /usr/bin/resolvectl command +- name: "Get DNS servers and search domains for {{ guest_os_ansible_distribution }}" + when: resolvectl_status_result + block: + - name: "Fetch the output file of '{{ guest_resolvectl_cmd }} status'" + include_tasks: ../../common/vm_guest_file_operation.yml vars: operation: "fetch_file" src_path: "/tmp/resolvectl_status.txt" dest_path: "{{ current_test_log_folder }}/resolvectl_status.txt" - # Run command 'resolvectl dns' to get DNS servers - - include_tasks: ../../common/vm_shell_in_guest.yml + - name: "Run command '{{ guest_resolvectl_cmd }} dns' to get DNS servers" + include_tasks: ../../common/vm_shell_in_guest.yml vars: - vm_shell_cmd: "/usr/bin/resolvectl" + vm_shell_cmd: "{{ guest_resolvectl_cmd }}" vm_shell_args: "dns" vm_shell_out: "/tmp/resolvectl_dns.txt" - - name: "Set fact of the 'resolvectl dns' command result" + - name: "Set fact of '{{ guest_resolvectl_cmd }} dns' command result" ansible.builtin.set_fact: - resolvectl_dns_result: "{{ false if vm_shell_result.exit_code is undefined or vm_shell_result.exit_code != 0 else true }}" + resolvectl_dns_result: "{{ vm_shell_result.exit_code is defined and vm_shell_result.exit_code == 0 }}" - - block: - - include_tasks: ../../common/vm_guest_file_operation.yml + - name: "Get DNS servers for {{ guest_os_ansible_distribution }}" + when: resolvectl_dns_result + block: + - name: "Fetch the output file of '{{ guest_resolvectl_cmd }} dns'" + include_tasks: ../../common/vm_guest_file_operation.yml vars: operation: "fetch_file" src_path: "/tmp/resolvectl_dns.txt" dest_path: "{{ current_test_log_folder }}/resolvectl_dns.txt" - - name: "Set fact of guest DNS servers" + - name: "Set fact of DNS servers for {{ guest_os_ansible_distribution }}" ansible.builtin.set_fact: - guest_dns_servers: "{{ lookup('file', current_test_log_folder ~ '/resolvectl_dns.txt').split('\n') | select('match', '^link', ignorecase=True) | regex_findall('\\b(?:[0-9]{1,3}\\.){3}[0-9]{1,3}\\b') }}" - when: resolvectl_dns_result | bool + guest_dns_servers: "{{ lookup('file', current_test_log_folder ~ '/resolvectl_dns.txt') | regex_search('link[^:]*:[\\d\\s\\.]+', ignorecase=True) | regex_findall('\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b') }}" - # Run command 'resolvectl domain' to get DNS servers - - include_tasks: ../../common/vm_shell_in_guest.yml + - name: "Run command '{{ guest_resolvectl_cmd }} domain' to get DNS search domains" + include_tasks: ../../common/vm_shell_in_guest.yml vars: - vm_shell_cmd: "/usr/bin/resolvectl" + vm_shell_cmd: "{{ guest_resolvectl_cmd }}" vm_shell_args: "domain" vm_shell_out: "/tmp/resolvectl_domain.txt" - - name: "Set fact of the 'resolvectl domain' command result" + - name: "Set fact of '{{ guest_resolvectl_cmd }} domain' command result" ansible.builtin.set_fact: - resolvectl_domain_result: "{{ false if vm_shell_result.exit_code is undefined or vm_shell_result.exit_code != 0 else true }}" + resolvectl_domain_result: "{{ vm_shell_result.exit_code is defined and vm_shell_result.exit_code == 0 }}" - - block: - - include_tasks: ../../common/vm_guest_file_operation.yml + - name: "Get DNS search domains for {{ guest_os_ansible_distribution }}" + when: resolvectl_domain_result + block: + - name: "Fetch the output file of '{{ guest_resolvectl_cmd }} domain'" + include_tasks: ../../common/vm_guest_file_operation.yml vars: operation: "fetch_file" src_path: "/tmp/resolvectl_domain.txt" dest_path: "{{ current_test_log_folder }}/resolvectl_domain.txt" - - name: "Set fact of guest DNS searching domains" + - name: "Set fact of DNS search domains for {{ guest_os_ansible_distribution }}" ansible.builtin.set_fact: - guest_dns_search: "{{ lookup('file', current_test_log_folder ~ '/resolvectl_domain.txt').split('\n') | select('match', '^link', ignorecase=True) | regex_findall('\\b(?:[a-zA-Z0-9-]{1,}\\.){1,}[a-zA-Z0-9-]{1,}\\b') }}" - when: resolvectl_domain_result | bool - when: resolvectl_status_result + guest_dns_search: "{{ lookup('file', current_test_log_folder ~ '/resolvectl_domain.txt') | regex_search('link[^:]*:[^:]+', ignorecase=True) | regex_findall('\\b(?:[\\w-]{1,}\\.){1,}[\\w-]{1,}\\b') }}" # If 'resolvectl' command failed and guest OS is not Ubuntu # Try to get DNS servers and DNS search domains from /etc/resolv.conf -- block: - # In SLES 15, /etc/resolv.conf is a symbolic link. But after cloud-initGOSC, +- name: "Get DNS servers and search domains for {{ guest_os_ansible_distribution }}" + when: + - not resolvectl_status_result + - guest_os_ansible_distribution != 'Ubuntu' + block: + # In SLES 15, /etc/resolv.conf is a symbolic link. But after cloud-init GOSC, # it will be overwritten to a file. Here we get content in /etc/resolv.conf # in case the file is overwritten - - include_tasks: ../../common/vm_shell_in_guest.yml + - name: "Dump content of /etc/resolv.conf" + include_tasks: ../../common/vm_shell_in_guest.yml vars: vm_shell_cmd: "/usr/bin/cat" vm_shell_args: "/etc/resolv.conf" vm_shell_out: "/tmp/resolv.conf" - - include_tasks: ../../common/vm_guest_file_operation.yml + - name: "Fetch the copy file of /etc/resolv.conf" + include_tasks: ../../common/vm_guest_file_operation.yml vars: operation: "fetch_file" src_path: "/tmp/resolv.conf" @@ -95,26 +109,32 @@ ansible.builtin.set_fact: guest_resolv_conf: "{{ lookup('file', current_test_log_folder ~ '/etc/resolv.conf').split('\n') }}" - - name: "Get guest DNS servers and search domains from /etc/resolv.conf" + - name: "Get DNS servers and search domains from /etc/resolv.conf" ansible.builtin.set_fact: guest_dns_servers: "{{ guest_resolv_conf | select('match', '^nameserver\\s*') | map('regex_replace', 'nameserver\\s*', '') }}" guest_dns_search: "{{ guest_resolv_conf | select('match', '^search\\s*') | join('\\n') | regex_replace('^search\\s*', '') | split() | map('regex_replace', '\\.$', '') }}" - when: - - not resolvectl_status_result - - guest_os_ansible_distribution != 'Ubuntu' # If 'resolvectl' command failed and guest OS is Ubuntu # For Ubuntu 18.04.4 or later guest, try to use systemd-resolve command -- block: - - include_tasks: ../../common/vm_shell_in_guest.yml +- name: "Get DNS servers and search domains for {{ guest_os_ansible_distribution }}" + when: + - not resolvectl_status_result + - guest_os_ansible_distribution == 'Ubuntu' + block: + - name: "Run command '/usr/bin/systemd-resolve --status' to get DNS servers and search domains" + include_tasks: ../../common/vm_shell_in_guest.yml vars: vm_shell_cmd: "/usr/bin/systemd-resolve" vm_shell_args: "--status" vm_shell_out: "/tmp/systemd_resolve_status.txt" - - name: "Set fact of the systemd-resolve command result" + + - name: "Set fact of '/usr/bin/systemd-resolve --status' command result" ansible.builtin.set_fact: - systemd_resolve_result: "{{ false if vm_shell_result.exit_code is undefined or vm_shell_result.exit_code != 0 else true }}" - - block: + systemd_resolve_result: "{{ vm_shell_result.exit_code is defined and vm_shell_result.exit_code == 0 }}" + + - name: "Get DNS servers and search domains from systemd-resolve status" + when: systemd_resolve_result + block: - include_tasks: ../../common/vm_guest_file_operation.yml vars: operation: "fetch_file" @@ -129,10 +149,6 @@ ansible.builtin.set_fact: guest_dns_servers: "{{ guest_resolve_status | regex_search('DNS Servers:\\s*(([0-9]+\\.){3}([0-9]+)\\n?)+') | regex_replace('DNS Servers:\\s*', '') | split('\\n') | reject('equalto', '') }}" guest_dns_search: "{{ guest_resolve_status | regex_search('DNS Domain:\\s*(([0-9a-zA-Z_\\-]+\\.){1,}([0-9a-zA-Z_\\-]+)\\n?)+') | regex_replace('DNS Domain:\\s*', '') | split('\\n') | reject('equalto', '') }}" - when: systemd_resolve_result - when: - - not resolvectl_status_result - - guest_os_ansible_distribution == 'Ubuntu' - name: "Set fact of the expected DNS servers after GOSC" ansible.builtin.set_fact: @@ -143,24 +159,28 @@ # Please refer to this issue: https://bugs.launchpad.net/ubuntu/+source/cloud-init/+bug/1892447 # File: https://github.com/canonical/cloud-init/blob/master/cloudinit/distros/parsers/resolv_conf.py # -- block: +- name: "Get DNS servers and search domains for {{ guest_os_ansible_distribution }}" + when: + - dns_servers_before_gosc is defined + - enable_cloudinit_gosc is defined and enable_cloudinit_gosc + - linux_gosc_spec['dns_servers'] | difference(guest_dns_servers) | length != 0 + block: - name: "Set fact of the combination of DNS servers list before GOSC and the configured list" ansible.builtin.set_fact: tmp_dns_server_list: "{{ (dns_servers_before_gosc + linux_gosc_spec['dns_servers']) | unique }}" + - name: "Set fact of the expected DNS servers" ansible.builtin.set_fact: expected_dns_servers: "{{ dns_servers_before_gosc }}" when: tmp_dns_server_list | length == dns_servers_before_gosc | length + - name: "Set fact of the expected DNS servers" ansible.builtin.set_fact: expected_dns_servers: "{{ tmp_dns_server_list[:3] if tmp_dns_server_list | length > 3 else tmp_dns_server_list }}" when: tmp_dns_server_list | length > dns_servers_before_gosc | length - when: - - dns_servers_before_gosc is defined - - enable_cloudinit_gosc is defined and enable_cloudinit_gosc - - linux_gosc_spec['dns_servers'] | difference(guest_dns_servers) | length != 0 -- ansible.builtin.debug: +- name: "Display the expected and actual DNS servers" + ansible.builtin.debug: msg: - "The expected DNS servers: {{ expected_dns_servers }}" - "The actual DNS servers got in guest: {{ guest_dns_servers }}" @@ -169,27 +189,32 @@ - name: "Check guest DNS servers are customized" ansible.builtin.set_fact: dns_servers_success: "{{ expected_dns_servers | difference(guest_dns_servers) | length == 0 }}" + - name: "Print DNS servers check result" ansible.builtin.debug: var=dns_servers_success -- include_tasks: set_gosc_validation_result.yml +- name: "Set GOSC validation result for checking DNS servers" + include_tasks: set_gosc_validation_result.yml vars: gosc_check_item: "dns_servers_success" gosc_check_error_msg: "VM DNS servers are {{ guest_dns_servers }}, not expected DNS servers {{ linux_gosc_spec['dns_servers'] }}" # Check guest DNS search domains -- ansible.builtin.debug: +- name: "Display the expected and actual DNS search domains" + ansible.builtin.debug: msg: - - "The expected search domains: {{ linux_gosc_spec['dns_suffix'] }}" + - "The expected DNS search domains: {{ linux_gosc_spec['dns_suffix'] }}" - "The actual DNS search domains got in guest: {{ guest_dns_search }}" - name: "Check DNS search domains are customized" ansible.builtin.set_fact: dns_suffix_success: "{{ linux_gosc_spec['dns_suffix'] | difference(guest_dns_search) | length == 0 }}" + - name: "Print DNS suffix check result" ansible.builtin.debug: var=dns_suffix_success -- include_tasks: set_gosc_validation_result.yml +- name: "Set GOSC validation result for checking DNS search domains" + include_tasks: set_gosc_validation_result.yml vars: gosc_check_item: "dns_suffix_success" - gosc_check_error_msg: "VM DNS domain search domains are {{ guest_dns_search }} not expected search domains {{ linux_gosc_spec['dns_suffix'] }}" + gosc_check_error_msg: "VM DNS domain search domains are {{ guest_dns_search }}, not expected search domains {{ linux_gosc_spec['dns_suffix'] }}"