1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
|
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2015, Joseph Callen <jcallen () csc.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
ANSIBLE_METADATA = {'metadata_version': '1.0',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: vmware_host
short_description: Add/remove ESXi host to/from vCenter
description:
- This module can be used to add/remove an ESXi host to/from vCenter
version_added: 2.0
author: "Joseph Callen (@jcpowermac), Russell Teague (@mtnbikenc)"
notes:
- Tested on vSphere 5.5
requirements:
- "python >= 2.6"
- PyVmomi
options:
datacenter_name:
description:
- Name of the datacenter to add the host
required: True
cluster_name:
description:
- Name of the cluster to add the host
required: True
esxi_hostname:
description:
- ESXi hostname to manage
required: True
esxi_username:
description:
- ESXi username
required: True
esxi_password:
description:
- ESXi password
required: True
state:
description:
- Add or remove the host
default: 'present'
choices:
- 'present'
- 'absent'
required: False
extends_documentation_fragment: vmware.documentation
'''
EXAMPLES = '''
# Example from Ansible playbook
- name: Add ESXi Host to VCSA
local_action:
module: vmware_host
hostname: vcsa_host
username: vcsa_user
password: vcsa_pass
datacenter_name: datacenter_name
cluster_name: cluster_name
esxi_hostname: esxi_hostname
esxi_username: esxi_username
esxi_password: esxi_password
state: present
'''
try:
from pyVmomi import vim, vmodl
HAS_PYVMOMI = True
except ImportError:
HAS_PYVMOMI = False
class VMwareHost(object):
def __init__(self, module):
self.module = module
self.datacenter_name = module.params['datacenter_name']
self.cluster_name = module.params['cluster_name']
self.esxi_hostname = module.params['esxi_hostname']
self.esxi_username = module.params['esxi_username']
self.esxi_password = module.params['esxi_password']
self.state = module.params['state']
self.dc = None
self.cluster = None
self.host = None
self.content = connect_to_api(module)
def process_state(self):
try:
# Currently state_update_dvs is not implemented.
host_states = {
'absent': {
'present': self.state_remove_host,
'absent': self.state_exit_unchanged,
},
'present': {
'present': self.state_exit_unchanged,
'absent': self.state_add_host,
}
}
host_states[self.state][self.check_host_state()]()
except vmodl.RuntimeFault as runtime_fault:
self.module.fail_json(msg=runtime_fault.msg)
except vmodl.MethodFault as method_fault:
self.module.fail_json(msg=method_fault.msg)
except Exception as e:
self.module.fail_json(msg=str(e))
def find_host_by_cluster_datacenter(self):
self.dc = find_datacenter_by_name(self.content, self.datacenter_name)
self.cluster = find_cluster_by_name_datacenter(self.dc, self.cluster_name)
for host in self.cluster.host:
if host.name == self.esxi_hostname:
return host, self.cluster
return None, self.cluster
def add_host_to_vcenter(self):
host_connect_spec = vim.host.ConnectSpec()
host_connect_spec.hostName = self.esxi_hostname
host_connect_spec.userName = self.esxi_username
host_connect_spec.password = self.esxi_password
host_connect_spec.force = True
host_connect_spec.sslThumbprint = ""
as_connected = True
esxi_license = None
resource_pool = None
try:
task = self.cluster.AddHost_Task(host_connect_spec, as_connected, resource_pool, esxi_license)
success, result = wait_for_task(task)
return success, result
except TaskError as add_task_error:
# This is almost certain to fail the first time.
# In order to get the sslThumbprint we first connect
# get the vim.fault.SSLVerifyFault then grab the sslThumbprint
# from that object.
#
# args is a tuple, selecting the first tuple
ssl_verify_fault = add_task_error.args[0]
host_connect_spec.sslThumbprint = ssl_verify_fault.thumbprint
task = self.cluster.AddHost_Task(host_connect_spec, as_connected, resource_pool, esxi_license)
success, result = wait_for_task(task)
return success, result
def state_exit_unchanged(self):
self.module.exit_json(changed=False)
def state_remove_host(self):
changed = True
result = None
if not self.module.check_mode:
if not self.host.runtime.inMaintenanceMode:
maintenance_mode_task = self.host.EnterMaintenanceMode_Task(300, True, None)
changed, result = wait_for_task(maintenance_mode_task)
if changed:
task = self.host.Destroy_Task()
changed, result = wait_for_task(task)
else:
raise Exception(result)
self.module.exit_json(changed=changed, result=str(result))
def state_update_host(self):
self.module.exit_json(changed=False, msg="Currently not implemented.")
def state_add_host(self):
changed = True
result = None
if not self.module.check_mode:
changed, result = self.add_host_to_vcenter()
self.module.exit_json(changed=changed, result=str(result))
def check_host_state(self):
self.host, self.cluster = self.find_host_by_cluster_datacenter()
if self.host is None:
return 'absent'
else:
return 'present'
def main():
argument_spec = vmware_argument_spec()
argument_spec.update(dict(datacenter_name=dict(required=True, type='str'),
cluster_name=dict(required=True, type='str'),
esxi_hostname=dict(required=True, type='str'),
esxi_username=dict(required=True, type='str'),
esxi_password=dict(required=True, type='str', no_log=True),
state=dict(default='present', choices=['present', 'absent'], type='str')))
module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
if not HAS_PYVMOMI:
module.fail_json(msg='pyvmomi is required for this module')
vmware_host = VMwareHost(module)
vmware_host.process_state()
from ansible.module_utils.vmware import *
from ansible.module_utils.basic import *
if __name__ == '__main__':
main()
|