mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
vmware_host_datastore: ability to target a ESXi
Until now, the module was only able to interact with vcenter. This commit adds the ability to directly target an ESXi without the `esxi_hostname` parameter.
This commit is contained in:
parent
fc94d79c47
commit
8cee127ee4
4 changed files with 112 additions and 18 deletions
2
changelogs/fragments/vmware_host_datastore_for_esxi.yaml
Normal file
2
changelogs/fragments/vmware_host_datastore_for_esxi.yaml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
minor_changes:
|
||||||
|
- vmware_host_datastore - Ability to directly target a ESXi.
|
|
@ -27,7 +27,7 @@ author:
|
||||||
- Ludovic Rivallain (@lrivallain) <ludovic.rivallain@gmail.com>
|
- Ludovic Rivallain (@lrivallain) <ludovic.rivallain@gmail.com>
|
||||||
- Christian Kotte (@ckotte) <christian.kotte@gmx.de>
|
- Christian Kotte (@ckotte) <christian.kotte@gmx.de>
|
||||||
notes:
|
notes:
|
||||||
- Tested on vSphere 6.0 and 6.5
|
- Tested on vSphere 6.0, 6.5 and ESXi 6.7
|
||||||
- NFS v4.1 tested on vSphere 6.5
|
- NFS v4.1 tested on vSphere 6.5
|
||||||
- Kerberos authentication with NFS v4.1 isn't implemented
|
- Kerberos authentication with NFS v4.1 isn't implemented
|
||||||
requirements:
|
requirements:
|
||||||
|
@ -75,7 +75,8 @@ options:
|
||||||
esxi_hostname:
|
esxi_hostname:
|
||||||
description:
|
description:
|
||||||
- ESXi hostname to manage the datastore.
|
- ESXi hostname to manage the datastore.
|
||||||
required: true
|
- Required when used with a vcenter
|
||||||
|
required: false
|
||||||
state:
|
state:
|
||||||
description:
|
description:
|
||||||
- "present: Mount datastore on host if datastore is absent else do nothing."
|
- "present: Mount datastore on host if datastore is absent else do nothing."
|
||||||
|
@ -133,13 +134,12 @@ EXAMPLES = r'''
|
||||||
- { 'name': 'NasDS_vol03', 'server': 'nas01,nas02', 'path': '/mnt/vol01', 'type': 'nfs41'}
|
- { 'name': 'NasDS_vol03', 'server': 'nas01,nas02', 'path': '/mnt/vol01', 'type': 'nfs41'}
|
||||||
- { 'name': 'NasDS_vol04', 'server': 'nas01,nas02', 'path': '/mnt/vol02', 'type': 'nfs41'}
|
- { 'name': 'NasDS_vol04', 'server': 'nas01,nas02', 'path': '/mnt/vol02', 'type': 'nfs41'}
|
||||||
|
|
||||||
- name: Remove/Umount Datastores from ESXi
|
- name: Remove/Umount Datastores from a ESXi
|
||||||
vmware_host_datastore:
|
vmware_host_datastore:
|
||||||
hostname: '{{ vcenter_hostname }}'
|
hostname: '{{ esxi_hostname }}'
|
||||||
username: '{{ vcenter_username }}'
|
username: '{{ esxi_username }}'
|
||||||
password: '{{ vcenter_password }}'
|
password: '{{ esxi_password }}'
|
||||||
datastore_name: NasDS_vol01
|
datastore_name: NasDS_vol01
|
||||||
esxi_hostname: '{{ inventory_hostname }}'
|
|
||||||
state: absent
|
state: absent
|
||||||
delegate_to: localhost
|
delegate_to: localhost
|
||||||
'''
|
'''
|
||||||
|
@ -153,7 +153,7 @@ except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi, find_datastore_by_name
|
from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi, find_datastore_by_name, find_obj
|
||||||
from ansible.module_utils._text import to_native
|
from ansible.module_utils._text import to_native
|
||||||
|
|
||||||
|
|
||||||
|
@ -173,9 +173,14 @@ class VMwareHostDatastore(PyVmomi):
|
||||||
self.esxi_hostname = module.params['esxi_hostname']
|
self.esxi_hostname = module.params['esxi_hostname']
|
||||||
self.state = module.params['state']
|
self.state = module.params['state']
|
||||||
|
|
||||||
|
if self.is_vcenter():
|
||||||
|
if not self.esxi_hostname:
|
||||||
|
self.module.fail_json(msg="esxi_hostname is mandatory with a vcenter")
|
||||||
self.esxi = self.find_hostsystem_by_name(self.esxi_hostname)
|
self.esxi = self.find_hostsystem_by_name(self.esxi_hostname)
|
||||||
if self.esxi is None:
|
if self.esxi is None:
|
||||||
self.module.fail_json(msg="Failed to find ESXi hostname %s" % self.esxi_hostname)
|
self.module.fail_json(msg="Failed to find ESXi hostname %s" % self.esxi_hostname)
|
||||||
|
else:
|
||||||
|
self.esxi = find_obj(self.content, [vim.HostSystem], None)
|
||||||
|
|
||||||
def process_state(self):
|
def process_state(self):
|
||||||
ds_states = {
|
ds_states = {
|
||||||
|
@ -220,14 +225,14 @@ class VMwareHostDatastore(PyVmomi):
|
||||||
if not ds:
|
if not ds:
|
||||||
self.module.fail_json(msg="No datastore found with name %s" % self.datastore_name)
|
self.module.fail_json(msg="No datastore found with name %s" % self.datastore_name)
|
||||||
if self.module.check_mode is False:
|
if self.module.check_mode is False:
|
||||||
error_message_umount = "Cannot umount datastore %s from host %s" % (self.datastore_name, self.esxi_hostname)
|
error_message_umount = "Cannot umount datastore %s from host %s" % (self.datastore_name, self.esxi.name)
|
||||||
try:
|
try:
|
||||||
self.esxi.configManager.datastoreSystem.RemoveDatastore(ds)
|
self.esxi.configManager.datastoreSystem.RemoveDatastore(ds)
|
||||||
except (vim.fault.NotFound, vim.fault.HostConfigFault, vim.fault.ResourceInUse) as fault:
|
except (vim.fault.NotFound, vim.fault.HostConfigFault, vim.fault.ResourceInUse) as fault:
|
||||||
self.module.fail_json(msg="%s: %s" % (error_message_umount, to_native(fault.msg)))
|
self.module.fail_json(msg="%s: %s" % (error_message_umount, to_native(fault.msg)))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.module.fail_json(msg="%s: %s" % (error_message_umount, to_native(e)))
|
self.module.fail_json(msg="%s: %s" % (error_message_umount, to_native(e)))
|
||||||
self.module.exit_json(changed=True, result="Datastore %s on host %s" % (self.datastore_name, self.esxi_hostname))
|
self.module.exit_json(changed=True, result="Datastore %s on host %s" % (self.datastore_name, self.esxi.name))
|
||||||
|
|
||||||
def mount_datastore_host(self):
|
def mount_datastore_host(self):
|
||||||
if self.datastore_type == 'nfs' or self.datastore_type == 'nfs41':
|
if self.datastore_type == 'nfs' or self.datastore_type == 'nfs41':
|
||||||
|
@ -254,7 +259,7 @@ class VMwareHostDatastore(PyVmomi):
|
||||||
mnt_specs.accessMode = "readOnly"
|
mnt_specs.accessMode = "readOnly"
|
||||||
else:
|
else:
|
||||||
mnt_specs.accessMode = "readWrite"
|
mnt_specs.accessMode = "readWrite"
|
||||||
error_message_mount = "Cannot mount datastore %s on host %s" % (self.datastore_name, self.esxi_hostname)
|
error_message_mount = "Cannot mount datastore %s on host %s" % (self.datastore_name, self.esxi.name)
|
||||||
try:
|
try:
|
||||||
ds = self.esxi.configManager.datastoreSystem.CreateNasDatastore(mnt_specs)
|
ds = self.esxi.configManager.datastoreSystem.CreateNasDatastore(mnt_specs)
|
||||||
if not ds:
|
if not ds:
|
||||||
|
@ -266,7 +271,7 @@ class VMwareHostDatastore(PyVmomi):
|
||||||
self.module.fail_json(msg="%s: %s" % (error_message_mount, to_native(fault.msg)))
|
self.module.fail_json(msg="%s: %s" % (error_message_mount, to_native(fault.msg)))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.module.fail_json(msg="%s : %s" % (error_message_mount, to_native(e)))
|
self.module.fail_json(msg="%s : %s" % (error_message_mount, to_native(e)))
|
||||||
self.module.exit_json(changed=True, result="Datastore %s on host %s" % (self.datastore_name, self.esxi_hostname))
|
self.module.exit_json(changed=True, result="Datastore %s on host %s" % (self.datastore_name, self.esxi.name))
|
||||||
|
|
||||||
def mount_vmfs_datastore_host(self):
|
def mount_vmfs_datastore_host(self):
|
||||||
if self.module.check_mode is False:
|
if self.module.check_mode is False:
|
||||||
|
@ -276,7 +281,7 @@ class VMwareHostDatastore(PyVmomi):
|
||||||
if self.vmfs_device_name in self.get_used_disks_names():
|
if self.vmfs_device_name in self.get_used_disks_names():
|
||||||
error_message_used_disk = "VMFS disk %s already in use" % self.vmfs_device_name
|
error_message_used_disk = "VMFS disk %s already in use" % self.vmfs_device_name
|
||||||
self.module.fail_json(msg="%s" % error_message_used_disk)
|
self.module.fail_json(msg="%s" % error_message_used_disk)
|
||||||
error_message_mount = "Cannot mount datastore %s on host %s" % (self.datastore_name, self.esxi_hostname)
|
error_message_mount = "Cannot mount datastore %s on host %s" % (self.datastore_name, self.esxi.name)
|
||||||
try:
|
try:
|
||||||
vmfs_ds_options = ds_system.QueryVmfsDatastoreCreateOptions(host_ds_system,
|
vmfs_ds_options = ds_system.QueryVmfsDatastoreCreateOptions(host_ds_system,
|
||||||
ds_path,
|
ds_path,
|
||||||
|
@ -289,7 +294,7 @@ class VMwareHostDatastore(PyVmomi):
|
||||||
self.module.fail_json(msg="%s : %s" % (error_message_mount, to_native(fault.msg)))
|
self.module.fail_json(msg="%s : %s" % (error_message_mount, to_native(fault.msg)))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.module.fail_json(msg="%s : %s" % (error_message_mount, to_native(e)))
|
self.module.fail_json(msg="%s : %s" % (error_message_mount, to_native(e)))
|
||||||
self.module.exit_json(changed=True, result="Datastore %s on host %s" % (self.datastore_name, self.esxi_hostname))
|
self.module.exit_json(changed=True, result="Datastore %s on host %s" % (self.datastore_name, self.esxi.name))
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -303,7 +308,7 @@ def main():
|
||||||
nfs_ro=dict(type='bool', default=False),
|
nfs_ro=dict(type='bool', default=False),
|
||||||
vmfs_device_name=dict(type='str'),
|
vmfs_device_name=dict(type='str'),
|
||||||
vmfs_version=dict(type='int'),
|
vmfs_version=dict(type='int'),
|
||||||
esxi_hostname=dict(type='str', required=True),
|
esxi_hostname=dict(type='str', required=False),
|
||||||
state=dict(type='str', default='present', choices=['absent', 'present'])
|
state=dict(type='str', default='present', choices=['absent', 'present'])
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
3
test/integration/targets/vmware_host_datastore/aliases
Normal file
3
test/integration/targets/vmware_host_datastore/aliases
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
cloud/vcenter
|
||||||
|
shippable/vcenter/group1
|
||||||
|
needs/target/prepare_vmware_tests
|
|
@ -0,0 +1,84 @@
|
||||||
|
- when: vcsim is not defined
|
||||||
|
block:
|
||||||
|
- import_role:
|
||||||
|
name: prepare_vmware_tests
|
||||||
|
vars:
|
||||||
|
setup_attach_host: true
|
||||||
|
|
||||||
|
- name: Mount NFS (ds1) datastores without esxi_hostname
|
||||||
|
vmware_host_datastore:
|
||||||
|
hostname: "{{ vcenter_hostname }}"
|
||||||
|
username: "{{ vcenter_username }}"
|
||||||
|
password: "{{ vcenter_password }}"
|
||||||
|
datastore_name: '{{ ds1 }}'
|
||||||
|
datastore_type: '{{ infra.datastores[ds1].type }}'
|
||||||
|
nfs_server: '{{ infra.datastores[ds1].server }}'
|
||||||
|
nfs_path: '{{ infra.datastores[ds1].path }}'
|
||||||
|
nfs_ro: '{{ infra.datastores[ds2].ro }}'
|
||||||
|
state: present
|
||||||
|
validate_certs: no
|
||||||
|
ignore_errors: true
|
||||||
|
register: mount_vmware_host_datastore
|
||||||
|
- debug: var=mount_vmware_host_datastore
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- mount_vmware_host_datastore is failed
|
||||||
|
- mount_vmware_host_datastore.msg == "esxi_hostname is mandatory with a vcenter"
|
||||||
|
|
||||||
|
- name: Mount NFS (ds1) datastores with non existing host in esxi_hostname
|
||||||
|
vmware_host_datastore:
|
||||||
|
hostname: "{{ vcenter_hostname }}"
|
||||||
|
username: "{{ vcenter_username }}"
|
||||||
|
password: "{{ vcenter_password }}"
|
||||||
|
esxi_hostname: 'nohost'
|
||||||
|
datastore_name: '{{ ds1 }}'
|
||||||
|
datastore_type: '{{ infra.datastores[ds1].type }}'
|
||||||
|
nfs_server: '{{ infra.datastores[ds1].server }}'
|
||||||
|
nfs_path: '{{ infra.datastores[ds1].path }}'
|
||||||
|
nfs_ro: '{{ infra.datastores[ds2].ro }}'
|
||||||
|
state: present
|
||||||
|
validate_certs: no
|
||||||
|
ignore_errors: true
|
||||||
|
register: mount_vmware_host_datastore
|
||||||
|
- debug: var=mount_vmware_host_datastore
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- mount_vmware_host_datastore is failed
|
||||||
|
- mount_vmware_host_datastore.msg == "Failed to find ESXi hostname nohost"
|
||||||
|
|
||||||
|
- name: Mount NFS (ds1) datastores on esxi1 using esxi_hostname
|
||||||
|
vmware_host_datastore:
|
||||||
|
hostname: "{{ vcenter_hostname }}"
|
||||||
|
username: "{{ vcenter_username }}"
|
||||||
|
password: "{{ vcenter_password }}"
|
||||||
|
esxi_hostname: '{{ esxi1 }}'
|
||||||
|
datastore_name: '{{ ds1 }}'
|
||||||
|
datastore_type: '{{ infra.datastores[ds1].type }}'
|
||||||
|
nfs_server: '{{ infra.datastores[ds1].server }}'
|
||||||
|
nfs_path: '{{ infra.datastores[ds1].path }}'
|
||||||
|
nfs_ro: '{{ infra.datastores[ds2].ro }}'
|
||||||
|
state: present
|
||||||
|
validate_certs: no
|
||||||
|
register: mount_vmware_host_datastore
|
||||||
|
- debug: var=mount_vmware_host_datastore
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- mount_vmware_host_datastore is changed
|
||||||
|
|
||||||
|
- name: Mount NFS (ds1) datastores to ESXi directly
|
||||||
|
vmware_host_datastore:
|
||||||
|
hostname: '{{ esxi1 }}'
|
||||||
|
username: '{{ esxi_user }}'
|
||||||
|
password: '{{ esxi_password }}'
|
||||||
|
datastore_name: '{{ ds1 }}'
|
||||||
|
datastore_type: '{{ infra.datastores[ds1].type }}'
|
||||||
|
nfs_server: '{{ infra.datastores[ds1].server }}'
|
||||||
|
nfs_path: '{{ infra.datastores[ds1].path }}'
|
||||||
|
nfs_ro: '{{ infra.datastores[ds2].ro }}'
|
||||||
|
state: present
|
||||||
|
validate_certs: no
|
||||||
|
register: mount_vmware_host_datastore
|
||||||
|
- debug: var=mount_vmware_host_datastore
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- not (mount_vmware_host_datastore is changed)
|
Loading…
Reference in a new issue