Skip to content

Commit

Permalink
Set VM primary NIC MAC address at env_setup or deploy_vm (#454)
Browse files Browse the repository at this point in the history
Signed-off-by: Qi Zhang <[email protected]>
  • Loading branch information
keirazhang authored Apr 11, 2023
1 parent 050b361 commit 3449128
Show file tree
Hide file tree
Showing 12 changed files with 141 additions and 268 deletions.
2 changes: 0 additions & 2 deletions common/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@
* vm_remove_network_adapter.yml: Remove network adapter from VM
* vm_configure_network_adapter.yml: Reconfig VM network adapter connection settings
* vm_wait_network_connected.yml: Wait for network adapter to be connected
* vm_test_nic.yml: Check if given network adapter is connectable through ssh
* vm_get_network_facts.yml: Get VM network adapters info
* vm_get_netadapter_number.yml: Get VM network adapters number with different types

Expand Down Expand Up @@ -82,7 +81,6 @@
### Tasks for getting VM IP
* vm_get_ip.yml: Get VM IP address by calling vm_get_ip_from_vmtools.yml
* vm_get_ip_from_vmtools.yml: Get VM IP address from VMware Tools guestinfo
* vm_get_primary_nic.yml: Get VM connectable network adapter MAC/IP address
* vm_get_ip_from_notools.yml: Get VM IP address when there is no VMware Tools installed
* vm_get_world_id.yml: Get VM world ID on ESXi host
* vm_get_ip_esxcli.yml: Get VM IP address on ESXi host by esxcli command
Expand Down
34 changes: 23 additions & 11 deletions common/vm_get_ip.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,42 @@
# SPDX-License-Identifier: BSD-2-Clause
---
# Get VM IP Address using esxcli command or from VMware Tools guestinfo
- name: Initialize VM guest IP address variable
# Parameter:
# vm_primary_nic_mac: The VM's primary network adapter MAC address
# Return:
# vm_guest_ip: The VM's guest IPv4 address
#
- name: "Check vm_primary_nic_mac is set for VM '{{ vm_name }}'"
ansible.builtin.assert:
that:
- vm_primary_nic_mac is defined
- vm_primary_nic_mac
fail_msg: "Parameter 'vm_primary_nic_mac' must be set for getting VM's guest IPv4 address."

- name: "Initialize VM guest IP address variable"
ansible.builtin.set_fact:
vm_guest_ip: ""

# Get VM power status
- include_tasks: vm_get_power_state.yml
- name: "Get VM power status"
include_tasks: vm_get_power_state.yml

# Power on VM when VM power status is not poweredOn
- include_tasks: vm_set_power_state.yml
- name: "Power on VM"
include_tasks: vm_set_power_state.yml
vars:
vm_power_state_set: 'powered-on'
when: vm_power_state_get != "poweredOn"

# Get VMware tools status
- include_tasks: vm_get_vmtools_status.yml
- name: "Get VMware Tools status"
include_tasks: vm_get_vmtools_status.yml

# Get VM IP address when VMware tools is installed
- include_tasks: vm_get_ip_from_vmtools.yml
- name: "Get VM IP address when VMware Tools is running"
include_tasks: vm_get_ip_from_vmtools.yml
when:
- vmtools_is_running is defined
- vmtools_is_running | bool

# Get VM IP address when VMware tools not installed or not get from VMware tools
- include_tasks: vm_get_ip_from_notools.yml
- name: "Get VM IP address when VMware Tools is not installed or not running"
include_tasks: vm_get_ip_from_notools.yml
when: >
(vmtools_is_installed is undefined) or
(not vmtools_is_installed | bool) or
Expand Down
134 changes: 32 additions & 102 deletions common/vm_get_ip_esxcli.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,111 +16,41 @@
- vm_world_id
fail_msg: "Can not get VM IP address by esxcli command if VM world ID is not defined or empty."

- name: "Initialize the fact for finding VM primary network adapter"
- name: "Set facts for getting primary network adapter IPv4 address for VM '{{ vm_name }}'"
ansible.builtin.set_fact:
find_primary_nic: false

- block:
# Wait for network adapters ready after VM power-on/reset
- include_tasks: vm_wait_network_connected.yml

- name: "Initialize the connected network adapter number for VM '{{ vm_name }}'"
ansible.builtin.set_fact:
vm_connected_nic_number: 0

- include_tasks: vm_get_network_facts.yml

- name: "Get connected network adapter number form VM '{{ vm_name }}'"
ansible.builtin.set_fact:
vm_connected_nic_number: "{{ vm_network_adapters | dict2items | selectattr('value.connected', 'equalto', true) | length }}"

- name: "VM '{{ vm_name }}' has {{ vm_connected_nic_number }} network adapter(s) connected"
ansible.builtin.assert:
that:
- vm_connected_nic_number | int >= 1
fail_msg: "Not found connected network adapter on VM '{{ vm_name }}'"

- name: "VM '{{ vm_name }}' has more than one network adapter connected. Need to find the primary NIC."
ansible.builtin.set_fact:
find_primary_nic: true
when: vm_connected_nic_number | int > 1
when: (router_vm_name is undefined) or (vm_name != router_vm_name)

# Deployed router VM can only get 1 valid IP even though it has 2 network adapteres
- block:
- name: "Wait for getting VM '{{ vm_name }}' IP address on ESXi '{{ esxi_hostname }}'"
ansible.builtin.shell: esxcli network vm port list -w '{{ vm_world_id }}' | awk '/IP Address/ {print $3}' | sed '/0.0.0.0/d' | sed '/^169.254./d'
delegate_to: "{{ esxi_hostname }}"
register: get_vm_ip_esxcli
until:
- get_vm_ip_esxcli is defined
- get_vm_ip_esxcli.stdout is defined
- get_vm_ip_esxcli.stdout
retries: "{{ ((vm_get_ip_timeout | default(300) | int) / 5) | int }}"
delay: 5
failed_when: false
changed_when: false

- name: "Set fact of VM guest IP with primary IP"
ansible.builtin.set_fact:
vm_guest_ip: "{% for ip in get_vm_ip_esxcli.stdout_lines %}{% if ip %}{{ ip.strip('\"') }}{% endif %}{% endfor %}"
when: not find_primary_nic

# Wait for target VM's all IP obtained
- block:
- name: "Initialize VM's primary MAC address for VM '{{ vm_name }}'"
ansible.builtin.set_fact:
vm_primary_mac: ""
when: vm_primary_mac is undefined

- name: "Initialize esxcli command for VM '{{ vm_name }}'"
ansible.builtin.set_fact:
esxcli_cmd: "esxcli network vm port list -w '{{ vm_world_id }}' | awk '/MAC Address|IP Address/ {key=$3; getline; print key \",\" $3;}'"

# If vm_primary_mac has been found, we can only wait for the IP of the primary mac
- name: "Set esxcli command with filter of MAC address {{ vm_primary_mac }} for VM '{{ vm_name }}'"
ansible.builtin.set_fact:
esxcli_cmd: "esxcli network vm port list -w '{{ vm_world_id }}' | awk '/MAC Address|IP Address/ {key=$3; getline; print key \",\" $3;}' | grep '{{ vm_primary_mac }}'"
when:
- vm_primary_mac is defined
- vm_primary_mac

- name: "Wait for getting VM '{{ vm_name }}' IP address on ESXi '{{ esxi_hostname }}'"
ansible.builtin.shell: "{{ esxcli_cmd }}"
delegate_to: "{{ esxi_hostname }}"
register: get_vm_ip_esxcli
until:
- get_vm_ip_esxcli is defined
- get_vm_ip_esxcli.stdout is defined
- get_vm_ip_esxcli.stdout
- not "'0.0.0.0' in get_vm_ip_esxcli.stdout"
- not "',169.254.' in get_vm_ip_esxcli.stdout"
retries: "{{ ((vm_get_ip_timeout | default(300) | int) / 5) | int }}"
delay: 5
failed_when: false
changed_when: false

- name: "Set fact of the VM IP info from esxcli command"
ansible.builtin.set_fact:
vm_ip_esxcli: "{{ get_vm_ip_esxcli.stdout_lines }}"
- name: "Print VM IP address got from esxcli command"
ansible.builtin.debug: var=vm_ip_esxcli

- name: "Initialize the fact of VM network interfaces for VM '{{ vm_name }}'"
ansible.builtin.set_fact:
vm_guest_mac_ipv4: {}
- name: "Set the fact of valid MAC address and IP address for VM '{{ vm_name }}'"
ansible.builtin.set_fact:
vm_guest_mac_ipv4: "{{ vm_guest_mac_ipv4 |combine({item.split(',')[0]:item.split(',')[1]}) }}"
when: item.split(',') | length == 2 and item.split(',')[1] != '0.0.0.0'
with_items: "{{ vm_ip_esxcli }}"
vm_guest_mac_ipv4: "{{ {vm_primary_nic_mac: ''} }}"
esxcli_cmd: "esxcli network vm port list -w '{{ vm_world_id }}' | awk '/MAC Address|IP Address/ {key=$3; getline; print key \": \" $3;}' | grep '{{ vm_primary_nic_mac }}'"

- name: "Wait for getting VM '{{ vm_name }}' primary IP address on ESXi '{{ esxi_hostname }}'"
ansible.builtin.shell: "{{ esxcli_cmd }}"
delegate_to: "{{ esxi_hostname }}"
register: get_vm_ip_esxcli
until:
- get_vm_ip_esxcli.stdout is defined
- get_vm_ip_esxcli.stdout
- (get_vm_ip_esxcli.stdout | from_yaml)[vm_primary_nic_mac] is defined
- (get_vm_ip_esxcli.stdout | from_yaml)[vm_primary_nic_mac] != '0.0.0.0'
- (get_vm_ip_esxcli.stdout | from_yaml)[vm_primary_nic_mac] is not match('^169.254.')
retries: "{{ ((vm_get_ip_timeout | default(300) | int) / 5) | int }}"
delay: 5
ignore_errors: true
changed_when: false

- name: "Set the fact of primary MAC address and IP address for VM '{{ vm_name }}'"
ansible.builtin.set_fact:
vm_guest_mac_ipv4: "{{ get_vm_ip_esxcli.stdout | from_yaml }}"
when:
- get_vm_ip_esxcli.stdout is defined
- get_vm_ip_esxcli.stdout
- get_vm_ip_esxcli.stdout | from_yaml
- (get_vm_ip_esxcli.stdout | from_yaml)[vm_primary_nic_mac] is defined

- include_tasks: vm_get_primary_nic.yml
- name: "Print the fact of primary MAC and IPv4 address for VM '{{ vm_name }}'"
ansible.builtin.debug: var=vm_guest_mac_ipv4

- name: "Set fact of VM guest IP with primary IP for VM '{{ vm_name }}'"
ansible.builtin.set_fact:
vm_guest_ip: "{{ vm_primary_ip }}"
when: find_primary_nic is defined and find_primary_nic
- name: "Set fact of VM guest IP with primary IP for VM '{{ vm_name }}'"
ansible.builtin.set_fact:
vm_guest_ip: "{{ vm_guest_mac_ipv4[vm_primary_nic_mac] }}"

- ansible.builtin.debug:
msg: "Get VM '{{ vm_name }}' IP address using esxcli command: {{ vm_guest_ip }}"
35 changes: 27 additions & 8 deletions common/vm_get_ip_from_notools.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
# Copyright 2021-2023 VMware, Inc.
# SPDX-License-Identifier: BSD-2-Clause
---
# Get VM IP address when there is no VMware tools installed in VM
# Get VM IP address when there is no VMware Tools installed in VM
# Parameter:
# vm_primary_nic_mac: The VM's primary network adapter MAC address
# Return:
# vm_guest_ip: The VM's guest IPv4 address
#
- name: "Check vm_primary_nic_mac is set for VM '{{ vm_name }}'"
ansible.builtin.assert:
that:
- vm_primary_nic_mac is defined
- vm_primary_nic_mac
fail_msg: "Parameter 'vm_primary_nic_mac' must be set for getting VM's guest IPv4 address."

- name: "Initialize VM world ID and VM IP address for '{{ vm_name }}'"
ansible.builtin.set_fact:
vm_world_id: ""
Expand All @@ -17,14 +29,20 @@

# When not get vm_world_id and VM original power status is power on,
# power off and power on VM to try again
- block:
- include_tasks: vm_set_power_state.yml
- name: "Reset VM to get VM world ID"
block:
- name: "Power off VM"
include_tasks: vm_set_power_state.yml
vars:
vm_power_state_set: 'powered-off'
- include_tasks: vm_set_power_state.yml

- name: "Power on VM"
include_tasks: vm_set_power_state.yml
vars:
vm_power_state_set: 'powered-on'
- include_tasks: vm_get_world_id.yml

- name: "Get VM word ID after reset"
include_tasks: vm_get_world_id.yml
when: not vm_world_id

# Fail after VM power off and power on still not get vm world ID
Expand All @@ -34,7 +52,8 @@
- vm_world_id
fail_msg: "Failed to get VM world ID after power off and power on VM."

# Get VM IP address via esxcli command by VM world ID
- include_tasks: vm_get_ip_esxcli.yml
- name: Display the VM IP address got via esxcli command
- name: "Get VM IP address via esxcli command by VM world ID"
include_tasks: vm_get_ip_esxcli.yml

- name: "Display the VM IP address got via esxcli command"
ansible.builtin.debug: var=vm_guest_ip
35 changes: 20 additions & 15 deletions common/vm_get_ip_from_vmtools.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
# Copyright 2021-2023 VMware, Inc.
# SPDX-License-Identifier: BSD-2-Clause
---
# Get VM IPv4 address through VMware Tools while VM is powered on
# Get VM IP address from VM's guest info collected by VMware Tools
# Parameter:
# vm_primary_nic_mac: The VM's primary network adapter MAC address
# Return:
# vm_guest_ip: The VM's guest IPv4 address
#
- name: "Check vm_primary_nic_mac is set for VM '{{ vm_name }}'"
ansible.builtin.assert:
that:
- vm_primary_nic_mac is defined
- vm_primary_nic_mac
fail_msg: "Parameter 'vm_primary_nic_mac' must be set for getting VM's guest IPv4 address."

- name: "Initialize VM guest IP/IP list variables"
ansible.builtin.set_fact:
vm_guest_ip: ""
vm_guest_all_ip: []
vm_guest_mac_ipv4: {}

- name: "Initialize VM's primary MAC address"
ansible.builtin.set_fact:
vm_primary_mac: ""
when: vm_primary_mac is undefined

- name: "Wait for VM's guest IP address"
include_tasks: vm_wait_guest_ip.yml

Expand All @@ -38,17 +45,15 @@
- item.ipAddress | ansible.utils.ipv4 | length == 1
with_items: "{{ vm_guest_net }}"

# Get VM primary NIC
- name: "Get VM primary network adapter by testing connection"
include_tasks: vm_get_primary_nic.yml
- name: "Print the fact of MAC and IPv4 addresses for VM '{{ vm_name }}'"
ansible.builtin.debug: var=vm_guest_mac_ipv4

# If VM only has 1 IP, vm_primary_ip should be equal to vm_guest_ip
# If VM has more than 1 IP, the IP in guest info might not be able to connected,
# then we need to update it with vm_primary_ip because vm_primary_ip is the connectable IP.
- name: "Set fact of VM guest IP with primary IP"
- name: "Set fact of VM guest IPv4 address with primary network adapter's IPv4 address"
ansible.builtin.set_fact:
vm_guest_ip: "{{ vm_primary_ip }}"
when: vm_guest_ip != vm_primary_ip
vm_guest_ip: "{{ vm_guest_mac_ipv4[vm_primary_nic_mac] }}"
when:
- vm_guest_mac_ipv4[vm_primary_nic_mac] is defined
- vm_guest_mac_ipv4[vm_primary_nic_mac]

- name: "Display VM's guest IP addresses retrieved by VMware Tools"
ansible.builtin.debug:
Expand Down
62 changes: 0 additions & 62 deletions common/vm_get_primary_nic.yml

This file was deleted.

Loading

0 comments on commit 3449128

Please sign in to comment.