Skip to content

Commit 4f7f005

Browse files
committed
feat: Add vmware_host_disk module for attaching disks to host
1 parent c55e2c7 commit 4f7f005

File tree

1 file changed

+176
-0
lines changed

1 file changed

+176
-0
lines changed

plugins/modules/vmware_host_disk.py

+176
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
#!/usr/bin/python
2+
# -*- coding: utf-8 -*-
3+
4+
# Copyright: (c) 2018, Ansible Project
5+
# Copyright: (c) 2023, Pure Storage, Inc.
6+
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
7+
# SPDX-License-Identifier: GPL-3.0-or-later
8+
9+
from __future__ import absolute_import, division, print_function
10+
__metaclass__ = type
11+
12+
13+
DOCUMENTATION = r'''
14+
---
15+
module: vmware_host_disk
16+
short_description: Attach or detach disks from an esxi host
17+
description:
18+
- This module can be used to attach / detach disks on an ESXi host.
19+
author:
20+
- Ryan BADAÏ (@ryanb74) <[email protected]>
21+
options:
22+
uuid:
23+
description:
24+
- uuid of the disk to attach / detach.
25+
- Can be obtained using community.vmware.vmware_host_scsidisk_info module.
26+
required: true
27+
type: str
28+
esxi_hostname:
29+
description:
30+
- Name of the ESXi host on which the operation is performed.
31+
- Required when used with a vcenter
32+
type: str
33+
required: false
34+
state:
35+
description:
36+
- "attached: Attach disk on esxi host if it is not attached, else do nothing."
37+
- "detached: Detach disk on esxi host if it is attached, else do nothing."
38+
default: attached
39+
choices: [ attached, detached ]
40+
type: str
41+
seealso:
42+
- VMware vSphere API Reference Documentation : https://vdc-repo.vmware.com/vmwb-repository/dcr-public/1ef6c336-7bef-477d-b9bb-caa1767d7e30/82521f49-9d9a-42b7-b19b-9e6cd9b30db1/right-pane.html
43+
extends_documentation_fragment:
44+
- community.vmware.vmware.documentation
45+
'''
46+
47+
EXAMPLES = r'''
48+
- name: Attach disk on esxi host
49+
vmware_host_disk:
50+
hostname: "{{ vcenter_hostname }}"
51+
esxi_hostname: "{{ esxi_hostname }}"
52+
uuid: "{{ disk_uuid }}"
53+
state: attached
54+
username: '{{ vcenter_username }}'
55+
password: '{{ vcenter_password }}'
56+
'''
57+
58+
RETURN = r'''
59+
result:
60+
description: A string that describes whether the mount/unmount was successfully performed.
61+
returned: success or changed
62+
type: str
63+
sample:
64+
- Disk with uuid 020001000060060e8008783a000050783a000000164f50454e2d56 is already attached.
65+
- Disk with uuid 020001000060060e8008783a000050783a000000164f50454e2d56 was successfully detached.
66+
- Disk with uuid 020001000060060e8008783a000050783a000000164f50454e2d56 is already detached.
67+
- Disk with uuid 020001000060060e8008783a000050783a000000164f50454e2d56 was successfully attached.
68+
- Disk with uuid FAKE_UUID was not found !
69+
'''
70+
71+
try:
72+
from pyVmomi import vim, vmodl
73+
except ImportError:
74+
pass
75+
76+
from ansible.module_utils.basic import AnsibleModule
77+
from ansible_collections.community.vmware.plugins.module_utils.vmware import vmware_argument_spec, find_obj
78+
from ansible_collections.community.vmware.plugins.module_utils.vmware_sms import SMS
79+
from ansible.module_utils._text import to_native
80+
81+
82+
class VMwareHostDisk(SMS):
83+
def __init__(self, module):
84+
super(VMwareHostDisk, self).__init__(module)
85+
86+
self.uuid = module.params['uuid']
87+
self.esxi_hostname = module.params['esxi_hostname']
88+
self.state = module.params['state']
89+
90+
if self.is_vcenter():
91+
if not self.esxi_hostname:
92+
self.module.fail_json(msg="esxi_hostname is mandatory with a vcenter")
93+
self.esxi = self.find_hostsystem_by_name(self.esxi_hostname)
94+
if self.esxi is None:
95+
self.module.fail_json(msg="Failed to find ESXi hostname %s" % self.esxi_hostname)
96+
else:
97+
self.esxi = find_obj(self.content, [vim.HostSystem], None)
98+
99+
def process_state(self):
100+
"""Evaluates what must be done based on current state"""
101+
ds_states = {
102+
'detached': {
103+
'attached': self.detach_disk_from_host,
104+
'detached': lambda: self.module.exit_json(changed=False, result="Disk with uuid %s is already detached." % self.uuid)
105+
},
106+
'attached': {
107+
'attached': lambda: self.module.exit_json(changed=False, result="Disk with uuid %s is already attached." % self.uuid),
108+
'detached': self.attach_disk_to_host
109+
}
110+
}
111+
try:
112+
ds_states[self.state][self.get_disk_attachment_state()]()
113+
except (vmodl.RuntimeFault, vmodl.MethodFault) as vmodl_fault:
114+
self.module.fail_json(msg=to_native(vmodl_fault.msg))
115+
except Exception as e:
116+
self.module.fail_json(msg=to_native(e))
117+
118+
def get_disk_attachment_state(self):
119+
"""Checks whether the disk is attached or not.
120+
:return: Current attachment state of the disk: "attached" or "detached"
121+
:rtype: string
122+
"""
123+
storage_system = self.esxi.configManager.storageSystem # VMware docs : https://vdc-repo.vmware.com/vmwb-repository/dcr-public/1ef6c336-7bef-477d-b9bb-caa1767d7e30/82521f49-9d9a-42b7-b19b-9e6cd9b30db1/vim.host.StorageSystem.html
124+
125+
for disk in storage_system.storageDeviceInfo.scsiLun: # VMware docs : https://vdc-repo.vmware.com/vmwb-repository/dcr-public/1ef6c336-7bef-477d-b9bb-caa1767d7e30/82521f49-9d9a-42b7-b19b-9e6cd9b30db1/vim.host.ScsiLun.html
126+
if disk.uuid == self.uuid:
127+
if "ok" in disk.operationalState: # https://vdc-repo.vmware.com/vmwb-repository/dcr-public/1ef6c336-7bef-477d-b9bb-caa1767d7e30/82521f49-9d9a-42b7-b19b-9e6cd9b30db1/vim.host.ScsiLun.State.html
128+
return "attached"
129+
elif "off" in disk.operationalState:
130+
return "detached"
131+
self.module.fail_json(msg='Disk is in an unexpected state !{} ' % disk.operationalState)
132+
133+
self.module.fail_json(msg='Disk with uuid %s was not found !' % self.uuid)
134+
135+
136+
def detach_disk_from_host(self):
137+
if self.module.check_mode is False:
138+
try:
139+
self.esxi.configManager.storageSystem.DetachScsiLun(self.uuid)
140+
self.module.exit_json(changed=True, result="Disk with uuid %s was successfully detached." % self.uuid)
141+
142+
except vim.fault.ResourceInUse as e:
143+
self.module.fail_json(msg='Disk with uuid {} is currently used and can\'t be detached ! {}' % self.uuid % e)
144+
except vim.fault.VimFault as e:
145+
self.module.fail_json(msg='Disk with uuid {} can\'t be detached because of an unexpected error ! {}' % self.uuid % e)
146+
self.module.exit_json(changed=True, result="CHECK MODE: Disk with uuid %s would be successfully detached." % self.uuid)
147+
148+
149+
def attach_disk_to_host(self):
150+
if self.module.check_mode is False:
151+
try:
152+
self.esxi.configManager.storageSystem.AttachScsiLun(self.uuid)
153+
self.module.exit_json(changed=True, result="Disk with uuid %s was successfully attached." % self.uuid)
154+
except vim.fault.VimFault as e:
155+
self.module.fail_json(msg='Disk with uuid {} can\'t be attached because of an unexpected error ! {}' % self.uuid % e)
156+
self.module.exit_json(changed=True, result="CHECK MODE: disk with uuid %s would be successfully attached." % self.uuid)
157+
158+
def main():
159+
argument_spec = vmware_argument_spec()
160+
argument_spec.update(
161+
uuid=dict(type='str', required=True),
162+
esxi_hostname=dict(type='str', required=False),
163+
state=dict(type='str', default='attached', choices=['detached', 'attached'])
164+
)
165+
166+
module = AnsibleModule(
167+
argument_spec=argument_spec,
168+
supports_check_mode=True
169+
)
170+
171+
vmware_host_datastore = VMwareHostDisk(module)
172+
vmware_host_datastore.process_state()
173+
174+
175+
if __name__ == '__main__':
176+
main()

0 commit comments

Comments
 (0)