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
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
|
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: (c) 2019, Ansible Project
# Copyright: (c) 2019, Pavan Bidkar <pbidkar@vmware.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {
'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'
}
DOCUMENTATION = r'''
---
module: vmware_content_deploy_template
short_description: Deploy Virtual Machine from template stored in content library.
description:
- Module to deploy virtual machine from template in content library.
- Content Library feature is introduced in vSphere 6.0 version.
- vmtx templates feature is introduced in vSphere 67U1 and APIs for clone template from content library in 67U2.
- This module does not work with vSphere version older than 67U2.
- All variables and VMware object names are case sensitive.
version_added: '2.9'
author:
- Pavan Bidkar (@pgbidkar)
notes:
- Tested on vSphere 6.7 U3
requirements:
- python >= 2.6
- PyVmomi
- vSphere Automation SDK
options:
template:
description:
- The name of template from which VM to be deployed.
type: str
required: True
aliases: ['template_src']
name:
description:
- The name of the VM to be deployed.
type: str
required: True
aliases: ['vm_name']
datacenter:
description:
- Name of the datacenter, where VM to be deployed.
type: str
required: True
datastore:
description:
- Name of the datastore to store deployed VM and disk.
type: str
required: True
folder:
description:
- Name of the folder in datacenter in which to place deployed VM.
type: str
required: True
host:
description:
- Name of the ESX Host in datacenter in which to place deployed VM.
type: str
required: True
resource_pool:
description:
- Name of the resourcepool in datacenter in which to place deployed VM.
type: str
required: False
cluster:
description:
- Name of the cluster in datacenter in which to place deployed VM.
type: str
required: False
state:
description:
- The state of Virtual Machine deployed from template in content library.
- If set to C(present) and VM does not exists, then VM is created.
- If set to C(present) and VM exists, no action is taken.
- If set to C(poweredon) and VM does not exists, then VM is created with powered on state.
- If set to C(poweredon) and VM exists, no action is taken.
type: str
required: False
default: 'present'
choices: [ 'present', 'poweredon' ]
extends_documentation_fragment: vmware_rest_client.documentation
'''
EXAMPLES = r'''
- name: Deploy Virtual Machine from template in content library
vmware_content_deploy_template:
hostname: '{{ vcenter_hostname }}'
username: '{{ vcenter_username }}'
password: '{{ vcenter_password }}'
template: rhel_test_template
datastore: Shared_NFS_Volume
folder: vm
datacenter: Sample_DC_1
name: Sample_VM
resource_pool: test_rp
validate_certs: False
state: present
delegate_to: localhost
- name: Deploy Virtual Machine from template in content library with PowerON State
vmware_content_deploy_template:
hostname: '{{ vcenter_hostname }}'
username: '{{ vcenter_username }}'
password: '{{ vcenter_password }}'
template: rhel_test_template
datastore: Shared_NFS_Volume
folder: vm
datacenter: Sample_DC_1
name: Sample_VM
resource_pool: test_rp
validate_certs: False
state: poweredon
delegate_to: localhost
'''
RETURN = r'''
vm_deploy_info:
description: Virtual machine deployment message and vm_id
returned: on success
type: dict
sample: {
"msg": "Deployed Virtual Machine 'Sample_VM'.",
"vm_id": "vm-1009"
}
'''
import uuid
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.vmware_rest_client import VmwareRestClient
from ansible.module_utils.vmware import PyVmomi
from ansible.module_utils._text import to_native
HAS_VAUTOMATION_PYTHON_SDK = False
try:
from com.vmware.vcenter.vm_template_client import LibraryItems
HAS_VAUTOMATION_PYTHON_SDK = True
except ImportError:
pass
class VmwareContentDeployTemplate(VmwareRestClient):
def __init__(self, module):
"""Constructor."""
super(VmwareContentDeployTemplate, self).__init__(module)
self.template_service = self.api_client.vcenter.vm_template.LibraryItems
self.template_name = self.params.get('template')
self.vm_name = self.params.get('name')
self.datacenter = self.params.get('datacenter')
self.datastore = self.params.get('datastore')
self.folder = self.params.get('folder')
self.resourcepool = self.params.get('resource_pool')
self.cluster = self.params.get('cluster')
self.host = self.params.get('host')
def deploy_vm_from_template(self, power_on=False):
# Find the datacenter by the given datacenter name
self.datacenter_id = self.get_datacenter_by_name(datacenter_name=self.datacenter)
if not self.datacenter_id:
self.module.fail_json(msg="Failed to find the datacenter %s" % self.datacenter)
# Find the datastore by the given datastore name
self.datastore_id = self.get_datastore_by_name(self.datacenter, self.datastore)
if not self.datastore_id:
self.module.fail_json(msg="Failed to find the datastore %s" % self.datastore)
# Find the LibraryItem (Template) by the given LibraryItem name
self.library_item_id = self.get_library_item_by_name(self.template_name)
if not self.library_item_id:
self.module.fail_json(msg="Failed to find the library Item %s" % self.template_name)
# Find the folder by the given folder name
self.folder_id = self.get_folder_by_name(self.datacenter, self.folder)
if not self.folder_id:
self.module.fail_json(msg="Failed to find the folder %s" % self.folder)
# Find the Host by given HostName
self.host_id = self.get_host_by_name(self.datacenter, self.host)
if not self.host_id:
self.module.fail_json(msg="Failed to find the Host %s" % self.host)
# Find the resourcepool by the given resourcepool name
self.resourcepool_id = None
if self.resourcepool:
self.resourcepool_id = self.get_resource_pool_by_name(self.datacenter, self.resourcepool)
if not self.resourcepool_id:
self.module.fail_json(msg="Failed to find the resource_pool %s" % self.resourcepool)
# Find the Cluster by the given Cluster name
self.cluster_id = None
if self.cluster:
self.cluster_id = self.get_cluster_by_name(self.datacenter, self.cluster)
if not self.cluster_id:
self.module.fail_json(msg="Failed to find the Cluster %s" % self.cluster)
# Create VM placement specs
self.placement_spec = LibraryItems.DeployPlacementSpec(folder=self.folder_id,
host=self.host_id
)
if self.resourcepool_id or self.cluster_id:
self.placement_spec.resource_pool = self.resourcepool_id
self.placement_spec.cluster = self.cluster_id
self.vm_home_storage_spec = LibraryItems.DeploySpecVmHomeStorage(datastore=to_native(self.datastore_id))
self.disk_storage_spec = LibraryItems.DeploySpecDiskStorage(datastore=to_native(self.datastore_id))
self.deploy_spec = LibraryItems.DeploySpec(name=self.vm_name,
placement=self.placement_spec,
vm_home_storage=self.vm_home_storage_spec,
disk_storage=self.disk_storage_spec,
powered_on=power_on
)
vm_id = self.template_service.deploy(self.library_item_id, self.deploy_spec)
if vm_id:
self.module.exit_json(
changed=True,
vm_deploy_info=dict(
msg="Deployed Virtual Machine '%s'." % self.vm_name,
vm_id=vm_id,
)
)
self.module.exit_json(changed=False,
vm_deploy_info=dict(msg="Virtual Machine deployment failed", vm_id=''))
def main():
argument_spec = VmwareRestClient.vmware_client_argument_spec()
argument_spec.update(
state=dict(type='str', default='present',
choices=['present', 'poweredon']),
template=dict(type='str', aliases=['template_src'], required=True),
name=dict(type='str', required=True, aliases=['vm_name']),
datacenter=dict(type='str', required=True),
datastore=dict(type='str', required=True),
folder=dict(type='str', required=True),
host=dict(type='str', required=True),
resource_pool=dict(type='str', required=False),
cluster=dict(type='str', required=False),
)
module = AnsibleModule(argument_spec=argument_spec,
supports_check_mode=True)
result = {'failed': False, 'changed': False}
pyv = PyVmomi(module=module)
vm = pyv.get_vm()
if vm:
module.exit_json(
changed=False,
vm_deploy_info=dict(
msg="Virtual Machine '%s' already Exists." % module.params['name'],
vm_id=vm._moId,
)
)
vmware_contentlib_create = VmwareContentDeployTemplate(module)
if module.params['state'] in ['present']:
if module.check_mode:
result.update(
vm_name=module.params['name'],
changed=True,
desired_operation='Create VM with PowerOff State',
)
module.exit_json(**result)
vmware_contentlib_create.deploy_vm_from_template()
if module.params['state'] == 'poweredon':
if module.check_mode:
result.update(
vm_name=module.params['name'],
changed=True,
desired_operation='Create VM with PowerON State',
)
module.exit_json(**result)
vmware_contentlib_create.deploy_vm_from_template(power_on=True)
if __name__ == '__main__':
main()
|