From 74c78ccc38502c0c3f3a11f493880feb5893364c Mon Sep 17 00:00:00 2001 From: Mike Morency Date: Thu, 11 Jul 2024 11:29:06 -0400 Subject: [PATCH] generalize folder lookup logic --- plugins/module_utils/vmware.py | 3 +- plugins/module_utils/vmware_folder_paths.py | 70 +++++++++++++++++++++ plugins/modules/folder_template_from_vm.py | 21 +++---- 3 files changed, 79 insertions(+), 15 deletions(-) create mode 100644 plugins/module_utils/vmware_folder_paths.py diff --git a/plugins/module_utils/vmware.py b/plugins/module_utils/vmware.py index 514fa89d..d0987e8d 100644 --- a/plugins/module_utils/vmware.py +++ b/plugins/module_utils/vmware.py @@ -287,7 +287,7 @@ def get_folder_by_name(self, folder_name, fail_on_missing=False): def get_folder_by_absolute_path(self, folder_path, fail_on_missing=False): """ - Get a folders with the given absolute path. Paths are unique so only + Get a folder with the given path. Paths are unique when they are absolute so only one folder can be returned at most. An absolute path might look like 'Datacenter Name/vm/my/folder/structure' Args: @@ -297,6 +297,7 @@ def get_folder_by_absolute_path(self, folder_path, fail_on_missing=False): folder object or None """ folder = self.si.content.searchIndex.FindByInventoryPath(folder_path) + if not folder and fail_on_missing: self.module.fail_json("Unable to find folder with absolute path %s" % folder_path) return folder diff --git a/plugins/module_utils/vmware_folder_paths.py b/plugins/module_utils/vmware_folder_paths.py new file mode 100644 index 00000000..5d18b41e --- /dev/null +++ b/plugins/module_utils/vmware_folder_paths.py @@ -0,0 +1,70 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Ansible Cloud Team (@ansible-collections) +# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) +# SPDX-License-Identifier: GPL-3.0-or-later + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +FOLDER_TYPES = ('vm', 'host', 'network', 'datastore') + + +def __prepend_datacenter_and_folder_type(folder_path, datacenter_name, folder_type=None): + """ + Formats a folder path so it is absolute, meaning it includes the datacenter name and + type (vm, host, etc) at the start of the path. If path already starts with + the datacenter name, nothing is added. + Eg: rest/of/path -> datacenter name/type/rest/of/path + """ + folder_path = folder_path.lstrip('/') + if folder_path.startswith(datacenter_name): + return folder_path + + if folder_type not in FOLDER_TYPES: + raise ValueError("folder_type %s not in acceptable " % folder_type + + "folder type values %s" % FOLDER_TYPES) + + return '/'.join([datacenter_name, folder_type, folder_path]) + + +def format_folder_path_as_vm_fq_path(folder_path, datacenter_name): + """ + Formats a VM folder path so it is absolute, meaning it prepends + 'datacenter name/vm/' to the path if needed. If path already starts with + the datacenter name, nothing is added. + Eg: rest/of/path -> datacenter name/vm/rest/of/path + """ + return __prepend_datacenter_and_folder_type(folder_path, datacenter_name, folder_type='vm') + + +def format_folder_path_as_host_fq_path(folder_path, datacenter_name): + """ + Formats a host folder path so it is absolute, meaning it prepends + 'datacenter name/vm/' to the path if needed. If path already starts with + the datacenter name, nothing is added. + Eg: rest/of/path -> datacenter name/host/rest/of/path + """ + return __prepend_datacenter_and_folder_type(folder_path, datacenter_name, folder_type='host') + + +def format_folder_path_as_network_fq_path(folder_path, datacenter_name): + """ + Formats a network folder path so it is absolute, meaning it prepends + 'datacenter name/network/' to the path if needed. If path already starts with + the datacenter name, nothing is added. + Eg: rest/of/path -> datacenter name/network/rest/of/path + """ + return __prepend_datacenter_and_folder_type(folder_path, datacenter_name, folder_type='network') + + +def format_folder_path_as_datastore_fq_path(folder_path, datacenter_name): + """ + Formats a datastore folder path so it is absolute, meaning it prepends + 'datacenter name/datastore/' to the path if needed. If path already starts with + the datacenter name, nothing is added. + Eg: rest/of/path -> datacenter name/datastore/rest/of/path + """ + return __prepend_datacenter_and_folder_type(folder_path, datacenter_name, folder_type='datastore') diff --git a/plugins/modules/folder_template_from_vm.py b/plugins/modules/folder_template_from_vm.py index ffd64bac..dc0ac17e 100644 --- a/plugins/modules/folder_template_from_vm.py +++ b/plugins/modules/folder_template_from_vm.py @@ -145,6 +145,7 @@ from ansible.module_utils.basic import AnsibleModule from ansible_collections.vmware.vmware.plugins.module_utils.vmware import PyVmomi, vmware_argument_spec +from ansible_collections.vmware.vmware.plugins.module_utils.vmware_folder_paths import format_folder_path_as_vm_fq_path PYVMOMI_IMP_ERR = None try: @@ -168,25 +169,17 @@ def __init__(self, module): self.template_name = self.params.get("template_name") - self.template_folder = self.__init_template_folder_param() + fq_folder_path = format_folder_path_as_vm_fq_path( + self.params.get("template_folder"), + self.params.get("datacenter") + ) + self.template_folder = self.get_folder_by_absolute_path(fq_folder_path, fail_on_missing=True) + self.vm_name_match = self.params.get("vm_name_match") self.datastore = self.params.get("datastore") self.resource_pool = self.params.get("resource_pool") self.wait_for_template = self.params.get("wait_for_template") - def __init_template_folder_param(self): - """ - Formats an absolute folder path for use within the class. If path does not start with - the datacenter name, we add that and 'vm' to the start of the path. - Eg: rest/of/path -> datacenter name/vm/rest/of/path - """ - folder_name = self.params.get("template_folder") - datacenter_name = self.params.get("datacenter") - if not folder_name.startswith((datacenter_name, '/' + datacenter_name)): - folder_name = datacenter_name + '/vm/' + folder_name - - return self.get_folder_by_absolute_path(folder_name, fail_on_missing=True) - def check_if_template_exists(self): """ Checks if a template with the given name and folder already exists