Skip to content

Commit

Permalink
Fix vm tagging for large environments (#439)
Browse files Browse the repository at this point in the history
* implement base_url for fabric api endpoint

Signed-off-by: Adam Robinson <[email protected]>

* use fabric base url for vm tags

Signed-off-by: Adam Robinson <[email protected]>

* use fabric endpoint and filter the query

Signed-off-by: Adam Robinson <[email protected]>

* use correct url to update the tags

Signed-off-by: Adam Robinson <[email protected]>

* prevent tags with the same scope from conflicting

Signed-off-by: Adam Robinson <[email protected]>

* prevent API NullPointerException with null scope

Signed-off-by: Adam Robinson <[email protected]>

---------

Signed-off-by: Adam Robinson <[email protected]>
  • Loading branch information
adarobin authored Feb 27, 2023
1 parent c221b18 commit a0d662d
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 34 deletions.
5 changes: 2 additions & 3 deletions plugins/module_utils/nsxt_resource_urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,8 @@
EDGE_CLUSTER_URL = _ENFORCEMENT_POINT_URL + '/{}/edge-clusters'
EDGE_NODE_URL = EDGE_CLUSTER_URL + '/{}/edge-nodes'

VM_LIST_URL = '/infra/realized-state/virtual-machines'
VM_UPDATE_URL = ('/infra/realized-state/enforcement-points/' +
'default/virtual-machines')
VM_LIST_URL = '/virtual-machines'
VM_UPDATE_URL = '/virtual-machines'

BFD_PROFILE_URL = '/infra/bfd-profiles'

Expand Down
14 changes: 11 additions & 3 deletions plugins/module_utils/policy_communicator.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ def __init__(self, key, mgr_hostname, mgr_username, mgr_password,
self.validate_certs = validate_certs

self.policy_url = 'https://{}/policy/api/v1'.format(mgr_hostname)
self.fabric_url = 'https://{}/api/v1/fabric'.format(mgr_hostname)
self.active_requests = set()

PolicyCommunicator.__instances[key] = self
Expand Down Expand Up @@ -136,9 +137,16 @@ def get_all_results(self, url, ignore_errors=False):

def request(self, url, data=None, method='GET',
use_proxy=True, force=False, last_mod_time=None,
timeout=300, http_agent=None, ignore_errors=False):
# prepend the policy url
url = self.policy_url + url
timeout=300, http_agent=None, ignore_errors=False, base_url='policy'):
if base_url == 'policy':
# prepend the policy url
# this is the default behavior if base_url is not specified
url = self.policy_url + url
elif base_url == 'fabric':
# prepend the fabric url
url = self.fabric_url + url
else:
raise Exception("invalid base_url specified in request call")
# create a request ID associated with this request
request_id = self._get_request_id(url, data, method)
if self.register_request(request_id):
Expand Down
57 changes: 29 additions & 28 deletions plugins/modules/nsxt_vm_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,35 +166,41 @@ def __hash__(self):

def _fetch_all_tags_on_vm_and_infer_id(
vm_id, policy_communicator, vm_display_name, module):
_, vms = policy_communicator.get_all_results(VM_LIST_URL)
target_vm = None
if vm_id:
for vm in vms:
if vm['external_id'] == vm_id:
return vm.get('tags', []), vm_id
module.fail_json(msg="No VM found with the provided "
"virtual_machine_id")
_, vms = policy_communicator.request(VM_LIST_URL+'?external_id='+vm_id, base_url='fabric')
if vms['result_count'] == 0:
module.fail_json(msg="No VM found with the provided "
"virtual_machine_id")
elif vms['result_count'] == 1:
return vms['results'][0].get('tags', []), vm_id
else:
# Multiple VMs with same external id name.
# This should not happen.
module.fail_json(msg="Multiple VMs with same external "
"id. Please investigate the environment.")
else:
for vm in vms:
if vm['display_name'] == vm_display_name:
if target_vm is not None:
# Multiple VMs with same display name. Ask user
# to provide VM ID instead
module.fail_json(msg="Multiple VMs with same display "
"name. Please provide "
"virtual_machine_id to identify the "
"target VM")
target_vm = vm
if target_vm:
return target_vm.get('tags', []), target_vm['external_id']
module.fail_json(msg="No VM found with the provided "
"virtual_machine_display_name")
_, vms = policy_communicator.request(VM_LIST_URL+'?display_name='+vm_display_name, base_url='fabric')
if vms['result_count'] == 0:
module.fail_json(msg="No VM found with the provided "
"virtual_machine_display_name")
elif vms['result_count'] == 1:
return vms['results'][0].get('tags', []), vms['results'][0]['external_id']
else:
# Multiple VMs with same display name. Ask user
# to provide VM ID instead
module.fail_json(msg="Multiple VMs with same display "
"name. Please provide "
"virtual_machine_id to identify the "
"target VM")


def _get_tags_as_set(tags=[], scope_list=[]):
tag_set = set()
if tags:
for tag in tags:
if tag['scope'] is None:
tag['scope'] = ''
tag_set.add(TagElement(tag))
if scope_list:
for scope in scope_list:
Expand Down Expand Up @@ -265,25 +271,20 @@ def realize():
final_tags = persistent_tags
final_tags_set = _get_tags_as_set(tags=final_tags)
for tag in _read_tags_from_module_params(module.params, 'add_tags'):
if TagElement(tag) in final_tags_set:
for final_tag in final_tags:
if final_tag['scope'] == tag['scope']:
final_tag['tag'] = tag['tag']
break
else:
if TagElement(tag) not in final_tags_set:
final_tags += tag,
final_tags_set = _get_tags_as_set(tags=final_tags)

if init_tags_set == final_tags_set:
module.exit_json(msg="No tags detected to update")

post_body = {
"virtual_machine_id": virtual_machine_id,
"external_id": virtual_machine_id,
"tags": final_tags
}
_, resp = policy_communicator.request(
VM_UPDATE_URL + '?action=update_tags', data=post_body,
method="POST")
method="POST", base_url='fabric')
module.exit_json(msg="Successfully updated tags on VM {}".format(
virtual_machine_id), changed=True)
except Exception as err:
Expand Down

0 comments on commit a0d662d

Please sign in to comment.