vmware_guest: networks definition as a list (#19857)
* vmware_guest: networks definition as a list Currently the networks definition is a dict, with the network range as key. This is problematic if the network information is coming from other sources. This patch turns the networks definition into a list. This fixes #19222. * Remove the option to provide either netmask or network It is more concise if there's only one way to configure it. So provide both `ip` and `network`. (I also re-indented a section due to a useless check) * Fix bugs reported by @dav1x Thanks !pull/4420/head
parent
20df62ab31
commit
439ef46898
|
@ -140,9 +140,11 @@ options:
|
||||||
version_added: "2.3"
|
version_added: "2.3"
|
||||||
networks:
|
networks:
|
||||||
description:
|
description:
|
||||||
- Network to use should include VM network name or VLAN, ip and gateway
|
- Network to use should include C(name) or C(vlan) entry
|
||||||
- Add an optional field C(mac) to customize mac address
|
- Add an optional C(ip) and C(netmask) for network configuration
|
||||||
- Add an optional field C(domain) to configure a different dns domain on windows network interfaces
|
- Add an optional C(gateway) entry to configure a gateway
|
||||||
|
- Add an optional C(mac) entry to customize mac address
|
||||||
|
- Add an optional C(dns_servers) or C(domain) entry per interface (Windows)
|
||||||
required: False
|
required: False
|
||||||
version_added: "2.3"
|
version_added: "2.3"
|
||||||
snapshot_op:
|
snapshot_op:
|
||||||
|
@ -211,9 +213,10 @@ EXAMPLES = '''
|
||||||
num_cpus: 1
|
num_cpus: 1
|
||||||
scsi: paravirtual
|
scsi: paravirtual
|
||||||
networks:
|
networks:
|
||||||
'192.168.1.0/24':
|
- network: VM Network
|
||||||
network: VM Network
|
ip: 192.168.1.100
|
||||||
mac: 'aa:bb:dd:aa:00:14'
|
netmask: 255.255.255.0
|
||||||
|
mac: 'aa:bb:dd:aa:00:14'
|
||||||
template: template_el7
|
template: template_el7
|
||||||
wait_for_ip_address: yes
|
wait_for_ip_address: yes
|
||||||
register: deploy
|
register: deploy
|
||||||
|
@ -230,15 +233,15 @@ EXAMPLES = '''
|
||||||
name: testvm-2
|
name: testvm-2
|
||||||
template: template_windows
|
template: template_windows
|
||||||
networks:
|
networks:
|
||||||
'192.168.1.0/24':
|
- name: VM Network
|
||||||
network: VM Network
|
ip: 192.168.1.100
|
||||||
gateway: 192.168.1.1
|
netmask: 255.255.255.0
|
||||||
ip: 192.168.1.100
|
gateway: 192.168.1.1
|
||||||
mac: 'aa:bb:dd:aa:00:14'
|
mac: 'aa:bb:dd:aa:00:14'
|
||||||
domain: my_domain
|
domain: my_domain
|
||||||
dns_servers:
|
dns_servers:
|
||||||
- 192.168.1.1
|
- 192.168.1.1
|
||||||
- 192.168.1.2
|
- 192.168.1.2
|
||||||
customization:
|
customization:
|
||||||
autologon: True
|
autologon: True
|
||||||
dns_servers:
|
dns_servers:
|
||||||
|
@ -364,7 +367,6 @@ instance:
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
from netaddr import IPNetwork, IPAddress
|
|
||||||
|
|
||||||
# import module snippets
|
# import module snippets
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
@ -470,13 +472,13 @@ class PyVmomiDeviceHelper(object):
|
||||||
nic.device = vim.vm.device.VirtualSriovEthernetCard()
|
nic.device = vim.vm.device.VirtualSriovEthernetCard()
|
||||||
else:
|
else:
|
||||||
self.module.fail_json(msg="Invalid device_type '%s' for network %s" %
|
self.module.fail_json(msg="Invalid device_type '%s' for network %s" %
|
||||||
(device_type, device_infos['network']))
|
(device_type, device_infos['name']))
|
||||||
|
|
||||||
nic.device.wakeOnLanEnabled = True
|
nic.device.wakeOnLanEnabled = True
|
||||||
nic.device.addressType = 'assigned'
|
nic.device.addressType = 'assigned'
|
||||||
nic.device.deviceInfo = vim.Description()
|
nic.device.deviceInfo = vim.Description()
|
||||||
nic.device.deviceInfo.label = device_label
|
nic.device.deviceInfo.label = device_label
|
||||||
nic.device.deviceInfo.summary = device_infos['network']
|
nic.device.deviceInfo.summary = device_infos['name']
|
||||||
nic.device.connectable = vim.vm.device.VirtualDevice.ConnectInfo()
|
nic.device.connectable = vim.vm.device.VirtualDevice.ConnectInfo()
|
||||||
nic.device.connectable.startConnected = True
|
nic.device.connectable.startConnected = True
|
||||||
nic.device.connectable.allowGuestControl = True
|
nic.device.connectable.allowGuestControl = True
|
||||||
|
@ -699,7 +701,7 @@ class PyVmomiHelper(object):
|
||||||
matches.append(thisvm)
|
matches.append(thisvm)
|
||||||
if len(matches) > 1:
|
if len(matches) > 1:
|
||||||
self.module.fail_json(
|
self.module.fail_json(
|
||||||
msg='more than 1 vm exists by the name %s. Please specify a uuid, or a folder, '
|
msg='More than 1 VM exists by the name %s. Please specify a uuid, or a folder, '
|
||||||
'or a datacenter or name_match' % name)
|
'or a datacenter or name_match' % name)
|
||||||
if matches:
|
if matches:
|
||||||
vm = matches[0]
|
vm = matches[0]
|
||||||
|
@ -893,33 +895,29 @@ class PyVmomiHelper(object):
|
||||||
|
|
||||||
network_devices = list()
|
network_devices = list()
|
||||||
for network in self.params['networks']:
|
for network in self.params['networks']:
|
||||||
if network:
|
if 'ip' in network or 'netmask' in network:
|
||||||
if 'ip' in self.params['networks'][network]:
|
if 'ip' not in network or not 'netmask' in network:
|
||||||
ip = self.params['networks'][network]['ip']
|
self.module.fail_json(msg="Both 'ip' and 'netmask' are required together.")
|
||||||
if ip not in IPNetwork(network):
|
|
||||||
self.module.fail_json(msg="ip '%s' not in network %s" % (ip, network))
|
|
||||||
|
|
||||||
ipnet = IPNetwork(network)
|
if 'name' in network:
|
||||||
self.params['networks'][network]['subnet_mask'] = str(ipnet.netmask)
|
if get_obj(self.content, [vim.Network], network['name']) is None:
|
||||||
|
self.module.fail_json(msg="Network '%(name)s' does not exists" % network)
|
||||||
|
|
||||||
if 'network' in self.params['networks'][network]:
|
elif 'vlan' in network:
|
||||||
if get_obj(self.content, [vim.Network], self.params['networks'][network]['network']) is None:
|
dvps = get_all_objs(self.content, [vim.dvs.DistributedVirtualPortgroup])
|
||||||
self.module.fail_json(msg="Network %s doesn't exists" % network)
|
for dvp in dvps:
|
||||||
elif 'vlan' in self.params['networks'][network]:
|
if hasattr(dvp.config.defaultPortConfig, 'vlan') and dvp.config.defaultPortConfig.vlan.vlanId == network['vlan']:
|
||||||
network_name = None
|
network['name'] = dvp.config.name
|
||||||
dvps = get_all_objs(self.content, [vim.dvs.DistributedVirtualPortgroup])
|
break
|
||||||
for dvp in dvps:
|
if dvp.config.name == network['vlan']:
|
||||||
if dvp.config.defaultPortConfig.vlan.vlanId == self.params['networks'][network]['vlan']:
|
network['name'] = dvp.config.name
|
||||||
network_name = dvp.config.name
|
break
|
||||||
break
|
|
||||||
if network_name:
|
|
||||||
self.params['networks'][network]['network'] = network_name
|
|
||||||
else:
|
|
||||||
self.module.fail_json(msg="VLAN %(vlan)s doesn't exists" % self.params['networks'][network])
|
|
||||||
else:
|
else:
|
||||||
self.module.fail_json(msg="You need to define a network or a vlan")
|
self.module.fail_json(msg="VLAN '%(vlan)s' does not exist" % network)
|
||||||
|
else:
|
||||||
|
self.module.fail_json(msg="You need to define a network name or a vlan")
|
||||||
|
|
||||||
network_devices.append(self.params['networks'][network])
|
network_devices.append(network)
|
||||||
|
|
||||||
# List current device for Clone or Idempotency
|
# List current device for Clone or Idempotency
|
||||||
current_net_devices = self.get_vm_network_interfaces(vm=vm_obj)
|
current_net_devices = self.get_vm_network_interfaces(vm=vm_obj)
|
||||||
|
@ -949,9 +947,9 @@ class PyVmomiHelper(object):
|
||||||
nic.operation = vim.vm.device.VirtualDeviceSpec.Operation.add
|
nic.operation = vim.vm.device.VirtualDeviceSpec.Operation.add
|
||||||
nic_change_detected = True
|
nic_change_detected = True
|
||||||
|
|
||||||
if hasattr(self.cache.get_network(network_devices[key]['network']), 'portKeys'):
|
if hasattr(self.cache.get_network(network_devices[key]['name']), 'portKeys'):
|
||||||
# VDS switch
|
# VDS switch
|
||||||
pg_obj = get_obj(self.content, [vim.dvs.DistributedVirtualPortgroup], network_devices[key]['network'])
|
pg_obj = get_obj(self.content, [vim.dvs.DistributedVirtualPortgroup], network_devices[key]['name'])
|
||||||
dvs_port_connection = vim.dvs.PortConnection()
|
dvs_port_connection = vim.dvs.PortConnection()
|
||||||
dvs_port_connection.portgroupKey = pg_obj.key
|
dvs_port_connection.portgroupKey = pg_obj.key
|
||||||
dvs_port_connection.switchUuid = pg_obj.config.distributedVirtualSwitch.uuid
|
dvs_port_connection.switchUuid = pg_obj.config.distributedVirtualSwitch.uuid
|
||||||
|
@ -963,13 +961,13 @@ class PyVmomiHelper(object):
|
||||||
nic.device.backing = vim.vm.device.VirtualEthernetCard.NetworkBackingInfo()
|
nic.device.backing = vim.vm.device.VirtualEthernetCard.NetworkBackingInfo()
|
||||||
nic_change_detected = True
|
nic_change_detected = True
|
||||||
|
|
||||||
net_obj = self.cache.get_network(network_devices[key]['network'])
|
net_obj = self.cache.get_network(network_devices[key]['name'])
|
||||||
if nic.device.backing.network != net_obj:
|
if nic.device.backing.network != net_obj:
|
||||||
nic.device.backing.network = net_obj
|
nic.device.backing.network = net_obj
|
||||||
nic_change_detected = True
|
nic_change_detected = True
|
||||||
|
|
||||||
if nic.device.backing.deviceName != network_devices[key]['network']:
|
if nic.device.backing.deviceName != network_devices[key]['name']:
|
||||||
nic.device.backing.deviceName = network_devices[key]['network']
|
nic.device.backing.deviceName = network_devices[key]['name']
|
||||||
nic_change_detected = True
|
nic_change_detected = True
|
||||||
|
|
||||||
if nic_change_detected:
|
if nic_change_detected:
|
||||||
|
@ -998,30 +996,29 @@ class PyVmomiHelper(object):
|
||||||
def customize_vm(self, vm_obj):
|
def customize_vm(self, vm_obj):
|
||||||
# Network settings
|
# Network settings
|
||||||
adaptermaps = []
|
adaptermaps = []
|
||||||
if len(self.params['networks']) > 0:
|
for network in self.params['networks']:
|
||||||
for network in self.params['networks']:
|
if 'ip' in network and 'netmask' in network:
|
||||||
if 'ip' in self.params['networks'][network]:
|
guest_map = vim.vm.customization.AdapterMapping()
|
||||||
guest_map = vim.vm.customization.AdapterMapping()
|
guest_map.adapter = vim.vm.customization.IPSettings()
|
||||||
guest_map.adapter = vim.vm.customization.IPSettings()
|
guest_map.adapter.ip = vim.vm.customization.FixedIp()
|
||||||
guest_map.adapter.ip = vim.vm.customization.FixedIp()
|
guest_map.adapter.ip.ipAddress = str(network['ip'])
|
||||||
guest_map.adapter.ip.ipAddress = str(self.params['networks'][network]['ip'])
|
guest_map.adapter.subnetMask = str(network['netmask'])
|
||||||
guest_map.adapter.subnetMask = str(self.params['networks'][network]['subnet_mask'])
|
|
||||||
|
|
||||||
if 'gateway' in self.params['networks'][network]:
|
if 'gateway' in network:
|
||||||
guest_map.adapter.gateway = self.params['networks'][network]['gateway']
|
guest_map.adapter.gateway = network['gateway']
|
||||||
|
|
||||||
# On Windows, DNS domain and DNS servers can be set by network interface
|
# On Windows, DNS domain and DNS servers can be set by network interface
|
||||||
# https://pubs.vmware.com/vi3/sdk/ReferenceGuide/vim.vm.customization.IPSettings.html
|
# https://pubs.vmware.com/vi3/sdk/ReferenceGuide/vim.vm.customization.IPSettings.html
|
||||||
if 'domain' in self.params['networks'][network]:
|
if 'domain' in network:
|
||||||
guest_map.adapter.dnsDomain = self.params['networks'][network]['domain']
|
guest_map.adapter.dnsDomain = network['domain']
|
||||||
elif self.params['customization'].get('domain'):
|
elif self.params['customization'].get('domain'):
|
||||||
guest_map.adapter.dnsDomain = self.params['customization']['domain']
|
guest_map.adapter.dnsDomain = self.params['customization']['domain']
|
||||||
if 'dns_servers' in self.params['networks'][network]:
|
if 'dns_servers' in network:
|
||||||
guest_map.adapter.dnsServerList = self.params['networks'][network]['dns_servers']
|
guest_map.adapter.dnsServerList = network['dns_servers']
|
||||||
elif self.params['customization'].get('dns_servers'):
|
elif self.params['customization'].get('dns_servers'):
|
||||||
guest_map.adapter.dnsServerList = self.params['customization']['dns_servers']
|
guest_map.adapter.dnsServerList = self.params['customization']['dns_servers']
|
||||||
|
|
||||||
adaptermaps.append(guest_map)
|
adaptermaps.append(guest_map)
|
||||||
|
|
||||||
# Global DNS settings
|
# Global DNS settings
|
||||||
globalip = vim.vm.customization.GlobalIPSettings()
|
globalip = vim.vm.customization.GlobalIPSettings()
|
||||||
|
@ -1650,7 +1647,7 @@ def main():
|
||||||
esxi_hostname=dict(required=False, type='str', default=None),
|
esxi_hostname=dict(required=False, type='str', default=None),
|
||||||
cluster=dict(required=False, type='str', default=None),
|
cluster=dict(required=False, type='str', default=None),
|
||||||
wait_for_ip_address=dict(required=False, type='bool', default=True),
|
wait_for_ip_address=dict(required=False, type='bool', default=True),
|
||||||
networks=dict(required=False, type='dict', default={}),
|
networks=dict(required=False, type='list', default=[]),
|
||||||
resource_pool=dict(required=False, type='str', default=None),
|
resource_pool=dict(required=False, type='str', default=None),
|
||||||
customization=dict(required=False, type='dict', no_log=True, default={}),
|
customization=dict(required=False, type='dict', no_log=True, default={}),
|
||||||
),
|
),
|
||||||
|
|
Loading…
Reference in New Issue