Repository: ansible/ansible

Issue:
vmware_guest does not allow changing vNIC networks
<!---

-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Bug Report


##### COMPONENT NAME
<!---   

-->
vmware_guest

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
ansible 2.3.0
  config file = /home/jenkins/.ansible.cfg
  configured module search path = Default w/o overrides
```

##### CONFIGURATION
<!---

-->

##### OS / ENVIRONMENT
<!---
-->
Ansible and guest:
Red Hat Enterprise Linux Server release 7.2 (Maipo)

##### SUMMARY
<!--- 
-->
Vsphere_guest allows changing the network a vNIC is connected to but this does not work in vmware_guest.

##### STEPS TO REPRODUCE
<!---

-->
Running the following play should connect the vNICs to the specified networks:
<!--- Paste example playbooks or commands between quotes below -->
```yaml
- name: VMWARE_GUEST | connect vNICs to correct network
  connection: local
  vmware_guest:
    hostname: "{{ vcenter_hostname }}"
    username:  "{{ vcenter_username }}"
    password: "{{ vcenter_password }}"
    name: "{{ vm_name }}"
    folder: "{{ vm_folder }}"
    datacenter: "{{ esxi_datacenter }}"
    cluster: "{{ vcenter_cluster }}"
    validate_certs: false
    state: present
    networks:
    - name: "{{ nic1_network }}"
      device_type: vmxnet3
    - name: "{{ nic2_network }}"
      device_type:  vmxnet3
  register: vm_net_reconfigured
```

I am able to get expected results with the vsphere_guest module with the following play:
```yaml
- name: VSPHERE_GUEST | connect vNICs to correct network
  connection: local
  vsphere_guest:
    vcenter_hostname: "{{ vcenter_hostname }}"
    username:  "{{ vcenter_username }}"
    password: "{{ vcenter_password }}"
    guest: "{{ vm_name }}"
    state: reconfigured
    esxi:
        datacenter: "{{ esxi_datacenter }}"
        hostname: "{{ esxi_hostname }}"
    vm_nic:
        nic1:
            type: vmxnet3
            network: "{{ nic1_network }}"
            network_type: dvs
            state: connected
        nic2:
            type: vmxnet3
            network: "{{ nic2_network }}"
            network_type: dvs
            state: connected
  register: vm_net_reconfigured    
```
<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- 
-->
Expect vNICs to connect correct network. 

##### ACTUAL RESULTS
<!--- 
-->
vNICs stay connected to the network they were connected to prior to running the play. 

<!--- Paste verbatim command output between quotes below -->
The names have been changed to protect the innocent. I've masked some output with "#".
```
changed: [derek-as1] => {
     "changed": true,
     "failed": false,
     "instance": {
         "annotation": "root = redhat",
         "customvalues": {}
         "hw_eth0": {
             "addresstype": "assigned",
             "ipaddresses": [
                 "##.##.##.###",
                 "####::####:####:####:####"
             ],
             "label": "Network adapter 1",
             "macaddress": "##:##:##:##:##:##",
             "macaddress_dash": "##-##-##-##-##-##",
             "summary": "DVSwitch: ## ## ## ## ## ## ## ## ##-## ## ## ## ## ## ## ##"
         },
         "hw_eth1: {
             "addresstype": "assigned",
             "ipaddresses": [
                 "##.##.##.###",
                 "####:###:####:####:####"
             ],
             "label": "Network adapter 2",
             "macaddress": "##:##:##:##:##:##",
             "macaddress_dash": "##-##-##-##-##-##",
             "summary": "DVSwitch: ## ## ## ## ## ## ## ## ##-## ## ## ## ## ## ## ##"
         },
         "hw_guest_full_name": "Red Hat Enterprise Linux 7 (64-bit)",
         "hw_guest_id": "rhel7_64Guest",
         "hw_interfaces": [
             "eth0",
             "eth1",
         ],
         "hw_memtotal_mb": 16384,
         "hw_name": "derek-as1",
         "hw_power_status": "poweredOn",
         "hw_processor_count": 8,
         "hw_product_uuid": "########-####-####-####-############",
         "ipv4": "##.##.##.##",
         "ipv6": "####::####:####:####:####",
         "module_hw": true
    },
    "invocation": {
         "module_args": {
             "annotation": null,
             "cluster": "####"
             "customization": {},
             "customvalues": [],
             "datacenter": "####",
             "disk": [],
             "esxi_hostname": null,
             "hardware": {},
             "hostname": "######.####.###",
             "is_template": false,
             "name": "derek-as1"
             "name_match": "first",
             "networks": [
                 {
                      "device_type": "vmxnet3",
                      "name": "VM_network1"
                 },
                 {
                      "device_type": "vmxnet3",
                      "name": "VM_network2"
                 },
             ],
             "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
             "resource_pool" null,
             "snapshot_op": {},
             "state": "present",
             "template_src" null,
             "username": "########",
             "uuid": null,
             "validate_certs": false,
             "wait_for_ip_address": true
         },
        "module_name": "vmware_guest"
    }
}         
```



Discussion:
cc @jctanner @nerzhul @dav1x
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
If i read the log carefully, module said it's changed, but not in your infrastructure ?

What is your VMWare version ?
That is correct. The module returns a change, but when I check the networks
the vNICs are connected to in vCenter they remain unchanged. We are on
vCenterServer version 6.0.0 Build 3339083. I'd send you some screenshots
but I'm operating on a network not connected to the internet.

We currently switch an existing VM's networks with the vsphere_guest
module, but we'd like to migrate to using the vmware_guest module for VM
actions.

On Fri, Feb 3, 2017 at 8:24 AM, Loïc Blot <notifications@github.com> wrote:

> If i read the log carefully, module said it's changed, but not in your
> infrastructure ?
>
> What is your VMWare version ?
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/ansible/ansible/issues/21011#issuecomment-277258180>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AUMi5LXZqo32uuf7PTi-IIztfE2QBWCNks5rYzicgaJpZM4L2YGe>
> .
>

Okay. I recreated this to a specific use case:
Only affects VDS ports and ONLY on reconfigure cases. 
- If you create a new NIC on the VDS port it works fine. 
- If you have an existing NIC on a vSwitch and move to port group on any vSwitch works fine.

-If you try to move an existing vSwitch port group to a VDS it says its moved but doesnt.
-If you try to move an existing VDS port group to another it says its moved but doesnt.

I'm looking at the code now
The VDS reconfigure fails to set: 

 nic_change_detected = True  

After a change, I added this to my test and it fixed this issue. I did notice that this still doesnt fix the migration from a vSwitch to a VDS. I can open this into another issue.

Resolving patch:
diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest.py b/lib/ansible/modules/cloud/vmware/vmware_guest.py
--- a/lib/ansible/modules/cloud/vmware/vmware_guest.py
+++ b/lib/ansible/modules/cloud/vmware/vmware_guest.py
@@ -801,6 +801,7 @@ def configure_network(self, vm_obj):
                 dvs_port_connection.switchUuid = pg_obj.config.distributedVirtualSwitch.uuid
                 nic.device.backing = vim.vm.device.VirtualEthernetCard.DistributedVirtualPortBackingInfo()
                 nic.device.backing.port = dvs_port_connection
+                nic_change_detected = True
             else:
                 # vSwitch
                 if not isinstance(nic.device.backing, vim.vm.device.VirtualEthernetCard.NetworkBackingInfo):


Test patch: