Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 31 additions & 6 deletions plugins/module_utils/vcenter_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,11 @@ def establish_vcenter_connection(module, vCenter_host, username, password, ignor
module.fail_json(msg="Caught vmodl fault while connecting to vCenter: " + error.msg)
return service_instance.RetrieveContent()


def get_resource_id_from_name(module, vCenter_host, username, password,
resource_type, resource_name, ignore_ssl_verification):
"""
params:
- resource_type: Type of vCenter resource. Accepted values 'host', 'cluster', 'storage' and 'network'.
- resource_type: Type of vCenter resource. Accepted values 'host', 'cluster', 'storage', 'network', 'folder', and 'compute'.
- resource_name: Name of the resource.
result:
- moref id of the resource name and type given.
Expand All @@ -101,21 +100,47 @@ def get_resource_id_from_name(module, vCenter_host, username, password,
elif resource_type == 'network':
objview = content.viewManager.CreateContainerView(content.rootFolder,
[vim.Network], True)
elif resource_type == 'folder':
objview = content.viewManager.CreateContainerView(content.rootFolder,
[vim.Folder], True)
elif resource_type == 'compute':
# For 'compute', we need to look for both clusters and resource pools
objview = content.viewManager.CreateContainerView(content.rootFolder,
[vim.ClusterComputeResource, vim.ResourcePool], True)
else:
module.fail_json(msg='Resource type provided by user either doesn\'t'
' exist or is not supported')

all_resources = objview.view
objview.Destroy()

for resource in all_resources:
if resource.name == resource_name:
if resource_type == 'folder' and resource.name == resource_name.split('/')[-1]:
folder_path = resource_name.split('/')
current_folder = resource.parent
for folder_name in reversed(folder_path[:-1]):
if current_folder.name == folder_name:
current_folder = current_folder.parent
else:
module.fail_json(msg='Folder path %s does not exist' % resource_name)
return resource._moId
module.fail_json(msg='%s doesnt exist in %s' % (resource_name,
resource_type))
elif resource.name == resource_name:
return resource._moId

if resource_type == 'compute':
# If we're here, we didn't find a matching cluster or top-level resource pool
# Let's search for nested resource pools
for resource in all_resources:
if isinstance(resource, vim.ClusterComputeResource):
for rp in resource.resourcePool.resourcePool: # Search immediate child resource pools
if rp.name == resource_name:
return rp._moId

module.fail_json(msg='%s doesn\'t exist in %s' % (resource_name, resource_type))
except vmodl.MethodFault as error:
print("Caught vmodl fault while fetching info from vCenter: " + error.msg)
return -1


def get_data_network_id_from_name(module, vCenter_host, username, password,
data_network_name_list, ignore_ssl_verification):
"""
Expand Down
93 changes: 74 additions & 19 deletions plugins/modules/nsxt_transport_nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,9 +249,27 @@
data_networks:
description: "List of distributed portgroup or VLAN logical identifiers or names to
which the datapath serving vnics of edge node vm will be connected. If vc_username
and vc_password are present then this field takes names else id."
required: true
and vc_password are present then this field takes names else id. If 'data_network_ids' and
'data_networks' is provided, this will error out."
required: false
type: list
data_network_ids:
description:
- List of data network IDs to which the datapath serving vnics of edge node vm will be connected.
- This parameter can be used instead of 'data_networks' to directly specify the data network IDs.
- If 'data_network_ids' and 'data_networks' is provided, this will error out.
required: false
type: list
example:
- "/infra/segments/segment-1"
- "/infra/segments/segment-2"
vm_folder:
description:
- The folder in the vCenter inventory where the VM should be placed.
- Example: "TargetFolder"
- If the specified folder path does not exist, the module will fail with an appropriate error message.
required: false
type: str
ignore_ssl_connection:
description: 'This is a boolean value which will work as a flag to control whether SSL
should be used while connecting to VC or not.
Expand Down Expand Up @@ -634,9 +652,13 @@
storage: "{{prod_vc_datastore}}"
management_network: "{{prod_vc_portgroup}}"
data_networks:
- "{{prod_vc_portgroup}}"
- "{{prod_vc_portgroup}}"
- "{{prod_vc_portgroup}}"
- "{{ prod_vc_portgroup }}"
- "{{ prod_vc_portgroup }}"
- "{{ prod_vc_portgroup }}"
data_network_ids:
- "/infra/segments/nsx-vlan-trunk"
- "/infra/segments/nsx-vlan-trunk"
vm_folder: "NSX Edge Nodes"
management_port_subnets:
- ip_addresses:
- "{{ip_address}}"
Expand Down Expand Up @@ -919,7 +941,6 @@ def get_api_cert_thumbprint(ip_address, module):
finally:
wrappedSocket.close()


def inject_vcenter_info(module, manager_url, mgr_username, mgr_password, validate_certs, transport_node_params):
'''
params:
Expand Down Expand Up @@ -954,27 +975,46 @@ def inject_vcenter_info(module, manager_url, mgr_username, mgr_password, validat
'storage', storage, ignore_ssl_verification)
transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config']['storage_id'] = str(storage_id)

cluster = vm_deployment_config.pop('compute')
cluster_id = get_resource_id_from_name(module, vc_ip, vc_username, vc_password,
'cluster', cluster, ignore_ssl_verification)
transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config']['compute_id'] = str(cluster_id)
cluster_or_rp = vm_deployment_config.pop('compute')
# Try to get the cluster ID or resource pool ID
compute_id = get_resource_id_from_name(module, vc_ip, vc_username, vc_password,
'compute', cluster_or_rp, ignore_ssl_verification)

if compute_id == -1:
module.fail_json(msg=f"Neither cluster nor resource pool with name '{cluster_or_rp}' found.")

transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config']['compute_id'] = str(compute_id)

management_network = vm_deployment_config.pop('management_network')
management_network_id = get_resource_id_from_name(module, vc_ip, vc_username, vc_password,
'network', management_network, ignore_ssl_verification)
transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config']['management_network_id'] = str(management_network_id)

data_networks = vm_deployment_config.pop('data_networks')
data_network_ids = get_data_network_id_from_name(module, vc_ip, vc_username, vc_password,
data_networks, ignore_ssl_verification)
transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config']['data_network_ids'] = data_network_ids
if vm_deployment_config.__contains__('data_network_ids') and vm_deployment_config.__contains__('data_networks'):
module.fail_json(msg="Error: Either 'data_network_ids' or 'data_networks' should be provided, but not both.")
elif vm_deployment_config.__contains__('data_network_ids'):
data_network_ids = vm_deployment_config.pop('data_network_ids')
transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config']['data_network_ids'] = data_network_ids
elif vm_deployment_config.__contains__('data_networks'):
data_networks = vm_deployment_config.pop('data_networks')
data_network_ids = get_data_network_id_from_name(module, vc_ip, vc_username, vc_password,
data_networks, ignore_ssl_verification)
transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config']['data_network_ids'] = data_network_ids
else:
module.fail_json(msg="Error: Either 'data_network_ids' or 'data_networks' must be provided.")

if vm_deployment_config.__contains__('vm_folder'):
vm_folder = vm_deployment_config.pop('vm_folder')
vm_folder_id = get_resource_id_from_name(module, vc_ip, vc_username, vc_password,
'folder', vm_folder, ignore_ssl_verification)
transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config']['compute_folder_id'] = str(vm_folder_id)

if vm_deployment_config.__contains__('host'):
transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config'].pop('host', None)
transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config'].pop('cluster', None)
transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config'].pop('storage', None)
transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config'].pop('management_network', None)
transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config'].pop('data_networks', None)
transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config'].pop('vm_folder', None)
else:
if vm_deployment_config.__contains__('host'):
host_id = transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config'].pop('host', None)
Expand All @@ -983,15 +1023,28 @@ def inject_vcenter_info(module, manager_url, mgr_username, mgr_password, validat
cluster_id = transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config'].pop('compute', None)
storage_id = transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config'].pop('storage', None)
management_network_id = transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config'].pop('management_network', None)
data_network_ids = transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config'].pop('data_networks', None)

if transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config'].__contains__('data_network_ids') and transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config'].__contains__('data_networks'):
module.fail_json(msg="Error: Either 'data_network_ids' or 'data_networks' should be provided, but not both.")
elif transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config'].__contains__('data_network_ids'):
data_network_ids = transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config'].pop('data_network_ids')
elif transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config'].__contains__('data_networks'):
data_network_ids = transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config'].pop('data_networks')
else:
module.fail_json(msg="Error: Either 'data_network_ids' or 'data_networks' must be provided.")

if transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config'].__contains__('vm_folder'):
vm_folder = transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config'].pop('vm_folder')
vm_folder_id = get_resource_id_from_name(module, vc_ip, vc_username, vc_password,
'folder', vm_folder, ignore_ssl_verification)
transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config']['compute_folder_id'] = str(vm_folder_id)

transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config']['compute_id'] = cluster_id
transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config']['storage_id'] = storage_id
transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config']['management_network_id'] = management_network_id
transport_node_params['node_deployment_info']['deployment_config']['vm_deployment_config']['data_network_ids'] = data_network_ids
transport_node_params['node_deployment_info']['vm_deployment_config'].pop('ignore_ssl_verification', None)



def main():
argument_spec = vmware_argument_spec()
argument_spec.update(display_name=dict(required=True, type='str'),
Expand All @@ -1010,7 +1063,8 @@ def main():
cli_password=dict(required=False, type='str', no_log=True),
audit_password=dict(required=False, type='str', no_log=True)),
vm_deployment_config=dict(required=True, type='dict',
data_networks=dict(required=True, type='list'),
data_networks=dict(required=False, type='list'),
data_network=dict(required=False, type='list'),
management_network=dict(required=True, type='str'),
vc_username=dict(required=False, type='str'),
vc_password=dict(required=False, type='str', no_log=True),
Expand Down Expand Up @@ -1072,6 +1126,7 @@ def main():
subnet_mask=dict(required=False, type='dict',
IPAddress=dict(required=False, type='str')))),
tags=dict(required=False, type='list'),
vm_folder=dict(required=False, type='str'),
state=dict(required=True, choices=['present', 'absent']))

module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
Expand Down