ansible-collections / community.vmware

Ansible Collection for VMware
GNU General Public License v3.0
348 stars 339 forks source link

VLAN is set to 0 when migrating a VMKernel port to a VSS port group #1297

Closed mpl241 closed 2 years ago

mpl241 commented 2 years ago
SUMMARY

When using vmware_migrate_vmk to migrate a VMKernel port from a DVS to a VSS port group, the resulting port group on the VSS is set to VLAN 0. There is no attribute to vmware_migrate_vmk to set the VLAN.

I think the code where the VLAN is set to 0 is on line 133 of vmware_migrate_vmk.py: https://github.com/ansible-collections/community.vmware/blob/1ee484fe3f116c305d8871f80aaf5a30ecdf0e74/plugins/modules/vmware_migrate_vmk.py#L128-L136

ISSUE TYPE
COMPONENT NAME

community.vmware.vmware_migrate_vmk

ANSIBLE VERSION
ansible 2.9.27
  config file = /home/REDACTED/.ansible.cfg
  configured module search path = ['/home/REDACTED/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.6/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.6.8 (default, Mar 25 2022, 11:15:52) [GCC 8.5.0 20210514 (Red Hat 8.5.0-10)]
COLLECTION VERSION
$ grep version ~/.ansible/collections/ansible_collections/community/vmware/MANIFEST.json 
  "version": "2.2.0",
CONFIGURATION
ANSIBLE_PIPELINING(/home/REDACTED/.ansible.cfg) = True
ANSIBLE_SSH_ARGS(/home/REDACTED/.ansible.cfg) = -C -o ControlMaster=auto -o ControlPersist=60s
CACHE_PLUGIN(/home/REDACTED/.ansible.cfg) = jsonfile
CACHE_PLUGIN_CONNECTION(/home/REDACTED/.ansible.cfg) = ~/.ansible/fact-cache
CACHE_PLUGIN_TIMEOUT(/home/REDACTED/.ansible.cfg) = 3600
DEFAULT_LOG_PATH(env: ANSIBLE_LOG_PATH) = /home/REDACTED/ansible.log
GALAXY_SERVER_LIST(/home/REDACTED/.ansible.cfg) = [REDACTED_ansible_galaxy']
INVENTORY_CACHE_ENABLED(/home/REDACTED/.ansible.cfg) = True
INVENTORY_CACHE_PLUGIN(/home/REDACTED/.ansible.cfg) = jsonfile
INVENTORY_CACHE_PLUGIN_CONNECTION(/home/REDACTED/.ansible.cfg) = ~/.ansible/inventory-cache
INVENTORY_CACHE_TIMEOUT(/home/REDACTED/.ansible.cfg) = 3600
OS / ENVIRONMENT
$ cat /etc/os-release 
NAME="CentOS Stream"
VERSION="8"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="8"
PLATFORM_ID="platform:el8"
PRETTY_NAME="CentOS Stream 8"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:8"
HOME_URL="https://centos.org/"
BUG_REPORT_URL="https://bugzilla.redhat.com/"
REDHAT_SUPPORT_PRODUCT="Red Hat Enterprise Linux 8"
REDHAT_SUPPORT_PRODUCT_VERSION="CentOS Stream"
    "about_info": {
        "about_info": {
            "api_type": "VirtualCenter",
            "api_version": "6.7.3",
            "build": "19299595",
            "instance_uuid": "REDACTED",
            "license_product_name": "VMware VirtualCenter Server",
            "license_product_version": "6.0",
            "locale_build": "000",
            "locale_version": "INTL",
            "os_type": "linux-x64",
            "product_full_name": "VMware vCenter Server 6.7.0 build-19299595",
            "product_line_id": "vpx",
            "product_name": "VMware vCenter Server",
            "vendor": "VMware, Inc.",
            "version": "6.7.0"
        },
STEPS TO REPRODUCE

Using a (not so) minimal playbook to migrate a VMKernel port from a DVS to a VSS, I can demonstrate the VLAN is not set correctly.

---
- hosts: all
  connection: local
  become: false
  gather_facts: false
  vars:
    current_portgroup: vds1-vlan-203
    current_switch: vds1
    datacenter: ExampleDC
    device: vmk1
    migrate_portgroup: vswitch0-vlan-203
    migrate_switch: vSwitch0

  tasks:
  - name: get VMKernel interface information
    community.vmware.vmware_vmkernel_info:
      hostname: "{{ vcenter_hostname }}"
      username: "{{ vcenter_username }}"
      password: "{{ vcenter_password }}"
      esxi_hostname: "{{ esxi_hostname }}"
    register: vmkernel_info
    delegate_to: localhost
    tags: always

  - name: display VMkernel interface information
    debug:
      msg: "{{ vmkernel_info.host_vmk_info[inventory_hostname] | selectattr('device', 'equalto', device) | list }}"
    delegate_to: localhost
    tags: always

  - name: get portgroup information
    community.vmware.vmware_dvs_portgroup_info:
      hostname: "{{ vcenter_hostname }}"
      username: "{{ vcenter_username }}"
      password: "{{ vcenter_password }}"
      datacenter: "{{ datacenter }}"
      dvswitch: "{{ current_switch }}"
      show_mac_learning: false
      show_network_policy: false
      show_port_policy: false
      show_teaming_policy: false
      show_uplinks: false
      show_vlan_info: true
    register: dvs_portgroup_info
    delegate_to: localhost
    tags: always

  - name: display portgroup information
    debug:
      msg: "{{ dvs_portgroup_info.dvs_portgroup_info[current_switch] | selectattr('portgroup_name', 'equalto', current_portgroup) | map(attribute='vlan_info') | list }}"
    delegate_to: localhost
    tags: always

  - name: migrate VMKernel interface
    community.vmware.vmware_migrate_vmk:
      hostname: "{{ vcenter_hostname }}"
      username: "{{ vcenter_username }}"
      password: "{{ vcenter_password }}"
      esxi_hostname: "{{ esxi_hostname }}"
      current_portgroup_name: "{{ current_portgroup }}"
      current_switch_name: "{{ current_switch }}"
      device: "{{ device }}"
      migrate_portgroup_name: "{{ migrate_portgroup }}"
      migrate_switch_name: "{{ migrate_switch }}"
    delegate_to: localhost
    tags:
      - never
      - migrate

  - name: get VMKernel interface information
    community.vmware.vmware_vmkernel_info:
      hostname: "{{ vcenter_hostname }}"
      username: "{{ vcenter_username }}"
      password: "{{ vcenter_password }}"
      esxi_hostname: "{{ esxi_hostname }}"
    register: vmkernel_info
    delegate_to: localhost
    tags: always

  - name: display VMkernel interface information
    debug:
      msg: "{{ vmkernel_info.host_vmk_info[inventory_hostname] | selectattr('device', 'equalto', device) | list }}"
    delegate_to: localhost
    tags: always

  - name: get portgroup information
    community.vmware.vmware_portgroup_info:
      hostname: "{{ vcenter_hostname }}"
      username: "{{ vcenter_username }}"
      password: "{{ vcenter_password }}"
      esxi_hostname: "{{ esxi_hostname }}"
    register: portgroup_info
    delegate_to: localhost
    tags: always

  - name: display VMkernel interface information
    debug:
      msg: "{{ portgroup_info.hosts_portgroup_info[inventory_hostname] | selectattr('portgroup', 'equalto', migrate_portgroup) | list }}"
    delegate_to: localhost
    tags: always
EXPECTED RESULTS

The VLAN_should be preserved from the old port group to the new port group.

ACTUAL RESULTS

The VLAN is set to 0 on the target port group.

$ ansible-playbook -i inventory migrate_vmk_to_vss.yml --ask-vault-pass -l esx.example.com -t migrate
Vault password: 

PLAY [all] *********************************************************************************************************************************************************************************************************

TASK [get VMKernel interface information] **************************************************************************************************************************************************************************
ok: [esx.example.com -> localhost]

TASK [display VMkernel interface information] **********************************************************************************************************************************************************************
ok: [esx.example.com -> localhost] => {
    "msg": [
        {
            "device": "vmk1",
            "dhcp": false,
            "enable_ft": false,
            "enable_management": false,
            "enable_vmotion": true,
            "enable_vsan": false,
            "ipv4_address": "10.xxx.xxx.50",
            "ipv4_subnet_mask": "255.255.252.0",
            "key": "key-vim.host.VirtualNic-vmk1",
            "mac": "00:50:56:xx:xx:xx",
            "mtu": 1500,
            "portgroup": "",
            "stack": "defaultTcpipStack"
        }
    ]
}

TASK [get portgroup information] ***********************************************************************************************************************************************************************************
ok: [esx.example.com -> localhost]

TASK [display portgroup information] *******************************************************************************************************************************************************************************
ok: [esx.example.com -> localhost] => {
    "msg": [
        {
            "pvlan": false,
            "trunk": false,
            "vlan_id": "203"
        }
    ]
}

TASK [migrate VMKernel interface] **********************************************************************************************************************************************************************************
changed: [esx.example.com -> localhost]

TASK [get VMKernel interface information] **************************************************************************************************************************************************************************
ok: [esx.example.com -> localhost]

TASK [display VMkernel interface information] **********************************************************************************************************************************************************************
ok: [esx.example.com -> localhost] => {
    "msg": [
        {
            "device": "vmk1",
            "dhcp": false,
            "enable_ft": false,
            "enable_management": false,
            "enable_vmotion": true,
            "enable_vsan": false,
            "ipv4_address": "10.xx.xx.50",
            "ipv4_subnet_mask": "255.255.252.0",
            "key": "key-vim.host.VirtualNic-vmk1",
            "mac": "00:50:56:xx:xx:xx",
            "mtu": 1500,
            "portgroup": "vswitch0-vlan-203",
            "stack": "defaultTcpipStack"
        }
    ]
}

TASK [get portgroup information] ***********************************************************************************************************************************************************************************
ok: [esx.example.com -> localhost]

TASK [display VMkernel interface information] **********************************************************************************************************************************************************************
ok: [esx.example.com -> localhost] => {
    "msg": [
        {
            "portgroup": "vswitch0-vlan-203",
            "vlan_id": 0,
            "vswitch": "vSwitch0"
        }
    ]
}

PLAY RECAP *********************************************************************************************************************************************************************************************************
esx.example.com         : ok=9    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
ansibullbot commented 2 years ago

Files identified in the description: None

If these files are inaccurate, please update the component name section of the description or use the !component bot command.

click here for bot help

mariolenz commented 2 years ago

When using vmware_migrate_vmk to migrate a VMKernel port from a DVS to a VSS port group, the resulting port group on the VSS is set to VLAN 0. There is no attribute to vmware_migrate_vmk to set the VLAN.

Yes, I think this was overlooked simply because migrating from VSS to DVS is the more common use case.

EXPECTED RESULTS

The VLAN should be preserved from the old port group to the new port group.

Yes... and no. The correct VLAN on the destination VSS might be (unusal, but possible) different from the DVS. And, of course, the uplinks of the VSS might be native ports, that is there are no VLANs tagged at all. So I think we need to have both, a way to keep the VLAN from the source portgroup and a way to set it explicitelly.

What do you think?

mpl241 commented 2 years ago

Several years ago, I write a PowerCLI script to migrate a VMKernel Port from a DVS to a VSS. I modeled the script after a code from a blog post by William Lam. If I recall correctly, on a VSS, a port group used by a VMKernel port is not the same as a virtual machine port group (vmnic port group verses VM port group), so when adding or migrating a VMKernel port to a VSS, a new port group is always created. When creating the vmnic port group, the default VLAN is 0. The VLAN is not configurable when connecting a VMKernel port to a DVS port group because an existing virtual machine port group is required, which already has the VLAN specified.

The PowerCLI script I wrote to migrate a VMKernel port to a VSS requires a VLAN number, and IIRC, is a requirement of the API and/or SDK. So, I think the correct way to fix the vmware.vmware_migrate_vmk module is to add a VLAN attribute so it can be set manually. The default can be 0 if not specified.

If the vmware.vmware_migrate_vmk module is able to also determine the VLAN from the source DVS port group, then I would consider it a nice bonus to the module functionality, but I don't think it's required based on my past experience with the equivalent PowerCLI commandlets.

mariolenz commented 2 years ago

If the vmware.vmware_migrate_vmk module is able to also determine the VLAN from the source DVS port group, then I would consider it a nice bonus to the module functionality, but I don't think it's required based on my past experience with the equivalent PowerCLI commandlets.

Great! I don't think I'll find the time to implement getting the VLAN from the source DVS port group. But I did implement a migrate_vlan_id parameter to set the destination VLAN. Do you think you could test PR #1305?

mkdir -p  ~/.ansible/collections/ansible_collections/community
git clone https://github.com/ansible-collections/community.vmware ~/.ansible/collections/ansible_collections/community/vmware
cd ~/.ansible/collections/ansible_collections/community/vmware
git fetch origin pull/1305/head:issue1297
git checkout issue1297
mpl241 commented 2 years ago

The VLAN was set correctly on the VSS port group when using the migrate_vlan_id attribute for vmware_migrate_vmk. I added migrate_vlan_id to the vars section and modified the vmware_migrate_vmk task in the playbook I shared earlier. You can see from the output the VLAN is set correctly.

  vars:
    migrate_vlan_id: 203
    - name: migrate VMKernel interface
      community.vmware.vmware_migrate_vmk:
        hostname: "{{ vcenter_hostname }}"
        username: "{{ vcenter_username }}"
        password: "{{ vcenter_password }}"
        esxi_hostname: "{{ esxi_hostname }}"
        current_portgroup_name: "{{ current_portgroup }}"
        current_switch_name: "{{ current_switch }}"
        device: "{{ device }}"
        migrate_portgroup_name: "{{ migrate_portgroup }}"
        migrate_switch_name: "{{ migrate_switch }}"
        migrate_vlan_id: "{{ migrate_vlan_id | default(omit) | int }}"
      delegate_to: localhost
      tags:
        - never
        - migrate
$ ansible-playbook -i inventory migrate_vmk_to_vss.yml --ask-vault-pass -l esx.example.com -t migrate
Vault password: 

PLAY [all] *********************************************************************************************************************************************************************************************************

TASK [get VMKernel interface information] **************************************************************************************************************************************************************************
ok: [esx.example.com -> localhost]

TASK [display VMkernel interface information] **********************************************************************************************************************************************************************
ok: [esx.example.com -> localhost] => {
    "msg": [
        {
            "device": "vmk1",
            "dhcp": false,
            "enable_ft": false,
            "enable_management": false,
            "enable_vmotion": true,
            "enable_vsan": false,
            "ipv4_address": "10.xxx.xxx.50",
            "ipv4_subnet_mask": "255.255.252.0",
            "key": "key-vim.host.VirtualNic-vmk1",
            "mac": "00:50:56:xx:xx:xx",
            "mtu": 1500,
            "portgroup": "",
            "stack": "defaultTcpipStack"
        }
    ]
}

TASK [get portgroup information] ***********************************************************************************************************************************************************************************
ok: [esx.example.com -> localhost]

TASK [display portgroup information] *******************************************************************************************************************************************************************************
ok: [esx.example.com -> localhost] => {
    "msg": [
        {
            "pvlan": false,
            "trunk": false,
            "vlan_id": "203"
        }
    ]
}

TASK [migrate VMKernel interface] **********************************************************************************************************************************************************************************
changed: [esx.example.com -> localhost]

TASK [get VMKernel interface information] **************************************************************************************************************************************************************************
ok: [esx.example.com -> localhost]

TASK [display VMkernel interface information] **********************************************************************************************************************************************************************
ok: [esx.example.com -> localhost] => {
    "msg": [
        {
            "device": "vmk1",
            "dhcp": false,
            "enable_ft": false,
            "enable_management": false,
            "enable_vmotion": true,
            "enable_vsan": false,
            "ipv4_address": "10.xx.xx.50",
            "ipv4_subnet_mask": "255.255.252.0",
            "key": "key-vim.host.VirtualNic-vmk1",
            "mac": "00:50:56:xx:xx:xx",
            "mtu": 1500,
            "portgroup": "vswitch0-vlan-203",
            "stack": "defaultTcpipStack"
        }
    ]
}

TASK [get portgroup information] ***********************************************************************************************************************************************************************************
ok: [esx.example.com -> localhost]

TASK [display VMkernel interface information] **********************************************************************************************************************************************************************
ok: [esx.example.com -> localhost] => {
    "msg": [
        {
            "portgroup": "vswitch0-vlan-203",
            "vlan_id": 203,
            "vswitch": "vSwitch0"
        }
    ]
}

PLAY RECAP *********************************************************************************************************************************************************************************************************
esx.example.com         : ok=9    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Retrieving the VLAN from the DVS port group can be performed in a couple of tasks, but the problem discussed in issue https://github.com/ansible-collections/community.vmware/issues/994 makes it less dynamic since vmware_vmkernel_info does not return the port group name when the VMKernel port is on a DVS.

Thanks for the quick solution to this issue, I appreciate your effort on this project! 🙌

mariolenz commented 2 years ago

Thanks for testing @mpl241!