VMware: Fix DVPG idempotency issue (#35837)
This fixes, cloning operation where template or existing VM does not have network or DVPG. Also, adds some strict type checking in network parameters. Signed-off-by: Abhijeet Kasurde <akasurde@redhat.com>
This commit is contained in:
parent
75a34f6668
commit
a377302d6b
4 changed files with 582 additions and 64 deletions
|
@ -502,23 +502,23 @@ class PyVmomiDeviceHelper(object):
|
|||
|
||||
return diskspec
|
||||
|
||||
def get_device(self, device_type, name):
|
||||
nic_dict = dict(pcnet32=vim.vm.device.VirtualPCNet32(),
|
||||
vmxnet2=vim.vm.device.VirtualVmxnet2(),
|
||||
vmxnet3=vim.vm.device.VirtualVmxnet3(),
|
||||
e1000=vim.vm.device.VirtualE1000(),
|
||||
e1000e=vim.vm.device.VirtualE1000e(),
|
||||
sriov=vim.vm.device.VirtualSriovEthernetCard(),
|
||||
)
|
||||
if device_type in nic_dict:
|
||||
return nic_dict[device_type]
|
||||
else:
|
||||
self.module.fail_json(msg='Invalid device_type "%s"'
|
||||
' for network "%s"' % (device_type, name))
|
||||
|
||||
def create_nic(self, device_type, device_label, device_infos):
|
||||
nic = vim.vm.device.VirtualDeviceSpec()
|
||||
if device_type == 'pcnet32':
|
||||
nic.device = vim.vm.device.VirtualPCNet32()
|
||||
elif device_type == 'vmxnet2':
|
||||
nic.device = vim.vm.device.VirtualVmxnet2()
|
||||
elif device_type == 'vmxnet3':
|
||||
nic.device = vim.vm.device.VirtualVmxnet3()
|
||||
elif device_type == 'e1000':
|
||||
nic.device = vim.vm.device.VirtualE1000()
|
||||
elif device_type == 'e1000e':
|
||||
nic.device = vim.vm.device.VirtualE1000e()
|
||||
elif device_type == 'sriov':
|
||||
nic.device = vim.vm.device.VirtualSriovEthernetCard()
|
||||
else:
|
||||
self.module.fail_json(msg='Invalid device_type "%s" for network "%s"' % (device_type, device_infos['name']))
|
||||
|
||||
nic.device = self.get_device(device_type, device_infos['name'])
|
||||
nic.device.wakeOnLanEnabled = bool(device_infos.get('wake_on_lan', True))
|
||||
nic.device.deviceInfo = vim.Description()
|
||||
nic.device.deviceInfo.label = device_label
|
||||
|
@ -544,11 +544,8 @@ class PyVmomiDeviceHelper(object):
|
|||
|
||||
Returns: (Boolean) True if string is valid MAC address, otherwise False
|
||||
"""
|
||||
ret = False
|
||||
mac_addr_regex = re.compile('[0-9a-f]{2}([-:])[0-9a-f]{2}(\\1[0-9a-f]{2}){4}$')
|
||||
if mac_addr_regex.match(mac_addr):
|
||||
ret = True
|
||||
return ret
|
||||
return bool(mac_addr_regex.match(mac_addr))
|
||||
|
||||
|
||||
class PyVmomiCache(object):
|
||||
|
@ -897,58 +894,93 @@ class PyVmomiHelper(PyVmomi):
|
|||
|
||||
return device_list
|
||||
|
||||
def configure_network(self, vm_obj):
|
||||
# Ignore empty networks, this permits to keep networks when deploying a template/cloning a VM
|
||||
if len(self.params['networks']) == 0:
|
||||
return
|
||||
def sanitize_network_params(self):
|
||||
"""
|
||||
Function to sanitize user provided network provided params
|
||||
|
||||
Returns: A sanitized list of network params, else fails
|
||||
|
||||
"""
|
||||
network_devices = list()
|
||||
# Clean up user data here
|
||||
for network in self.params['networks']:
|
||||
if 'ip' in network or 'netmask' in network:
|
||||
if 'ip' not in network or 'netmask' not in network:
|
||||
self.module.fail_json(msg="Both 'ip' and 'netmask' are required together.")
|
||||
|
||||
if 'name' in network:
|
||||
if find_obj(self.content, [vim.Network], network['name']) is None:
|
||||
self.module.fail_json(msg="Network '%(name)s' does not exists" % network)
|
||||
if 'name' not in network and 'vlan' not in network:
|
||||
self.module.fail_json(msg="Please specify at least a network name or"
|
||||
" a VLAN name under VM network list.")
|
||||
|
||||
if 'name' in network and find_obj(self.content, [vim.Network], network['name']) is None:
|
||||
self.module.fail_json(msg="Network '%(name)s' does not exists" % network)
|
||||
elif 'vlan' in network:
|
||||
dvps = self.cache.get_all_objs(self.content, [vim.dvs.DistributedVirtualPortgroup])
|
||||
for dvp in dvps:
|
||||
if hasattr(dvp.config.defaultPortConfig, 'vlan') and dvp.config.defaultPortConfig.vlan.vlanId == network['vlan']:
|
||||
if hasattr(dvp.config.defaultPortConfig, 'vlan') and \
|
||||
dvp.config.defaultPortConfig.vlan.vlanId == network['vlan']:
|
||||
network['name'] = dvp.config.name
|
||||
break
|
||||
if dvp.config.name == network['vlan']:
|
||||
network['name'] = dvp.config.name
|
||||
break
|
||||
else:
|
||||
self.module.fail_json(msg="VLAN '%(vlan)s' does not exist" % network)
|
||||
self.module.fail_json(msg="VLAN '%(vlan)s' does not exist." % network)
|
||||
|
||||
if 'type' in network:
|
||||
if network['type'] not in ['dhcp', 'static']:
|
||||
self.module.fail_json(msg="Network type '%(type)s' is not a valid parameter."
|
||||
" Valid parameters are ['dhcp', 'static']." % network)
|
||||
if network['type'] != 'static' and ('ip' in network or 'netmask' in network):
|
||||
self.module.fail_json(msg='Static IP information provided for network "%(name)s",'
|
||||
' but "type" is set to "%(type)s".' % network)
|
||||
else:
|
||||
self.module.fail_json(msg="You need to define a network name or a vlan")
|
||||
# Type is optional parameter, if user provided IP or Subnet assume
|
||||
# network type as 'static'
|
||||
if 'ip' in network or 'netmask' in network:
|
||||
network['type'] = 'static'
|
||||
|
||||
if network.get('type') == 'static':
|
||||
if 'ip' in network and 'netmask' not in network:
|
||||
self.module.fail_json(msg="'netmask' is required if 'ip' is"
|
||||
" specified under VM network list.")
|
||||
if 'ip' not in network and 'netmask' in network:
|
||||
self.module.fail_json(msg="'ip' is required if 'netmask' is"
|
||||
" specified under VM network list.")
|
||||
|
||||
validate_device_types = ['pcnet32', 'vmxnet2', 'vmxnet3', 'e1000', 'e1000e', 'sriov']
|
||||
if 'device_type' in network and network['device_type'] not in validate_device_types:
|
||||
self.module.fail_json(msg="Device type specified '%s' is not valid."
|
||||
" Please specify correct device"
|
||||
" type from ['%s']." % (network['device_type'],
|
||||
"', '".join(validate_device_types)))
|
||||
|
||||
if 'mac' in network and not PyVmomiDeviceHelper.is_valid_mac_addr(network['mac']):
|
||||
self.module.fail_json(msg="Device MAC address '%s' is invalid."
|
||||
" Please provide correct MAC address." % network['mac'])
|
||||
|
||||
network_devices.append(network)
|
||||
|
||||
return network_devices
|
||||
|
||||
def configure_network(self, vm_obj):
|
||||
# Ignore empty networks, this permits to keep networks when deploying a template/cloning a VM
|
||||
if len(self.params['networks']) == 0:
|
||||
return
|
||||
|
||||
network_devices = self.sanitize_network_params()
|
||||
|
||||
# List current device for Clone or Idempotency
|
||||
current_net_devices = self.get_vm_network_interfaces(vm=vm_obj)
|
||||
if len(network_devices) < len(current_net_devices):
|
||||
self.module.fail_json(msg="given network device list is lesser than current VM device list (%d < %d). "
|
||||
self.module.fail_json(msg="Given network device list is lesser than current VM device list (%d < %d). "
|
||||
"Removing interfaces is not allowed"
|
||||
% (len(network_devices), len(current_net_devices)))
|
||||
|
||||
for key in range(0, len(network_devices)):
|
||||
# Default device type is vmxnet3, VMWare best practice
|
||||
device_type = network_devices[key].get('device_type', 'vmxnet3')
|
||||
nic = self.device_helper.create_nic(device_type,
|
||||
'Network Adapter %s' % (key + 1),
|
||||
network_devices[key])
|
||||
|
||||
nic_change_detected = False
|
||||
network_name = network_devices[key]['name']
|
||||
if key < len(current_net_devices) and (vm_obj or self.params['template']):
|
||||
# We are editing existing network devices, this is either when
|
||||
# are cloning from VM or Template
|
||||
nic = vim.vm.device.VirtualDeviceSpec()
|
||||
nic.operation = vim.vm.device.VirtualDeviceSpec.Operation.edit
|
||||
# Changing mac address has no effect when editing interface
|
||||
if 'mac' in network_devices[key] and nic.device.macAddress != current_net_devices[key].macAddress:
|
||||
self.module.fail_json(msg="Changing MAC address has not effect when interface is already present. "
|
||||
"The failing new MAC address is %s" % nic.device.macAddress)
|
||||
|
||||
nic.device = current_net_devices[key]
|
||||
if ('wake_on_lan' in network_devices[key] and
|
||||
|
@ -964,37 +996,56 @@ class PyVmomiHelper(PyVmomi):
|
|||
nic.device.connectable.allowGuestControl = network_devices[key].get('allow_guest_control')
|
||||
nic_change_detected = True
|
||||
|
||||
nic.device.deviceInfo = vim.Description()
|
||||
if nic.device.deviceInfo.summary != network_name:
|
||||
nic.device.deviceInfo.summary = network_name
|
||||
nic_change_detected = True
|
||||
if 'device_type' in network_devices[key]:
|
||||
device = self.device_helper.get_device(network_devices[key]['device_type'], network_name)
|
||||
if nic.device != device:
|
||||
self.module.fail_json(msg="Changing the device type is not possible when interface is already present. "
|
||||
"The failing device type is %s" % network_devices[key]['device_type'])
|
||||
# Changing mac address has no effect when editing interface
|
||||
if 'mac' in network_devices[key] and nic.device.macAddress != current_net_devices[key].macAddress:
|
||||
self.module.fail_json(msg="Changing MAC address has not effect when interface is already present. "
|
||||
"The failing new MAC address is %s" % nic.device.macAddress)
|
||||
|
||||
else:
|
||||
# Default device type is vmxnet3, VMWare best practice
|
||||
device_type = network_devices[key].get('device_type', 'vmxnet3')
|
||||
nic = self.device_helper.create_nic(device_type,
|
||||
'Network Adapter %s' % (key + 1),
|
||||
network_devices[key])
|
||||
nic.operation = vim.vm.device.VirtualDeviceSpec.Operation.add
|
||||
nic_change_detected = True
|
||||
|
||||
if hasattr(self.cache.get_network(network_devices[key]['name']), 'portKeys'):
|
||||
if hasattr(self.cache.get_network(network_name), 'portKeys'):
|
||||
# VDS switch
|
||||
pg_obj = find_obj(self.content, [vim.dvs.DistributedVirtualPortgroup], network_devices[key]['name'])
|
||||
pg_obj = find_obj(self.content, [vim.dvs.DistributedVirtualPortgroup], network_name)
|
||||
|
||||
if vm_obj is None or (nic.device.backing and not hasattr(nic.device.backing, 'port')) or \
|
||||
(nic.device.backing and (nic.device.backing.port.portgroupKey != pg_obj.key or
|
||||
nic.device.backing.port.switchUuid != pg_obj.config.distributedVirtualSwitch.uuid)):
|
||||
dvs_port_connection = vim.dvs.PortConnection()
|
||||
dvs_port_connection.portgroupKey = pg_obj.key
|
||||
dvs_port_connection.switchUuid = pg_obj.config.distributedVirtualSwitch.uuid
|
||||
nic.device.backing = vim.vm.device.VirtualEthernetCard.DistributedVirtualPortBackingInfo()
|
||||
nic.device.backing.port = dvs_port_connection
|
||||
if (nic.device.backing and
|
||||
(not hasattr(nic.device.backing, 'port') or
|
||||
(nic.device.backing.port.portgroupKey != pg_obj.key or
|
||||
nic.device.backing.port.switchUuid != pg_obj.config.distributedVirtualSwitch.uuid))):
|
||||
nic_change_detected = True
|
||||
|
||||
dvs_port_connection = vim.dvs.PortConnection()
|
||||
dvs_port_connection.portgroupKey = pg_obj.key
|
||||
dvs_port_connection.switchUuid = pg_obj.config.distributedVirtualSwitch.uuid
|
||||
nic.device.backing = vim.vm.device.VirtualEthernetCard.DistributedVirtualPortBackingInfo()
|
||||
nic.device.backing.port = dvs_port_connection
|
||||
else:
|
||||
# vSwitch
|
||||
if not isinstance(nic.device.backing, vim.vm.device.VirtualEthernetCard.NetworkBackingInfo):
|
||||
nic.device.backing = vim.vm.device.VirtualEthernetCard.NetworkBackingInfo()
|
||||
nic_change_detected = True
|
||||
|
||||
net_obj = self.cache.get_network(network_devices[key]['name'])
|
||||
net_obj = self.cache.get_network(network_name)
|
||||
if nic.device.backing.network != net_obj:
|
||||
nic.device.backing.network = net_obj
|
||||
nic_change_detected = True
|
||||
|
||||
if nic.device.backing.deviceName != network_devices[key]['name']:
|
||||
nic.device.backing.deviceName = network_devices[key]['name']
|
||||
if nic.device.backing.deviceName != network_name:
|
||||
nic.device.backing.deviceName = network_name
|
||||
nic_change_detected = True
|
||||
|
||||
if nic_change_detected:
|
||||
|
@ -1035,17 +1086,11 @@ class PyVmomiHelper(PyVmomi):
|
|||
guest_map.adapter = vim.vm.customization.IPSettings()
|
||||
|
||||
if 'ip' in network and 'netmask' in network:
|
||||
if 'type' in network and network['type'] != 'static':
|
||||
self.module.fail_json(msg='Static IP information provided for network "%(name)s", but "type" is set to "%(type)s".' % network)
|
||||
guest_map.adapter.ip = vim.vm.customization.FixedIp()
|
||||
guest_map.adapter.ip.ipAddress = str(network['ip'])
|
||||
guest_map.adapter.subnetMask = str(network['netmask'])
|
||||
elif 'type' in network and network['type'] == 'static':
|
||||
self.module.fail_json(msg='Network "%(name)s" was set to type "%(type)s", but "ip" and "netmask" are missing.' % network)
|
||||
elif 'type' in network and network['type'] == 'dhcp':
|
||||
guest_map.adapter.ip = vim.vm.customization.DhcpIpGenerator()
|
||||
else:
|
||||
self.module.fail_json(msg='Network "%(name)s" was set to unknown type "%(type)s".' % network)
|
||||
|
||||
if 'gateway' in network:
|
||||
guest_map.adapter.gateway = network['gateway']
|
||||
|
|
|
@ -27,4 +27,7 @@
|
|||
- include: create_nw_d1_c1_f0.yml
|
||||
- include: delete_vm.yml
|
||||
- include: non_existent_vm_ops.yml
|
||||
- include: network_negative_test.yml
|
||||
# Currently, VCSIM doesn't support DVPG (as portkeys are not available) so commenting this test
|
||||
#- include: network_with_dvpg.yml
|
||||
#- include: template_d1_c1_f0.yml
|
||||
|
|
|
@ -0,0 +1,341 @@
|
|||
# Test code for the vmware_guest module.
|
||||
# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com>
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
- name: Wait for Flask controller to come up online
|
||||
wait_for:
|
||||
host: "{{ vcsim }}"
|
||||
port: 5000
|
||||
state: started
|
||||
|
||||
- name: kill vcsim
|
||||
uri:
|
||||
url: http://{{ vcsim }}:5000/killall
|
||||
- name: start vcsim with no folders
|
||||
uri:
|
||||
url: http://{{ vcsim }}:5000/spawn?datacenter=1&cluster=1&folder=0
|
||||
register: vcsim_instance
|
||||
|
||||
- name: Wait for Flask controller to come up online
|
||||
wait_for:
|
||||
host: "{{ vcsim }}"
|
||||
port: 443
|
||||
state: started
|
||||
|
||||
- name: get a list of VMS from vcsim
|
||||
uri:
|
||||
url: http://{{ vcsim }}:5000/govc_find?filter=VM
|
||||
register: vmlist
|
||||
|
||||
- debug: var=vcsim_instance
|
||||
|
||||
- debug: var=vmlist
|
||||
|
||||
- set_fact:
|
||||
vm1: "{{ vmlist['json'][0] }}"
|
||||
|
||||
- debug: var=vm1
|
||||
|
||||
- name: create new VMs with non-existent network
|
||||
vmware_guest:
|
||||
validate_certs: False
|
||||
hostname: "{{ vcsim }}"
|
||||
username: "{{ vcsim_instance['json']['username'] }}"
|
||||
password: "{{ vcsim_instance['json']['password'] }}"
|
||||
name: new_vm
|
||||
guest_id: centos64Guest
|
||||
datacenter: "{{ (vm1 | basename).split('_')[0] }}"
|
||||
disk:
|
||||
- size: 3mb
|
||||
type: thin
|
||||
autoselect_datastore: yes
|
||||
networks:
|
||||
- name: "Non existent VM"
|
||||
hardware:
|
||||
num_cpus: 3
|
||||
memory_mb: 512
|
||||
state: poweredoff
|
||||
folder: "{{ vm1 | dirname }}"
|
||||
register: non_existent_network
|
||||
ignore_errors: yes
|
||||
|
||||
- debug: var=non_existent_network
|
||||
|
||||
- name: assert that no changes were made
|
||||
assert:
|
||||
that:
|
||||
- "not non_existent_network.changed"
|
||||
- "\"Network 'Non existent VM' does not exists\" in non_existent_network.msg"
|
||||
|
||||
- name: create new VMs with network and with only IP
|
||||
vmware_guest:
|
||||
validate_certs: False
|
||||
hostname: "{{ vcsim }}"
|
||||
username: "{{ vcsim_instance['json']['username'] }}"
|
||||
password: "{{ vcsim_instance['json']['password'] }}"
|
||||
name: new_vm
|
||||
guest_id: centos64Guest
|
||||
datacenter: "{{ (vm1 | basename).split('_')[0] }}"
|
||||
disk:
|
||||
- size: 3mb
|
||||
type: thin
|
||||
autoselect_datastore: yes
|
||||
networks:
|
||||
- name: "VM Network"
|
||||
type: static
|
||||
ip: 10.10.10.10
|
||||
hardware:
|
||||
num_cpus: 3
|
||||
memory_mb: 512
|
||||
state: poweredoff
|
||||
folder: "{{ vm1 | dirname }}"
|
||||
register: no_netmask
|
||||
ignore_errors: yes
|
||||
|
||||
- debug: var=no_netmask
|
||||
|
||||
- name: assert that no changes were made
|
||||
assert:
|
||||
that:
|
||||
- "not no_netmask.changed"
|
||||
- "\"'netmask' is required if 'ip' is specified under VM network list.\" in no_netmask.msg"
|
||||
|
||||
- name: create new VMs with network and with only netmask
|
||||
vmware_guest:
|
||||
validate_certs: False
|
||||
hostname: "{{ vcsim }}"
|
||||
username: "{{ vcsim_instance['json']['username'] }}"
|
||||
password: "{{ vcsim_instance['json']['password'] }}"
|
||||
name: new_vm
|
||||
guest_id: centos64Guest
|
||||
datacenter: "{{ (vm1 | basename).split('_')[0] }}"
|
||||
disk:
|
||||
- size: 3mb
|
||||
type: thin
|
||||
autoselect_datastore: yes
|
||||
networks:
|
||||
- name: "VM Network"
|
||||
type: static
|
||||
netmask: 255.255.255.0
|
||||
hardware:
|
||||
num_cpus: 3
|
||||
memory_mb: 512
|
||||
state: poweredoff
|
||||
folder: "{{ vm1 | dirname }}"
|
||||
register: no_ip
|
||||
ignore_errors: yes
|
||||
|
||||
- debug: var=no_ip
|
||||
|
||||
- name: assert that changes were made
|
||||
assert:
|
||||
that:
|
||||
- "not no_ip.changed"
|
||||
- "\"'ip' is required if 'netmask' is specified under VM network list.\" in no_ip.msg"
|
||||
|
||||
- name: create new VMs with network and without network name
|
||||
vmware_guest:
|
||||
validate_certs: False
|
||||
hostname: "{{ vcsim }}"
|
||||
username: "{{ vcsim_instance['json']['username'] }}"
|
||||
password: "{{ vcsim_instance['json']['password'] }}"
|
||||
name: new_vm
|
||||
guest_id: centos64Guest
|
||||
datacenter: "{{ (vm1 | basename).split('_')[0] }}"
|
||||
disk:
|
||||
- size: 3mb
|
||||
type: thin
|
||||
autoselect_datastore: yes
|
||||
networks:
|
||||
- ip: 10.10.10.10
|
||||
netmask: 255.255.255
|
||||
type: static
|
||||
hardware:
|
||||
num_cpus: 3
|
||||
memory_mb: 512
|
||||
state: poweredoff
|
||||
folder: "{{ vm1 | dirname }}"
|
||||
register: no_network_name
|
||||
ignore_errors: yes
|
||||
|
||||
- debug: var=no_network_name
|
||||
|
||||
- name: assert that no changes were made
|
||||
assert:
|
||||
that:
|
||||
- "not no_network_name.changed"
|
||||
- "\"Please specify at least a network name or a VLAN name under VM network list.\" in no_network_name.msg"
|
||||
|
||||
- name: create new VMs with network and without network name
|
||||
vmware_guest:
|
||||
validate_certs: False
|
||||
hostname: "{{ vcsim }}"
|
||||
username: "{{ vcsim_instance['json']['username'] }}"
|
||||
password: "{{ vcsim_instance['json']['password'] }}"
|
||||
name: new_vm
|
||||
guest_id: centos64Guest
|
||||
datacenter: "{{ (vm1 | basename).split('_')[0] }}"
|
||||
disk:
|
||||
- size: 3mb
|
||||
type: thin
|
||||
autoselect_datastore: yes
|
||||
networks:
|
||||
- vlan: non_existing_vlan
|
||||
ip: 10.10.10.10
|
||||
netmask: 255.255.255
|
||||
hardware:
|
||||
num_cpus: 3
|
||||
memory_mb: 512
|
||||
state: poweredoff
|
||||
folder: "{{ vm1 | dirname }}"
|
||||
register: no_network
|
||||
ignore_errors: yes
|
||||
|
||||
- debug: var=no_network
|
||||
|
||||
- name: assert that changes were made
|
||||
assert:
|
||||
that:
|
||||
- "not no_network.changed"
|
||||
- "\"VLAN 'non_existing_vlan' does not exist.\" in no_network.msg"
|
||||
|
||||
- name: create new VMs with invalid device type
|
||||
vmware_guest:
|
||||
validate_certs: False
|
||||
hostname: "{{ vcsim }}"
|
||||
username: "{{ vcsim_instance['json']['username'] }}"
|
||||
password: "{{ vcsim_instance['json']['password'] }}"
|
||||
name: new_vm
|
||||
guest_id: centos64Guest
|
||||
datacenter: "{{ (vm1 | basename).split('_')[0] }}"
|
||||
disk:
|
||||
- size: 3mb
|
||||
type: thin
|
||||
autoselect_datastore: yes
|
||||
networks:
|
||||
- name: "VM Network"
|
||||
ip: 10.10.10.10
|
||||
netmask: 255.255.255
|
||||
device_type: abc
|
||||
hardware:
|
||||
num_cpus: 3
|
||||
memory_mb: 512
|
||||
state: poweredoff
|
||||
folder: "{{ vm1 | dirname }}"
|
||||
register: invalid_device_type
|
||||
ignore_errors: yes
|
||||
|
||||
- debug: var=invalid_device_type
|
||||
|
||||
- name: assert that changes were made
|
||||
assert:
|
||||
that:
|
||||
- "not invalid_device_type.changed"
|
||||
- "\"Device type specified 'abc' is not valid.\" in invalid_device_type.msg"
|
||||
|
||||
- name: create new VMs with invalid device MAC address
|
||||
vmware_guest:
|
||||
validate_certs: False
|
||||
hostname: "{{ vcsim }}"
|
||||
username: "{{ vcsim_instance['json']['username'] }}"
|
||||
password: "{{ vcsim_instance['json']['password'] }}"
|
||||
name: new_vm
|
||||
guest_id: centos64Guest
|
||||
datacenter: "{{ (vm1 | basename).split('_')[0] }}"
|
||||
disk:
|
||||
- size: 3mb
|
||||
type: thin
|
||||
autoselect_datastore: yes
|
||||
networks:
|
||||
- name: "VM Network"
|
||||
ip: 10.10.10.10
|
||||
netmask: 255.255.255
|
||||
device_type: e1000
|
||||
mac: abcdef
|
||||
hardware:
|
||||
num_cpus: 3
|
||||
memory_mb: 512
|
||||
state: poweredoff
|
||||
folder: "{{ vm1 | dirname }}"
|
||||
register: invalid_mac
|
||||
ignore_errors: yes
|
||||
|
||||
- debug: var=invalid_mac
|
||||
|
||||
- name: assert that changes were made
|
||||
assert:
|
||||
that:
|
||||
- "not invalid_mac.changed"
|
||||
- "\"Device MAC address 'abcdef' is invalid.\" in invalid_mac.msg"
|
||||
|
||||
- name: create new VMs with invalid network type
|
||||
vmware_guest:
|
||||
validate_certs: False
|
||||
hostname: "{{ vcsim }}"
|
||||
username: "{{ vcsim_instance['json']['username'] }}"
|
||||
password: "{{ vcsim_instance['json']['password'] }}"
|
||||
name: new_vm
|
||||
guest_id: centos64Guest
|
||||
datacenter: "{{ (vm1 | basename).split('_')[0] }}"
|
||||
disk:
|
||||
- size: 3mb
|
||||
type: thin
|
||||
autoselect_datastore: yes
|
||||
networks:
|
||||
- name: "VM Network"
|
||||
ip: 10.10.10.10
|
||||
netmask: 255.255.255
|
||||
device_type: e1000
|
||||
mac: 01:23:45:67:89:ab
|
||||
type: aaaaa
|
||||
hardware:
|
||||
num_cpus: 3
|
||||
memory_mb: 512
|
||||
state: poweredoff
|
||||
folder: "{{ vm1 | dirname }}"
|
||||
register: invalid_network_type
|
||||
ignore_errors: yes
|
||||
|
||||
- debug: var=invalid_network_type
|
||||
|
||||
- name: assert that changes were made
|
||||
assert:
|
||||
that:
|
||||
- "not invalid_network_type.changed"
|
||||
- "\"Network type 'aaaaa' is not a valid parameter.\" in invalid_network_type.msg"
|
||||
|
||||
- name: create new VMs with IP, netmask and network type as "DHCP"
|
||||
vmware_guest:
|
||||
validate_certs: False
|
||||
hostname: "{{ vcsim }}"
|
||||
username: "{{ vcsim_instance['json']['username'] }}"
|
||||
password: "{{ vcsim_instance['json']['password'] }}"
|
||||
name: new_vm
|
||||
guest_id: centos64Guest
|
||||
datacenter: "{{ (vm1 | basename).split('_')[0] }}"
|
||||
disk:
|
||||
- size: 3mb
|
||||
type: thin
|
||||
autoselect_datastore: yes
|
||||
networks:
|
||||
- name: "VM Network"
|
||||
ip: 10.10.10.10
|
||||
netmask: 255.255.255
|
||||
device_type: e1000
|
||||
mac: 01:23:45:67:89:ab
|
||||
type: dhcp
|
||||
hardware:
|
||||
num_cpus: 3
|
||||
memory_mb: 512
|
||||
state: poweredoff
|
||||
folder: "{{ vm1 | dirname }}"
|
||||
register: invalid_dhcp_network_type
|
||||
ignore_errors: yes
|
||||
|
||||
- debug: var=invalid_dhcp_network_type
|
||||
|
||||
- name: assert that changes were made
|
||||
assert:
|
||||
that:
|
||||
- "not invalid_dhcp_network_type.changed"
|
||||
- "\"Static IP information provided for network\" in invalid_dhcp_network_type.msg"
|
|
@ -0,0 +1,129 @@
|
|||
# Test code for the vmware_guest module.
|
||||
# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com>
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
- name: Wait for Flask controller to come up online
|
||||
wait_for:
|
||||
host: "{{ vcsim }}"
|
||||
port: 5000
|
||||
state: started
|
||||
|
||||
- name: kill vcsim
|
||||
uri:
|
||||
url: http://{{ vcsim }}:5000/killall
|
||||
- name: start vcsim with no folders
|
||||
uri:
|
||||
url: http://{{ vcsim }}:5000/spawn?datacenter=1&cluster=1&folder=0
|
||||
register: vcsim_instance
|
||||
|
||||
- name: Wait for Flask controller to come up online
|
||||
wait_for:
|
||||
host: "{{ vcsim }}"
|
||||
port: 443
|
||||
state: started
|
||||
|
||||
- name: get a list of VMS from vcsim
|
||||
uri:
|
||||
url: http://{{ vcsim }}:5000/govc_find?filter=VM
|
||||
register: vmlist
|
||||
|
||||
- debug: var=vcsim_instance
|
||||
|
||||
- debug: var=vmlist
|
||||
|
||||
- set_fact:
|
||||
vm1: "{{ vmlist['json'][0] }}"
|
||||
|
||||
- debug: var=vm1
|
||||
|
||||
- set_fact:
|
||||
vm_name: "VM_{{ 10000 | random }}"
|
||||
|
||||
# Clone from existing VM with DVPG
|
||||
- name: Deploy VM from template {{ vm1 | basename }}
|
||||
vmware_guest:
|
||||
hostname: "{{ vcsim }}"
|
||||
username: "{{ vcsim_instance['json']['username'] }}"
|
||||
password: "{{ vcsim_instance['json']['password'] }}"
|
||||
validate_certs: no
|
||||
datacenter: "{{ (vm1|basename).split('_')[0] }}"
|
||||
state: poweredon
|
||||
folder: "{{ vm1 | dirname }}"
|
||||
template: "{{ vm1 | basename }}"
|
||||
name: "{{ vm_name }}"
|
||||
disk:
|
||||
- size: 10mb
|
||||
autoselect_datastore: yes
|
||||
guest_id: rhel7_64guest
|
||||
hardware:
|
||||
memory_mb: 512
|
||||
num_cpus: 1
|
||||
networks:
|
||||
- name: "DC0_DVPG0"
|
||||
register: no_vm_result
|
||||
|
||||
- debug: var=no_vm_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "no_vm_result.changed"
|
||||
|
||||
# New clone with DVPG
|
||||
- set_fact:
|
||||
vm_name: "VM_{{ 10000 | random }}"
|
||||
|
||||
- debug: var=vm_name
|
||||
|
||||
- name: Deploy new VM with DVPG
|
||||
vmware_guest:
|
||||
hostname: "{{ vcsim }}"
|
||||
username: "{{ vcsim_instance['json']['username'] }}"
|
||||
password: "{{ vcsim_instance['json']['password'] }}"
|
||||
validate_certs: no
|
||||
datacenter: "{{ (vm1|basename).split('_')[0] }}"
|
||||
state: poweredon
|
||||
folder: "{{ vm1 | dirname }}"
|
||||
name: "{{ vm_name }}"
|
||||
disk:
|
||||
- size: 10mb
|
||||
autoselect_datastore: yes
|
||||
guest_id: rhel7_64guest
|
||||
hardware:
|
||||
memory_mb: 512
|
||||
num_cpus: 1
|
||||
networks:
|
||||
- name: "DC0_DVPG0"
|
||||
register: no_vm_result
|
||||
|
||||
- debug: var=no_vm_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "no_vm_result.changed"
|
||||
|
||||
- name: Deploy same {{ vm_name }} VM again
|
||||
vmware_guest:
|
||||
hostname: "{{ vcsim }}"
|
||||
username: "{{ vcsim_instance['json']['username'] }}"
|
||||
password: "{{ vcsim_instance['json']['password'] }}"
|
||||
validate_certs: no
|
||||
datacenter: "{{ (vm1|basename).split('_')[0] }}"
|
||||
state: poweredon
|
||||
folder: "{{ vm1 | dirname }}"
|
||||
name: "{{ vm_name }}"
|
||||
disk:
|
||||
- size: 10mb
|
||||
autoselect_datastore: yes
|
||||
guest_id: rhel7_64guest
|
||||
hardware:
|
||||
memory_mb: 512
|
||||
num_cpus: 1
|
||||
networks:
|
||||
- name: "DC0_DVPG0"
|
||||
register: no_vm_result
|
||||
|
||||
- debug: var=no_vm_result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "not no_vm_result.changed"
|
Loading…
Reference in a new issue