diff options
513 files changed, 0 insertions, 71349 deletions
diff --git a/contrib/inventory/vmware.ini b/contrib/inventory/vmware.ini deleted file mode 100644 index 93de5d67b4..0000000000 --- a/contrib/inventory/vmware.ini +++ /dev/null @@ -1,50 +0,0 @@ -# Ansible VMware external inventory script settings - -[defaults] - -# If true (the default), return only guest VMs. If false, also return host -# systems in the results. -guests_only = True - -# Specify an alternate group name for guest VMs. If not defined, defaults to -# the basename of the inventory script + "_vm", e.g. "vmware_vm". -#vm_group = vm_group_name - -# Specify an alternate group name for host systems when guests_only=false. -# If not defined, defaults to the basename of the inventory script + "_hw", -# e.g. "vmware_hw". -#hw_group = hw_group_name - -# Specify the number of seconds to use the inventory cache before it is -# considered stale. If not defined, defaults to 0 seconds. -#cache_max_age = 3600 - -# Specify the directory used for storing the inventory cache. If not defined, -# caching will be disabled. -#cache_dir = ~/.cache/ansible - -# Specify a prefix filter. Any VMs with names beginning with this string will -# not be returned. -# prefix_filter = test_ - -# Specify a cluster filter list (colon delimited). Only clusters matching by -# name will be scanned for virtualmachines -#clusters = cluster1,cluster2 - -[auth] - -# Specify hostname or IP address of vCenter/ESXi server. A port may be -# included with the hostname, e.g.: vcenter.example.com:8443. This setting -# may also be defined via the VMWARE_HOST environment variable. -host = vcenter.example.com - -# Specify a username to access the vCenter host. This setting may also be -# defined with the VMWARE_USER environment variable. -user = ihasaccess - -# Specify a password to access the vCenter host. This setting may also be -# defined with the VMWARE_PASSWORD environment variable. -password = ssshverysecret - -# Force SSL certificate checking by default or ignore self-signed certs. -#sslcheck=True diff --git a/contrib/inventory/vmware.py b/contrib/inventory/vmware.py deleted file mode 100755 index 483fd42318..0000000000 --- a/contrib/inventory/vmware.py +++ /dev/null @@ -1,472 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -''' -VMware Inventory Script -======================= - -Retrieve information about virtual machines from a vCenter server or -standalone ESX host. When `group_by=false` (in the INI file), host systems -are also returned in addition to VMs. - -This script will attempt to read configuration from an INI file with the same -base filename if present, or `vmware.ini` if not. It is possible to create -symlinks to the inventory script to support multiple configurations, e.g.: - -* `vmware.py` (this script) -* `vmware.ini` (default configuration, will be read by `vmware.py`) -* `vmware_test.py` (symlink to `vmware.py`) -* `vmware_test.ini` (test configuration, will be read by `vmware_test.py`) -* `vmware_other.py` (symlink to `vmware.py`, will read `vmware.ini` since no - `vmware_other.ini` exists) - -The path to an INI file may also be specified via the `VMWARE_INI` environment -variable, in which case the filename matching rules above will not apply. - -Host and authentication parameters may be specified via the `VMWARE_HOST`, -`VMWARE_USER` and `VMWARE_PASSWORD` environment variables; these options will -take precedence over options present in the INI file. An INI file is not -required if these options are specified using environment variables. -''' - -from __future__ import print_function - -import json -import logging -import optparse -import os -import ssl -import sys -import time - -from ansible.module_utils.common._collections_compat import MutableMapping -from ansible.module_utils.six import integer_types, text_type, string_types -from ansible.module_utils.six.moves import configparser - -# Disable logging message trigged by pSphere/suds. -try: - from logging import NullHandler -except ImportError: - from logging import Handler - - class NullHandler(Handler): - def emit(self, record): - pass - -logging.getLogger('psphere').addHandler(NullHandler()) -logging.getLogger('suds').addHandler(NullHandler()) - -from psphere.client import Client -from psphere.errors import ObjectNotFoundError -from psphere.managedobjects import HostSystem, VirtualMachine, ManagedObject, Network, ClusterComputeResource -from suds.sudsobject import Object as SudsObject - - -class VMwareInventory(object): - - def __init__(self, guests_only=None): - self.config = configparser.SafeConfigParser() - if os.environ.get('VMWARE_INI', ''): - config_files = [os.environ['VMWARE_INI']] - else: - config_files = [os.path.abspath(sys.argv[0]).rstrip('.py') + '.ini', 'vmware.ini'] - for config_file in config_files: - if os.path.exists(config_file): - self.config.read(config_file) - break - - # Retrieve only guest VMs, or include host systems? - if guests_only is not None: - self.guests_only = guests_only - elif self.config.has_option('defaults', 'guests_only'): - self.guests_only = self.config.getboolean('defaults', 'guests_only') - else: - self.guests_only = True - - # Read authentication information from VMware environment variables - # (if set), otherwise from INI file. - auth_host = os.environ.get('VMWARE_HOST') - if not auth_host and self.config.has_option('auth', 'host'): - auth_host = self.config.get('auth', 'host') - auth_user = os.environ.get('VMWARE_USER') - if not auth_user and self.config.has_option('auth', 'user'): - auth_user = self.config.get('auth', 'user') - auth_password = os.environ.get('VMWARE_PASSWORD') - if not auth_password and self.config.has_option('auth', 'password'): - auth_password = self.config.get('auth', 'password') - sslcheck = os.environ.get('VMWARE_SSLCHECK') - if not sslcheck and self.config.has_option('auth', 'sslcheck'): - sslcheck = self.config.get('auth', 'sslcheck') - if not sslcheck: - sslcheck = True - else: - if sslcheck.lower() in ['no', 'false']: - sslcheck = False - else: - sslcheck = True - - # Limit the clusters being scanned - self.filter_clusters = os.environ.get('VMWARE_CLUSTERS') - if not self.filter_clusters and self.config.has_option('defaults', 'clusters'): - self.filter_clusters = self.config.get('defaults', 'clusters') - if self.filter_clusters: - self.filter_clusters = [x.strip() for x in self.filter_clusters.split(',') if x.strip()] - - # Override certificate checks - if not sslcheck: - if hasattr(ssl, '_create_unverified_context'): - ssl._create_default_https_context = ssl._create_unverified_context - - # Create the VMware client connection. - self.client = Client(auth_host, auth_user, auth_password) - - def _put_cache(self, name, value): - ''' - Saves the value to cache with the name given. - ''' - if self.config.has_option('defaults', 'cache_dir'): - cache_dir = os.path.expanduser(self.config.get('defaults', 'cache_dir')) - if not os.path.exists(cache_dir): - os.makedirs(cache_dir) - cache_file = os.path.join(cache_dir, name) - with open(cache_file, 'w') as cache: - json.dump(value, cache) - - def _get_cache(self, name, default=None): - ''' - Retrieves the value from cache for the given name. - ''' - if self.config.has_option('defaults', 'cache_dir'): - cache_dir = self.config.get('defaults', 'cache_dir') - cache_file = os.path.join(cache_dir, name) - if os.path.exists(cache_file): - if self.config.has_option('defaults', 'cache_max_age'): - cache_max_age = self.config.getint('defaults', 'cache_max_age') - else: - cache_max_age = 0 - cache_stat = os.stat(cache_file) - if (cache_stat.st_mtime + cache_max_age) >= time.time(): - with open(cache_file) as cache: - return json.load(cache) - return default - - def _flatten_dict(self, d, parent_key='', sep='_'): - ''' - Flatten nested dicts by combining keys with a separator. Lists with - only string items are included as is; any other lists are discarded. - ''' - items = [] - for k, v in d.items(): - if k.startswith('_'): - continue - new_key = parent_key + sep + k if parent_key else k - if isinstance(v, MutableMapping): - items.extend(self._flatten_dict(v, new_key, sep).items()) - elif isinstance(v, (list, tuple)): - if all([isinstance(x, string_types) for x in v]): - items.append((new_key, v)) - else: - items.append((new_key, v)) - return dict(items) - - def _get_obj_info(self, obj, depth=99, seen=None): - ''' - Recursively build a data structure for the given pSphere object (depth - only applies to ManagedObject instances). - ''' - seen = seen or set() - if isinstance(obj, ManagedObject): - try: - obj_unicode = text_type(getattr(obj, 'name')) - except AttributeError: - obj_unicode = () - if obj in seen: - return obj_unicode - seen.add(obj) - if depth <= 0: - return obj_unicode - d = {} - for attr in dir(obj): - if attr.startswith('_'): - continue - try: - val = getattr(obj, attr) - obj_info = self._get_obj_info(val, depth - 1, seen) - if obj_info != (): - d[attr] = obj_info - except Exception as e: - pass - return d - elif isinstance(obj, SudsObject): - d = {} - for key, val in iter(obj): - obj_info = self._get_obj_info(val, depth, seen) - if obj_info != (): - d[key] = obj_info - return d - elif isinstance(obj, (list, tuple)): - l = [] - for val in iter(obj): - obj_info = self._get_obj_info(val, depth, seen) - if obj_info != (): - l.append(obj_info) - return l - elif isinstance(obj, (type(None), bool, float) + string_types + integer_types): - return obj - else: - return () - - def _get_host_info(self, host, prefix='vmware'): - ''' - Return a flattened dict with info about the given host system. - ''' - host_info = { - 'name': host.name, - } - for attr in ('datastore', 'network', 'vm'): - try: - value = getattr(host, attr) - host_info['%ss' % attr] = self._get_obj_info(value, depth=0) - except AttributeError: - host_info['%ss' % attr] = [] - for k, v in self._get_obj_info(host.summary, depth=0).items(): - if isinstance(v, MutableMapping): - for k2, v2 in v.items(): - host_info[k2] = v2 - elif k != 'host': - host_info[k] = v - try: - host_info['ipAddress'] = host.config.network.vnic[0].spec.ip.ipAddress - except Exception as e: - print(e, file=sys.stderr) - host_info = self._flatten_dict(host_info, prefix) - if ('%s_ipAddress' % prefix) in host_info: - host_info['ansible_ssh_host'] = host_info['%s_ipAddress' % prefix] - return host_info - - def _get_vm_info(self, vm, prefix='vmware'): - ''' - Return a flattened dict with info about the given virtual machine. - ''' - vm_info = { - 'name': vm.name, - } - for attr in ('datastore', 'network'): - try: - value = getattr(vm, attr) - vm_info['%ss' % attr] = self._get_obj_info(value, depth=0) - except AttributeError: - vm_info['%ss' % attr] = [] - try: - vm_info['resourcePool'] = self._get_obj_info(vm.resourcePool, depth=0) - except AttributeError: - vm_info['resourcePool'] = '' - try: - vm_info['guestState'] = vm.guest.guestState - except AttributeError: - vm_info['guestState'] = '' - for k, v in self._get_obj_info(vm.summary, depth=0).items(): - if isinstance(v, MutableMapping): - for k2, v2 in v.items(): - if k2 == 'host': - k2 = 'hostSystem' - vm_info[k2] = v2 - elif k != 'vm': - vm_info[k] = v - vm_info = self._flatten_dict(vm_info, prefix) - if ('%s_ipAddress' % prefix) in vm_info: - vm_info['ansible_ssh_host'] = vm_info['%s_ipAddress' % prefix] - return vm_info - - def _add_host(self, inv, parent_group, host_name): - ''' - Add the host to the parent group in the given inventory. - ''' - p_group = inv.setdefault(parent_group, []) - if isinstance(p_group, dict): - group_hosts = p_group.setdefault('hosts', []) - else: - group_hosts = p_group - if host_name not in group_hosts: - group_hosts.append(host_name) - - def _add_child(self, inv, parent_group, child_group): - ''' - Add a child group to a parent group in the given inventory. - ''' - if parent_group != 'all': - p_group = inv.setdefault(parent_group, {}) - if not isinstance(p_group, dict): - inv[parent_group] = {'hosts': p_group} - p_group = inv[parent_group] - group_children = p_group.setdefault('children', []) - if child_group not in group_children: - group_children.append(child_group) - inv.setdefault(child_group, []) - - def get_inventory(self, meta_hostvars=True): - ''' - Reads the inventory from cache or VMware API via pSphere. - ''' - # Use different cache names for guests only vs. all hosts. - if self.guests_only: - cache_name = '__inventory_guests__' - else: - cache_name = '__inventory_all__' - - inv = self._get_cache(cache_name, None) - if inv is not None: - return inv - - inv = {'all': {'hosts': []}} - if meta_hostvars: - inv['_meta'] = {'hostvars': {}} - - default_group = os.path.basename(sys.argv[0]).rstrip('.py') - - if not self.guests_only: - if self.config.has_option('defaults', 'hw_group'): - hw_group = self.config.get('defaults', 'hw_group') - else: - hw_group = default_group + '_hw' - - if self.config.has_option('defaults', 'vm_group'): - vm_group = self.config.get('defaults', 'vm_group') - else: - vm_group = default_group + '_vm' - - if self.config.has_option('defaults', 'prefix_filter'): - prefix_filter = self.config.get('defaults', 'prefix_filter') - else: - prefix_filter = None - - if self.filter_clusters: - # Loop through clusters and find hosts: - hosts = [] - for cluster in ClusterComputeResource.all(self.client): - if cluster.name in self.filter_clusters: - for host in cluster.host: - hosts.append(host) - else: - # Get list of all physical hosts - hosts = HostSystem.all(self.client) - - # Loop through physical hosts: - for host in hosts: - - if not self.guests_only: - self._add_host(inv, 'all', host.name) - self._add_host(inv, hw_group, host.name) - host_info = self._get_host_info(host) - if meta_hostvars: - inv['_meta']['hostvars'][host.name] = host_info - self._put_cache(host.name, host_info) - - # Loop through all VMs on physical host. - for vm in host.vm: - if prefix_filter: - if vm.name.startswith(prefix_filter): - continue - self._add_host(inv, 'all', vm.name) - self._add_host(inv, vm_group, vm.name) - vm_info = self._get_vm_info(vm) - if meta_hostvars: - inv['_meta']['hostvars'][vm.name] = vm_info - self._put_cache(vm.name, vm_info) - - # Group by resource pool. - vm_resourcePool = vm_info.get('vmware_resourcePool', None) - if vm_resourcePool: - self._add_child(inv, vm_group, 'resource_pools') - self._add_child(inv, 'resource_pools', vm_resourcePool) - self._add_host(inv, vm_resourcePool, vm.name) - - # Group by datastore. - for vm_datastore in vm_info.get('vmware_datastores', []): - self._add_child(inv, vm_group, 'datastores') - self._add_child(inv, 'datastores', vm_datastore) - self._add_host(inv, vm_datastore, vm.name) - - # Group by network. - for vm_network in vm_info.get('vmware_networks', []): - self._add_child(inv, vm_group, 'networks') - self._add_child(inv, 'networks', vm_network) - self._add_host(inv, vm_network, vm.name) - - # Group by guest OS. - vm_guestId = vm_info.get('vmware_guestId', None) - if vm_guestId: - self._add_child(inv, vm_group, 'guests') - self._add_child(inv, 'guests', vm_guestId) - self._add_host(inv, vm_guestId, vm.name) - - # Group all VM templates. - vm_template = vm_info.get('vmware_template', False) - if vm_template: - self._add_child(inv, vm_group, 'templates') - self._add_host(inv, 'templates', vm.name) - - self._put_cache(cache_name, inv) - return inv - - def get_host(self, hostname): - ''' - Read info about a specific host or VM from cache or VMware API. - ''' - inv = self._get_cache(hostname, None) - if inv is not None: - return inv - - if not self.guests_only: - try: - host = HostSystem.get(self.client, name=hostname) - inv = self._get_host_info(host) - except ObjectNotFoundError: - pass - - if inv is None: - try: - vm = VirtualMachine.get(self.client, name=hostname) - inv = self._get_vm_info(vm) - except ObjectNotFoundError: - pass - - if inv is not None: - self._put_cache(hostname, inv) - return inv or {} - - -def main(): - parser = optparse.OptionParser() - parser.add_option('--list', action='store_true', dest='list', - default=False, help='Output inventory groups and hosts') - parser.add_option('--host', dest='host', default=None, metavar='HOST', - help='Output variables only for the given hostname') - # Additional options for use when running the script standalone, but never - # used by Ansible. - parser.add_option('--pretty', action='store_true', dest='pretty', - default=False, help='Output nicely-formatted JSON') - parser.add_option('--include-host-systems', action='store_true', - dest='include_host_systems', default=False, - help='Include host systems in addition to VMs') - parser.add_option('--no-meta-hostvars', action='store_false', - dest='meta_hostvars', default=True, - help='Exclude [\'_meta\'][\'hostvars\'] with --list') - options, args = parser.parse_args() - - if options.include_host_systems: - vmware_inventory = VMwareInventory(guests_only=False) - else: - vmware_inventory = VMwareInventory() - if options.host is not None: - inventory = vmware_inventory.get_host(options.host) - else: - inventory = vmware_inventory.get_inventory(options.meta_hostvars) - - json_kwargs = {} - if options.pretty: - json_kwargs.update({'indent': 4, 'sort_keys': True}) - json.dump(inventory, sys.stdout, **json_kwargs) - - -if __name__ == '__main__': - main() diff --git a/contrib/inventory/vmware_inventory.ini b/contrib/inventory/vmware_inventory.ini deleted file mode 100644 index f94570f891..0000000000 --- a/contrib/inventory/vmware_inventory.ini +++ /dev/null @@ -1,127 +0,0 @@ -# Ansible VMware external inventory script settings - -[vmware] - -# The resolvable hostname or ip address of the vsphere -server=vcenter - -# The port for the vsphere API -#port=443 - -# The username with access to the vsphere API. This setting -# may also be defined via the VMWARE_USERNAME environment variable. -username=administrator@vsphere.local - -# The password for the vsphere API. This setting -# may also be defined via the VMWARE_PASSWORD environment variable. -password=vmware - -# Verify the server's SSL certificate -#validate_certs = True - -# Specify the number of seconds to use the inventory cache before it is -# considered stale. If not defined, defaults to 0 seconds. -#cache_max_age = 3600 - - -# Specify the directory used for storing the inventory cache. If not defined, -# caching will be disabled. -#cache_path = ~/.cache/ansible - - -# Max object level refers to the level of recursion the script will delve into -# the objects returned from pyvomi to find serializable facts. The default -# level of 0 is sufficient for most tasks and will be the most performant. -# Beware that the recursion can exceed python's limit (causing traceback), -# cause sluggish script performance and return huge blobs of facts. -# If you do not know what you are doing, leave this set to 1. -#max_object_level=1 - - -# Lower the keynames for facts to make addressing them easier. -#lower_var_keys=True - - -# Don't retrieve and process some VMware attribute keys -# Default values permit to sanitize inventory meta and to improve a little bit -# performance by removing non-common group attributes. -#skip_keys = declaredalarmstate,disabledmethod,dynamicproperty,dynamictype,environmentbrowser,managedby,parent,childtype,resourceconfig - - -# Host alias for objects in the inventory. VMware allows duplicate VM names -# so they can not be considered unique. Use this setting to alter the alias -# returned for the hosts. Any atributes for the guest can be used to build -# this alias. The default combines the config name and the config uuid and -# expects that the ansible_host will be set by the host_pattern. -#alias_pattern={{ config.name + '_' + config.uuid }} - - -# Host pattern is the value set for ansible_host and ansible_ssh_host, which -# needs to be a hostname or ipaddress the ansible controlhost can reach. -#host_pattern={{ guest.ipaddress }} - - -# Host filters are a comma separated list of jinja patterns to remove -# non-matching hosts from the final result. -# EXAMPLES: -# host_filters={{ config.guestid == 'rhel7_64Guest' }} -# host_filters={{ config.cpuhotremoveenabled != False }},{{ runtime.maxmemoryusage >= 512 }} -# host_filters={{ config.cpuhotremoveenabled != False }},{{ runtime.maxmemoryusage >= 512 }} -# host_filters={{ runtime.powerstate == "poweredOn" }} -# host_filters={{ guest.gueststate == "notRunning" }} -# The default value is powerstate of virtual machine equal to "poweredOn". (Changed in version 2.5) -# Runtime state does not require to have vmware tools installed as compared to "guest.gueststate" -#host_filters={{ runtime.powerstate == "poweredOn" }} - - - -# Groupby patterns enable the user to create groups via any possible jinja -# expression. The resulting value will the groupname and the host will be added -# to that group. Be careful to not make expressions that simply return True/False -# because those values will become the literal group name. The patterns can be -# comma delimited to create as many groups as necessary -#groupby_patterns={{ guest.guestid }},{{ 'templates' if config.template else 'guests'}} - -# Group by custom fields will use VMware custom fields to generate hostgroups -# based on {{ custom_field_group_prefix }} + field_name + _ + field_value -# Set groupby_custom_field to True will enable this feature -# If custom field value is comma separated, multiple groups are created. -# Warning: This required max_object_level to be set to 2 or greater. -#groupby_custom_field = False - -# You can customize prefix used by custom field hostgroups generation here. -# vmware_tag_ prefix is the default and consistent with ec2_tag_ -#custom_field_group_prefix = vmware_tag_ - -# You can blacklist custom fields so that they are not included in the -# groupby_custom_field option. This is useful when you have custom fields that -# have values that are unique to individual hosts. Timestamps for example. -# The groupby_custom_field_excludes option should be a comma separated list of custom -# field keys to be blacklisted. -#groupby_custom_field_excludes=<custom_field_1>,<custom_field_2>,<custom_field_3> - -# The script attempts to recurse into virtualmachine objects and serialize -# all available data. The serialization is comprehensive but slow. If the -# vcenter environment is large and the desired properties are known, create -# a 'properties' section in this config and make an arbitrary list of -# key=value settings where the value is a path to a specific property. If -# If this feature is enabled, be sure to fetch every property that is used -# in the jinja expressions defined above. For performance tuning, reduce -# the number of properties to the smallest amount possible and limit the -# use of properties that are not direct attributes of vim.VirtualMachine -#[properties] -#prop01=name -#prop02=config.cpuHotAddEnabled -#prop03=config.cpuHotRemoveEnabled -#prop04=config.instanceUuid -#prop05=config.hardware.numCPU -#prop06=config.template -#prop07=config.name -#prop08=guest.hostName -#prop09=guest.ipAddress -#prop10=guest.guestId -#prop11=guest.guestState -#prop12=runtime.maxMemoryUsage -# In order to populate `customValue` (virtual machine's custom attributes) inside hostvars, -# uncomment following property. Please see - https://github.com/ansible/ansible/issues/41395 -#prop13=customValue diff --git a/contrib/inventory/vmware_inventory.py b/contrib/inventory/vmware_inventory.py deleted file mode 100755 index 0271110c96..0000000000 --- a/contrib/inventory/vmware_inventory.py +++ /dev/null @@ -1,793 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# Copyright (C): 2017, Ansible Project -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# Requirements -# - pyvmomi >= 6.0.0.2016.4 - -# TODO: -# * more jq examples -# * optional folder hierarchy - -""" -$ jq '._meta.hostvars[].config' data.json | head -{ - "alternateguestname": "", - "instanceuuid": "5035a5cd-b8e8-d717-e133-2d383eb0d675", - "memoryhotaddenabled": false, - "guestfullname": "Red Hat Enterprise Linux 7 (64-bit)", - "changeversion": "2016-05-16T18:43:14.977925Z", - "uuid": "4235fc97-5ddb-7a17-193b-9a3ac97dc7b4", - "cpuhotremoveenabled": false, - "vpmcenabled": false, - "firmware": "bios", -""" - -from __future__ import print_function - -import atexit -import datetime -import itertools -import json -import os -import re -import ssl -import sys -import uuid -from time import time - -from jinja2 import Environment - -from ansible.module_utils.six import integer_types, PY3 -from ansible.module_utils.six.moves import configparser - -try: - import argparse -except ImportError: - sys.exit('Error: This inventory script required "argparse" python module. Please install it or upgrade to python-2.7') - -try: - from pyVmomi import vim, vmodl - from pyVim.connect import SmartConnect, Disconnect -except ImportError: - sys.exit("ERROR: This inventory script required 'pyVmomi' Python module, it was not able to load it") - - -def regex_match(s, pattern): - '''Custom filter for regex matching''' - reg = re.compile(pattern) - if reg.match(s): - return True - else: - return False - - -def select_chain_match(inlist, key, pattern): - '''Get a key from a list of dicts, squash values to a single list, then filter''' - outlist = [x[key] for x in inlist] - outlist = list(itertools.chain(*outlist)) - outlist = [x for x in outlist if regex_match(x, pattern)] - return outlist - - -class VMwareMissingHostException(Exception): - pass - - -class VMWareInventory(object): - __name__ = 'VMWareInventory' - - guest_props = False - instances = [] - debug = False - load_dumpfile = None - write_dumpfile = None - maxlevel = 1 - lowerkeys = True - config = None - cache_max_age = None - cache_path_cache = None - cache_path_index = None - cache_dir = None - server = None - port = None - username = None - password = None - validate_certs = True - host_filters = [] - skip_keys = [] - groupby_patterns = [] - groupby_custom_field_excludes = [] - - safe_types = [bool, str, float, None] + list(integer_types) - iter_types = [dict, list] - - bad_types = ['Array', 'disabledMethod', 'declaredAlarmState'] - - vimTableMaxDepth = { - "vim.HostSystem": 2, - "vim.VirtualMachine": 2, - } - - custom_fields = {} - - # use jinja environments to allow for custom filters - env = Environment() - env.filters['regex_match'] = regex_match - env.filters['select_chain_match'] = select_chain_match - - # translation table for attributes to fetch for known vim types - - vimTable = { - vim.Datastore: ['_moId', 'name'], - vim.ResourcePool: ['_moId', 'name'], - vim.HostSystem: ['_moId', 'name'], - } - - @staticmethod - def _empty_inventory(): - return {"_meta": {"hostvars": {}}} - - def __init__(self, load=True): - self.inventory = VMWareInventory._empty_inventory() - - if load: - # Read settings and parse CLI arguments - self.parse_cli_args() - self.read_settings() - - # Check the cache - cache_valid = self.is_cache_valid() - - # Handle Cache - if self.args.refresh_cache or not cache_valid: - self.do_api_calls_update_cache() - else: - self.debugl('loading inventory from cache') - self.inventory = self.get_inventory_from_cache() - - def debugl(self, text): - if self.args.debug: - try: - text = str(text) - except UnicodeEncodeError: - text = text.encode('utf-8') - print('%s %s' % (datetime.datetime.now(), text)) - - def show(self): - # Data to print - self.debugl('dumping results') - data_to_print = None - if self.args.host: - data_to_print = self.get_host_info(self.args.host) - elif self.args.list: - # Display list of instances for inventory - data_to_print = self.inventory - return json.dumps(data_to_print, indent=2) - - def is_cache_valid(self): - ''' Determines if the cache files have expired, or if it is still valid ''' - - valid = False - - if os.path.isfile(self.cache_path_cache): - mod_time = os.path.getmtime(self.cache_path_cache) - current_time = time() - if (mod_time + self.cache_max_age) > current_time: - valid = True - - return valid - - def do_api_calls_update_cache(self): - ''' Get instances and cache the data ''' - self.inventory = self.instances_to_inventory(self.get_instances()) - self.write_to_cache(self.inventory) - - def write_to_cache(self, data): - ''' Dump inventory to json file ''' - with open(self.cache_path_cache, 'w') as f: - f.write(json.dumps(data, indent=2)) - - def get_inventory_from_cache(self): - ''' Read in jsonified inventory ''' - - jdata = None - with open(self.cache_path_cache, 'r') as f: - jdata = f.read() - return json.loads(jdata) - - def read_settings(self): - ''' Reads the settings from the vmware_inventory.ini file ''' - - scriptbasename = __file__ - scriptbasename = os.path.basename(scriptbasename) - scriptbasename = scriptbasename.replace('.py', '') - - defaults = {'vmware': { - 'server': '', - 'port': 443, - 'username': '', - 'password': '', - 'validate_certs': True, - 'ini_path': os.path.join(os.path.dirname(__file__), '%s.ini' % scriptbasename), - 'cache_name': 'ansible-vmware', - 'cache_path': '~/.ansible/tmp', - 'cache_max_age': 3600, - 'max_object_level': 1, - 'skip_keys': 'declaredalarmstate,' - 'disabledmethod,' - 'dynamicproperty,' - 'dynamictype,' - 'environmentbrowser,' - 'managedby,' - 'parent,' - 'childtype,' - 'resourceconfig', - 'alias_pattern': '{{ config.name + "_" + config.uuid }}', - 'host_pattern': '{{ guest.ipaddress }}', - 'host_filters': '{{ runtime.powerstate == "poweredOn" }}', - 'groupby_patterns': '{{ guest.guestid }},{{ "templates" if config.template else "guests"}}', - 'lower_var_keys': True, - 'custom_field_group_prefix': 'vmware_tag_', - 'groupby_custom_field_excludes': '', - 'groupby_custom_field': False} - } - - if PY3: - config = configparser.ConfigParser() - else: - config = configparser.SafeConfigParser() - - # where is the config? - vmware_ini_path = os.environ.get('VMWARE_INI_PATH', defaults['vmware']['ini_path']) - vmware_ini_path = os.path.expanduser(os.path.expandvars(vmware_ini_path)) - config.read(vmware_ini_path) - - if 'vmware' not in config.sections(): - config.add_section('vmware') - - # apply defaults - for k, v in defaults['vmware'].items(): - if not config.has_option('vmware', k): - config.set('vmware', k, str(v)) - - # where is the cache? - self.cache_dir = os.path.expanduser(config.get('vmware', 'cache_path')) - if self.cache_dir and not os.path.exists(self.cache_dir): - os.makedirs(self.cache_dir) - - # set the cache filename and max age - cache_name = config.get('vmware', 'cache_name') - self.cache_path_cache = self.cache_dir + "/%s.cache" % cache_name - self.debugl('cache path is %s' % self.cache_path_cache) - self.cache_max_age = int(config.getint('vmware', 'cache_max_age')) - - # mark the connection info - self.server = os.environ.get('VMWARE_SERVER', config.get('vmware', 'server')) - self.debugl('server is %s' % self.server) - self.port = int(os.environ.get('VMWARE_PORT', config.get('vmware', 'port'))) - self.username = os.environ.get('VMWARE_USERNAME', config.get('vmware', 'username')) - self.debugl('username is %s' % self.username) - self.password = os.environ.get('VMWARE_PASSWORD', config.get('vmware', 'password', raw=True)) - self.validate_certs = os.environ.get('VMWARE_VALIDATE_CERTS', config.get('vmware', 'validate_certs')) - if self.validate_certs in ['no', 'false', 'False', False]: - self.validate_certs = False - - self.debugl('cert validation is %s' % self.validate_certs) - - # behavior control - self.maxlevel = int(config.get('vmware', 'max_object_level')) - self.debugl('max object level is %s' % self.maxlevel) - self.lowerkeys = config.get('vmware', 'lower_var_keys') - if type(self.lowerkeys) != bool: - if str(self.lowerkeys).lower() in ['yes', 'true', '1']: - self.lowerkeys = True - else: - self.lowerkeys = False - self.debugl('lower keys is %s' % self.lowerkeys) - self.skip_keys = list(config.get('vmware', 'skip_keys').split(',')) - self.debugl('skip keys is %s' % self.skip_keys) - temp_host_filters = list(config.get('vmware', 'host_filters').split('}},')) - for host_filter in temp_host_filters: - host_filter = host_filter.rstrip() - if host_filter != "": - if not host_filter.endswith("}}"): - host_filter += "}}" - self.host_filters.append(host_filter) - self.debugl('host filters are %s' % self.host_filters) - - temp_groupby_patterns = list(config.get('vmware', 'groupby_patterns').split('}},')) - for groupby_pattern in temp_groupby_patterns: - groupby_pattern = groupby_pattern.rstrip() - if groupby_pattern != "": - if not groupby_pattern.endswith("}}"): - groupby_pattern += "}}" - self.groupby_patterns.append(groupby_pattern) - self.debugl('groupby patterns are %s' % self.groupby_patterns) - temp_groupby_custom_field_excludes = config.get('vmware', 'groupby_custom_field_excludes') - self.groupby_custom_field_excludes = [x.strip('"') for x in [y.strip("'") for y in temp_groupby_custom_field_excludes.split(",")]] - self.debugl('groupby exclude strings are %s' % self.groupby_custom_field_excludes) - - # Special feature to disable the brute force serialization of the - # virtual machine objects. The key name for these properties does not - # matter because the values are just items for a larger list. - if config.has_section('properties'): - self.guest_props = [] - for prop in config.items('properties'): - self.guest_props.append(prop[1]) - - # save the config - self.config = config - - def parse_cli_args(self): - ''' Command line argument processing ''' - - parser = argparse.ArgumentParser(description='Produce an Ansible Inventory file based on PyVmomi') - parser.add_argument('--debug', action='store_true', default=False, - help='show debug info') - parser.add_argument('--list', action='store_true', default=True, - help='List instances (default: True)') - parser.add_argument('--host', action='store', - help='Get all the variables about a specific instance') - parser.add_argument('--refresh-cache', action='store_true', default=False, - help='Force refresh of cache by making API requests to VSphere (default: False - use cache files)') - parser.add_argument('--max-instances', default=None, type=int, - help='maximum number of instances to retrieve') - self.args = parser.parse_args() - - def get_instances(self): - ''' Get a list of vm instances with pyvmomi ''' - kwargs = {'host': self.server, - 'user': self.username, - 'pwd': self.password, - 'port': int(self.port)} - - if self.validate_certs and hasattr(ssl, 'SSLContext'): - context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) - context.verify_mode = ssl.CERT_REQUIRED - context.check_hostname = True - kwargs['sslContext'] = context - elif self.validate_certs and not hasattr(ssl, 'SSLContext'): - sys.exit('pyVim does not support changing verification mode with python < 2.7.9. Either update ' - 'python or use validate_certs=false.') - elif not self.validate_certs and hasattr(ssl, 'SSLContext'): - context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) - context.verify_mode = ssl.CERT_NONE - context.check_hostname = False - kwargs['sslContext'] = context - elif not self.validate_certs and not hasattr(ssl, 'SSLContext'): - # Python 2.7.9 < or RHEL/CentOS 7.4 < - pass - - return self._get_instances(kwargs) - - def _get_instances(self, inkwargs): - ''' Make API calls ''' - instances = [] - si = None - try: - si = SmartConnect(**inkwargs) - except ssl.SSLError as connection_error: - if '[SSL: CERTIFICATE_VERIFY_FAILED]' in str(connection_error) and self.validate_certs: - sys.exit("Unable to connect to ESXi server due to %s, " - "please specify validate_certs=False and try again" % connection_error) - - except Exception as exc: - self.debugl("Unable to connect to ESXi server due to %s" % exc) - sys.exit("Unable to connect to ESXi server due to %s" % exc) - - self.debugl('retrieving all instances') - if not si: - sys.exit("Could not connect to the specified host using specified " - "username and password") - atexit.register(Disconnect, si) - content = si.RetrieveContent() - - # Create a search container for virtualmachines - self.debugl('creating containerview for virtualmachines') - container = content.rootFolder - viewType = [vim.VirtualMachine] - recursive = True - containerView = content.viewManager.CreateContainerView(container, viewType, recursive) - children = containerView.view - for child in children: - # If requested, limit the total number of instances - if self.args.max_instances: - if len(instances) >= self.args.max_instances: - break - instances.append(child) - self.debugl("%s total instances in container view" % len(instances)) - - if self.args.host: - instances = [x for x in instances if x.name == self.args.host] - - instance_tuples = [] - for instance in instances: - if self.guest_props: - ifacts = self.facts_from_proplist(instance) - else: - ifacts = self.facts_from_vobj(instance) - instance_tuples.append((instance, ifacts)) - self.debugl('facts collected for all instances') - - try: - cfm = content.customFieldsManager - if cfm is not None and cfm.field: - for f in cfm.field: - if not f.managedObjectType or f.managedObjectType == vim.VirtualMachine: - self.custom_fields[f.key] = f.name - self.debugl('%d custom fields collected' % len(self.custom_fields)) - except vmodl.RuntimeFault as exc: - self.debugl("Unable to gather custom fields due to %s" % exc.msg) - except IndexError as exc: - self.debugl("Unable to gather custom fields due to %s" % exc) - - return instance_tuples - - def instances_to_inventory(self, instances): - ''' Convert a list of vm objects into a json compliant inventory ''' - self.debugl('re-indexing instances based on ini settings') - inventory = VMWareInventory._empty_inventory() - inventory['all'] = {} - inventory['all']['hosts'] = [] - for idx, instance in enumerate(instances): - # make a unique id for this object to avoid vmware's - # numerous uuid's which aren't all unique. - thisid = str(uuid.uuid4()) - idata = instance[1] - - # Put it in the inventory - inventory['all']['hosts'].append(thisid) - inventory['_meta']['hostvars'][thisid] = idata.copy() - inventory['_meta']['hostvars'][thisid]['ansible_uuid'] = thisid - - # Make a map of the uuid to the alias the user wants - name_mapping = self.create_template_mapping( - inventory, - self.config.get('vmware', 'alias_pattern') - ) - - # Make a map of the uuid to the ssh hostname the user wants - host_mapping = self.create_template_mapping( - inventory, - self.config.get('vmware', 'host_pattern') - ) - - # Reset the inventory keys - for k, v in name_mapping.items(): - - if not host_mapping or k not in host_mapping: - continue - - # set ansible_host (2.x) - try: - inventory['_meta']['hostvars'][k]['ansible_host'] = host_mapping[k] - # 1.9.x backwards compliance - inventory['_meta']['hostvars'][k]['ansible_ssh_host'] = host_mapping[k] - except Exception: - continue - - if k == v: - continue - - # add new key - inventory['all']['hosts'].append(v) - inventory['_meta']['hostvars'][v] = inventory['_meta']['hostvars'][k] - - # cleanup old key - inventory['all']['hosts'].remove(k) - inventory['_meta']['hostvars'].pop(k, None) - - self.debugl('pre-filtered hosts:') - for i in inventory['all']['hosts']: - self.debugl(' * %s' % i) - # Apply host filters - for hf in self.host_filters: - if not hf: - continue - self.debugl('filter: %s' % hf) - filter_map = self.create_template_mapping(inventory, hf, dtype='boolean') - for k, v in filter_map.items(): - if not v: - # delete this host - inventory['all']['hosts'].remove(k) - inventory['_meta']['hostvars'].pop(k, None) - - self.debugl('post-filter hosts:') - for i in inventory['all']['hosts']: - self.debugl(' * %s' % i) - - # Create groups - for gbp in self.groupby_patterns: - groupby_map = self.create_template_mapping(inventory, gbp) - for k, v in groupby_map.items(): - if v not in inventory: - inventory[v] = {} - inventory[v]['hosts'] = [] - if k not in inventory[v]['hosts']: - inventory[v]['hosts'].append(k) - - if self.config.get('vmware', 'groupby_custom_field'): - for k, v in inventory['_meta']['hostvars'].items(): - if 'customvalue' in v: - for tv in v['customvalue']: - newkey = None - field_name = self.custom_fields[tv['key']] if tv['key'] in self.custom_fields else tv['key'] - if field_name in self.groupby_custom_field_excludes: - continue - values = [] - keylist = map(lambda x: x.strip(), tv['value'].split(',')) - for kl in keylist: - try: - newkey = "%s%s_%s" % (self.config.get('vmware', 'custom_field_group_prefix'), str(field_name), kl) - newkey = newkey.strip() - except Exception as e: - self.debugl(e) - values.append(newkey) - for tag in values: - if not tag: - continue - if tag not in inventory: - inventory[tag] = {} - inventory[tag]['hosts'] = [] - if k not in inventory[tag]['hosts']: - inventory[tag]['hosts'].append(k) - - return inventory - - def create_template_mapping(self, inventory, pattern, dtype='string'): - ''' Return a hash of uuid to templated string from pattern ''' - mapping = {} - for k, v in inventory['_meta']['hostvars'].items(): - t = self.env.from_string(pattern) - newkey = None - try: - newkey = t.render(v) - newkey = newkey.strip() - except Exception as e: - self.debugl(e) - if not newkey: - continue - elif dtype == 'integer': - newkey = int(newkey) - elif dtype == 'boolean': - if newkey.lower() == 'false': - newkey = False - elif newkey.lower() == 'true': - newkey = True - elif dtype == 'string': - pass - mapping[k] = newkey - return mapping - - def facts_from_proplist(self, vm): - '''Get specific properties instead of serializing everything''' - - rdata = {} - for prop in self.guest_props: - self.debugl('getting %s property for %s' % (prop, vm.name)) - key = prop - if self.lowerkeys: - key = key.lower() - - if '.' not in prop: - # props without periods are direct attributes of the parent - vm_property = getattr(vm, prop) - if isinstance(vm_property, vim.CustomFieldsManager.Value.Array): - temp_vm_property = [] - for vm_prop in vm_property: - temp_vm_property.append({'key': vm_prop.key, - 'value': vm_prop.value}) - rdata[key] = temp_vm_property - else: - rdata[key] = vm_property - else: - # props with periods are subkeys of parent attributes - parts = prop.split('.') - total = len(parts) - 1 - - # pointer to the current object - val = None - # pointer to the current result key - lastref = rdata - - for idx, x in enumerate(parts): - - if isinstance(val, dict): - if x in val: - val = val.get(x) - elif x.lower() in val: - val = val.get(x.lower()) - else: - # if the val wasn't set yet, get it from the parent - if not val: - try: - val = getattr(vm, x) - except AttributeError as e: - self.debugl(e) - else: - # in a subkey, get the subprop from the previous attrib - try: - val = getattr(val, x) - except AttributeError as e: - self.debugl(e) - - # make sure it serializes - val = self._process_object_types(val) - - # lowercase keys if requested - if self.lowerkeys: - x = x.lower() - - # change the pointer or set the final value - if idx != total: - if x not in lastref: - lastref[x] = {} - lastref = lastref[x] - else: - lastref[x] = val - if self.args.debug: - self.debugl("For %s" % vm.name) - for key in list(rdata.keys()): - if isinstance(rdata[key], dict): - for ikey in list(rdata[key].keys()): - self.debugl("Property '%s.%s' has value '%s'" % (key, ikey, rdata[key][ikey])) - else: - self.debugl("Property '%s' has value '%s'" % (key, rdata[key])) - return rdata - - def facts_from_vobj(self, vobj, level=0): - ''' Traverse a VM object and return a json compliant data structure ''' - - # pyvmomi objects are not yet serializable, but may be one day ... - # https://github.com/vmware/pyvmomi/issues/21 - - # WARNING: - # Accessing an object attribute will trigger a SOAP call to the remote. - # Increasing the attributes collected or the depth of recursion greatly - # increases runtime duration and potentially memory+network utilization. - - if level == 0: - try: - self.debugl("get facts for %s" % vobj.name) - except Exception as e: - self.debugl(e) - - rdata = {} - - methods = dir(vobj) - methods = [str(x) for x in methods if not x.startswith('_')] - methods = [x for x in methods if x not in self.bad_types] - methods = [x for x in methods if not x.lower() in self.skip_keys] - methods = sorted(methods) - - for method in methods: - # Attempt to get the method, skip on fail - try: - methodToCall = getattr(vobj, method) - except Exception as e: - continue - - # Skip callable methods - if callable(methodToCall): - continue - - if self.lowerkeys: - method = method.lower() - - rdata[method] = self._process_object_types( - methodToCall, - thisvm=vobj, - inkey=method, - ) - - return rdata - - def _process_object_types(self, vobj, thisvm=None, inkey='', level=0): - ''' Serialize an object ''' - rdata = {} - - if type(vobj).__name__ in self.vimTableMaxDepth and level >= self.vimTableMaxDepth[type(vobj).__name__]: - return rdata - - if vobj is None: - rdata = None - elif type(vobj) in self.vimTable: - rdata = {} - for key in self.vimTable[type(vobj)]: - try: - rdata[key] = getattr(vobj, key) - except Exception as e: - self.debugl(e) - - elif issubclass(type(vobj), str) or isinstance(vobj, str): - if vobj.isalnum(): - rdata = vobj - else: - rdata = vobj.encode('utf-8').decode('utf-8') - elif issubclass(type(vobj), bool) or isinstance(vobj, bool): - rdata = vobj - elif issubclass(type(vobj), integer_types) or isinstance(vobj, integer_types): - rdata = vobj - elif issubclass(type(vobj), float) or isinstance(vobj, float): - rdata = vobj - elif issubclass(type(vobj), list) or issubclass(type(vobj), tuple): - rdata = [] - try: - vobj = sorted(vobj) - except Exception: - pass - - for idv, vii in enumerate(vobj): - if level + 1 <= self.maxlevel: - vid = self._process_object_types( - vii, - thisvm=thisvm, - inkey=inkey + '[' + str(idv) + ']', - level=(level + 1) - ) - - if vid: - rdata.append(vid) - - elif issubclass(type(vobj), dict): - pass - - elif issubclass(type(vobj), object): - methods = dir(vobj) - methods = [str(x) for x in methods if not x.startswith('_')] - methods = [x for x in methods if x not in self.bad_types] - methods = [x for x in methods if not inkey + '.' + x.lower() in self.skip_keys] - methods = sorted(methods) - - for method in methods: - # Attempt to get the method, skip on fail - try: - methodToCall = getattr(vobj, method) - except Exception as e: - continue - - if callable(methodToCall): - continue - - if self.lowerkeys: - method = method.lower() - if level + 1 <= self.maxlevel: - try: - rdata[method] = self._process_object_types( - methodToCall, - thisvm=thisvm, - inkey=inkey + '.' + method, - level=(level + 1) - ) - except vim.fault.NoPermission: - self.debugl("Skipping method %s (NoPermission)" % method) - else: - pass - - return rdata - - def get_host_info(self, host): - ''' Return hostvars for a single host ''' - - if host in self.inventory['_meta']['hostvars']: - return self.inventory['_meta']['hostvars'][host] - elif self.args.host and self.inventory['_meta']['hostvars']: - match = None - for k, v in self.inventory['_meta']['hostvars'].items(): - if self.inventory['_meta']['hostvars'][k]['name'] == self.args.host: - match = k - break - if match: - return self.inventory['_meta']['hostvars'][match] - else: - raise VMwareMissingHostException('%s not found' % host) - else: - raise VMwareMissingHostException('%s not found' % host) - - -if __name__ == "__main__": - # Run the script - print(VMWareInventory().show()) diff --git a/lib/ansible/module_utils/vca.py b/lib/ansible/module_utils/vca.py deleted file mode 100644 index 62cd82d29f..0000000000 --- a/lib/ansible/module_utils/vca.py +++ /dev/null @@ -1,337 +0,0 @@ -# -# 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/>. - -import os -import traceback - -PYVCLOUD_IMP_ERR = None -try: - from pyvcloud.vcloudair import VCA - HAS_PYVCLOUD = True -except ImportError: - PYVCLOUD_IMP_ERR = traceback.format_exc() - HAS_PYVCLOUD = False - -from ansible.module_utils.basic import AnsibleModule, missing_required_lib - -SERVICE_MAP = {'vca': 'ondemand', 'vchs': 'subscription', 'vcd': 'vcd'} -LOGIN_HOST = {'vca': 'vca.vmware.com', 'vchs': 'vchs.vmware.com'} - -DEFAULT_SERVICE_TYPE = 'vca' -DEFAULT_VERSION = '5.7' - - -class VcaError(Exception): - - def __init__(self, msg, **kwargs): - self.kwargs = kwargs - super(VcaError, self).__init__(msg) - - -def vca_argument_spec(): - return dict( - username=dict(type='str', aliases=['user'], required=True), - password=dict(type='str', aliases=['pass', 'passwd'], required=True, no_log=True), - org=dict(), - service_id=dict(), - instance_id=dict(), - host=dict(), - api_version=dict(default=DEFAULT_VERSION), - service_type=dict(default=DEFAULT_SERVICE_TYPE, choices=SERVICE_MAP.keys()), - vdc_name=dict(), - gateway_name=dict(default='gateway'), - validate_certs=dict(type='bool', default=True, aliases=['verify_certs']) - ) - - -class VcaAnsibleModule(AnsibleModule): - - def __init__(self, *args, **kwargs): - argument_spec = vca_argument_spec() - argument_spec.update(kwargs.get('argument_spec', dict())) - kwargs['argument_spec'] = argument_spec - - super(VcaAnsibleModule, self).__init__(*args, **kwargs) - - if not HAS_PYVCLOUD: - self.fail(missing_required_lib('pyvcloud'), - exception=PYVCLOUD_IMP_ERR) - - self._vca = self.create_instance() - self.login() - - self._gateway = None - self._vdc = None - - @property - def vca(self): - return self._vca - - @property - def gateway(self): - if self._gateway is not None: - return self._gateway - vdc_name = self.params['vdc_name'] - gateway_name = self.params['gateway_name'] - _gateway = self.vca.get_gateway(vdc_name, gateway_name) - if not _gateway: - raise VcaError('vca instance has no gateway named %s' % gateway_name) - self._gateway = _gateway - return _gateway - - @property - def vdc(self): - if self._vdc is not None: - return self._vdc - vdc_name = self.params['vdc_name'] - _vdc = self.vca.get_vdc(vdc_name) - if not _vdc: - raise VcaError('vca instance has no vdc named %s' % vdc_name) - self._vdc = _vdc - return _vdc - - def get_vapp(self, vapp_name): - vapp = self.vca.get_vapp(self.vdc, vapp_name) - if not vapp: - raise VcaError('vca instance has no vapp named %s' % vapp_name) - return vapp - - def get_vm(self, vapp_name, vm_name): - vapp = self.get_vapp(vapp_name) - children = vapp.me.get_Children() - vms = [vm for vm in children.get_Vm() if vm.name == vm_name] - try: - return vms[0] - except IndexError: - raise VcaError('vapp has no vm named %s' % vm_name) - - def create_instance(self): - service_type = self.params.get('service_type', DEFAULT_SERVICE_TYPE) - if service_type == 'vcd': - host = self.params['host'] - else: - host = LOGIN_HOST[service_type] - username = self.params['username'] - - version = self.params.get('api_version') - if service_type == 'vchs': - version = '5.6' - - verify = self.params.get('validate_certs') - - return VCA(host=host, username=username, - service_type=SERVICE_MAP[service_type], - version=version, verify=verify) - - def login(self): - service_type = self.params['service_type'] - password = self.params['password'] - - login_org = None - if service_type == 'vcd': - login_org = self.params['org'] - - if not self.vca.login(password=password, org=login_org): - self.fail('Login to VCA failed', response=self.vca.response.content) - - try: - method_name = 'login_%s' % service_type - meth = getattr(self, method_name) - meth() - except AttributeError: - self.fail('no login method exists for service_type %s' % service_type) - except VcaError as e: - self.fail(e.message, response=self.vca.response.content, **e.kwargs) - - def login_vca(self): - instance_id = self.params['instance_id'] - if not instance_id: - raise VcaError('missing required instance_id for service_type vca') - self.vca.login_to_instance_sso(instance=instance_id) - - def login_vchs(self): - service_id = self.params['service_id'] - if not service_id: - raise VcaError('missing required service_id for service_type vchs') - - org = self.params['org'] - if not org: - raise VcaError('missing required org for service_type vchs') - - self.vca.login_to_org(service_id, org) - - def login_vcd(self): - org = self.params['org'] - if not org: - raise VcaError('missing required org for service_type vcd') - - if not self.vca.token: - raise VcaError('unable to get token for service_type vcd') - - if not self.vca.vcloud_session.org_url: - raise VcaError('unable to get org_url for service_type vcd') - - self.vca.login(token=self.vca.token, org=org, - org_url=self.vca.vcloud_session.org_url) - - def save_services_config(self, blocking=True): - task = self.gateway.save_services_configuration() - if not task: - self.fail(msg='unable to save gateway services configuration') - if blocking: - self.vca.block_until_completed(task) - - def fail(self, msg, **kwargs): - self.fail_json(msg=msg, **kwargs) - - def exit(self, **kwargs): - self.exit_json(**kwargs) - - -# ------------------------------------------------------------- -# 9/18/2015 @privateip -# All of the functions below here were migrated from the original -# vca_* modules. All functions below should be considered deprecated -# and will be removed once all of the vca_* modules have been updated -# to use the new instance module above -# ------------------------------------------------------------- - -VCA_REQ_ARGS = ['instance_id', 'vdc_name'] -VCHS_REQ_ARGS = ['service_id'] -VCD_REQ_ARGS = [] - - -def _validate_module(module): - if not HAS_PYVCLOUD: - module.fail_json(msg=missing_required_lib("pyvcloud"), - exception=PYVCLOUD_IMP_ERR) - - service_type = module.params.get('service_type', DEFAULT_SERVICE_TYPE) - - if service_type == 'vca': - for arg in VCA_REQ_ARGS: - if module.params.get(arg) is None: - module.fail_json(msg="argument %s is mandatory when service type " - "is vca" % arg) - - if service_type == 'vchs': - for arg in VCHS_REQ_ARGS: - if module.params.get(arg) is None: - module.fail_json(msg="argument %s is mandatory when service type " - "is vchs" % arg) - - if service_type == 'vcd': - for arg in VCD_REQ_ARGS: - if module.params.get(arg) is None: - module.fail_json(msg="argument %s is mandatory when service type " - "is vcd" % arg) - - -def serialize_instances(instance_list): - instances = [] - for i in instance_list: - instances.append(dict(apiUrl=i['apiUrl'], instance_id=i['id'])) - return instances - - -def _vca_login(vca, password, instance): - if not vca.login(password=password): - raise VcaError("Login Failed: Please check username or password", - error=vca.response.content) - - if not vca.login_to_instance_sso(instance=instance): - s_json = serialize_instances(vca.instances) - raise VcaError("Login to Instance failed: Seems like instance_id provided " - "is wrong .. Please check", valid_instances=s_json) - - return vca - - -def _vchs_login(vca, password, service, org): - if not vca.login(password=password): - raise VcaError("Login Failed: Please check username or password", - error=vca.response.content) - - if not vca.login_to_org(service, org): - raise VcaError("Failed to login to org, Please check the orgname", - error=vca.response.content) - - -def _vcd_login(vca, password, org): - # TODO: this function needs to be refactored - if not vca.login(password=password, org=org): - raise VcaError("Login Failed: Please check username or password " - "or host parameters") - - if not vca.login(password=password, org=org): - raise VcaError("Failed to get the token", - error=vca.response.content) - - if not vca.login(token=vca.token, org=org, org_url=vca.vcloud_session.org_url): - raise VcaError("Failed to login to org", error=vca.response.content) - - -def vca_login(module): - service_type = module.params.get('service_type') - username = module.params.get('username') - password = module.params.get('password') - instance = module.params.get('instance_id') - org = module.params.get('org') - vdc_name = module.params.get('vdc_name') - service = module.params.get('service_id') - version = module.params.get('api_version') - verify = module.params.get('validate_certs') - - _validate_module(module) - - if not vdc_name and service_type == 'vchs': - vdc_name = module.params.get('service_id') - - if not org and service_type == 'vchs': - org = vdc_name or service - - if service_type == 'vcd': - host = module.params.get('host') - else: - host = LOGIN_HOST[service_type] - - username = os.environ.get('VCA_USER', username) - password = os.environ.get('VCA_PASS', password) - - if not username or not password: - msg = "Either the username or password is not set, please check args" - module.fail_json(msg=msg) - - if service_type == 'vchs': - version = '5.6' - elif service_type == 'vcd' and not version: - version = '5.6' - - vca = VCA(host=host, username=username, - service_type=SERVICE_MAP[service_type], - version=version, verify=verify) - - try: - if service_type == 'vca': - _vca_login(vca, password, instance) - elif service_type == 'vchs': - _vchs_login(vca, password, service, org) - elif service_type == 'vcd': - _vcd_login(vca, password, org) - except VcaError as e: - module.fail_json(msg=e.message, **e.kwargs) - - return vca diff --git a/lib/ansible/module_utils/vmware.py b/lib/ansible/module_utils/vmware.py deleted file mode 100644 index 765e8c18f2..0000000000 --- a/lib/ansible/module_utils/vmware.py +++ /dev/null @@ -1,1630 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright: (c) 2015, Joseph Callen <jcallen () csc.com> -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, James E. King III (@jeking3) <jking@apache.org> -# 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 - -import atexit -import ansible.module_utils.common._collections_compat as collections_compat -import json -import os -import re -import ssl -import time -import traceback -from random import randint -from distutils.version import StrictVersion - -REQUESTS_IMP_ERR = None -try: - # requests is required for exception handling of the ConnectionError - import requests - HAS_REQUESTS = True -except ImportError: - REQUESTS_IMP_ERR = traceback.format_exc() - HAS_REQUESTS = False - -PYVMOMI_IMP_ERR = None -try: - from pyVim import connect - from pyVmomi import vim, vmodl, VmomiSupport - HAS_PYVMOMI = True - HAS_PYVMOMIJSON = hasattr(VmomiSupport, 'VmomiJSONEncoder') -except ImportError: - PYVMOMI_IMP_ERR = traceback.format_exc() - HAS_PYVMOMI = False - HAS_PYVMOMIJSON = False - -from ansible.module_utils._text import to_text, to_native -from ansible.module_utils.six import integer_types, iteritems, string_types, raise_from -from ansible.module_utils.basic import env_fallback, missing_required_lib - - -class TaskError(Exception): - def __init__(self, *args, **kwargs): - super(TaskError, self).__init__(*args, **kwargs) - - -def wait_for_task(task, max_backoff=64, timeout=3600): - """Wait for given task using exponential back-off algorithm. - - Args: - task: VMware task object - max_backoff: Maximum amount of sleep time in seconds - timeout: Timeout for the given task in seconds - - Returns: Tuple with True and result for successful task - Raises: TaskError on failure - """ - failure_counter = 0 - start_time = time.time() - - while True: - if time.time() - start_time >= timeout: - raise TaskError("Timeout") - if task.info.state == vim.TaskInfo.State.success: - return True, task.info.result - if task.info.state == vim.TaskInfo.State.error: - error_msg = task.info.error - host_thumbprint = None - try: - error_msg = error_msg.msg - if hasattr(task.info.error, 'thumbprint'): - host_thumbprint = task.info.error.thumbprint - except AttributeError: - pass - finally: - raise_from(TaskError(error_msg, host_thumbprint), task.info.error) - if task.info.state in [vim.TaskInfo.State.running, vim.TaskInfo.State.queued]: - sleep_time = min(2 ** failure_counter + randint(1, 1000) / 1000, max_backoff) - time.sleep(sleep_time) - failure_counter += 1 - - -def wait_for_vm_ip(content, vm, timeout=300): - facts = dict() - interval = 15 - while timeout > 0: - _facts = gather_vm_facts(content, vm) - if _facts['ipv4'] or _facts['ipv6']: - facts = _facts - break - time.sleep(interval) - timeout -= interval - - return facts - - -def find_obj(content, vimtype, name, first=True, folder=None): - container = content.viewManager.CreateContainerView(folder or content.rootFolder, recursive=True, type=vimtype) - # Get all objects matching type (and name if given) - obj_list = [obj for obj in container.view if not name or to_text(obj.name) == to_text(name)] - container.Destroy() - - # Return first match or None - if first: - if obj_list: - return obj_list[0] - return None - - # Return all matching objects or empty list - return obj_list - - -def find_dvspg_by_name(dv_switch, portgroup_name): - portgroup_name = quote_obj_name(portgroup_name) - portgroups = dv_switch.portgroup - - for pg in portgroups: - if pg.name == portgroup_name: - return pg - - return None - - -def find_object_by_name(content, name, obj_type, folder=None, recurse=True): - if not isinstance(obj_type, list): - obj_type = [obj_type] - - objects = get_all_objs(content, obj_type, folder=folder, recurse=recurse) - for obj in objects: - if obj.name == name: - return obj - - return None - - -def find_cluster_by_name(content, cluster_name, datacenter=None): - - if datacenter and hasattr(datacenter, 'hostFolder'): - folder = datacenter.hostFolder - else: - folder = content.rootFolder - - return find_object_by_name(content, cluster_name, [vim.ClusterComputeResource], folder=folder) - - -def find_datacenter_by_name(content, datacenter_name): - return find_object_by_name(content, datacenter_name, [vim.Datacenter]) - - -def get_parent_datacenter(obj): - """ Walk the parent tree to find the objects datacenter """ - if isinstance(obj, vim.Datacenter): - return obj - datacenter = None - while True: - if not hasattr(obj, 'parent'): - break - obj = obj.parent - if isinstance(obj, vim.Datacenter): - datacenter = obj - break - return datacenter - - -def find_datastore_by_name(content, datastore_name, datacenter_name=None): - return find_object_by_name(content, datastore_name, [vim.Datastore], datacenter_name) - - -def find_folder_by_name(content, folder_name): - return find_object_by_name(content, folder_name, [vim.Folder]) - - -def find_dvs_by_name(content, switch_name, folder=None): - return find_object_by_name(content, switch_name, [vim.DistributedVirtualSwitch], folder=folder) - - -def find_hostsystem_by_name(content, hostname): - return find_object_by_name(content, hostname, [vim.HostSystem]) - - -def find_resource_pool_by_name(content, resource_pool_name): - return find_object_by_name(content, resource_pool_name, [vim.ResourcePool]) - - -def find_resource_pool_by_cluster(content, resource_pool_name='Resources', cluster=None): - return find_object_by_name(content, resource_pool_name, [vim.ResourcePool], folder=cluster) - - -def find_network_by_name(content, network_name): - return find_object_by_name(content, quote_obj_name(network_name), [vim.Network]) - - -def find_vm_by_id(content, vm_id, vm_id_type="vm_name", datacenter=None, - cluster=None, folder=None, match_first=False): - """ UUID is unique to a VM, every other id returns the first match. """ - si = content.searchIndex - vm = None - - if vm_id_type == 'dns_name': - vm = si.FindByDnsName(datacenter=datacenter, dnsName=vm_id, vmSearch=True) - elif vm_id_type == 'uuid': - # Search By BIOS UUID rather than instance UUID - vm = si.FindByUuid(datacenter=datacenter, instanceUuid=False, uuid=vm_id, vmSearch=True) - elif vm_id_type == 'instance_uuid': - vm = si.FindByUuid(datacenter=datacenter, instanceUuid=True, uuid=vm_id, vmSearch=True) - elif vm_id_type == 'ip': - vm = si.FindByIp(datacenter=datacenter, ip=vm_id, vmSearch=True) - elif vm_id_type == 'vm_name': - folder = None - if cluster: - folder = cluster - elif datacenter: - folder = datacenter.hostFolder - vm = find_vm_by_name(content, vm_id, folder) - elif vm_id_type == 'inventory_path': - searchpath = folder - # get all objects for this path - f_obj = si.FindByInventoryPath(searchpath) - if f_obj: - if isinstance(f_obj, vim.Datacenter): - f_obj = f_obj.vmFolder - for c_obj in f_obj.childEntity: - if not isinstance(c_obj, vim.VirtualMachine): - continue - if c_obj.name == vm_id: - vm = c_obj - if match_first: - break - return vm - - -def find_vm_by_name(content, vm_name, folder=None, recurse=True): - return find_object_by_name(content, vm_name, [vim.VirtualMachine], folder=folder, recurse=recurse) - - -def find_host_portgroup_by_name(host, portgroup_name): - - for portgroup in host.config.network.portgroup: - if portgroup.spec.name == portgroup_name: - return portgroup - return None - - -def compile_folder_path_for_object(vobj): - """ make a /vm/foo/bar/baz like folder path for an object """ - - paths = [] - if isinstance(vobj, vim.Folder): - paths.append(vobj.name) - - thisobj = vobj - while hasattr(thisobj, 'parent'): - thisobj = thisobj.parent - try: - moid = thisobj._moId - except AttributeError: - moid = None - if moid in ['group-d1', 'ha-folder-root']: - break - if isinstance(thisobj, vim.Folder): - paths.append(thisobj.name) - paths.reverse() - return '/' + '/'.join(paths) - - -def _get_vm_prop(vm, attributes): - """Safely get a property or return None""" - result = vm - for attribute in attributes: - try: - result = getattr(result, attribute) - except (AttributeError, IndexError): - return None - return result - - -def gather_vm_facts(content, vm): - """ Gather facts from vim.VirtualMachine object. """ - facts = { - 'module_hw': True, - 'hw_name': vm.config.name, - 'hw_power_status': vm.summary.runtime.powerState, - 'hw_guest_full_name': vm.summary.guest.guestFullName, - 'hw_guest_id': vm.summary.guest.guestId, - 'hw_product_uuid': vm.config.uuid, - 'hw_processor_count': vm.config.hardware.numCPU, - 'hw_cores_per_socket': vm.config.hardware.numCoresPerSocket, - 'hw_memtotal_mb': vm.config.hardware.memoryMB, - 'hw_interfaces': [], - 'hw_datastores': [], - 'hw_files': [], - 'hw_esxi_host': None, - 'hw_guest_ha_state': None, - 'hw_is_template': vm.config.template, - 'hw_folder': None, - 'hw_version': vm.config.version, - 'instance_uuid': vm.config.instanceUuid, - 'guest_tools_status': _get_vm_prop(vm, ('guest', 'toolsRunningStatus')), - 'guest_tools_version': _get_vm_prop(vm, ('guest', 'toolsVersion')), - 'guest_question': vm.summary.runtime.question, - 'guest_consolidation_needed': vm.summary.runtime.consolidationNeeded, - 'ipv4': None, - 'ipv6': None, - 'annotation': vm.config.annotation, - 'customvalues': {}, - 'snapshots': [], - 'current_snapshot': None, - 'vnc': {}, - 'moid': vm._moId, - 'vimref': "vim.VirtualMachine:%s" % vm._moId, - } - - # facts that may or may not exist - if vm.summary.runtime.host: - try: - host = vm.summary.runtime.host - facts['hw_esxi_host'] = host.summary.config.name - facts['hw_cluster'] = host.parent.name if host.parent and isinstance(host.parent, vim.ClusterComputeResource) else None - - except vim.fault.NoPermission: - # User does not have read permission for the host system, - # proceed without this value. This value does not contribute or hamper - # provisioning or power management operations. - pass - if vm.summary.runtime.dasVmProtection: - facts['hw_guest_ha_state'] = vm.summary.runtime.dasVmProtection.dasProtected - - datastores = vm.datastore - for ds in datastores: - facts['hw_datastores'].append(ds.info.name) - - try: - files = vm.config.files - layout = vm.layout - if files: - facts['hw_files'] = [files.vmPathName] - for item in layout.snapshot: - for snap in item.snapshotFile: - if 'vmsn' in snap: - facts['hw_files'].append(snap) - for item in layout.configFile: - facts['hw_files'].append(os.path.join(os.path.dirname(files.vmPathName), item)) - for item in vm.layout.logFile: - facts['hw_files'].append(os.path.join(files.logDirectory, item)) - for item in vm.layout.disk: - for disk in item.diskFile: - facts['hw_files'].append(disk) - except Exception: - pass - - facts['hw_folder'] = PyVmomi.get_vm_path(content, vm) - - cfm = content.customFieldsManager - # Resolve custom values - for value_obj in vm.summary.customValue: - kn = value_obj.key - if cfm is not None and cfm.field: - for f in cfm.field: - if f.key == value_obj.key: - kn = f.name - # Exit the loop immediately, we found it - break - - facts['customvalues'][kn] = value_obj.value - - net_dict = {} - vmnet = _get_vm_prop(vm, ('guest', 'net')) - if vmnet: - for device in vmnet: - if device.deviceConfigId > 0: - net_dict[device.macAddress] = list(device.ipAddress) - - if vm.guest.ipAddress: - if ':' in vm.guest.ipAddress: - facts['ipv6'] = vm.guest.ipAddress - else: - facts['ipv4'] = vm.guest.ipAddress - - ethernet_idx = 0 - for entry in vm.config.hardware.device: - if not hasattr(entry, 'macAddress'): - continue - - if entry.macAddress: - mac_addr = entry.macAddress - mac_addr_dash = mac_addr.replace(':', '-') - else: - mac_addr = mac_addr_dash = None - - if (hasattr(entry, 'backing') and hasattr(entry.backing, 'port') and - hasattr(entry.backing.port, 'portKey') and hasattr(entry.backing.port, 'portgroupKey')): - port_group_key = entry.backing.port.portgroupKey - port_key = entry.backing.port.portKey - else: - port_group_key = None - port_key = None - - factname = 'hw_eth' + str(ethernet_idx) - facts[factname] = { - 'addresstype': entry.addressType, - 'label': entry.deviceInfo.label, - 'macaddress': mac_addr, - 'ipaddresses': net_dict.get(entry.macAddress, None), - 'macaddress_dash': mac_addr_dash, - 'summary': entry.deviceInfo.summary, - 'portgroup_portkey': port_key, - 'portgroup_key': port_group_key, - } - facts['hw_interfaces'].append('eth' + str(ethernet_idx)) - ethernet_idx += 1 - - snapshot_facts = list_snapshots(vm) - if 'snapshots' in snapshot_facts: - facts['snapshots'] = snapshot_facts['snapshots'] - facts['current_snapshot'] = snapshot_facts['current_snapshot'] - - facts['vnc'] = get_vnc_extraconfig(vm) - return facts - - -def deserialize_snapshot_obj(obj): - return {'id': obj.id, - 'name': obj.name, - 'description': obj.description, - 'creation_time': obj.createTime, - 'state': obj.state} - - -def list_snapshots_recursively(snapshots): - snapshot_data = [] - for snapshot in snapshots: - snapshot_data.append(deserialize_snapshot_obj(snapshot)) - snapshot_data = snapshot_data + list_snapshots_recursively(snapshot.childSnapshotList) - return snapshot_data - - -def get_current_snap_obj(snapshots, snapob): - snap_obj = [] - for snapshot in snapshots: - if snapshot.snapshot == snapob: - snap_obj.append(snapshot) - snap_obj = snap_obj + get_current_snap_obj(snapshot.childSnapshotList, snapob) - return snap_obj - - -def list_snapshots(vm): - result = {} - snapshot = _get_vm_prop(vm, ('snapshot',)) - if not snapshot: - return result - if vm.snapshot is None: - return result - - result['snapshots'] = list_snapshots_recursively(vm.snapshot.rootSnapshotList) - current_snapref = vm.snapshot.currentSnapshot - current_snap_obj = get_current_snap_obj(vm.snapshot.rootSnapshotList, current_snapref) - if current_snap_obj: - result['current_snapshot'] = deserialize_snapshot_obj(current_snap_obj[0]) - else: - result['current_snapshot'] = dict() - return result - - -def get_vnc_extraconfig(vm): - result = {} - for opts in vm.config.extraConfig: - for optkeyname in ['enabled', 'ip', 'port', 'password']: - if opts.key.lower() == "remotedisplay.vnc." + optkeyname: - result[optkeyname] = opts.value - return result - - -def vmware_argument_spec(): - return dict( - hostname=dict(type='str', - required=False, - fallback=(env_fallback, ['VMWARE_HOST']), - ), - username=dict(type='str', - aliases=['user', 'admin'], - required=False, - fallback=(env_fallback, ['VMWARE_USER'])), - password=dict(type='str', - aliases=['pass', 'pwd'], - required=False, - no_log=True, - fallback=(env_fallback, ['VMWARE_PASSWORD'])), - port=dict(type='int', - default=443, - fallback=(env_fallback, ['VMWARE_PORT'])), - validate_certs=dict(type='bool', - required=False, - default=True, - fallback=(env_fallback, ['VMWARE_VALIDATE_CERTS']) - ), - proxy_host=dict(type='str', - required=False, - default=None, - fallback=(env_fallback, ['VMWARE_PROXY_HOST'])), - proxy_port=dict(type='int', - required=False, - default=None, - fallback=(env_fallback, ['VMWARE_PROXY_PORT'])), - ) - - -def connect_to_api(module, disconnect_atexit=True, return_si=False, hostname=None, username=None, password=None, port=None, validate_certs=None): - hostname = hostname if hostname else module.params['hostname'] - username = username if username else module.params['username'] - password = password if password else module.params['password'] - port = port if port else module.params.get('port', 443) - validate_certs = validate_certs if validate_certs else module.params['validate_certs'] - - if not hostname: - module.fail_json(msg="Hostname parameter is missing." - " Please specify this parameter in task or" - " export environment variable like 'export VMWARE_HOST=ESXI_HOSTNAME'") - - if not username: - module.fail_json(msg="Username parameter is missing." - " Please specify this parameter in task or" - " export environment variable like 'export VMWARE_USER=ESXI_USERNAME'") - - if not password: - module.fail_json(msg="Password parameter is missing." - " Please specify this parameter in task or" - " export environment variable like 'export VMWARE_PASSWORD=ESXI_PASSWORD'") - - if validate_certs and not hasattr(ssl, 'SSLContext'): - module.fail_json(msg='pyVim does not support changing verification mode with python < 2.7.9. Either update ' - 'python or use validate_certs=false.') - elif validate_certs: - ssl_context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) - ssl_context.verify_mode = ssl.CERT_REQUIRED - ssl_context.check_hostname = True - ssl_context.load_default_certs() - elif hasattr(ssl, 'SSLContext'): - ssl_context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) - ssl_context.verify_mode = ssl.CERT_NONE - ssl_context.check_hostname = False - else: # Python < 2.7.9 or RHEL/Centos < 7.4 - ssl_context = None - - service_instance = None - proxy_host = module.params.get('proxy_host') - proxy_port = module.params.get('proxy_port') - - connect_args = dict( - host=hostname, - port=port, - ) - if ssl_context: - connect_args.update(sslContext=ssl_context) - - msg_suffix = '' - try: - if proxy_host: - msg_suffix = " [proxy: %s:%d]" % (proxy_host, proxy_port) - connect_args.update(httpProxyHost=proxy_host, httpProxyPort=proxy_port) - smart_stub = connect.SmartStubAdapter(**connect_args) - session_stub = connect.VimSessionOrientedStub(smart_stub, connect.VimSessionOrientedStub.makeUserLoginMethod(username, password)) - service_instance = vim.ServiceInstance('ServiceInstance', session_stub) - else: - connect_args.update(user=username, pwd=password) - service_instance = connect.SmartConnect(**connect_args) - except vim.fault.InvalidLogin as invalid_login: - msg = "Unable to log on to vCenter or ESXi API at %s:%s " % (hostname, port) - module.fail_json(msg="%s as %s: %s" % (msg, username, invalid_login.msg) + msg_suffix) - except vim.fault.NoPermission as no_permission: - module.fail_json(msg="User %s does not have required permission" - " to log on to vCenter or ESXi API at %s:%s : %s" % (username, hostname, port, no_permission.msg)) - except (requests.ConnectionError, ssl.SSLError) as generic_req_exc: - module.fail_json(msg="Unable to connect to vCenter or ESXi API at %s on TCP/%s: %s" % (hostname, port, generic_req_exc)) - except vmodl.fault.InvalidRequest as invalid_request: - # Request is malformed - msg = "Failed to get a response from server %s:%s " % (hostname, port) - module.fail_json(msg="%s as request is malformed: %s" % (msg, invalid_request.msg) + msg_suffix) - except Exception as generic_exc: - msg = "Unknown error while connecting to vCenter or ESXi API at %s:%s" % (hostname, port) + msg_suffix - module.fail_json(msg="%s : %s" % (msg, generic_exc)) - - if service_instance is None: - msg = "Unknown error while connecting to vCenter or ESXi API at %s:%s" % (hostname, port) - module.fail_json(msg=msg + msg_suffix) - - # Disabling atexit should be used in special cases only. - # Such as IP change of the ESXi host which removes the connection anyway. - # Also removal significantly speeds up the return of the module - if disconnect_atexit: - atexit.register(connect.Disconnect, service_instance) - if return_si: - return service_instance, service_instance.RetrieveContent() - return service_instance.RetrieveContent() - - -def get_all_objs(content, vimtype, folder=None, recurse=True): - if not folder: - folder = content.rootFolder - - obj = {} - container = content.viewManager.CreateContainerView(folder, vimtype, recurse) - for managed_object_ref in container.view: - obj.update({managed_object_ref: managed_object_ref.name}) - return obj - - -def run_command_in_guest(content, vm, username, password, program_path, program_args, program_cwd, program_env): - - result = {'failed': False} - - tools_status = vm.guest.toolsStatus - if (tools_status == 'toolsNotInstalled' or - tools_status == 'toolsNotRunning'): - result['failed'] = True - result['msg'] = "VMwareTools is not installed or is not running in the guest" - return result - - # https://github.com/vmware/pyvmomi/blob/master/docs/vim/vm/guest/NamePasswordAuthentication.rst - creds = vim.vm.guest.NamePasswordAuthentication( - username=username, password=password - ) - - try: - # https://github.com/vmware/pyvmomi/blob/master/docs/vim/vm/guest/ProcessManager.rst - pm = content.guestOperationsManager.processManager - # https://www.vmware.com/support/developer/converter-sdk/conv51_apireference/vim.vm.guest.ProcessManager.ProgramSpec.html - ps = vim.vm.guest.ProcessManager.ProgramSpec( - # programPath=program, - # arguments=args - programPath=program_path, - arguments=program_args, - workingDirectory=program_cwd, - ) - - res = pm.StartProgramInGuest(vm, creds, ps) - result['pid'] = res - pdata = pm.ListProcessesInGuest(vm, creds, [res]) - - # wait for pid to finish - while not pdata[0].endTime: - time.sleep(1) - pdata = pm.ListProcessesInGuest(vm, creds, [res]) - - result['owner'] = pdata[0].owner - result['startTime'] = pdata[0].startTime.isoformat() - result['endTime'] = pdata[0].endTime.isoformat() - result['exitCode'] = pdata[0].exitCode - if result['exitCode'] != 0: - result['failed'] = True - result['msg'] = "program exited non-zero" - else: - result['msg'] = "program completed successfully" - - except Exception as e: - result['msg'] = str(e) - result['failed'] = True - - return result - - -def serialize_spec(clonespec): - """Serialize a clonespec or a relocation spec""" - data = {} - attrs = dir(clonespec) - attrs = [x for x in attrs if not x.startswith('_')] - for x in attrs: - xo = getattr(clonespec, x) - if callable(xo): - continue - xt = type(xo) - if xo is None: - data[x] = None - elif isinstance(xo, vim.vm.ConfigSpec): - data[x] = serialize_spec(xo) - elif isinstance(xo, vim.vm.RelocateSpec): - data[x] = serialize_spec(xo) - elif isinstance(xo, vim.vm.device.VirtualDisk): - data[x] = serialize_spec(xo) - elif isinstance(xo, vim.vm.device.VirtualDeviceSpec.FileOperation): - data[x] = to_text(xo) - elif isinstance(xo, vim.Description): - data[x] = { - 'dynamicProperty': serialize_spec(xo.dynamicProperty), - 'dynamicType': serialize_spec(xo.dynamicType), - 'label': serialize_spec(xo.label), - 'summary': serialize_spec(xo.summary), - } - elif hasattr(xo, 'name'): - data[x] = to_text(xo) + ':' + to_text(xo.name) - elif isinstance(xo, vim.vm.ProfileSpec): - pass - elif issubclass(xt, list): - data[x] = [] - for xe in xo: - data[x].append(serialize_spec(xe)) - elif issubclass(xt, string_types + integer_types + (float, bool)): - if issubclass(xt, integer_types): - data[x] = int(xo) - else: - data[x] = to_text(xo) - elif issubclass(xt, bool): - data[x] = xo - elif issubclass(xt, dict): - data[to_text(x)] = {} - for k, v in xo.items(): - k = to_text(k) - data[x][k] = serialize_spec(v) - else: - data[x] = str(xt) - - return data - - -def find_host_by_cluster_datacenter(module, content, datacenter_name, cluster_name, host_name): - dc = find_datacenter_by_name(content, datacenter_name) - if dc is None: - module.fail_json(msg="Unable to find datacenter with name %s" % datacenter_name) - cluster = find_cluster_by_name(content, cluster_name, datacenter=dc) - if cluster is None: - module.fail_json(msg="Unable to find cluster with name %s" % cluster_name) - - for host in cluster.host: - if host.name == host_name: - return host, cluster - - return None, cluster - - -def set_vm_power_state(content, vm, state, force, timeout=0): - """ - Set the power status for a VM determined by the current and - requested states. force is forceful - """ - facts = gather_vm_facts(content, vm) - expected_state = state.replace('_', '').replace('-', '').lower() - current_state = facts['hw_power_status'].lower() - result = dict( - changed=False, - failed=False, - ) - - # Need Force - if not force and current_state not in ['poweredon', 'poweredoff']: - result['failed'] = True - result['msg'] = "Virtual Machine is in %s power state. Force is required!" % current_state - result['instance'] = gather_vm_facts(content, vm) - return result - - # State is not already true - if current_state != expected_state: - task = None - try: - if expected_state == 'poweredoff': - task = vm.PowerOff() - - elif expected_state == 'poweredon': - task = vm.PowerOn() - - elif expected_state == 'restarted': - if current_state in ('poweredon', 'poweringon', 'resetting', 'poweredoff'): - task = vm.Reset() - else: - result['failed'] = True - result['msg'] = "Cannot restart virtual machine in the current state %s" % current_state - - elif expected_state == 'suspended': - if current_state in ('poweredon', 'poweringon'): - task = vm.Suspend() - else: - result['failed'] = True - result['msg'] = 'Cannot suspend virtual machine in the current state %s' % current_state - - elif expected_state in ['shutdownguest', 'rebootguest']: - if current_state == 'poweredon': - if vm.guest.toolsRunningStatus == 'guestToolsRunning': - if expected_state == 'shutdownguest': - task = vm.ShutdownGuest() - if timeout > 0: - result.update(wait_for_poweroff(vm, timeout)) - else: - task = vm.RebootGuest() - # Set result['changed'] immediately because - # shutdown and reboot return None. - result['changed'] = True - else: - result['failed'] = True - result['msg'] = "VMware tools should be installed for guest shutdown/reboot" - else: - result['failed'] = True - result['msg'] = "Virtual machine %s must be in poweredon state for guest shutdown/reboot" % vm.name - - else: - result['failed'] = True - result['msg'] = "Unsupported expected state provided: %s" % expected_state - - except Exception as e: - result['failed'] = True - result['msg'] = to_text(e) - - if task: - wait_for_task(task) - if task.info.state == 'error': - result['failed'] = True - result['msg'] = task.info.error.msg - else: - result['changed'] = True - - # need to get new metadata if changed - result['instance'] = gather_vm_facts(content, vm) - - return result - - -def wait_for_poweroff(vm, timeout=300): - result = dict() - interval = 15 - while timeout > 0: - if vm.runtime.powerState.lower() == 'poweredoff': - break - time.sleep(interval) - timeout -= interval - else: - result['failed'] = True - result['msg'] = 'Timeout while waiting for VM power off.' - return result - - -def is_integer(value, type_of='int'): - try: - VmomiSupport.vmodlTypes[type_of](value) - return True - except (TypeError, ValueError): - return False - - -def is_boolean(value): - if str(value).lower() in ['true', 'on', 'yes', 'false', 'off', 'no']: - return True - return False - - -def is_truthy(value): - if str(value).lower() in ['true', 'on', 'yes']: - return True - return False - - -# options is the dict as defined in the module parameters, current_options is -# the list of the currently set options as returned by the vSphere API. -def option_diff(options, current_options): - current_options_dict = {} - for option in current_options: - current_options_dict[option.key] = option.value - - change_option_list = [] - for option_key, option_value in options.items(): - if is_boolean(option_value): - option_value = VmomiSupport.vmodlTypes['bool'](is_truthy(option_value)) - elif isinstance(option_value, int): - option_value = VmomiSupport.vmodlTypes['int'](option_value) - elif isinstance(option_value, float): - option_value = VmomiSupport.vmodlTypes['float'](option_value) - elif isinstance(option_value, str): - option_value = VmomiSupport.vmodlTypes['string'](option_value) - - if option_key not in current_options_dict or current_options_dict[option_key] != option_value: - change_option_list.append(vim.option.OptionValue(key=option_key, value=option_value)) - - return change_option_list - - -def quote_obj_name(object_name=None): - """ - Replace special characters in object name - with urllib quote equivalent - - """ - if not object_name: - return None - - from collections import OrderedDict - SPECIAL_CHARS = OrderedDict({ - '%': '%25', - '/': '%2f', - '\\': '%5c' - }) - for key in SPECIAL_CHARS.keys(): - if key in object_name: - object_name = object_name.replace(key, SPECIAL_CHARS[key]) - - return object_name - - -class PyVmomi(object): - def __init__(self, module): - """ - Constructor - """ - if not HAS_REQUESTS: - module.fail_json(msg=missing_required_lib('requests'), - exception=REQUESTS_IMP_ERR) - - if not HAS_PYVMOMI: - module.fail_json(msg=missing_required_lib('PyVmomi'), - exception=PYVMOMI_IMP_ERR) - - self.module = module - self.params = module.params - self.current_vm_obj = None - self.si, self.content = connect_to_api(self.module, return_si=True) - self.custom_field_mgr = [] - if self.content.customFieldsManager: # not an ESXi - self.custom_field_mgr = self.content.customFieldsManager.field - - def is_vcenter(self): - """ - Check if given hostname is vCenter or ESXi host - Returns: True if given connection is with vCenter server - False if given connection is with ESXi server - - """ - api_type = None - try: - api_type = self.content.about.apiType - except (vmodl.RuntimeFault, vim.fault.VimFault) as exc: - self.module.fail_json(msg="Failed to get status of vCenter server : %s" % exc.msg) - - if api_type == 'VirtualCenter': - return True - elif api_type == 'HostAgent': - return False - - def get_managed_objects_properties(self, vim_type, properties=None): - """ - Look up a Managed Object Reference in vCenter / ESXi Environment - :param vim_type: Type of vim object e.g, for datacenter - vim.Datacenter - :param properties: List of properties related to vim object e.g. Name - :return: local content object - """ - # Get Root Folder - root_folder = self.content.rootFolder - - if properties is None: - properties = ['name'] - - # Create Container View with default root folder - mor = self.content.viewManager.CreateContainerView(root_folder, [vim_type], True) - - # Create Traversal spec - traversal_spec = vmodl.query.PropertyCollector.TraversalSpec( - name="traversal_spec", - path='view', - skip=False, - type=vim.view.ContainerView - ) - - # Create Property Spec - property_spec = vmodl.query.PropertyCollector.PropertySpec( - type=vim_type, # Type of object to retrieved - all=False, - pathSet=properties - ) - - # Create Object Spec - object_spec = vmodl.query.PropertyCollector.ObjectSpec( - obj=mor, - skip=True, - selectSet=[traversal_spec] - ) - - # Create Filter Spec - filter_spec = vmodl.query.PropertyCollector.FilterSpec( - objectSet=[object_spec], - propSet=[property_spec], - reportMissingObjectsInResults=False - ) - - return self.content.propertyCollector.RetrieveContents([filter_spec]) - - # Virtual Machine related functions - def get_vm(self): - """ - Find unique virtual machine either by UUID, MoID or Name. - Returns: virtual machine object if found, else None. - - """ - vm_obj = None - user_desired_path = None - use_instance_uuid = self.params.get('use_instance_uuid') or False - if 'uuid' in self.params and self.params['uuid']: - if not use_instance_uuid: - vm_obj = find_vm_by_id(self.content, vm_id=self.params['uuid'], vm_id_type="uuid") - elif use_instance_uuid: - vm_obj = find_vm_by_id(self.content, - vm_id=self.params['uuid'], - vm_id_type="instance_uuid") - elif 'name' in self.params and self.params['name']: - objects = self.get_managed_objects_properties(vim_type=vim.VirtualMachine, properties=['name']) - vms = [] - - for temp_vm_object in objects: - if ( - len(temp_vm_object.propSet) == 1 and - temp_vm_object.propSet[0].val == self.params['name']): - vms.append(temp_vm_object.obj) - - # get_managed_objects_properties may return multiple virtual machine, - # following code tries to find user desired one depending upon the folder specified. - if len(vms) > 1: - # We have found multiple virtual machines, decide depending upon folder value - if self.params['folder'] is None: - self.module.fail_json(msg="Multiple virtual machines with same name [%s] found, " - "Folder value is a required parameter to find uniqueness " - "of the virtual machine" % self.params['name'], - details="Please see documentation of the vmware_guest module " - "for folder parameter.") - - # Get folder path where virtual machine is located - # User provided folder where user thinks virtual machine is present - user_folder = self.params['folder'] - # User defined datacenter - user_defined_dc = self.params['datacenter'] - # User defined datacenter's object - datacenter_obj = find_datacenter_by_name(self.content, self.params['datacenter']) - # Get Path for Datacenter - dcpath = compile_folder_path_for_object(vobj=datacenter_obj) - - # Nested folder does not return trailing / - if not dcpath.endswith('/'): - dcpath += '/' - - if user_folder in [None, '', '/']: - # User provided blank value or - # User provided only root value, we fail - self.module.fail_json(msg="vmware_guest found multiple virtual machines with same " - "name [%s], please specify folder path other than blank " - "or '/'" % self.params['name']) - elif user_folder.startswith('/vm/'): - # User provided nested folder under VMware default vm folder i.e. folder = /vm/india/finance - user_desired_path = "%s%s%s" % (dcpath, user_defined_dc, user_folder) - else: - # User defined datacenter is not nested i.e. dcpath = '/' , or - # User defined datacenter is nested i.e. dcpath = '/F0/DC0' or - # User provided folder starts with / and datacenter i.e. folder = /ha-datacenter/ or - # User defined folder starts with datacenter without '/' i.e. - # folder = DC0/vm/india/finance or - # folder = DC0/vm - user_desired_path = user_folder - - for vm in vms: - # Check if user has provided same path as virtual machine - actual_vm_folder_path = self.get_vm_path(content=self.content, vm_name=vm) - if not actual_vm_folder_path.startswith("%s%s" % (dcpath, user_defined_dc)): - continue - if user_desired_path in actual_vm_folder_path: - vm_obj = vm - break - elif vms: - # Unique virtual machine found. - actual_vm_folder_path = self.get_vm_path(content=self.content, vm_name=vms[0]) - if self.params.get('folder') is None: - vm_obj = vms[0] - elif self.params['folder'] in actual_vm_folder_path: - vm_obj = vms[0] - elif 'moid' in self.params and self.params['moid']: - vm_obj = VmomiSupport.templateOf('VirtualMachine')(self.params['moid'], self.si._stub) - - if vm_obj: - self.current_vm_obj = vm_obj - - return vm_obj - - def gather_facts(self, vm): - """ - Gather facts of virtual machine. - Args: - vm: Name of virtual machine. - - Returns: Facts dictionary of the given virtual machine. - - """ - return gather_vm_facts(self.content, vm) - - @staticmethod - def get_vm_path(content, vm_name): - """ - Find the path of virtual machine. - Args: - content: VMware content object - vm_name: virtual machine managed object - - Returns: Folder of virtual machine if exists, else None - - """ - folder_name = None - folder = vm_name.parent - if folder: - folder_name = folder.name - fp = folder.parent - # climb back up the tree to find our path, stop before the root folder - while fp is not None and fp.name is not None and fp != content.rootFolder: - folder_name = fp.name + '/' + folder_name - try: - fp = fp.parent - except Exception: - break - folder_name = '/' + folder_name - return folder_name - - def get_vm_or_template(self, template_name=None): - """ - Find the virtual machine or virtual machine template using name - used for cloning purpose. - Args: - template_name: Name of virtual machine or virtual machine template - - Returns: virtual machine or virtual machine template object - - """ - template_obj = None - if not template_name: - return template_obj - - if "/" in template_name: - vm_obj_path = os.path.dirname(template_name) - vm_obj_name = os.path.basename(template_name) - template_obj = find_vm_by_id(self.content, vm_obj_name, vm_id_type="inventory_path", folder=vm_obj_path) - if template_obj: - return template_obj - else: - template_obj = find_vm_by_id(self.content, vm_id=template_name, vm_id_type="uuid") - if template_obj: - return template_obj - - objects = self.get_managed_objects_properties(vim_type=vim.VirtualMachine, properties=['name']) - templates = [] - - for temp_vm_object in objects: - if len(temp_vm_object.propSet) != 1: - continue - for temp_vm_object_property in temp_vm_object.propSet: - if temp_vm_object_property.val == template_name: - templates.append(temp_vm_object.obj) - break - - if len(templates) > 1: - # We have found multiple virtual machine templates - self.module.fail_json(msg="Multiple virtual machines or templates with same name [%s] found." % template_name) - elif templates: - template_obj = templates[0] - - return template_obj - - # Cluster related functions - def find_cluster_by_name(self, cluster_name, datacenter_name=None): - """ - Find Cluster by name in given datacenter - Args: - cluster_name: Name of cluster name to find - datacenter_name: (optional) Name of datacenter - - Returns: True if found - - """ - return find_cluster_by_name(self.content, cluster_name, datacenter=datacenter_name) - - def get_all_hosts_by_cluster(self, cluster_name): - """ - Get all hosts from cluster by cluster name - Args: - cluster_name: Name of cluster - - Returns: List of hosts - - """ - cluster_obj = self.find_cluster_by_name(cluster_name=cluster_name) - if cluster_obj: - return [host for host in cluster_obj.host] - else: - return [] - - # Hosts related functions - def find_hostsystem_by_name(self, host_name): - """ - Find Host by name - Args: - host_name: Name of ESXi host - - Returns: True if found - - """ - return find_hostsystem_by_name(self.content, hostname=host_name) - - def get_all_host_objs(self, cluster_name=None, esxi_host_name=None): - """ - Get all host system managed object - - Args: - cluster_name: Name of Cluster - esxi_host_name: Name of ESXi server - - Returns: A list of all host system managed objects, else empty list - - """ - host_obj_list = [] - if not self.is_vcenter(): - hosts = get_all_objs(self.content, [vim.HostSystem]).keys() - if hosts: - host_obj_list.append(list(hosts)[0]) - else: - if cluster_name: - cluster_obj = self.find_cluster_by_name(cluster_name=cluster_name) - if cluster_obj: - host_obj_list = [host for host in cluster_obj.host] - else: - self.module.fail_json(changed=False, msg="Cluster '%s' not found" % cluster_name) - elif esxi_host_name: - if isinstance(esxi_host_name, str): - esxi_host_name = [esxi_host_name] - - for host in esxi_host_name: - esxi_host_obj = self.find_hostsystem_by_name(host_name=host) - if esxi_host_obj: - host_obj_list.append(esxi_host_obj) - else: - self.module.fail_json(changed=False, msg="ESXi '%s' not found" % host) - - return host_obj_list - - def host_version_at_least(self, version=None, vm_obj=None, host_name=None): - """ - Check that the ESXi Host is at least a specific version number - Args: - vm_obj: virtual machine object, required one of vm_obj, host_name - host_name (string): ESXi host name - version (tuple): a version tuple, for example (6, 7, 0) - Returns: bool - """ - if vm_obj: - host_system = vm_obj.summary.runtime.host - elif host_name: - host_system = self.find_hostsystem_by_name(host_name=host_name) - else: - self.module.fail_json(msg='VM object or ESXi host name must be set one.') - if host_system and version: - host_version = host_system.summary.config.product.version - return StrictVersion(host_version) >= StrictVersion('.'.join(map(str, version))) - else: - self.module.fail_json(msg='Unable to get the ESXi host from vm: %s, or hostname %s,' - 'or the passed ESXi version: %s is None.' % (vm_obj, host_name, version)) - - # Network related functions - @staticmethod - def find_host_portgroup_by_name(host, portgroup_name): - """ - Find Portgroup on given host - Args: - host: Host config object - portgroup_name: Name of portgroup - - Returns: True if found else False - - """ - for portgroup in host.config.network.portgroup: - if portgroup.spec.name == portgroup_name: - return portgroup - return False - - def get_all_port_groups_by_host(self, host_system): - """ - Get all Port Group by host - Args: - host_system: Name of Host System - - Returns: List of Port Group Spec - """ - pgs_list = [] - for pg in host_system.config.network.portgroup: - pgs_list.append(pg) - return pgs_list - - def find_network_by_name(self, network_name=None): - """ - Get network specified by name - Args: - network_name: Name of network - - Returns: List of network managed objects - """ - networks = [] - - if not network_name: - return networks - - objects = self.get_managed_objects_properties(vim_type=vim.Network, properties=['name']) - - for temp_vm_object in objects: - if len(temp_vm_object.propSet) != 1: - continue - for temp_vm_object_property in temp_vm_object.propSet: - if temp_vm_object_property.val == network_name: - networks.append(temp_vm_object.obj) - break - return networks - - def network_exists_by_name(self, network_name=None): - """ - Check if network with a specified name exists or not - Args: - network_name: Name of network - - Returns: True if network exists else False - """ - ret = False - if not network_name: - return ret - ret = True if self.find_network_by_name(network_name=network_name) else False - return ret - - # Datacenter - def find_datacenter_by_name(self, datacenter_name): - """ - Get datacenter managed object by name - - Args: - datacenter_name: Name of datacenter - - Returns: datacenter managed object if found else None - - """ - return find_datacenter_by_name(self.content, datacenter_name=datacenter_name) - - def is_datastore_valid(self, datastore_obj=None): - """ - Check if datastore selected is valid or not - Args: - datastore_obj: datastore managed object - - Returns: True if datastore is valid, False if not - """ - if not datastore_obj \ - or datastore_obj.summary.maintenanceMode != 'normal' \ - or not datastore_obj.summary.accessible: - return False - return True - - def find_datastore_by_name(self, datastore_name, datacenter_name=None): - """ - Get datastore managed object by name - Args: - datastore_name: Name of datastore - datacenter_name: Name of datacenter where the datastore resides. This is needed because Datastores can be - shared across Datacenters, so we need to specify the datacenter to assure we get the correct Managed Object Reference - - Returns: datastore managed object if found else None - - """ - return find_datastore_by_name(self.content, datastore_name=datastore_name, datacenter_name=datacenter_name) - - def find_folder_by_name(self, folder_name): - """ - Get vm folder managed object by name - Args: - folder_name: Name of the vm folder - - Returns: vm folder managed object if found else None - - """ - return find_folder_by_name(self.content, folder_name=folder_name) - - # Datastore cluster - def find_datastore_cluster_by_name(self, datastore_cluster_name): - """ - Get datastore cluster managed object by name - Args: - datastore_cluster_name: Name of datastore cluster - - Returns: Datastore cluster managed object if found else None - - """ - data_store_clusters = get_all_objs(self.content, [vim.StoragePod]) - for dsc in data_store_clusters: - if dsc.name == datastore_cluster_name: - return dsc - return None - - # Resource pool - def find_resource_pool_by_name(self, resource_pool_name, folder=None): - """ - Get resource pool managed object by name - Args: - resource_pool_name: Name of resource pool - - Returns: Resource pool managed object if found else None - - """ - if not folder: - folder = self.content.rootFolder - - resource_pools = get_all_objs(self.content, [vim.ResourcePool], folder=folder) - for rp in resource_pools: - if rp.name == resource_pool_name: - return rp - return None - - def find_resource_pool_by_cluster(self, resource_pool_name='Resources', cluster=None): - """ - Get resource pool managed object by cluster object - Args: - resource_pool_name: Name of resource pool - cluster: Managed object of cluster - - Returns: Resource pool managed object if found else None - - """ - desired_rp = None - if not cluster: - return desired_rp - - if resource_pool_name != 'Resources': - # Resource pool name is different than default 'Resources' - resource_pools = cluster.resourcePool.resourcePool - if resource_pools: - for rp in resource_pools: - if rp.name == resource_pool_name: - desired_rp = rp - break - else: - desired_rp = cluster.resourcePool - - return desired_rp - - # VMDK stuff - def vmdk_disk_path_split(self, vmdk_path): - """ - Takes a string in the format - - [datastore_name] path/to/vm_name.vmdk - - Returns a tuple with multiple strings: - - 1. datastore_name: The name of the datastore (without brackets) - 2. vmdk_fullpath: The "path/to/vm_name.vmdk" portion - 3. vmdk_filename: The "vm_name.vmdk" portion of the string (os.path.basename equivalent) - 4. vmdk_folder: The "path/to/" portion of the string (os.path.dirname equivalent) - """ - try: - datastore_name = re.match(r'^\[(.*?)\]', vmdk_path, re.DOTALL).groups()[0] - vmdk_fullpath = re.match(r'\[.*?\] (.*)$', vmdk_path).groups()[0] - vmdk_filename = os.path.basename(vmdk_fullpath) - vmdk_folder = os.path.dirname(vmdk_fullpath) - return datastore_name, vmdk_fullpath, vmdk_filename, vmdk_folder - except (IndexError, AttributeError) as e: - self.module.fail_json(msg="Bad path '%s' for filename disk vmdk image: %s" % (vmdk_path, to_native(e))) - - def find_vmdk_file(self, datastore_obj, vmdk_fullpath, vmdk_filename, vmdk_folder): - """ - Return vSphere file object or fail_json - Args: - datastore_obj: Managed object of datastore - vmdk_fullpath: Path of VMDK file e.g., path/to/vm/vmdk_filename.vmdk - vmdk_filename: Name of vmdk e.g., VM0001_1.vmdk - vmdk_folder: Base dir of VMDK e.g, path/to/vm - - """ - - browser = datastore_obj.browser - datastore_name = datastore_obj.name - datastore_name_sq = "[" + datastore_name + "]" - if browser is None: - self.module.fail_json(msg="Unable to access browser for datastore %s" % datastore_name) - - detail_query = vim.host.DatastoreBrowser.FileInfo.Details( - fileOwner=True, - fileSize=True, - fileType=True, - modification=True - ) - search_spec = vim.host.DatastoreBrowser.SearchSpec( - details=detail_query, - matchPattern=[vmdk_filename], - searchCaseInsensitive=True, - ) - search_res = browser.SearchSubFolders( - datastorePath=datastore_name_sq, - searchSpec=search_spec - ) - - changed = False - vmdk_path = datastore_name_sq + " " + vmdk_fullpath - try: - changed, result = wait_for_task(search_res) - except TaskError as task_e: - self.module.fail_json(msg=to_native(task_e)) - - if not changed: - self.module.fail_json(msg="No valid disk vmdk image found for path %s" % vmdk_path) - - target_folder_paths = [ - datastore_name_sq + " " + vmdk_folder + '/', - datastore_name_sq + " " + vmdk_folder, - ] - - for file_result in search_res.info.result: - for f in getattr(file_result, 'file'): - if f.path == vmdk_filename and file_result.folderPath in target_folder_paths: - return f - - self.module.fail_json(msg="No vmdk file found for path specified [%s]" % vmdk_path) - - # - # Conversion to JSON - # - - def _deepmerge(self, d, u): - """ - Deep merges u into d. - - Credit: - https://bit.ly/2EDOs1B (stackoverflow question 3232943) - License: - cc-by-sa 3.0 (https://creativecommons.org/licenses/by-sa/3.0/) - Changes: - using collections_compat for compatibility - - Args: - - d (dict): dict to merge into - - u (dict): dict to merge into d - - Returns: - dict, with u merged into d - """ - for k, v in iteritems(u): - if isinstance(v, collections_compat.Mapping): - d[k] = self._deepmerge(d.get(k, {}), v) - else: - d[k] = v - return d - - def _extract(self, data, remainder): - """ - This is used to break down dotted properties for extraction. - - Args: - - data (dict): result of _jsonify on a property - - remainder: the remainder of the dotted property to select - - Return: - dict - """ - result = dict() - if '.' not in remainder: - result[remainder] = data[remainder] - return result - key, remainder = remainder.split('.', 1) - result[key] = self._extract(data[key], remainder) - return result - - def _jsonify(self, obj): - """ - Convert an object from pyVmomi into JSON. - - Args: - - obj (object): vim object - - Return: - dict - """ - return json.loads(json.dumps(obj, cls=VmomiSupport.VmomiJSONEncoder, - sort_keys=True, strip_dynamic=True)) - - def to_json(self, obj, properties=None): - """ - Convert a vSphere (pyVmomi) Object into JSON. This is a deep - transformation. The list of properties is optional - if not - provided then all properties are deeply converted. The resulting - JSON is sorted to improve human readability. - - Requires upstream support from pyVmomi > 6.7.1 - (https://github.com/vmware/pyvmomi/pull/732) - - Args: - - obj (object): vim object - - properties (list, optional): list of properties following - the property collector specification, for example: - ["config.hardware.memoryMB", "name", "overallStatus"] - default is a complete object dump, which can be large - - Return: - dict - """ - if not HAS_PYVMOMIJSON: - self.module.fail_json(msg='The installed version of pyvmomi lacks JSON output support; need pyvmomi>6.7.1') - - result = dict() - if properties: - for prop in properties: - try: - if '.' in prop: - key, remainder = prop.split('.', 1) - tmp = dict() - tmp[key] = self._extract(self._jsonify(getattr(obj, key)), remainder) - self._deepmerge(result, tmp) - else: - result[prop] = self._jsonify(getattr(obj, prop)) - # To match gather_vm_facts output - prop_name = prop - if prop.lower() == '_moid': - prop_name = 'moid' - elif prop.lower() == '_vimref': - prop_name = 'vimref' - result[prop_name] = result[prop] - except (AttributeError, KeyError): - self.module.fail_json(msg="Property '{0}' not found.".format(prop)) - else: - result = self._jsonify(obj) - return result - - def get_folder_path(self, cur): - full_path = '/' + cur.name - while hasattr(cur, 'parent') and cur.parent: - if cur.parent == self.content.rootFolder: - break - cur = cur.parent - full_path = '/' + cur.name + full_path - return full_path diff --git a/lib/ansible/module_utils/vmware_rest_client.py b/lib/ansible/module_utils/vmware_rest_client.py deleted file mode 100644 index fe89ade75c..0000000000 --- a/lib/ansible/module_utils/vmware_rest_client.py +++ /dev/null @@ -1,432 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause) - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - -import traceback - -REQUESTS_IMP_ERR = None -try: - import requests - HAS_REQUESTS = True -except ImportError: - REQUESTS_IMP_ERR = traceback.format_exc() - HAS_REQUESTS = False - -PYVMOMI_IMP_ERR = None -try: - from pyVim import connect - from pyVmomi import vim, vmodl - HAS_PYVMOMI = True -except ImportError: - PYVMOMI_IMP_ERR = traceback.format_exc() - HAS_PYVMOMI = False - -VSPHERE_IMP_ERR = None -try: - from com.vmware.vapi.std_client import DynamicID - from vmware.vapi.vsphere.client import create_vsphere_client - from com.vmware.vapi.std.errors_client import Unauthorized - from com.vmware.content.library_client import Item - from com.vmware.vcenter_client import (Folder, - Datacenter, - ResourcePool, - Datastore, - Cluster, - Host) - HAS_VSPHERE = True -except ImportError: - VSPHERE_IMP_ERR = traceback.format_exc() - HAS_VSPHERE = False - -from ansible.module_utils.basic import env_fallback, missing_required_lib - - -class VmwareRestClient(object): - def __init__(self, module): - """ - Constructor - - """ - self.module = module - self.params = module.params - self.check_required_library() - self.api_client = self.connect_to_vsphere_client() - - # Helper function - def get_error_message(self, error): - """ - Helper function to show human readable error messages. - """ - err_msg = [] - if not error.messages: - if isinstance(error, Unauthorized): - return "Authorization required." - return "Generic error occurred." - - for err in error.messages: - err_msg.append(err.default_message % err.args) - - return " ,".join(err_msg) - - def check_required_library(self): - """ - Check required libraries - - """ - if not HAS_REQUESTS: - self.module.fail_json(msg=missing_required_lib('requests'), - exception=REQUESTS_IMP_ERR) - if not HAS_PYVMOMI: - self.module.fail_json(msg=missing_required_lib('PyVmomi'), - exception=PYVMOMI_IMP_ERR) - if not HAS_VSPHERE: - self.module.fail_json( - msg=missing_required_lib('vSphere Automation SDK', - url='https://code.vmware.com/web/sdk/65/vsphere-automation-python'), - exception=VSPHERE_IMP_ERR) - - @staticmethod - def vmware_client_argument_spec(): - return dict( - hostname=dict(type='str', - fallback=(env_fallback, ['VMWARE_HOST'])), - username=dict(type='str', - fallback=(env_fallback, ['VMWARE_USER']), - aliases=['user', 'admin']), - password=dict(type='str', - fallback=(env_fallback, ['VMWARE_PASSWORD']), - aliases=['pass', 'pwd'], - no_log=True), - port=dict(type='int', - default=443, - fallback=(env_fallback, ['VMWARE_PORT'])), - protocol=dict(type='str', - default='https', - choices=['https', 'http']), - validate_certs=dict(type='bool', - fallback=(env_fallback, ['VMWARE_VALIDATE_CERTS']), - default=True), - ) - - def connect_to_vsphere_client(self): - """ - Connect to vSphere API Client with Username and Password - - """ - username = self.params.get('username') - password = self.params.get('password') - hostname = self.params.get('hostname') - port = self.params.get('port') - session = requests.Session() - session.verify = self.params.get('validate_certs') - - if not all([hostname, username, password]): - self.module.fail_json(msg="Missing one of the following : hostname, username, password." - " Please read the documentation for more information.") - - client = create_vsphere_client( - server="%s:%s" % (hostname, port), - username=username, - password=password, - session=session) - if client is None: - self.module.fail_json(msg="Failed to login to %s" % hostname) - - return client - - def get_tags_for_object(self, tag_service=None, tag_assoc_svc=None, dobj=None): - """ - Return list of tag objects associated with an object - Args: - dobj: Dynamic object - tag_service: Tag service object - tag_assoc_svc: Tag Association object - Returns: List of tag objects associated with the given object - """ - # This method returns list of tag objects only, - # Please use get_tags_for_dynamic_obj for more object details - tags = [] - if not dobj: - return tags - - if not tag_service: - tag_service = self.api_client.tagging.Tag - - if not tag_assoc_svc: - tag_assoc_svc = self.api_client.tagging.TagAssociation - - tag_ids = tag_assoc_svc.list_attached_tags(dobj) - - for tag_id in tag_ids: - tags.append(tag_service.get(tag_id)) - - return tags - - def get_tags_for_dynamic_obj(self, dobj=None): - """ - Return list of tag object details associated with object - Args: - mid: Dynamic object for specified object - - Returns: List of tag object details associated with the given object - - """ - tags = [] - if dobj is None: - return tags - - temp_tags_model = self.get_tags_for_object(dobj) - - category_service = self.api_client.tagging.Category - - for tag_obj in temp_tags_model: - tags.append({ - 'id': tag_obj.id, - 'category_name': category_service.get(tag_obj.category_id).name, - 'name': tag_obj.name, - 'description': tag_obj.description, - 'category_id': tag_obj.category_id, - }) - - return tags - - def get_tags_for_cluster(self, cluster_mid=None): - """ - Return list of tag object associated with cluster - Args: - cluster_mid: Dynamic object for cluster - - Returns: List of tag object associated with the given cluster - - """ - dobj = DynamicID(type='cluster', id=cluster_mid) - return self.get_tags_for_dynamic_obj(dobj) - - def get_tags_for_hostsystem(self, hostsystem_mid=None): - """ - Return list of tag object associated with host system - Args: - hostsystem_mid: Dynamic object for host system - - Returns: List of tag object associated with the given host system - - """ - dobj = DynamicID(type='HostSystem', id=hostsystem_mid) - return self.get_tags_for_dynamic_obj(dobj) - - def get_tags_for_vm(self, vm_mid=None): - """ - Return list of tag object associated with virtual machine - Args: - vm_mid: Dynamic object for virtual machine - - Returns: List of tag object associated with the given virtual machine - - """ - dobj = DynamicID(type='VirtualMachine', id=vm_mid) - return self.get_tags_for_dynamic_obj(dobj) - - def get_vm_tags(self, tag_service=None, tag_association_svc=None, vm_mid=None): - """ - Return list of tag name associated with virtual machine - Args: - tag_service: Tag service object - tag_association_svc: Tag association object - vm_mid: Dynamic object for virtual machine - - Returns: List of tag names associated with the given virtual machine - - """ - # This API returns just names of tags - # Please use get_tags_for_vm for more tag object details - tags = [] - if vm_mid is None: - return tags - - temp_tags_model = self.get_tags_for_object( - tag_service=tag_service, - tag_assoc_svc=tag_association_svc, - dobj=vm_mid - ) - - for tag_obj in temp_tags_model: - tags.append(tag_obj.name) - - return tags - - def get_library_item_by_name(self, name): - """ - Returns the identifier of the library item with the given name. - - Args: - name (str): The name of item to look for - - Returns: - str: The item ID or None if the item is not found - """ - find_spec = Item.FindSpec(name=name) - item_ids = self.api_client.content.library.Item.find(find_spec) - item_id = item_ids[0] if item_ids else None - return item_id - - def get_datacenter_by_name(self, datacenter_name): - """ - Returns the identifier of a datacenter - Note: The method assumes only one datacenter with the mentioned name. - """ - filter_spec = Datacenter.FilterSpec(names=set([datacenter_name])) - datacenter_summaries = self.api_client.vcenter.Datacenter.list(filter_spec) - datacenter = datacenter_summaries[0].datacenter if len(datacenter_summaries) > 0 else None - return datacenter - - def get_folder_by_name(self, datacenter_name, folder_name): - """ - Returns the identifier of a folder - with the mentioned names. - """ - datacenter = self.get_datacenter_by_name(datacenter_name) - if not datacenter: - return None - filter_spec = Folder.FilterSpec(type=Folder.Type.VIRTUAL_MACHINE, - names=set([folder_name]), - datacenters=set([datacenter])) - folder_summaries = self.api_client.vcenter.Folder.list(filter_spec) - folder = folder_summaries[0].folder if len(folder_summaries) > 0 else None - return folder - - def get_resource_pool_by_name(self, datacenter_name, resourcepool_name): - """ - Returns the identifier of a resource pool - with the mentioned names. - """ - datacenter = self.get_datacenter_by_name(datacenter_name) - if not datacenter: - return None - names = set([resourcepool_name]) if resourcepool_name else None - filter_spec = ResourcePool.FilterSpec(datacenters=set([datacenter]), - names=names) - resource_pool_summaries = self.api_client.vcenter.ResourcePool.list(filter_spec) - resource_pool = resource_pool_summaries[0].resource_pool if len(resource_pool_summaries) > 0 else None - return resource_pool - - def get_datastore_by_name(self, datacenter_name, datastore_name): - """ - Returns the identifier of a datastore - with the mentioned names. - """ - datacenter = self.get_datacenter_by_name(datacenter_name) - if not datacenter: - return None - names = set([datastore_name]) if datastore_name else None - filter_spec = Datastore.FilterSpec(datacenters=set([datacenter]), - names=names) - datastore_summaries = self.api_client.vcenter.Datastore.list(filter_spec) - datastore = datastore_summaries[0].datastore if len(datastore_summaries) > 0 else None - return datastore - - def get_cluster_by_name(self, datacenter_name, cluster_name): - """ - Returns the identifier of a cluster - with the mentioned names. - """ - datacenter = self.get_datacenter_by_name(datacenter_name) - if not datacenter: - return None - names = set([cluster_name]) if cluster_name else None - filter_spec = Cluster.FilterSpec(datacenters=set([datacenter]), - names=names) - cluster_summaries = self.api_client.vcenter.Cluster.list(filter_spec) - cluster = cluster_summaries[0].cluster if len(cluster_summaries) > 0 else None - return cluster - - def get_host_by_name(self, datacenter_name, host_name): - """ - Returns the identifier of a Host - with the mentioned names. - """ - datacenter = self.get_datacenter_by_name(datacenter_name) - if not datacenter: - return None - names = set([host_name]) if host_name else None - filter_spec = Host.FilterSpec(datacenters=set([datacenter]), - names=names) - host_summaries = self.api_client.vcenter.Host.list(filter_spec) - host = host_summaries[0].host if len(host_summaries) > 0 else None - return host - - @staticmethod - def search_svc_object_by_name(service, svc_obj_name=None): - """ - Return service object by name - Args: - service: Service object - svc_obj_name: Name of service object to find - - Returns: Service object if found else None - - """ - if not svc_obj_name: - return None - - for svc_object in service.list(): - svc_obj = service.get(svc_object) - if svc_obj.name == svc_obj_name: - return svc_obj - return None - - def get_tag_by_name(self, tag_name=None): - """ - Return tag object by name - Args: - tag_name: Name of tag - - Returns: Tag object if found else None - """ - if not tag_name: - return None - - return self.search_svc_object_by_name(service=self.api_client.tagging.Tag, svc_obj_name=tag_name) - - def get_category_by_name(self, category_name=None): - """ - Return category object by name - Args: - category_name: Name of category - - Returns: Category object if found else None - """ - if not category_name: - return None - - return self.search_svc_object_by_name(service=self.api_client.tagging.Category, svc_obj_name=category_name) - - def get_tag_by_category(self, tag_name=None, category_name=None): - """ - Return tag object by name and category name specified - Args: - tag_name: Name of tag - category_name: Name of category - - Returns: Tag object if found else None - """ - - if not tag_name: - return None - - if category_name: - category_obj = self.get_category_by_name(category_name=category_name) - - if not category_obj: - return None - - for tag_object in self.api_client.tagging.Tag.list(): - tag_obj = self.api_client.tagging.Tag.get(tag_object) - - if tag_obj.name == tag_name and tag_obj.category_id == category_obj.id: - return tag_obj - else: - return self.search_svc_object_by_name(service=self.api_client.tagging.Tag, svc_obj_name=tag_name) diff --git a/lib/ansible/module_utils/vmware_spbm.py b/lib/ansible/module_utils/vmware_spbm.py deleted file mode 100644 index 168213a9f4..0000000000 --- a/lib/ansible/module_utils/vmware_spbm.py +++ /dev/null @@ -1,43 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright: (c) 2019, Ansible Project -# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause) - -from __future__ import absolute_import, division, print_function -__metaclass__ = type - -try: - from pyVmomi import vim, pbm - from pyVim.connect import SoapStubAdapter -except ImportError: - pass - -from ansible.module_utils.vmware import PyVmomi - - -class SPBM(PyVmomi): - def __init__(self, module): - super(SPBM, self).__init__(module) - self.spbm_content = None - self.spbm_si = None - self.version = "pbm.version.version2" - - def get_spbm_connection(self): - """ - Creates a Service instance for VMware SPBM - """ - client_stub = self.si._GetStub() - try: - session_cookie = client_stub.cookie.split('"')[1] - except IndexError: - self.module.fail_json(msg="Failed to get session cookie") - ssl_context = client_stub.schemeArgs.get('context') - additional_headers = {'vcSessionCookie': session_cookie} - hostname = self.module.params['hostname'] - if not hostname: - self.module.fail_json(msg="Please specify required parameter - hostname") - stub = SoapStubAdapter(host=hostname, path="/pbm/sdk", version=self.version, - sslContext=ssl_context, requestContext=additional_headers) - - self.spbm_si = pbm.ServiceInstance("ServiceInstance", stub) - self.spbm_content = self.spbm_si.PbmRetrieveServiceContent() diff --git a/lib/ansible/modules/cloud/vmware/_vcenter_extension_facts.py b/lib/ansible/modules/cloud/vmware/_vcenter_extension_facts.py deleted file mode 100644 index 37a03b7aa6..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vcenter_extension_facts.py +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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': ['deprecated'], - 'supported_by': 'community' -} - -DOCUMENTATION = r''' ---- -module: vcenter_extension_facts -deprecated: - removed_in: '2.13' - why: Deprecated in favour of C(_info) module. - alternative: Use M(vcenter_extension_info) instead. -short_description: Gather facts vCenter extensions -description: -- This module can be used to gather facts about vCenter extension. -version_added: 2.8 -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather facts about vCenter Extensions - vcenter_extension_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - register: ext_facts - delegate_to: localhost -''' - -RETURN = r''' -extension_facts: - description: List of extensions - returned: success - type: list - sample: [ - { - "extension_company": "VMware, Inc.", - "extension_key": "com.vmware.vim.ls", - "extension_label": "License Services", - "extension_last_heartbeat_time": "2018-09-03T09:36:18.003768+00:00", - "extension_subject_name": "", - "extension_summary": "Provides various license services", - "extension_type": "", - "extension_version": "5.0" - }, - { - "extension_company": "VMware Inc.", - "extension_key": "com.vmware.vim.sms", - "extension_label": "VMware vCenter Storage Monitoring Service", - "extension_last_heartbeat_time": "2018-09-03T09:36:18.005730+00:00", - "extension_subject_name": "", - "extension_summary": "Storage Monitoring and Reporting", - "extension_type": "", - "extension_version": "5.5" - } - ] -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class VmwareExtManager(PyVmomi): - def __init__(self, module): - super(VmwareExtManager, self).__init__(module) - - def gather_plugin_facts(self): - result = dict(changed=False, extension_facts=[]) - ext_manager = self.content.extensionManager - if not ext_manager: - self.module.exit_json(**result) - - for ext in ext_manager.extensionList: - ext_info = dict( - extension_label=ext.description.label, - extension_summary=ext.description.summary, - extension_key=ext.key, - extension_company=ext.company, - extension_version=ext.version, - extension_type=ext.type if ext.type else '', - extension_subject_name=ext.subjectName if ext.subjectName else '', - extension_last_heartbeat_time=ext.lastHeartbeatTime, - ) - result['extension_facts'].append(ext_info) - - self.module.exit_json(**result) - - -def main(): - argument_spec = vmware_argument_spec() - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - vcenter_extension_facts_mgr = VmwareExtManager(module) - vcenter_extension_facts_mgr.gather_plugin_facts() - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/_vmware_about_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_about_facts.py deleted file mode 100644 index 764230cdcd..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_about_facts.py +++ /dev/null @@ -1,130 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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': ['deprecated'], - 'supported_by': 'community' -} - -DOCUMENTATION = r''' ---- -module: vmware_about_facts -deprecated: - removed_in: '2.13' - why: Deprecated in favour of C(_info) module. - alternative: Use M(vmware_about_info) instead. -short_description: Provides information about VMware server to which user is connecting to -description: -- This module can be used to gather information about VMware server to which user is trying to connect. -version_added: 2.7 -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Provide information about vCenter - vmware_about_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - delegate_to: localhost - register: vcenter_about_info - -- name: Provide information about a standalone ESXi server - vmware_about_facts: - hostname: '{{ esxi_hostname }}' - username: '{{ esxi_username }}' - password: '{{ esxi_password }}' - delegate_to: localhost - register: esxi_about_info -''' - -RETURN = r''' -about_facts: - description: - - dict about VMware server - returned: success - type: str - sample: - { - "api_type": "VirtualCenter", - "api_version": "6.5", - "build": "5973321", - "instance_uuid": "dbed6e0c-bd88-4ef6-b594-21283e1c677f", - "license_product_name": "VMware VirtualCenter Server", - "license_product_version": "6.0", - "locale_build": "000", - "locale_version": "INTL", - "os_type": "darwin-amd64", - "product_full_name": "VMware vCenter Server 6.5.0 build-5973321", - "product_line_id": "vpx", - "product_name": "VMware vCenter Server (govmomi simulator)", - "vendor": "VMware, Inc.", - "version": "6.5.0" - } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class VmwareAboutManager(PyVmomi): - def __init__(self, module): - super(VmwareAboutManager, self).__init__(module) - - def gather_about_facts(self): - - if not self.content: - self.module.exit_json(changed=False, about_facts=dict()) - - about = self.content.about - - self.module.exit_json( - changed=False, - about_facts=dict( - product_name=about.name, - product_full_name=about.fullName, - vendor=about.vendor, - version=about.version, - build=about.build, - locale_version=about.localeVersion, - locale_build=about.localeBuild, - os_type=about.osType, - product_line_id=about.productLineId, - api_type=about.apiType, - api_version=about.apiVersion, - instance_uuid=about.instanceUuid, - license_product_name=about.licenseProductName, - license_product_version=about.licenseProductVersion, - ) - ) - - -def main(): - argument_spec = vmware_argument_spec() - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - vmware_about_facts_mgr = VmwareAboutManager(module) - vmware_about_facts_mgr.gather_about_facts() - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/_vmware_category_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_category_facts.py deleted file mode 100644 index 4e8f7c9346..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_category_facts.py +++ /dev/null @@ -1,132 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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': ['deprecated'], - 'supported_by': 'community' -} - -DOCUMENTATION = r''' ---- -module: vmware_category_facts -deprecated: - removed_in: '2.13' - why: Deprecated in favour of C(_info) module. - alternative: Use M(vmware_category_info) instead. -short_description: Gather facts about VMware tag categories -description: -- This module can be used to gather facts about VMware tag categories. -- Tag feature is introduced in vSphere 6 version, so this module is not supported in earlier versions of vSphere. -- All variables and VMware object names are case sensitive. -version_added: '2.7' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -- vSphere Automation SDK -extends_documentation_fragment: vmware_rest_client.documentation -''' - -EXAMPLES = r''' -- name: Gather facts about tag categories - vmware_category_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - delegate_to: localhost - register: all_tag_category_facts - -- name: Gather category id from given tag category - vmware_category_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - delegate_to: localhost - register: tag_category_results - -- set_fact: - category_id: "{{ item.category_id }}" - loop: "{{ tag_category_results.tag_category_facts|json_query(query) }}" - vars: - query: "[?category_name==`Category0001`]" -- debug: var=category_id - -''' - -RETURN = r''' -tag_category_facts: - description: metadata of tag categories - returned: always - type: list - sample: [ - { - "category_associable_types": [], - "category_cardinality": "MULTIPLE", - "category_description": "awesome description", - "category_id": "urn:vmomi:InventoryServiceCategory:e785088d-6981-4b1c-9fb8-1100c3e1f742:GLOBAL", - "category_name": "Category0001", - "category_used_by": [] - }, - { - "category_associable_types": [ - "VirtualMachine" - ], - "category_cardinality": "SINGLE", - "category_description": "another awesome description", - "category_id": "urn:vmomi:InventoryServiceCategory:ae5b7c6c-e622-4671-9b96-76e93adb70f2:GLOBAL", - "category_name": "template_tag", - "category_used_by": [] - } - ] -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware_rest_client import VmwareRestClient - - -class VmwareCategoryFactsManager(VmwareRestClient): - def __init__(self, module): - super(VmwareCategoryFactsManager, self).__init__(module) - self.category_service = self.api_client.tagging.Category - - def get_all_tag_categories(self): - """Retrieve all tag category information.""" - global_tag_categories = [] - for category in self.category_service.list(): - category_obj = self.category_service.get(category) - global_tag_categories.append( - dict( - category_description=category_obj.description, - category_used_by=category_obj.used_by, - category_cardinality=str(category_obj.cardinality), - category_associable_types=category_obj.associable_types, - category_id=category_obj.id, - category_name=category_obj.name, - ) - ) - - self.module.exit_json(changed=False, tag_category_facts=global_tag_categories) - - -def main(): - argument_spec = VmwareRestClient.vmware_client_argument_spec() - module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) - - vmware_category_facts = VmwareCategoryFactsManager(module) - vmware_category_facts.get_all_tag_categories() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/_vmware_cluster_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_cluster_facts.py deleted file mode 120000 index 35f337b7eb..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_cluster_facts.py +++ /dev/null @@ -1 +0,0 @@ -vmware_cluster_info.py
\ No newline at end of file diff --git a/lib/ansible/modules/cloud/vmware/_vmware_datastore_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_datastore_facts.py deleted file mode 120000 index 8d2b783a77..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_datastore_facts.py +++ /dev/null @@ -1 +0,0 @@ -vmware_datastore_info.py
\ No newline at end of file diff --git a/lib/ansible/modules/cloud/vmware/_vmware_dns_config.py b/lib/ansible/modules/cloud/vmware/_vmware_dns_config.py deleted file mode 100644 index 45fe1e9b29..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_dns_config.py +++ /dev/null @@ -1,130 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2015, Joseph Callen <jcallen () csc.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': ['deprecated'], - 'supported_by': 'community'} - -DOCUMENTATION = ''' ---- -module: vmware_dns_config -short_description: Manage VMware ESXi DNS Configuration -description: - - Manage VMware ESXi DNS Configuration -version_added: 2.0 -author: -- Joseph Callen (@jcpowermac) -notes: - - Tested on vSphere 5.5 -requirements: - - "python >= 2.6" - - PyVmomi -deprecated: - removed_in: '2.14' - why: Will be replaced with new module vmware_host_dns. - alternative: Use M(vmware_host_dns) instead. -options: - change_hostname_to: - description: - - The hostname that an ESXi host should be changed to. - required: True - type: str - domainname: - description: - - The domain the ESXi host should be apart of. - required: True - type: str - dns_servers: - description: - - The DNS servers that the host should be configured to use. - required: True - type: list -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Configure ESXi hostname and DNS servers - vmware_dns_config: - hostname: '{{ esxi_hostname }}' - username: '{{ esxi_username }}' - password: '{{ esxi_password }}' - change_hostname_to: esx01 - domainname: foo.org - dns_servers: - - 8.8.8.8 - - 8.8.4.4 - delegate_to: localhost -''' -try: - from pyVmomi import vim, vmodl - HAS_PYVMOMI = True -except ImportError: - HAS_PYVMOMI = False - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import HAS_PYVMOMI, connect_to_api, get_all_objs, vmware_argument_spec - - -def configure_dns(host_system, hostname, domainname, dns_servers): - - changed = False - host_config_manager = host_system.configManager - host_network_system = host_config_manager.networkSystem - config = host_network_system.dnsConfig - - config.dhcp = False - - if config.address != dns_servers: - config.address = dns_servers - changed = True - if config.domainName != domainname: - config.domainName = domainname - changed = True - if config.hostName != hostname: - config.hostName = hostname - changed = True - if changed: - host_network_system.UpdateDnsConfig(config) - - return changed - - -def main(): - - argument_spec = vmware_argument_spec() - argument_spec.update(dict(change_hostname_to=dict(required=True, type='str'), - domainname=dict(required=True, type='str'), - dns_servers=dict(required=True, type='list'))) - - module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False) - - if not HAS_PYVMOMI: - module.fail_json(msg='pyvmomi is required for this module') - - change_hostname_to = module.params['change_hostname_to'] - domainname = module.params['domainname'] - dns_servers = module.params['dns_servers'] - try: - content = connect_to_api(module) - host = get_all_objs(content, [vim.HostSystem]) - if not host: - module.fail_json(msg="Unable to locate Physical Host.") - host_system = list(host)[0] - changed = configure_dns(host_system, change_hostname_to, domainname, dns_servers) - module.exit_json(changed=changed) - except vmodl.RuntimeFault as runtime_fault: - module.fail_json(msg=runtime_fault.msg) - except vmodl.MethodFault as method_fault: - module.fail_json(msg=method_fault.msg) - except Exception as e: - module.fail_json(msg=str(e)) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/_vmware_drs_group_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_drs_group_facts.py deleted file mode 100644 index 3873d582be..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_drs_group_facts.py +++ /dev/null @@ -1,285 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Karsten Kaj Jakobsen <kj@patientsky.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': ['deprecated'], - 'supported_by': 'community' -} - -DOCUMENTATION = r''' ---- -deprecated: - removed_in: '2.13' - why: Deprecated in favour of C(_info) module. - alternative: Use M(vmware_drs_group_info) instead. -author: - - "Karsten Kaj Jakobsen (@karstenjakobsen)" -description: - - "This module can be used to gather facts about DRS VM/HOST groups from the given cluster." -extends_documentation_fragment: vmware.documentation -module: vmware_drs_group_facts -notes: - - "Tested on vSphere 6.5 and 6.7" -options: - cluster_name: - description: - - "Cluster to search for VM/Host groups." - - "If set, facts of DRS groups belonging this cluster will be returned." - - "Not needed if C(datacenter) is set." - required: false - type: str - datacenter: - aliases: - - datacenter_name - description: - - "Datacenter to search for DRS VM/Host groups." - required: true - type: str -requirements: - - "python >= 2.6" - - PyVmomi -short_description: "Gathers facts about DRS VM/Host groups on the given cluster" -version_added: "2.8" -''' - -EXAMPLES = r''' ---- -- name: "Gather DRS facts about given Cluster" - register: cluster_drs_group_facts - vmware_drs_group_facts: - hostname: "{{ vcenter_hostname }}" - password: "{{ vcenter_password }}" - username: "{{ vcenter_username }}" - cluster_name: "{{ cluster_name }}" - datacenter: "{{ datacenter }}" - delegate_to: localhost - -- name: "Gather DRS group facts about all clusters in given datacenter" - register: cluster_drs_group_facts - vmware_drs_group_facts: - hostname: "{{ vcenter_hostname }}" - password: "{{ vcenter_password }}" - username: "{{ vcenter_username }}" - datacenter: "{{ datacenter }}" - delegate_to: localhost -''' - -RETURN = r''' -drs_group_facts: - description: Metadata about DRS group from given cluster / datacenter - returned: always - type: dict - sample: - "drs_group_facts": { - "DC0_C0": [ - { - "group_name": "GROUP_HOST_S01", - "hosts": [ - "vm-01.zone", - "vm-02.zone" - ], - "type": "host" - }, - { - "group_name": "GROUP_HOST_S02", - "hosts": [ - "vm-03.zone", - "vm-04.zone" - ], - "type": "host" - }, - { - "group_name": "GROUP_VM_S01", - "type": "vm", - "vms": [ - "test-node01" - ] - }, - { - "group_name": "GROUP_VM_S02", - "type": "vm", - "vms": [ - "test-node02" - ] - } - ], - "DC0_C1": [] - } -''' - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi, find_datacenter_by_name, get_all_objs - - -class VmwareDrsGroupFactManager(PyVmomi): - - def __init__(self, module, datacenter_name, cluster_name=None): - """ - Doctring: Init - """ - - super(VmwareDrsGroupFactManager, self).__init__(module) - - self.__datacenter_name = datacenter_name - self.__datacenter_obj = None - self.__cluster_name = cluster_name - self.__cluster_obj = None - self.__msg = 'Nothing to see here...' - self.__result = dict() - self.__changed = False - - if datacenter_name: - - datacenter_obj = find_datacenter_by_name(self.content, datacenter_name=datacenter_name) - self.cluster_obj_list = [] - - if datacenter_obj: - folder = datacenter_obj.hostFolder - self.cluster_obj_list = get_all_objs(self.content, [vim.ClusterComputeResource], folder) - else: - raise Exception("Datacenter '%s' not found" % self.__datacenter_name) - - if cluster_name: - - cluster_obj = self.find_cluster_by_name(cluster_name=self.__cluster_name) - - if cluster_obj is None: - raise Exception("Cluster '%s' not found" % self.__cluster_name) - else: - self.cluster_obj_list = [cluster_obj] - - def get_result(self): - """ - Docstring - """ - return self.__result - - def __set_result(self, result): - """ - Sets result - Args: - result: drs group result list - - Returns: None - - """ - self.__result = result - - def __get_all_from_group(self, group_obj, host_group=False): - """ - Return all VM / Host names using given group - Args: - group_obj: Group object - host_group: True if we want only host name from group - - Returns: List of VM / Host names belonging to given group object - - """ - obj_name_list = [] - - if not all([group_obj]): - return obj_name_list - - if not host_group and isinstance(group_obj, vim.cluster.VmGroup): - obj_name_list = [vm.name for vm in group_obj.vm] - elif host_group and isinstance(group_obj, vim.cluster.HostGroup): - obj_name_list = [host.name for host in group_obj.host] - - return obj_name_list - - def __normalize_group_data(self, group_obj): - """ - Return human readable group spec - Args: - group_obj: Group object - - Returns: Dictionary with DRS groups - - """ - if not all([group_obj]): - return {} - - # Check if group is a host group - if hasattr(group_obj, 'host'): - return dict( - group_name=group_obj.name, - hosts=self.__get_all_from_group(group_obj=group_obj, host_group=True), - type="host" - ) - else: - return dict( - group_name=group_obj.name, - vms=self.__get_all_from_group(group_obj=group_obj), - type="vm" - ) - - def gather_facts(self): - """ - Gather DRS group facts about given cluster - Returns: Dictionary of clusters with DRS groups - - """ - cluster_group_facts = dict() - - for cluster_obj in self.cluster_obj_list: - - cluster_group_facts[cluster_obj.name] = [] - - for drs_group in cluster_obj.configurationEx.group: - cluster_group_facts[cluster_obj.name].append(self.__normalize_group_data(drs_group)) - - self.__set_result(cluster_group_facts) - - -def main(): - - argument_spec = vmware_argument_spec() - - argument_spec.update( - datacenter=dict(type='str', required=False, aliases=['datacenter_name']), - cluster_name=dict(type='str', required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - required_one_of=[['cluster_name', 'datacenter']], - mutually_exclusive=[['cluster_name', 'datacenter']], - ) - - try: - # Create instance of VmwareDrsGroupManager - vmware_drs_group_facts = VmwareDrsGroupFactManager(module=module, - datacenter_name=module.params.get('datacenter'), - cluster_name=module.params.get('cluster_name', None)) - - vmware_drs_group_facts.gather_facts() - - # Set results - results = dict(failed=False, - drs_group_facts=vmware_drs_group_facts.get_result()) - - except Exception as error: - results = dict(failed=True, msg="Error: %s" % error) - - if results['failed']: - module.fail_json(**results) - else: - module.exit_json(**results) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/_vmware_drs_rule_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_drs_rule_facts.py deleted file mode 100644 index ea2273a1ab..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_drs_rule_facts.py +++ /dev/null @@ -1,265 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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': ['deprecated'], - 'supported_by': 'community' -} - -DOCUMENTATION = r''' ---- -module: vmware_drs_rule_facts -deprecated: - removed_in: '2.13' - why: Deprecated in favour of C(_info) module. - alternative: Use M(vmware_drs_rule_info) instead. -short_description: Gathers facts about DRS rule on the given cluster -description: -- 'This module can be used to gather facts about DRS VM-VM and VM-HOST rules from the given cluster.' -version_added: '2.5' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of the cluster. - - DRS facts for the given cluster will be returned. - - This is required parameter if C(datacenter) parameter is not provided. - type: str - datacenter: - description: - - Name of the datacenter. - - DRS facts for all the clusters from the given datacenter will be returned. - - This is required parameter if C(cluster_name) parameter is not provided. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather DRS facts about given Cluster - vmware_drs_rule_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: '{{ cluster_name }}' - delegate_to: localhost - register: cluster_drs_facts - -- name: Gather DRS facts about all Clusters in given datacenter - vmware_drs_rule_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: '{{ datacenter_name }}' - delegate_to: localhost - register: datacenter_drs_facts -''' - -RETURN = r''' -drs_rule_facts: - description: metadata about DRS rule from given cluster / datacenter - returned: always - type: dict - sample: { - "DC0_C0": [ - { - "rule_affinity": false, - "rule_enabled": true, - "rule_key": 1, - "rule_mandatory": true, - "rule_name": "drs_rule_0001", - "rule_type": "vm_vm_rule", - "rule_uuid": "52be5061-665a-68dc-3d25-85cd2d37e114", - "rule_vms": [ - "VM_65", - "VM_146" - ] - }, - ], - "DC1_C1": [ - { - "rule_affine_host_group_name": "host_group_1", - "rule_affine_hosts": [ - "10.76.33.204" - ], - "rule_anti_affine_host_group_name": null, - "rule_anti_affine_hosts": [], - "rule_enabled": true, - "rule_key": 1, - "rule_mandatory": false, - "rule_name": "vm_host_rule_0001", - "rule_type": "vm_host_rule", - "rule_uuid": "52687108-4d3a-76f2-d29c-b708c40dbe40", - "rule_vm_group_name": "test_vm_group_1", - "rule_vms": [ - "VM_8916", - "VM_4010" - ] - } - ], - } -''' - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi, find_datacenter_by_name, get_all_objs - - -class VmwareDrsFactManager(PyVmomi): - def __init__(self, module): - super(VmwareDrsFactManager, self).__init__(module) - - datacenter_name = self.params.get('datacenter', None) - if datacenter_name: - datacenter_obj = find_datacenter_by_name(self.content, datacenter_name=datacenter_name) - self.cluster_obj_list = [] - if datacenter_obj: - folder = datacenter_obj.hostFolder - self.cluster_obj_list = get_all_objs(self.content, [vim.ClusterComputeResource], folder) - else: - self.module.fail_json(changed=False, msg="Datacenter '%s' not found" % datacenter_name) - - cluster_name = self.params.get('cluster_name', None) - if cluster_name: - cluster_obj = self.find_cluster_by_name(cluster_name=cluster_name) - if cluster_obj is None: - self.module.fail_json(changed=False, msg="Cluster '%s' not found" % cluster_name) - else: - self.cluster_obj_list = [cluster_obj] - - def get_all_from_group(self, group_name=None, cluster_obj=None, hostgroup=False): - """ - Return all VM / Host names using given group name - Args: - group_name: Rule name - cluster_obj: Cluster managed object - hostgroup: True if we want only host name from group - - Returns: List of VM / Host names belonging to given group object - - """ - obj_name_list = [] - if not all([group_name, cluster_obj]): - return obj_name_list - - for group in cluster_obj.configurationEx.group: - if group.name == group_name: - if not hostgroup and isinstance(group, vim.cluster.VmGroup): - obj_name_list = [vm.name for vm in group.vm] - break - elif hostgroup and isinstance(group, vim.cluster.HostGroup): - obj_name_list = [host.name for host in group.host] - break - - return obj_name_list - - @staticmethod - def normalize_vm_vm_rule_spec(rule_obj=None): - """ - Return human readable rule spec - Args: - rule_obj: Rule managed object - - Returns: Dictionary with DRS VM VM Rule info - - """ - if rule_obj is None: - return {} - return dict(rule_key=rule_obj.key, - rule_enabled=rule_obj.enabled, - rule_name=rule_obj.name, - rule_mandatory=rule_obj.mandatory, - rule_uuid=rule_obj.ruleUuid, - rule_vms=[vm.name for vm in rule_obj.vm], - rule_type="vm_vm_rule", - rule_affinity=True if isinstance(rule_obj, vim.cluster.AffinityRuleSpec) else False, - ) - - def normalize_vm_host_rule_spec(self, rule_obj=None, cluster_obj=None): - """ - Return human readable rule spec - Args: - rule_obj: Rule managed object - cluster_obj: Cluster managed object - - Returns: Dictionary with DRS VM HOST Rule info - - """ - if not all([rule_obj, cluster_obj]): - return {} - return dict(rule_key=rule_obj.key, - rule_enabled=rule_obj.enabled, - rule_name=rule_obj.name, - rule_mandatory=rule_obj.mandatory, - rule_uuid=rule_obj.ruleUuid, - rule_vm_group_name=rule_obj.vmGroupName, - rule_affine_host_group_name=rule_obj.affineHostGroupName, - rule_anti_affine_host_group_name=rule_obj.antiAffineHostGroupName, - rule_vms=self.get_all_from_group(group_name=rule_obj.vmGroupName, - cluster_obj=cluster_obj), - rule_affine_hosts=self.get_all_from_group(group_name=rule_obj.affineHostGroupName, - cluster_obj=cluster_obj, - hostgroup=True), - rule_anti_affine_hosts=self.get_all_from_group(group_name=rule_obj.antiAffineHostGroupName, - cluster_obj=cluster_obj, - hostgroup=True), - rule_type="vm_host_rule", - ) - - def gather_drs_rule_facts(self): - """ - Gather DRS rule facts about given cluster - Returns: Dictionary of clusters with DRS facts - - """ - cluster_rule_facts = dict() - for cluster_obj in self.cluster_obj_list: - cluster_rule_facts[cluster_obj.name] = [] - for drs_rule in cluster_obj.configuration.rule: - if isinstance(drs_rule, vim.cluster.VmHostRuleInfo): - cluster_rule_facts[cluster_obj.name].append(self.normalize_vm_host_rule_spec(rule_obj=drs_rule, - cluster_obj=cluster_obj)) - else: - cluster_rule_facts[cluster_obj.name].append(self.normalize_vm_vm_rule_spec(rule_obj=drs_rule)) - - return cluster_rule_facts - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - datacenter=dict(type='str', required=False), - cluster_name=dict(type='str', required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'datacenter'], - ], - supports_check_mode=True, - ) - - vmware_drs_facts = VmwareDrsFactManager(module) - module.exit_json(changed=False, drs_rule_facts=vmware_drs_facts.gather_drs_rule_facts()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/_vmware_dvs_portgroup_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_dvs_portgroup_facts.py deleted file mode 100644 index d2617d6c0b..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_dvs_portgroup_facts.py +++ /dev/null @@ -1,278 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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': ['deprecated'], - 'supported_by': 'community' -} - -DOCUMENTATION = r''' ---- -module: vmware_dvs_portgroup_facts -deprecated: - removed_in: '2.13' - why: Deprecated in favour of C(_info) module. - alternative: Use M(vmware_dvs_portgroup_info) instead. -short_description: Gathers facts DVS portgroup configurations -description: -- This module can be used to gather facts about DVS portgroup configurations. -version_added: 2.8 -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - datacenter: - description: - - Name of the datacenter. - required: true - type: str - dvswitch: - description: - - Name of a dvswitch to look for. - required: false - type: str - version_added: "2.9" - show_network_policy: - description: - - Show or hide network policies of DVS portgroup. - type: bool - default: True - show_port_policy: - description: - - Show or hide port policies of DVS portgroup. - type: bool - default: True - show_teaming_policy: - description: - - Show or hide teaming policies of DVS portgroup. - type: bool - default: True - show_vlan_info: - description: - - Show or hide vlan information of the DVS portgroup. - type: bool - default: False - version_added: "2.9" -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Get facts about DVPG - vmware_dvs_portgroup_facts: - hostname: "{{ vcenter_server }}" - username: "{{ vcenter_user }}" - password: "{{ vcenter_pass }}" - validate_certs: no - datacenter: "{{ datacenter_name }}" - register: dvpg_facts -- name: Get number of ports for portgroup 'dvpg_001' in 'dvs_001' - debug: - msg: "{{ item.num_ports }}" - with_items: - - "{{ dvpg_facts.dvs_portgroup_facts['dvs_001'] | json_query(query) }}" - vars: - query: "[?portgroup_name=='dvpg_001']" -''' - -RETURN = r''' -dvs_portgroup_facts: - description: metadata about DVS portgroup configuration - returned: on success - type: dict - sample: { - "dvs_0":[ - { - "description": null, - "dvswitch_name": "dvs_001", - "network_policy": { - "forged_transmits": false, - "mac_changes": false, - "promiscuous": false - }, - "num_ports": 8, - "port_policy": { - "block_override": true, - "ipfix_override": false, - "live_port_move": false, - "network_rp_override": false, - "port_config_reset_at_disconnect": true, - "security_override": false, - "shaping_override": false, - "traffic_filter_override": false, - "uplink_teaming_override": false, - "vendor_config_override": false, - "vlan_override": false - }, - "portgroup_name": "dvpg_001", - "teaming_policy": { - "inbound_policy": true, - "notify_switches": true, - "policy": "loadbalance_srcid", - "rolling_order": false - }, - "vlan_info": { - "trunk": false, - "pvlan": false, - "vlan_id": 0 - }, - "type": "earlyBinding" - }, - ] - } -''' - -try: - from pyVmomi import vim -except ImportError as e: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi, get_all_objs, find_dvs_by_name - - -class DVSPortgroupFactsManager(PyVmomi): - def __init__(self, module): - super(DVSPortgroupFactsManager, self).__init__(module) - self.dc_name = self.params['datacenter'] - self.dvs_name = self.params['dvswitch'] - - datacenter = self.find_datacenter_by_name(self.dc_name) - if datacenter is None: - self.module.fail_json(msg="Failed to find the datacenter %s" % self.dc_name) - if self.dvs_name: - # User specified specific dvswitch name to gather information - dvsn = find_dvs_by_name(self.content, self.dvs_name) - if dvsn is None: - self.module.fail_json(msg="Failed to find the dvswitch %s" % self.dvs_name) - - self.dvsls = [dvsn] - else: - # default behaviour, gather information about all dvswitches - self.dvsls = get_all_objs(self.content, [vim.DistributedVirtualSwitch], folder=datacenter.networkFolder) - - def get_vlan_info(self, vlan_obj=None): - """ - Return vlan information from given object - Args: - vlan_obj: vlan managed object - Returns: Dict of vlan details of the specific object - """ - - vdret = dict() - if not vlan_obj: - return vdret - - if isinstance(vlan_obj, vim.dvs.VmwareDistributedVirtualSwitch.TrunkVlanSpec): - vlan_id_list = [] - for vli in vlan_obj.vlanId: - if vli.start == vli.end: - vlan_id_list.append(str(vli.start)) - else: - vlan_id_list.append(str(vli.start) + "-" + str(vli.end)) - vdret = dict(trunk=True, pvlan=False, vlan_id=vlan_id_list) - elif isinstance(vlan_obj, vim.dvs.VmwareDistributedVirtualSwitch.PvlanSpec): - vdret = dict(trunk=False, pvlan=True, vlan_id=str(vlan_obj.pvlanId)) - else: - vdret = dict(trunk=False, pvlan=False, vlan_id=str(vlan_obj.vlanId)) - - return vdret - - def gather_dvs_portgroup_facts(self): - dvs_lists = self.dvsls - result = dict() - for dvs in dvs_lists: - result[dvs.name] = list() - for dvs_pg in dvs.portgroup: - network_policy = dict() - teaming_policy = dict() - port_policy = dict() - vlan_info = dict() - - if self.module.params['show_network_policy'] and dvs_pg.config.defaultPortConfig.securityPolicy: - network_policy = dict( - forged_transmits=dvs_pg.config.defaultPortConfig.securityPolicy.forgedTransmits.value, - promiscuous=dvs_pg.config.defaultPortConfig.securityPolicy.allowPromiscuous.value, - mac_changes=dvs_pg.config.defaultPortConfig.securityPolicy.macChanges.value - ) - if self.module.params['show_teaming_policy']: - # govcsim does not have uplinkTeamingPolicy, remove this check once - # PR https://github.com/vmware/govmomi/pull/1524 merged. - if dvs_pg.config.defaultPortConfig.uplinkTeamingPolicy: - teaming_policy = dict( - policy=dvs_pg.config.defaultPortConfig.uplinkTeamingPolicy.policy.value, - inbound_policy=dvs_pg.config.defaultPortConfig.uplinkTeamingPolicy.reversePolicy.value, - notify_switches=dvs_pg.config.defaultPortConfig.uplinkTeamingPolicy.notifySwitches.value, - rolling_order=dvs_pg.config.defaultPortConfig.uplinkTeamingPolicy.rollingOrder.value, - ) - - if self.params['show_port_policy']: - # govcsim does not have port policy - if dvs_pg.config.policy: - port_policy = dict( - block_override=dvs_pg.config.policy.blockOverrideAllowed, - ipfix_override=dvs_pg.config.policy.ipfixOverrideAllowed, - live_port_move=dvs_pg.config.policy.livePortMovingAllowed, - network_rp_override=dvs_pg.config.policy.networkResourcePoolOverrideAllowed, - port_config_reset_at_disconnect=dvs_pg.config.policy.portConfigResetAtDisconnect, - security_override=dvs_pg.config.policy.securityPolicyOverrideAllowed, - shaping_override=dvs_pg.config.policy.shapingOverrideAllowed, - traffic_filter_override=dvs_pg.config.policy.trafficFilterOverrideAllowed, - uplink_teaming_override=dvs_pg.config.policy.uplinkTeamingOverrideAllowed, - vendor_config_override=dvs_pg.config.policy.vendorConfigOverrideAllowed, - vlan_override=dvs_pg.config.policy.vlanOverrideAllowed - ) - - if self.params['show_vlan_info']: - vlan_info = self.get_vlan_info(dvs_pg.config.defaultPortConfig.vlan) - - dvpg_details = dict( - portgroup_name=dvs_pg.name, - num_ports=dvs_pg.config.numPorts, - dvswitch_name=dvs_pg.config.distributedVirtualSwitch.name, - description=dvs_pg.config.description, - type=dvs_pg.config.type, - teaming_policy=teaming_policy, - port_policy=port_policy, - network_policy=network_policy, - vlan_info=vlan_info, - ) - result[dvs.name].append(dvpg_details) - - return result - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - datacenter=dict(type='str', required=True), - show_network_policy=dict(type='bool', default=True), - show_teaming_policy=dict(type='bool', default=True), - show_port_policy=dict(type='bool', default=True), - dvswitch=dict(), - show_vlan_info=dict(type='bool', default=False), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - dvs_pg_mgr = DVSPortgroupFactsManager(module) - module.exit_json(changed=False, - dvs_portgroup_facts=dvs_pg_mgr.gather_dvs_portgroup_facts()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/_vmware_guest_boot_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_guest_boot_facts.py deleted file mode 100644 index 6a8fe3928d..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_guest_boot_facts.py +++ /dev/null @@ -1,220 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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': ['deprecated'], - 'supported_by': 'community' -} - -DOCUMENTATION = ''' ---- -module: vmware_guest_boot_facts -deprecated: - removed_in: '2.13' - why: Deprecated in favour of C(_info) module. - alternative: Use M(vmware_guest_boot_info) instead. -short_description: Gather facts about boot options for the given virtual machine -description: - - Gather facts about boot options for the given virtual machine. -version_added: 2.7 -author: - - Abhijeet Kasurde (@Akasurde) -notes: - - Tested on vSphere 6.5 -requirements: - - "python >= 2.6" - - PyVmomi -options: - name: - description: - - Name of the VM to work with. - - This is required if C(uuid) or C(moid) parameter is not supplied. - type: str - uuid: - description: - - UUID of the instance to manage if known, this is VMware's BIOS UUID by default. - - This is required if C(name) or C(moid) parameter is not supplied. - type: str - moid: - description: - - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. - - This is required if C(name) or C(uuid) is not supplied. - version_added: '2.9' - type: str - use_instance_uuid: - description: - - Whether to use the VMware instance UUID rather than the BIOS UUID. - default: no - type: bool - version_added: '2.8' - name_match: - description: - - If multiple virtual machines matching the name, use the first or last found. - default: 'first' - choices: ['first', 'last'] - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather facts about virtual machine's boot order and related parameters - vmware_guest_boot_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - name: "{{ vm_name }}" - register: vm_boot_order_facts - -- name: Gather facts about virtual machine's boot order using MoID - vmware_guest_boot_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - moid: "vm-42" - register: vm_moid_boot_order_facts -''' - -RETURN = r""" -vm_boot_facts: - description: metadata about boot order of virtual machine - returned: always - type: dict - sample: { - "current_boot_order": [ - "floppy", - "disk", - "ethernet", - "cdrom" - ], - "current_boot_delay": 2000, - "current_boot_retry_delay": 22300, - "current_boot_retry_enabled": true, - "current_enter_bios_setup": true, - "current_boot_firmware": "bios", - "current_secure_boot_enabled": false, - } -""" - - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec, find_vm_by_id - -try: - from pyVmomi import vim, VmomiSupport -except ImportError: - pass - - -class VmBootFactsManager(PyVmomi): - def __init__(self, module): - super(VmBootFactsManager, self).__init__(module) - self.name = self.params['name'] - self.uuid = self.params['uuid'] - self.moid = self.params['moid'] - self.use_instance_uuid = self.params['use_instance_uuid'] - self.vm = None - - def _get_vm(self): - vms = [] - - if self.uuid: - if self.use_instance_uuid: - vm_obj = find_vm_by_id(self.content, vm_id=self.uuid, vm_id_type="use_instance_uuid") - else: - vm_obj = find_vm_by_id(self.content, vm_id=self.uuid, vm_id_type="uuid") - if vm_obj is None: - self.module.fail_json(msg="Failed to find the virtual machine with UUID : %s" % self.uuid) - vms = [vm_obj] - - elif self.name: - objects = self.get_managed_objects_properties(vim_type=vim.VirtualMachine, properties=['name']) - for temp_vm_object in objects: - if temp_vm_object.obj.name == self.name: - vms.append(temp_vm_object.obj) - - elif self.moid: - vm_obj = VmomiSupport.templateOf('VirtualMachine')(self.module.params['moid'], self.si._stub) - if vm_obj: - vms.append(vm_obj) - - if vms: - if self.params.get('name_match') == 'first': - self.vm = vms[0] - elif self.params.get('name_match') == 'last': - self.vm = vms[-1] - else: - self.module.fail_json(msg="Failed to find virtual machine using %s" % (self.name or self.uuid or self.moid)) - - @staticmethod - def humanize_boot_order(boot_order): - results = [] - for device in boot_order: - if isinstance(device, vim.vm.BootOptions.BootableCdromDevice): - results.append('cdrom') - elif isinstance(device, vim.vm.BootOptions.BootableDiskDevice): - results.append('disk') - elif isinstance(device, vim.vm.BootOptions.BootableEthernetDevice): - results.append('ethernet') - elif isinstance(device, vim.vm.BootOptions.BootableFloppyDevice): - results.append('floppy') - return results - - def ensure(self): - self._get_vm() - - results = dict() - if self.vm and self.vm.config: - results = dict( - current_boot_order=self.humanize_boot_order(self.vm.config.bootOptions.bootOrder), - current_boot_delay=self.vm.config.bootOptions.bootDelay, - current_enter_bios_setup=self.vm.config.bootOptions.enterBIOSSetup, - current_boot_retry_enabled=self.vm.config.bootOptions.bootRetryEnabled, - current_boot_retry_delay=self.vm.config.bootOptions.bootRetryDelay, - current_boot_firmware=self.vm.config.firmware, - current_secure_boot_enabled=self.vm.config.bootOptions.efiSecureBootEnabled - ) - - self.module.exit_json(changed=False, vm_boot_facts=results) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - name=dict(type='str'), - uuid=dict(type='str'), - moid=dict(type='str'), - use_instance_uuid=dict(type='bool', default=False), - name_match=dict( - choices=['first', 'last'], - default='first' - ), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['name', 'uuid', 'moid'] - ], - mutually_exclusive=[ - ['name', 'uuid', 'moid'] - ], - supports_check_mode=True, - ) - - pyv = VmBootFactsManager(module) - pyv.ensure() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/_vmware_guest_customization_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_guest_customization_facts.py deleted file mode 100644 index afe0ce82b5..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_guest_customization_facts.py +++ /dev/null @@ -1,197 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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': ['deprecated'], - 'supported_by': 'community' -} - -DOCUMENTATION = ''' ---- -module: vmware_guest_customization_facts -deprecated: - removed_in: '2.13' - why: Deprecated in favour of C(_info) module. - alternative: Use M(vmware_guest_customization_info) instead. -short_description: Gather facts about VM customization specifications -description: - - This module can be used to gather facts about customization specifications. - - All parameters and VMware object names are case sensitive. -version_added: 2.8 -author: - - Abhijeet Kasurde (@Akasurde) -notes: - - Tested on vSphere 6.0 and 6.5 -requirements: - - "python >= 2.6" - - PyVmomi -options: - spec_name: - description: - - Name of customization specification to find. - required: False - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Gather facts about all customization specification - vmware_guest_customization_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - delegate_to: localhost - register: all_custom_spec_facts - -- name: Gather facts about customization specification with the given name - vmware_guest_customization_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - spec_name: custom_linux_spec - delegate_to: localhost - register: custom_spec_facts -''' - -RETURN = """ -custom_spec_facts: - description: metadata about the customization specification - returned: always - type: dict - sample: { - "assignip-eee0d684-44b7-457c-8c55-2585590b0d99": { - "change_version": "1523438001", - "description": "sample description", - "dns_server_list": [], - "dns_suffix_list": [], - "domain": "None", - "hostname": "sample1", - "hw_clock_utc": null, - "last_updated_time": "2018-04-11T09:13:21+00:00", - "name": "sample", - "nic_setting_map": [ - { - "dns_domain": null, - "gateway": [], - "ip_address": "192.168.10.10", - "net_bios": null, - "nic_dns_server_list": [], - "primary_wins": null, - "secondry_wins": null, - "subnet_mask": "255.255.255.0" - } - ], - "time_zone": null, - "type": "Linux" - }, - } -""" - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils._text import to_text -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec - - -class VmwareCustomSpecManger(PyVmomi): - def __init__(self, module): - super(VmwareCustomSpecManger, self).__init__(module) - self.cc_mgr = self.content.customizationSpecManager - if self.cc_mgr is None: - self.module.fail_json(msg="Failed to get customization spec manager.") - - def gather_custom_spec_facts(self): - """ - Gather facts about customization specifications - """ - - spec_name = self.params.get('spec_name', None) - specs_list = [] - if spec_name: - if self.cc_mgr.DoesCustomizationSpecExist(name=spec_name): - specs_list.append(spec_name) - else: - self.module.fail_json(msg="Unable to find customization specification named '%s'" % spec_name) - else: - available_specs = self.cc_mgr.info - for spec_info in available_specs: - specs_list.append(spec_info.name) - - spec_facts = dict() - for spec in specs_list: - current_spec = self.cc_mgr.GetCustomizationSpec(name=spec) - adapter_mapping_list = [] - for nic in current_spec.spec.nicSettingMap: - temp_data = dict( - mac_address=nic.macAddress, - ip_address=nic.adapter.ip.ipAddress, - subnet_mask=nic.adapter.subnetMask, - gateway=[gw for gw in nic.adapter.gateway], - nic_dns_server_list=[ndsl for ndsl in nic.adapter.dnsServerList], - dns_domain=nic.adapter.dnsDomain, - primary_wins=nic.adapter.primaryWINS, - secondry_wins=nic.adapter.secondaryWINS, - net_bios=nic.adapter.netBIOS, - ) - adapter_mapping_list.append(temp_data) - - current_hostname = None - if isinstance(current_spec.spec.identity.hostName, vim.vm.customization.PrefixNameGenerator): - current_hostname = current_spec.spec.identity.hostName.base - elif isinstance(current_spec.spec.identity.hostName, vim.vm.customization.FixedName): - current_hostname = current_spec.spec.identity.hostName.name - - spec_facts[spec] = dict( - # Spec - name=current_spec.info.name, - description=current_spec.info.description, - type=current_spec.info.type, - last_updated_time=current_spec.info.lastUpdateTime, - change_version=current_spec.info.changeVersion, - # Identity - hostname=current_hostname, - domain=current_spec.spec.identity.domain, - time_zone=current_spec.spec.identity.timeZone, - hw_clock_utc=current_spec.spec.identity.hwClockUTC, - # global IP Settings - dns_suffix_list=[i for i in current_spec.spec.globalIPSettings.dnsSuffixList], - dns_server_list=[i for i in current_spec.spec.globalIPSettings.dnsServerList], - # NIC setting map - nic_setting_map=adapter_mapping_list, - ) - return spec_facts - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - spec_name=dict(type='str'), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True - ) - - pyv = VmwareCustomSpecManger(module) - try: - module.exit_json(custom_spec_facts=pyv.gather_custom_spec_facts()) - except Exception as exc: - module.fail_json(msg="Failed to gather facts with exception : %s" % to_text(exc)) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/_vmware_guest_disk_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_guest_disk_facts.py deleted file mode 100644 index 5afd4c6806..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_guest_disk_facts.py +++ /dev/null @@ -1,332 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2019, NAER William Leemans (@bushvin) <willie@elaba.net> -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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': ['deprecated'], - 'supported_by': 'community' -} - -DOCUMENTATION = ''' ---- -module: vmware_guest_disk_facts -deprecated: - removed_in: '2.13' - why: Deprecated in favour of C(_info) module. - alternative: Use M(vmware_guest_disk_info) instead. -short_description: Gather facts about disks of given virtual machine -description: - - This module can be used to gather facts about disks belonging to given virtual machine. - - All parameters and VMware object names are case sensitive. -version_added: 2.6 -author: - - Abhijeet Kasurde (@Akasurde) <akasurde@redhat.com> -notes: - - Tested on vSphere 6.0 and 6.5. - - Disk UUID information is added in version 2.8. - - Additional information about guest disk backings added in version 2.8. -requirements: - - "python >= 2.6" - - PyVmomi -options: - name: - description: - - Name of the virtual machine. - - This is required parameter, if parameter C(uuid) or C(moid) is not supplied. - type: str - uuid: - description: - - UUID of the instance to gather facts if known, this is VMware's unique identifier. - - This is required parameter, if parameter C(name) or C(moid) is not supplied. - type: str - moid: - description: - - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. - - This is required if C(name) or C(uuid) is not supplied. - version_added: '2.9' - type: str - use_instance_uuid: - description: - - Whether to use the VMware instance UUID rather than the BIOS UUID. - default: no - type: bool - version_added: '2.8' - folder: - description: - - Destination folder, absolute or relative path to find an existing guest. - - This is required parameter, only if multiple VMs are found with same name. - - The folder should include the datacenter. ESX's datacenter is ha-datacenter - - 'Examples:' - - ' folder: /ha-datacenter/vm' - - ' folder: ha-datacenter/vm' - - ' folder: /datacenter1/vm' - - ' folder: datacenter1/vm' - - ' folder: /datacenter1/vm/folder1' - - ' folder: datacenter1/vm/folder1' - - ' folder: /folder1/datacenter1/vm' - - ' folder: folder1/datacenter1/vm' - - ' folder: /folder1/datacenter1/vm/folder2' - type: str - datacenter: - description: - - The datacenter name to which virtual machine belongs to. - required: True - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Gather disk facts from virtual machine using UUID - vmware_guest_disk_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: ha-datacenter - validate_certs: no - uuid: 421e4592-c069-924d-ce20-7e7533fab926 - delegate_to: localhost - register: disk_facts - -- name: Gather disk facts from virtual machine using name - vmware_guest_disk_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: ha-datacenter - validate_certs: no - name: VM_225 - delegate_to: localhost - register: disk_facts - -- name: Gather disk facts from virtual machine using moid - vmware_guest_disk_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: ha-datacenter - validate_certs: no - moid: vm-42 - delegate_to: localhost - register: disk_facts -''' - -RETURN = """ -guest_disk_facts: - description: metadata about the virtual machine's disks - returned: always - type: dict - sample: { - "0": { - "backing_datastore": "datastore2", - "backing_disk_mode": "persistent", - "backing_eagerlyscrub": false, - "backing_filename": "[datastore2] VM_225/VM_225.vmdk", - "backing_thinprovisioned": false, - "backing_type": "FlatVer2", - "backing_writethrough": false, - "backing_uuid": "200C3A00-f82a-97af-02ff-62a595f0020a", - "capacity_in_bytes": 10485760, - "capacity_in_kb": 10240, - "controller_bus_number": 0, - "controller_key": 1000, - "controller_type": "paravirtual", - "key": 2000, - "label": "Hard disk 1", - "summary": "10,240 KB", - "unit_number": 0 - }, - "1": { - "backing_datastore": "datastore3", - "backing_devicename": "vml.012345678901234567890123456789012345678901234567890123", - "backing_disk_mode": "independent_persistent", - "backing_filename": "[datastore3] VM_226/VM_226.vmdk", - "backing_lunuuid": "012345678901234567890123456789012345678901234567890123", - "backing_type": "RawDiskMappingVer1", - "backing_uuid": null, - "capacity_in_bytes": 15728640, - "capacity_in_kb": 15360, - "controller_bus_number": 0, - "controller_key": 1000, - "controller_type": "paravirtual", - "key": 2001, - "label": "Hard disk 3", - "summary": "15,360 KB", - "unit_number": 1 - }, - } -""" - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils._text import to_text -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec - - -class PyVmomiHelper(PyVmomi): - def __init__(self, module): - super(PyVmomiHelper, self).__init__(module) - - def gather_disk_facts(self, vm_obj): - """ - Gather facts about VM's disks - Args: - vm_obj: Managed object of virtual machine - - Returns: A list of dict containing disks information - - """ - controller_facts = dict() - disks_facts = dict() - if vm_obj is None: - return disks_facts - - controller_types = { - vim.vm.device.VirtualLsiLogicController: 'lsilogic', - vim.vm.device.ParaVirtualSCSIController: 'paravirtual', - vim.vm.device.VirtualBusLogicController: 'buslogic', - vim.vm.device.VirtualLsiLogicSASController: 'lsilogicsas', - vim.vm.device.VirtualIDEController: 'ide' - } - - controller_index = 0 - for controller in vm_obj.config.hardware.device: - if isinstance(controller, tuple(controller_types.keys())): - controller_facts[controller_index] = dict( - key=controller.key, - controller_type=controller_types[type(controller)], - bus_number=controller.busNumber, - devices=controller.device - ) - controller_index += 1 - - disk_index = 0 - for disk in vm_obj.config.hardware.device: - if isinstance(disk, vim.vm.device.VirtualDisk): - disks_facts[disk_index] = dict( - key=disk.key, - label=disk.deviceInfo.label, - summary=disk.deviceInfo.summary, - backing_filename=disk.backing.fileName, - backing_datastore=disk.backing.datastore.name, - controller_key=disk.controllerKey, - unit_number=disk.unitNumber, - capacity_in_kb=disk.capacityInKB, - capacity_in_bytes=disk.capacityInBytes, - ) - if isinstance(disk.backing, vim.vm.device.VirtualDisk.FlatVer1BackingInfo): - disks_facts[disk_index]['backing_type'] = 'FlatVer1' - disks_facts[disk_index]['backing_writethrough'] = disk.backing.writeThrough - - elif isinstance(disk.backing, vim.vm.device.VirtualDisk.FlatVer2BackingInfo): - disks_facts[disk_index]['backing_type'] = 'FlatVer2' - disks_facts[disk_index]['backing_writethrough'] = bool(disk.backing.writeThrough) - disks_facts[disk_index]['backing_thinprovisioned'] = bool(disk.backing.thinProvisioned) - disks_facts[disk_index]['backing_eagerlyscrub'] = bool(disk.backing.eagerlyScrub) - disks_facts[disk_index]['backing_uuid'] = disk.backing.uuid - - elif isinstance(disk.backing, vim.vm.device.VirtualDisk.LocalPMemBackingInfo): - disks_facts[disk_index]['backing_type'] = 'LocalPMem' - disks_facts[disk_index]['backing_volumeuuid'] = disk.backing.volumeUUID - disks_facts[disk_index]['backing_uuid'] = disk.backing.uuid - - elif isinstance(disk.backing, vim.vm.device.VirtualDisk.PartitionedRawDiskVer2BackingInfo): - disks_facts[disk_index]['backing_type'] = 'PartitionedRawDiskVer2' - disks_facts[disk_index]['backing_descriptorfilename'] = disk.backing.descriptorFileName - disks_facts[disk_index]['backing_uuid'] = disk.backing.uuid - - elif isinstance(disk.backing, vim.vm.device.VirtualDisk.RawDiskMappingVer1BackingInfo): - disks_facts[disk_index]['backing_type'] = 'RawDiskMappingVer1' - disks_facts[disk_index]['backing_devicename'] = disk.backing.deviceName - disks_facts[disk_index]['backing_diskmode'] = disk.backing.diskMode - disks_facts[disk_index]['backing_lunuuid'] = disk.backing.lunUuid - disks_facts[disk_index]['backing_uuid'] = disk.backing.uuid - - elif isinstance(disk.backing, vim.vm.device.VirtualDisk.RawDiskVer2BackingInfo): - disks_facts[disk_index]['backing_type'] = 'RawDiskVer2' - disks_facts[disk_index]['backing_descriptorfilename'] = disk.backing.descriptorFileName - disks_facts[disk_index]['backing_uuid'] = disk.backing.uuid - - elif isinstance(disk.backing, vim.vm.device.VirtualDisk.SeSparseBackingInfo): - disks_facts[disk_index]['backing_type'] = 'SeSparse' - disks_facts[disk_index]['backing_diskmode'] = disk.backing.diskMode - disks_facts[disk_index]['backing_writethrough'] = bool(disk.backing.writeThrough) - disks_facts[disk_index]['backing_uuid'] = disk.backing.uuid - - elif isinstance(disk.backing, vim.vm.device.VirtualDisk.SparseVer1BackingInfo): - disks_facts[disk_index]['backing_type'] = 'SparseVer1' - disks_facts[disk_index]['backing_diskmode'] = disk.backing.diskMode - disks_facts[disk_index]['backing_spaceusedinkb'] = disk.backing.spaceUsedInKB - disks_facts[disk_index]['backing_split'] = bool(disk.backing.split) - disks_facts[disk_index]['backing_writethrough'] = bool(disk.backing.writeThrough) - - elif isinstance(disk.backing, vim.vm.device.VirtualDisk.SparseVer2BackingInfo): - disks_facts[disk_index]['backing_type'] = 'SparseVer2' - disks_facts[disk_index]['backing_diskmode'] = disk.backing.diskMode - disks_facts[disk_index]['backing_spaceusedinkb'] = disk.backing.spaceUsedInKB - disks_facts[disk_index]['backing_split'] = bool(disk.backing.split) - disks_facts[disk_index]['backing_writethrough'] = bool(disk.backing.writeThrough) - disks_facts[disk_index]['backing_uuid'] = disk.backing.uuid - - for controller_index in range(len(controller_facts)): - if controller_facts[controller_index]['key'] == disks_facts[disk_index]['controller_key']: - disks_facts[disk_index]['controller_bus_number'] = controller_facts[controller_index]['bus_number'] - disks_facts[disk_index]['controller_type'] = controller_facts[controller_index]['controller_type'] - - disk_index += 1 - return disks_facts - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - name=dict(type='str'), - uuid=dict(type='str'), - moid=dict(type='str'), - use_instance_uuid=dict(type='bool', default=False), - folder=dict(type='str'), - datacenter=dict(type='str', required=True), - ) - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['name', 'uuid', 'moid'] - ], - supports_check_mode=True, - ) - - if module.params['folder']: - # FindByInventoryPath() does not require an absolute path - # so we should leave the input folder path unmodified - module.params['folder'] = module.params['folder'].rstrip('/') - - pyv = PyVmomiHelper(module) - # Check if the VM exists before continuing - vm = pyv.get_vm() - - if vm: - # VM exists - try: - module.exit_json(guest_disk_facts=pyv.gather_disk_facts(vm)) - except Exception as exc: - module.fail_json(msg="Failed to gather facts with exception : %s" % to_text(exc)) - else: - # We unable to find the virtual machine user specified - # Bail out - vm_id = (module.params.get('uuid') or module.params.get('moid') or module.params.get('name')) - module.fail_json(msg="Unable to gather disk facts for non-existing VM %s" % vm_id) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/_vmware_guest_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_guest_facts.py deleted file mode 120000 index 8049c039cf..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_guest_facts.py +++ /dev/null @@ -1 +0,0 @@ -vmware_guest_info.py
\ No newline at end of file diff --git a/lib/ansible/modules/cloud/vmware/_vmware_guest_snapshot_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_guest_snapshot_facts.py deleted file mode 120000 index 0ea90bcedd..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_guest_snapshot_facts.py +++ /dev/null @@ -1 +0,0 @@ -vmware_guest_snapshot_info.py
\ No newline at end of file diff --git a/lib/ansible/modules/cloud/vmware/_vmware_host_capability_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_host_capability_facts.py deleted file mode 100644 index 9b686b2868..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_host_capability_facts.py +++ /dev/null @@ -1,226 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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': ['deprecated'], - 'supported_by': 'community' -} - -DOCUMENTATION = r''' ---- -module: vmware_host_capability_facts -deprecated: - removed_in: '2.13' - why: Deprecated in favour of C(_info) module. - alternative: Use M(vmware_host_capability_info) instead. -short_description: Gathers facts about an ESXi host's capability information -description: -- This module can be used to gather facts about an ESXi host's capability information when ESXi hostname or Cluster name is given. -version_added: 2.6 -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of the cluster from all host systems to be used for facts gathering. - - If C(esxi_hostname) is not given, this parameter is required. - type: str - esxi_hostname: - description: - - ESXi hostname to gather facts from. - - If C(cluster_name) is not given, this parameter is required. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather capability facts about all ESXi Host in given Cluster - vmware_host_capability_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: cluster_name - delegate_to: localhost - register: all_cluster_hosts_facts - -- name: Gather capability facts about ESXi Host - vmware_host_capability_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - delegate_to: localhost - register: hosts_facts -''' - -RETURN = r''' -hosts_capability_facts: - description: metadata about host's capability information - returned: always - type: dict - sample: { - "esxi_hostname_0001": { - "accel3dSupported": false, - "backgroundSnapshotsSupported": false, - "checkpointFtCompatibilityIssues": [], - "checkpointFtSupported": false, - "cloneFromSnapshotSupported": true, - "cpuHwMmuSupported": true, - } - } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class CapabilityFactsManager(PyVmomi): - def __init__(self, module): - super(CapabilityFactsManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - - def gather_host_capability_facts(self): - hosts_capability_facts = dict() - for host in self.hosts: - hc = host.capability - hosts_capability_facts[host.name] = dict( - recursiveResourcePoolsSupported=hc.recursiveResourcePoolsSupported, - cpuMemoryResourceConfigurationSupported=hc.cpuMemoryResourceConfigurationSupported, - rebootSupported=hc.rebootSupported, - shutdownSupported=hc.shutdownSupported, - vmotionSupported=hc.vmotionSupported, - standbySupported=hc.standbySupported, - ipmiSupported=hc.ipmiSupported, - maxSupportedVMs=hc.maxSupportedVMs, - maxRunningVMs=hc.maxRunningVMs, - maxSupportedVcpus=hc.maxSupportedVcpus, - maxRegisteredVMs=hc.maxRegisteredVMs, - datastorePrincipalSupported=hc.datastorePrincipalSupported, - sanSupported=hc.sanSupported, - nfsSupported=hc.nfsSupported, - iscsiSupported=hc.iscsiSupported, - vlanTaggingSupported=hc.vlanTaggingSupported, - nicTeamingSupported=hc.nicTeamingSupported, - highGuestMemSupported=hc.highGuestMemSupported, - maintenanceModeSupported=hc.maintenanceModeSupported, - suspendedRelocateSupported=hc.suspendedRelocateSupported, - restrictedSnapshotRelocateSupported=hc.restrictedSnapshotRelocateSupported, - perVmSwapFiles=hc.perVmSwapFiles, - localSwapDatastoreSupported=hc.localSwapDatastoreSupported, - unsharedSwapVMotionSupported=hc.unsharedSwapVMotionSupported, - backgroundSnapshotsSupported=hc.backgroundSnapshotsSupported, - preAssignedPCIUnitNumbersSupported=hc.preAssignedPCIUnitNumbersSupported, - screenshotSupported=hc.screenshotSupported, - scaledScreenshotSupported=hc.scaledScreenshotSupported, - storageVMotionSupported=hc.storageVMotionSupported, - vmotionWithStorageVMotionSupported=hc.vmotionWithStorageVMotionSupported, - vmotionAcrossNetworkSupported=hc.vmotionAcrossNetworkSupported, - maxNumDisksSVMotion=hc.maxNumDisksSVMotion, - hbrNicSelectionSupported=hc.hbrNicSelectionSupported, - vrNfcNicSelectionSupported=hc.vrNfcNicSelectionSupported, - recordReplaySupported=hc.recordReplaySupported, - ftSupported=hc.ftSupported, - replayUnsupportedReason=hc.replayUnsupportedReason, - checkpointFtSupported=hc.checkpointFtSupported, - smpFtSupported=hc.smpFtSupported, - maxVcpusPerFtVm=hc.maxVcpusPerFtVm, - loginBySSLThumbprintSupported=hc.loginBySSLThumbprintSupported, - cloneFromSnapshotSupported=hc.cloneFromSnapshotSupported, - deltaDiskBackingsSupported=hc.deltaDiskBackingsSupported, - perVMNetworkTrafficShapingSupported=hc.perVMNetworkTrafficShapingSupported, - tpmSupported=hc.tpmSupported, - virtualExecUsageSupported=hc.virtualExecUsageSupported, - storageIORMSupported=hc.storageIORMSupported, - vmDirectPathGen2Supported=hc.vmDirectPathGen2Supported, - vmDirectPathGen2UnsupportedReasonExtended=hc.vmDirectPathGen2UnsupportedReasonExtended, - vStorageCapable=hc.vStorageCapable, - snapshotRelayoutSupported=hc.snapshotRelayoutSupported, - firewallIpRulesSupported=hc.firewallIpRulesSupported, - servicePackageInfoSupported=hc.servicePackageInfoSupported, - maxHostRunningVms=hc.maxHostRunningVms, - maxHostSupportedVcpus=hc.maxHostSupportedVcpus, - vmfsDatastoreMountCapable=hc.vmfsDatastoreMountCapable, - eightPlusHostVmfsSharedAccessSupported=hc.eightPlusHostVmfsSharedAccessSupported, - nestedHVSupported=hc.nestedHVSupported, - vPMCSupported=hc.vPMCSupported, - interVMCommunicationThroughVMCISupported=hc.interVMCommunicationThroughVMCISupported, - scheduledHardwareUpgradeSupported=hc.scheduledHardwareUpgradeSupported, - featureCapabilitiesSupported=hc.featureCapabilitiesSupported, - latencySensitivitySupported=hc.latencySensitivitySupported, - storagePolicySupported=hc.storagePolicySupported, - accel3dSupported=hc.accel3dSupported, - reliableMemoryAware=hc.reliableMemoryAware, - multipleNetworkStackInstanceSupported=hc.multipleNetworkStackInstanceSupported, - messageBusProxySupported=hc.messageBusProxySupported, - vsanSupported=hc.vsanSupported, - vFlashSupported=hc.vFlashSupported, - hostAccessManagerSupported=hc.hostAccessManagerSupported, - provisioningNicSelectionSupported=hc.provisioningNicSelectionSupported, - nfs41Supported=hc.nfs41Supported, - nfs41Krb5iSupported=hc.nfs41Krb5iSupported, - turnDiskLocatorLedSupported=hc.turnDiskLocatorLedSupported, - virtualVolumeDatastoreSupported=hc.virtualVolumeDatastoreSupported, - markAsSsdSupported=hc.markAsSsdSupported, - markAsLocalSupported=hc.markAsLocalSupported, - smartCardAuthenticationSupported=hc.smartCardAuthenticationSupported, - cryptoSupported=hc.cryptoSupported, - oneKVolumeAPIsSupported=hc.oneKVolumeAPIsSupported, - gatewayOnNicSupported=hc.gatewayOnNicSupported, - upitSupported=hc.upitSupported, - cpuHwMmuSupported=hc.cpuHwMmuSupported, - encryptedVMotionSupported=hc.encryptedVMotionSupported, - encryptionChangeOnAddRemoveSupported=hc.encryptionChangeOnAddRemoveSupported, - encryptionHotOperationSupported=hc.encryptionHotOperationSupported, - encryptionWithSnapshotsSupported=hc.encryptionWithSnapshotsSupported, - encryptionFaultToleranceSupported=hc.encryptionFaultToleranceSupported, - encryptionMemorySaveSupported=hc.encryptionMemorySaveSupported, - encryptionRDMSupported=hc.encryptionRDMSupported, - encryptionVFlashSupported=hc.encryptionVFlashSupported, - encryptionCBRCSupported=hc.encryptionCBRCSupported, - encryptionHBRSupported=hc.encryptionHBRSupported, - supportedVmfsMajorVersion=[version for version in hc.supportedVmfsMajorVersion], - vmDirectPathGen2UnsupportedReason=[reason for reason in hc.vmDirectPathGen2UnsupportedReason], - ftCompatibilityIssues=[issue for issue in hc.ftCompatibilityIssues], - checkpointFtCompatibilityIssues=[issue for issue in hc.checkpointFtCompatibilityIssues], - smpFtCompatibilityIssues=[issue for issue in hc.smpFtCompatibilityIssues], - replayCompatibilityIssues=[issue for issue in hc.replayCompatibilityIssues], - ) - return hosts_capability_facts - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True, - ) - - host_capability_manager = CapabilityFactsManager(module) - module.exit_json(changed=False, - hosts_capability_facts=host_capability_manager.gather_host_capability_facts()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/_vmware_host_config_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_host_config_facts.py deleted file mode 100644 index bdc24dcb12..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_host_config_facts.py +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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': ['deprecated'], - 'supported_by': 'community' -} - -DOCUMENTATION = r''' ---- -module: vmware_host_config_facts -deprecated: - removed_in: '2.13' - why: Deprecated in favour of C(_info) module. - alternative: Use M(vmware_host_config_info) instead. -short_description: Gathers facts about an ESXi host's advance configuration information -description: -- This module can be used to gather facts about an ESXi host's advance configuration information when ESXi hostname or Cluster name is given. -version_added: '2.5' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of the cluster from which the ESXi host belong to. - - If C(esxi_hostname) is not given, this parameter is required. - type: str - esxi_hostname: - description: - - ESXi hostname to gather facts from. - - If C(cluster_name) is not given, this parameter is required. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather facts about all ESXi Host in given Cluster - vmware_host_config_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: cluster_name - delegate_to: localhost - -- name: Gather facts about ESXi Host - vmware_host_config_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - delegate_to: localhost -''' - -RETURN = r''' -hosts_facts: - description: - - dict with hostname as key and dict with host config facts - returned: always - type: dict - sample: { - "10.76.33.226": { - "Annotations.WelcomeMessage": "", - "BufferCache.FlushInterval": 30000, - "BufferCache.HardMaxDirty": 95, - "BufferCache.PerFileHardMaxDirty": 50, - "BufferCache.SoftMaxDirty": 15, - } - } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class VmwareConfigFactsManager(PyVmomi): - def __init__(self, module): - super(VmwareConfigFactsManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - - def gather_host_facts(self): - hosts_facts = {} - for host in self.hosts: - host_facts = {} - for option in host.configManager.advancedOption.QueryOptions(): - host_facts[option.key] = option.value - hosts_facts[host.name] = host_facts - return hosts_facts - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True - ) - - vmware_host_config = VmwareConfigFactsManager(module) - module.exit_json(changed=False, hosts_facts=vmware_host_config.gather_host_facts()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/_vmware_host_dns_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_host_dns_facts.py deleted file mode 100644 index f4bfdd2571..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_host_dns_facts.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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': ['deprecated'], - 'supported_by': 'community' -} - -DOCUMENTATION = r''' ---- -module: vmware_host_dns_facts -deprecated: - removed_in: '2.13' - why: Deprecated in favour of C(_info) module. - alternative: Use M(vmware_host_dns_info) instead. -short_description: Gathers facts about an ESXi host's DNS configuration information -description: -- This module can be used to gather facts about an ESXi host's DNS configuration information when ESXi hostname or Cluster name is given. -- All parameters and VMware object names are case sensitive. -version_added: '2.5' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of the cluster from which the ESXi host belong to. - - If C(esxi_hostname) is not given, this parameter is required. - type: str - esxi_hostname: - description: - - ESXi hostname to gather facts from. - - If C(cluster_name) is not given, this parameter is required. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather DNS facts about all ESXi Hosts in given Cluster - vmware_host_dns_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: cluster_name - delegate_to: localhost - -- name: Gather DNS facts about ESXi Host - vmware_host_dns_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - delegate_to: localhost -''' - -RETURN = r''' -hosts_dns_facts: - description: metadata about DNS config from given cluster / host system - returned: always - type: dict - sample: { - "DC0_C0_H0": { - "dhcp": true, - "domain_name": "localdomain", - "host_name": "localhost", - "ip_address": [ - "8.8.8.8" - ], - "search_domain": [ - "localdomain" - ], - "virtual_nic_device": "vmk0" - } - } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class VmwareDnsFactsManager(PyVmomi): - def __init__(self, module): - super(VmwareDnsFactsManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - - def gather_dns_facts(self): - hosts_facts = {} - for host in self.hosts: - host_facts = {} - dns_config = host.config.network.dnsConfig - host_facts['dhcp'] = dns_config.dhcp - host_facts['virtual_nic_device'] = dns_config.virtualNicDevice - host_facts['host_name'] = dns_config.hostName - host_facts['domain_name'] = dns_config.domainName - host_facts['ip_address'] = [ip for ip in dns_config.address] - host_facts['search_domain'] = [domain for domain in dns_config.searchDomain] - hosts_facts[host.name] = host_facts - return hosts_facts - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True - ) - - vmware_dns_config = VmwareDnsFactsManager(module) - module.exit_json(changed=False, hosts_dns_facts=vmware_dns_config.gather_dns_facts()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/_vmware_host_feature_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_host_feature_facts.py deleted file mode 100644 index 6dbbbcce72..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_host_feature_facts.py +++ /dev/null @@ -1,147 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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': ['deprecated'], - 'supported_by': 'community' -} - -DOCUMENTATION = r''' ---- -module: vmware_host_feature_facts -deprecated: - removed_in: '2.13' - why: Deprecated in favour of C(_info) module. - alternative: Use M(vmware_host_feature_info) instead. -short_description: Gathers facts about an ESXi host's feature capability information -description: -- This module can be used to gather facts about an ESXi host's feature capability information when ESXi hostname or Cluster name is given. -version_added: 2.8 -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of the cluster from all host systems to be used for facts gathering. - - If C(esxi_hostname) is not given, this parameter is required. - type: str - esxi_hostname: - description: - - ESXi hostname to gather facts from. - - If C(cluster_name) is not given, this parameter is required. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather feature capability facts about all ESXi Hosts in given Cluster - vmware_host_feature_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: cluster_name - delegate_to: localhost - register: all_cluster_hosts_facts - -- name: Check if ESXi is vulnerable for Speculative Store Bypass Disable (SSBD) vulnerability - vmware_host_feature_facts: - hostname: "{{ vcenter_server }}" - username: "{{ vcenter_user }}" - password: "{{ vcenter_pass }}" - validate_certs: no - esxi_hostname: "{{ esxi_hostname }}" - register: features_set -- set_fact: - ssbd : "{{ item.value }}" - loop: "{{ features_set.host_feature_facts[esxi_hostname] |json_query(name) }}" - vars: - name: "[?key=='cpuid.SSBD']" -- assert: - that: - - ssbd|int == 1 - when: ssbd is defined -''' - -RETURN = r''' -hosts_feature_facts: - description: metadata about host's feature capability information - returned: always - type: dict - sample: { - "10.76.33.226": [ - { - "feature_name": "cpuid.3DNOW", - "key": "cpuid.3DNOW", - "value": "0" - }, - { - "feature_name": "cpuid.3DNOWPLUS", - "key": "cpuid.3DNOWPLUS", - "value": "0" - }, - ] - } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class FeatureCapabilityFactsManager(PyVmomi): - def __init__(self, module): - super(FeatureCapabilityFactsManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - - def gather_host_feature_facts(self): - host_feature_facts = dict() - for host in self.hosts: - host_feature_capabilities = host.config.featureCapability - capability = [] - for fc in host_feature_capabilities: - temp_dict = { - 'key': fc.key, - 'feature_name': fc.featureName, - 'value': fc.value, - } - capability.append(temp_dict) - - host_feature_facts[host.name] = capability - - return host_feature_facts - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True, - ) - - host_capability_manager = FeatureCapabilityFactsManager(module) - module.exit_json(changed=False, - hosts_feature_facts=host_capability_manager.gather_host_feature_facts()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/_vmware_host_firewall_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_host_firewall_facts.py deleted file mode 100644 index 2a34715687..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_host_firewall_facts.py +++ /dev/null @@ -1,168 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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': ['deprecated'], - 'supported_by': 'community' -} - -DOCUMENTATION = r''' ---- -module: vmware_host_firewall_facts -deprecated: - removed_in: '2.13' - why: Deprecated in favour of C(_info) module. - alternative: Use M(vmware_host_firewall_info) instead. -short_description: Gathers facts about an ESXi host's firewall configuration information -description: -- This module can be used to gather facts about an ESXi host's firewall configuration information when ESXi hostname or Cluster name is given. -version_added: '2.5' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of the cluster from which the ESXi host belong to. - - If C(esxi_hostname) is not given, this parameter is required. - type: str - esxi_hostname: - description: - - ESXi hostname to gather facts from. - - If C(cluster_name) is not given, this parameter is required. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather firewall facts about all ESXi Host in given Cluster - vmware_host_firewall_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: cluster_name - delegate_to: localhost - -- name: Gather firewall facts about ESXi Host - vmware_host_firewall_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - delegate_to: localhost -''' - -RETURN = r''' -hosts_firewall_facts: - description: metadata about host's firewall configuration - returned: on success - type: dict - sample: { - "esxi_hostname_0001": [ - { - "allowed_hosts": { - "all_ip": true, - "ip_address": [ - "10.10.10.1", - ], - "ip_network": [ - "11.111.112.0/22", - "192.168.10.1/24" - ], - }, - "enabled": true, - "key": "CIMHttpServer", - "rule": [ - { - "direction": "inbound", - "end_port": null, - "port": 5988, - "port_type": "dst", - "protocol": "tcp" - } - ], - "service": "sfcbd-watchdog" - }, - ] - } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class FirewallFactsManager(PyVmomi): - def __init__(self, module): - super(FirewallFactsManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - - @staticmethod - def normalize_rule_set(rule_obj): - rule_dict = dict() - rule_dict['key'] = rule_obj.key - rule_dict['service'] = rule_obj.service - rule_dict['enabled'] = rule_obj.enabled - rule_dict['rule'] = [] - - for rule in rule_obj.rule: - rule_set_dict = dict() - rule_set_dict['port'] = rule.port - rule_set_dict['end_port'] = rule.endPort - rule_set_dict['direction'] = rule.direction - rule_set_dict['port_type'] = rule.portType - rule_set_dict['protocol'] = rule.protocol - rule_dict['rule'].append(rule_set_dict) - - allowed_host = rule_obj.allowedHosts - rule_allow_host = dict() - rule_allow_host['ip_address'] = [ip for ip in allowed_host.ipAddress] - rule_allow_host['ip_network'] = [ip.network + "/" + str(ip.prefixLength) for ip in allowed_host.ipNetwork] - rule_allow_host['all_ip'] = allowed_host.allIp - rule_dict['allowed_hosts'] = rule_allow_host - return rule_dict - - def gather_host_firewall_facts(self): - hosts_firewall_facts = dict() - for host in self.hosts: - firewall_system = host.configManager.firewallSystem - if firewall_system: - hosts_firewall_facts[host.name] = [] - for rule_set_obj in firewall_system.firewallInfo.ruleset: - hosts_firewall_facts[host.name].append(self.normalize_rule_set(rule_obj=rule_set_obj)) - return hosts_firewall_facts - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True - ) - - vmware_host_firewall = FirewallFactsManager(module) - module.exit_json(changed=False, hosts_firewall_facts=vmware_host_firewall.gather_host_firewall_facts()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/_vmware_host_ntp_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_host_ntp_facts.py deleted file mode 100644 index cdd912315e..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_host_ntp_facts.py +++ /dev/null @@ -1,139 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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': ['deprecated'], - 'supported_by': 'community' -} - -DOCUMENTATION = r''' ---- -module: vmware_host_ntp_facts -deprecated: - removed_in: '2.13' - why: Deprecated in favour of C(_info) module. - alternative: Use M(vmware_host_ntp_info) instead. -short_description: Gathers facts about NTP configuration on an ESXi host -description: -- This module can be used to gather facts about NTP configurations on an ESXi host. -version_added: 2.7 -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of the cluster. - - NTP config facts about each ESXi server will be returned for the given cluster. - - If C(esxi_hostname) is not given, this parameter is required. - type: str - esxi_hostname: - description: - - ESXi hostname. - - NTP config facts about this ESXi server will be returned. - - If C(cluster_name) is not given, this parameter is required. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather NTP facts about all ESXi Host in the given Cluster - vmware_host_ntp_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: cluster_name - delegate_to: localhost - register: cluster_host_ntp - -- name: Gather NTP facts about ESXi Host - vmware_host_ntp_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - delegate_to: localhost - register: host_ntp -''' - -RETURN = r''' -hosts_ntp_facts: - description: - - dict with hostname as key and dict with NTP facts as value - returned: hosts_ntp_facts - type: dict - sample: { - "10.76.33.226": [ - { - "ntp_servers": [], - "time_zone_description": "UTC", - "time_zone_gmt_offset": 0, - "time_zone_identifier": "UTC", - "time_zone_name": "UTC" - } - ] - } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class VmwareNtpFactManager(PyVmomi): - def __init__(self, module): - super(VmwareNtpFactManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - - def gather_ntp_facts(self): - hosts_facts = {} - for host in self.hosts: - host_ntp_facts = [] - host_date_time_manager = host.configManager.dateTimeSystem - if host_date_time_manager: - host_ntp_facts.append( - dict( - time_zone_identifier=host_date_time_manager.dateTimeInfo.timeZone.key, - time_zone_name=host_date_time_manager.dateTimeInfo.timeZone.name, - time_zone_description=host_date_time_manager.dateTimeInfo.timeZone.description, - time_zone_gmt_offset=host_date_time_manager.dateTimeInfo.timeZone.gmtOffset, - ntp_servers=[ntp_server for ntp_server in host_date_time_manager.dateTimeInfo.ntpConfig.server] - ) - ) - hosts_facts[host.name] = host_ntp_facts - return hosts_facts - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True, - ) - - vmware_host_ntp_config = VmwareNtpFactManager(module) - module.exit_json(changed=False, hosts_ntp_facts=vmware_host_ntp_config.gather_ntp_facts()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/_vmware_host_package_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_host_package_facts.py deleted file mode 100644 index 184fae8a72..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_host_package_facts.py +++ /dev/null @@ -1,132 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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': ['deprecated'], - 'supported_by': 'community' -} - -DOCUMENTATION = r''' ---- -module: vmware_host_package_facts -deprecated: - removed_in: '2.13' - why: Deprecated in favour of C(_info) module. - alternative: Use M(vmware_host_package_info) instead. -short_description: Gathers facts about available packages on an ESXi host -description: -- This module can be used to gather facts about available packages and their status on an ESXi host. -version_added: '2.5' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of the cluster. - - Package facts about each ESXi server will be returned for given cluster. - - If C(esxi_hostname) is not given, this parameter is required. - type: str - esxi_hostname: - description: - - ESXi hostname. - - Package facts about this ESXi server will be returned. - - If C(cluster_name) is not given, this parameter is required. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather facts about all ESXi Host in given Cluster - vmware_host_package_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: cluster_name - delegate_to: localhost - register: cluster_host_packages - -- name: Gather facts about ESXi Host - vmware_host_package_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - delegate_to: localhost - register: host_packages -''' - -RETURN = r''' -hosts_package_facts: - description: - - dict with hostname as key and dict with package facts as value - returned: hosts_package_facts - type: dict - sample: { "hosts_package_facts": { "localhost.localdomain": []}} -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class VmwarePackageManager(PyVmomi): - def __init__(self, module): - super(VmwarePackageManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - - def gather_package_facts(self): - hosts_facts = {} - for host in self.hosts: - host_package_facts = [] - host_pkg_mgr = host.configManager.imageConfigManager - if host_pkg_mgr: - pkgs = host_pkg_mgr.FetchSoftwarePackages() - for pkg in pkgs: - host_package_facts.append(dict(name=pkg.name, - version=pkg.version, - vendor=pkg.vendor, - summary=pkg.summary, - description=pkg.description, - acceptance_level=pkg.acceptanceLevel, - maintenance_mode_required=pkg.maintenanceModeRequired, - creation_date=pkg.creationDate, - ) - ) - hosts_facts[host.name] = host_package_facts - return hosts_facts - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True, - ) - - vmware_host_package_config = VmwarePackageManager(module) - module.exit_json(changed=False, hosts_package_facts=vmware_host_package_config.gather_package_facts()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/_vmware_host_service_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_host_service_facts.py deleted file mode 100644 index c8404ac9a4..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_host_service_facts.py +++ /dev/null @@ -1,158 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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': ['deprecated'], - 'supported_by': 'community' -} - -DOCUMENTATION = r''' ---- -module: vmware_host_service_facts -deprecated: - removed_in: '2.13' - why: Deprecated in favour of C(_info) module. - alternative: Use M(vmware_host_service_info) instead. -short_description: Gathers facts about an ESXi host's services -description: -- This module can be used to gather facts about an ESXi host's services. -version_added: '2.5' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -- If source package name is not available then fact is populated as null. -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of the cluster. - - Service facts about each ESXi server will be returned for given cluster. - - If C(esxi_hostname) is not given, this parameter is required. - type: str - esxi_hostname: - description: - - ESXi hostname. - - Service facts about this ESXi server will be returned. - - If C(cluster_name) is not given, this parameter is required. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather facts about all ESXi Host in given Cluster - vmware_host_service_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: cluster_name - delegate_to: localhost - register: cluster_host_services - -- name: Gather facts about ESXi Host - vmware_host_service_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - delegate_to: localhost - register: host_services -''' - -RETURN = r''' -host_service_facts: - description: - - dict with hostname as key and dict with host service config facts - returned: always - type: dict - sample: { - "10.76.33.226": [ - { - "key": "DCUI", - "label": "Direct Console UI", - "policy": "on", - "required": false, - "running": true, - "uninstallable": false, - "source_package_name": "esx-base", - "source_package_desc": "This VIB contains all of the base functionality of vSphere ESXi." - }, - { - "key": "TSM", - "label": "ESXi Shell", - "policy": "off", - "required": false, - "running": false, - "uninstallable": false, - "source_package_name": "esx-base", - "source_package_desc": "This VIB contains all of the base functionality of vSphere ESXi." - }, - ] - } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class VmwareServiceManager(PyVmomi): - def __init__(self, module): - super(VmwareServiceManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - - def gather_host_facts(self): - hosts_facts = {} - for host in self.hosts: - host_service_facts = [] - host_service_system = host.configManager.serviceSystem - if host_service_system: - services = host_service_system.serviceInfo.service - for service in services: - host_service_facts.append( - dict( - key=service.key, - label=service.label, - required=service.required, - uninstallable=service.uninstallable, - running=service.running, - policy=service.policy, - source_package_name=service.sourcePackage.sourcePackageName if service.sourcePackage else None, - source_package_desc=service.sourcePackage.description if service.sourcePackage else None, - ) - ) - hosts_facts[host.name] = host_service_facts - return hosts_facts - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True, - ) - - vmware_host_service_config = VmwareServiceManager(module) - module.exit_json(changed=False, host_service_facts=vmware_host_service_config.gather_host_facts()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/_vmware_host_ssl_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_host_ssl_facts.py deleted file mode 100644 index 2cd6d60704..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_host_ssl_facts.py +++ /dev/null @@ -1,152 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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': ['deprecated'], - 'supported_by': 'community' -} - -DOCUMENTATION = r''' ---- -module: vmware_host_ssl_facts -deprecated: - removed_in: '2.13' - why: Deprecated in favour of C(_info) module. - alternative: Use M(vmware_host_ssl_info) instead. -short_description: Gather facts of ESXi host system about SSL -description: -- This module can be used to gather facts of the SSL thumbprint information for a host. -version_added: 2.7 -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of the cluster. - - SSL thumbprint information about all ESXi host system in the given cluster will be reported. - - If C(esxi_hostname) is not given, this parameter is required. - type: str - esxi_hostname: - description: - - ESXi hostname. - - SSL thumbprint information of this ESXi host system will be reported. - - If C(cluster_name) is not given, this parameter is required. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather SSL thumbprint information about all ESXi Hosts in given Cluster - vmware_host_ssl_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: '{{ cluster_name }}' - delegate_to: localhost - register: all_host_ssl_facts - -- name: Get SSL Thumbprint info about "{{ esxi_hostname }}" - vmware_host_ssl_facts: - hostname: "{{ vcenter_server }}" - username: "{{ vcenter_user }}" - password: "{{ vcenter_pass }}" - esxi_hostname: '{{ esxi_hostname }}' - register: ssl_facts -- set_fact: - ssl_thumbprint: "{{ ssl_facts['host_ssl_facts'][esxi_hostname]['ssl_thumbprints'][0] }}" -- debug: - msg: "{{ ssl_thumbprint }}" -- name: Add ESXi Host to vCenter - vmware_host: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter_name: '{{ datacenter_name }}' - cluster_name: '{{ cluster_name }}' - esxi_hostname: '{{ esxi_hostname }}' - esxi_username: '{{ esxi_username }}' - esxi_password: '{{ esxi_password }}' - esxi_ssl_thumbprint: '{{ ssl_thumbprint }}' - state: present -''' - -RETURN = r''' -host_ssl_facts: - description: - - dict with hostname as key and dict with SSL thumbprint related facts - returned: facts - type: dict - sample: - { - "10.76.33.215": { - "owner_tag": "", - "principal": "vpxuser", - "ssl_thumbprints": [ - "E3:E8:A9:20:8D:32:AE:59:C6:8D:A5:91:B0:20:EF:00:A2:7C:27:EE", - "F1:AC:DA:6E:D8:1E:37:36:4A:5C:07:E5:04:0B:87:C8:75:FB:42:01" - ] - } - } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class VMwareHostSslManager(PyVmomi): - def __init__(self, module): - super(VMwareHostSslManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - self.hosts_facts = {} - - def gather_ssl_facts(self): - for host in self.hosts: - self.hosts_facts[host.name] = dict(principal='', - owner_tag='', - ssl_thumbprints=[]) - - host_ssl_info_mgr = host.config.sslThumbprintInfo - if host_ssl_info_mgr: - self.hosts_facts[host.name]['principal'] = host_ssl_info_mgr.principal - self.hosts_facts[host.name]['owner_tag'] = host_ssl_info_mgr.ownerTag - self.hosts_facts[host.name]['ssl_thumbprints'] = [i for i in host_ssl_info_mgr.sslThumbprints] - - self.module.exit_json(changed=False, host_ssl_facts=self.hosts_facts) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str'), - esxi_hostname=dict(type='str'), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True, - ) - - vmware_host_accept_config = VMwareHostSslManager(module) - vmware_host_accept_config.gather_ssl_facts() - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/_vmware_host_vmhba_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_host_vmhba_facts.py deleted file mode 100644 index 84cc19d317..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_host_vmhba_facts.py +++ /dev/null @@ -1,222 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# 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': ['deprecated'], - 'supported_by': 'community' -} - -DOCUMENTATION = r''' ---- -module: vmware_host_vmhba_facts -deprecated: - removed_in: '2.13' - why: Deprecated in favour of C(_info) module. - alternative: Use M(vmware_host_vmhba_info) instead. -short_description: Gathers facts about vmhbas available on the given ESXi host -description: -- This module can be used to gather facts about vmhbas available on the given ESXi host. -- If C(cluster_name) is provided, then vmhba facts about all hosts from given cluster will be returned. -- If C(esxi_hostname) is provided, then vmhba facts about given host system will be returned. -version_added: '2.8' -author: -- Christian Kotte (@ckotte) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - esxi_hostname: - description: - - Name of the host system to work with. - - Vmhba facts about this ESXi server will be returned. - - This parameter is required if C(cluster_name) is not specified. - type: str - cluster_name: - description: - - Name of the cluster from which all host systems will be used. - - Vmhba facts about each ESXi server will be returned for the given cluster. - - This parameter is required if C(esxi_hostname) is not specified. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather facts about vmhbas of all ESXi Host in the given Cluster - vmware_host_vmhba_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: '{{ cluster_name }}' - delegate_to: localhost - register: cluster_host_vmhbas - -- name: Gather facts about vmhbas of an ESXi Host - vmware_host_vmhba_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - delegate_to: localhost - register: host_vmhbas -''' - -RETURN = r''' -hosts_vmhbas_facts: - description: - - dict with hostname as key and dict with vmhbas facts as value. - returned: hosts_vmhbas_facts - type: dict - sample: - { - "10.76.33.204": { - "vmhba_details": [ - { - "adapter": "HPE Smart Array P440ar", - "bus": 3, - "device": "vmhba0", - "driver": "nhpsa", - "location": "0000:03:00.0", - "model": "Smart Array P440ar", - "node_wwn": "50:01:43:80:37:18:9e:a0", - "status": "unknown", - "type": "SAS" - }, - { - "adapter": "QLogic Corp ISP2532-based 8Gb Fibre Channel to PCI Express HBA", - "bus": 5, - "device": "vmhba1", - "driver": "qlnativefc", - "location": "0000:05:00.0", - "model": "ISP2532-based 8Gb Fibre Channel to PCI Express HBA", - "node_wwn": "57:64:96:32:15:90:23:95:82", - "port_type": "unknown", - "port_wwn": "57:64:96:32:15:90:23:95:82", - "speed": 8, - "status": "online", - "type": "Fibre Channel" - }, - { - "adapter": "QLogic Corp ISP2532-based 8Gb Fibre Channel to PCI Express HBA", - "bus": 8, - "device": "vmhba2", - "driver": "qlnativefc", - "location": "0000:08:00.0", - "model": "ISP2532-based 8Gb Fibre Channel to PCI Express HBA", - "node_wwn": "57:64:96:32:15:90:23:95:21", - "port_type": "unknown", - "port_wwn": "57:64:96:32:15:90:23:95:21", - "speed": 8, - "status": "online", - "type": "Fibre Channel" - } - ], - } - } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class HostVmhbaMgr(PyVmomi): - """Class to manage vmhba facts""" - def __init__(self, module): - super(HostVmhbaMgr, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - if not self.hosts: - self.module.fail_json(msg="Failed to find host system.") - - def gather_host_vmhba_facts(self): - """Gather vmhba facts""" - hosts_vmhba_facts = {} - for host in self.hosts: - host_vmhba_facts = dict() - host_st_system = host.configManager.storageSystem - if host_st_system: - device_info = host_st_system.storageDeviceInfo - host_vmhba_facts['vmhba_details'] = [] - for hba in device_info.hostBusAdapter: - hba_facts = dict() - if hba.pci: - hba_facts['location'] = hba.pci - for pci_device in host.hardware.pciDevice: - if pci_device.id == hba.pci: - hba_facts['adapter'] = pci_device.vendorName + ' ' + pci_device.deviceName - break - else: - hba_facts['location'] = 'PCI' - hba_facts['device'] = hba.device - # contains type as string in format of 'key-vim.host.FibreChannelHba-vmhba1' - hba_type = hba.key.split(".")[-1].split("-")[0] - if hba_type == 'SerialAttachedHba': - hba_facts['type'] = 'SAS' - elif hba_type == 'FibreChannelHba': - hba_facts['type'] = 'Fibre Channel' - else: - hba_facts['type'] = hba_type - hba_facts['bus'] = hba.bus - hba_facts['status'] = hba.status - hba_facts['model'] = hba.model - hba_facts['driver'] = hba.driver - try: - hba_facts['node_wwn'] = self.format_number(hba.nodeWorldWideName) - except AttributeError: - pass - try: - hba_facts['port_wwn'] = self.format_number(hba.portWorldWideName) - except AttributeError: - pass - try: - hba_facts['port_type'] = hba.portType - except AttributeError: - pass - try: - hba_facts['speed'] = hba.speed - except AttributeError: - pass - host_vmhba_facts['vmhba_details'].append(hba_facts) - - hosts_vmhba_facts[host.name] = host_vmhba_facts - return hosts_vmhba_facts - - @staticmethod - def format_number(number): - """Format number""" - string = str(number) - return ':'.join(a + b for a, b in zip(string[::2], string[1::2])) - - -def main(): - """Main""" - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True, - ) - - host_vmhba_mgr = HostVmhbaMgr(module) - module.exit_json(changed=False, hosts_vmhbas_facts=host_vmhba_mgr.gather_host_vmhba_facts()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/_vmware_host_vmnic_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_host_vmnic_facts.py deleted file mode 100644 index 6a5d4b1eec..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_host_vmnic_facts.py +++ /dev/null @@ -1,324 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# 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': ['deprecated'], - 'supported_by': 'community' -} - -DOCUMENTATION = r''' ---- -module: vmware_host_vmnic_facts -deprecated: - removed_in: '2.13' - why: Deprecated in favour of C(_info) module. - alternative: Use M(vmware_host_vmnic_info) instead. -short_description: Gathers facts about vmnics available on the given ESXi host -description: -- This module can be used to gather facts about vmnics available on the given ESXi host. -- If C(cluster_name) is provided, then vmnic facts about all hosts from given cluster will be returned. -- If C(esxi_hostname) is provided, then vmnic facts about given host system will be returned. -- Additional details about vswitch and dvswitch with respective vmnic is also provided which is added in 2.7 version. -version_added: '2.5' -author: -- Abhijeet Kasurde (@Akasurde) -- Christian Kotte (@ckotte) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - capabilities: - description: - - Gather facts about general capabilities (Auto negotiation, Wake On LAN, and Network I/O Control). - type: bool - default: false - version_added: 2.8 - directpath_io: - description: - - Gather facts about DirectPath I/O capabilities and configuration. - type: bool - default: false - version_added: 2.8 - sriov: - description: - - Gather facts about SR-IOV capabilities and configuration. - type: bool - default: false - version_added: 2.8 - esxi_hostname: - description: - - Name of the host system to work with. - - Vmnic facts about this ESXi server will be returned. - - This parameter is required if C(cluster_name) is not specified. - type: str - cluster_name: - description: - - Name of the cluster from which all host systems will be used. - - Vmnic facts about each ESXi server will be returned for the given cluster. - - This parameter is required if C(esxi_hostname) is not specified. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather facts about vmnics of all ESXi Host in the given Cluster - vmware_host_vmnic_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: '{{ cluster_name }}' - delegate_to: localhost - register: cluster_host_vmnics - -- name: Gather facts about vmnics of an ESXi Host - vmware_host_vmnic_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - delegate_to: localhost - register: host_vmnics -''' - -RETURN = r''' -hosts_vmnics_facts: - description: - - dict with hostname as key and dict with vmnics facts as value. - - for C(num_vmnics), only NICs starting with vmnic are counted. NICs like vusb* are not counted. - - details about vswitch and dvswitch was added in version 2.7. - - details about vmnics was added in version 2.8. - returned: hosts_vmnics_facts - type: dict - sample: - { - "10.76.33.204": { - "all": [ - "vmnic0", - "vmnic1" - ], - "available": [], - "dvswitch": { - "dvs_0002": [ - "vmnic1" - ] - }, - "num_vmnics": 2, - "used": [ - "vmnic1", - "vmnic0" - ], - "vmnic_details": [ - { - "actual_duplex": "Full Duplex", - "actual_speed": 10000, - "adapter": "Intel(R) 82599 10 Gigabit Dual Port Network Connection", - "configured_duplex": "Auto negotiate", - "configured_speed": "Auto negotiate", - "device": "vmnic0", - "driver": "ixgbe", - "location": "0000:01:00.0", - "mac": "aa:bb:cc:dd:ee:ff", - "status": "Connected", - }, - { - "actual_duplex": "Full Duplex", - "actual_speed": 10000, - "adapter": "Intel(R) 82599 10 Gigabit Dual Port Network Connection", - "configured_duplex": "Auto negotiate", - "configured_speed": "Auto negotiate", - "device": "vmnic1", - "driver": "ixgbe", - "location": "0000:01:00.1", - "mac": "ab:ba:cc:dd:ee:ff", - "status": "Connected", - }, - ], - "vswitch": { - "vSwitch0": [ - "vmnic0" - ] - } - } - } -''' - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi, get_all_objs - - -class HostVmnicMgr(PyVmomi): - """Class to manage vmnic facts""" - def __init__(self, module): - super(HostVmnicMgr, self).__init__(module) - self.capabilities = self.params.get('capabilities') - self.directpath_io = self.params.get('directpath_io') - self.sriov = self.params.get('sriov') - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - if not self.hosts: - self.module.fail_json(msg="Failed to find host system.") - - def find_dvs_by_uuid(self, uuid=None): - """Find DVS by it's UUID""" - dvs_obj = None - if uuid is None: - return dvs_obj - - dvswitches = get_all_objs(self.content, [vim.DistributedVirtualSwitch]) - for dvs in dvswitches: - if dvs.uuid == uuid: - dvs_obj = dvs - break - - return dvs_obj - - def gather_host_vmnic_facts(self): - """Gather vmnic facts""" - hosts_vmnic_facts = {} - for host in self.hosts: - host_vmnic_facts = dict(all=[], available=[], used=[], vswitch=dict(), dvswitch=dict()) - host_nw_system = host.configManager.networkSystem - if host_nw_system: - nw_config = host_nw_system.networkConfig - vmnics = [pnic.device for pnic in nw_config.pnic if pnic.device.startswith('vmnic')] - host_vmnic_facts['all'] = [pnic.device for pnic in nw_config.pnic] - host_vmnic_facts['num_vmnics'] = len(vmnics) - host_vmnic_facts['vmnic_details'] = [] - for pnic in host.config.network.pnic: - pnic_facts = dict() - if pnic.device.startswith('vmnic'): - if pnic.pci: - pnic_facts['location'] = pnic.pci - for pci_device in host.hardware.pciDevice: - if pci_device.id == pnic.pci: - pnic_facts['adapter'] = pci_device.vendorName + ' ' + pci_device.deviceName - break - else: - pnic_facts['location'] = 'PCI' - pnic_facts['device'] = pnic.device - pnic_facts['driver'] = pnic.driver - if pnic.linkSpeed: - pnic_facts['status'] = 'Connected' - pnic_facts['actual_speed'] = pnic.linkSpeed.speedMb - pnic_facts['actual_duplex'] = 'Full Duplex' if pnic.linkSpeed.duplex else 'Half Duplex' - else: - pnic_facts['status'] = 'Disconnected' - pnic_facts['actual_speed'] = 'N/A' - pnic_facts['actual_duplex'] = 'N/A' - if pnic.spec.linkSpeed: - pnic_facts['configured_speed'] = pnic.spec.linkSpeed.speedMb - pnic_facts['configured_duplex'] = 'Full Duplex' if pnic.spec.linkSpeed.duplex else 'Half Duplex' - else: - pnic_facts['configured_speed'] = 'Auto negotiate' - pnic_facts['configured_duplex'] = 'Auto negotiate' - pnic_facts['mac'] = pnic.mac - # General NIC capabilities - if self.capabilities: - pnic_facts['nioc_status'] = 'Allowed' if pnic.resourcePoolSchedulerAllowed else 'Not allowed' - pnic_facts['auto_negotiation_supported'] = pnic.autoNegotiateSupported - pnic_facts['wake_on_lan_supported'] = pnic.wakeOnLanSupported - # DirectPath I/O and SR-IOV capabilities and configuration - if self.directpath_io: - pnic_facts['directpath_io_supported'] = pnic.vmDirectPathGen2Supported - if self.directpath_io or self.sriov: - if pnic.pci: - for pci_device in host.configManager.pciPassthruSystem.pciPassthruInfo: - if pci_device.id == pnic.pci: - if self.directpath_io: - pnic_facts['passthru_enabled'] = pci_device.passthruEnabled - pnic_facts['passthru_capable'] = pci_device.passthruCapable - pnic_facts['passthru_active'] = pci_device.passthruActive - if self.sriov: - try: - if pci_device.sriovCapable: - pnic_facts['sriov_status'] = ( - 'Enabled' if pci_device.sriovEnabled else 'Disabled' - ) - pnic_facts['sriov_active'] = \ - pci_device.sriovActive - pnic_facts['sriov_virt_functions'] = \ - pci_device.numVirtualFunction - pnic_facts['sriov_virt_functions_requested'] = \ - pci_device.numVirtualFunctionRequested - pnic_facts['sriov_virt_functions_supported'] = \ - pci_device.maxVirtualFunctionSupported - else: - pnic_facts['sriov_status'] = 'Not supported' - except AttributeError: - pnic_facts['sriov_status'] = 'Not supported' - host_vmnic_facts['vmnic_details'].append(pnic_facts) - - vswitch_vmnics = [] - proxy_switch_vmnics = [] - if nw_config.vswitch: - for vswitch in nw_config.vswitch: - host_vmnic_facts['vswitch'][vswitch.name] = [] - # Workaround for "AttributeError: 'NoneType' object has no attribute 'nicDevice'" - # this issue doesn't happen every time; vswitch.spec.bridge.nicDevice exists! - try: - for vnic in vswitch.spec.bridge.nicDevice: - vswitch_vmnics.append(vnic) - host_vmnic_facts['vswitch'][vswitch.name].append(vnic) - except AttributeError: - pass - - if nw_config.proxySwitch: - for proxy_config in nw_config.proxySwitch: - dvs_obj = self.find_dvs_by_uuid(uuid=proxy_config.uuid) - if dvs_obj: - host_vmnic_facts['dvswitch'][dvs_obj.name] = [] - for proxy_nic in proxy_config.spec.backing.pnicSpec: - proxy_switch_vmnics.append(proxy_nic.pnicDevice) - if dvs_obj: - host_vmnic_facts['dvswitch'][dvs_obj.name].append(proxy_nic.pnicDevice) - - used_vmics = proxy_switch_vmnics + vswitch_vmnics - host_vmnic_facts['used'] = used_vmics - host_vmnic_facts['available'] = [pnic.device for pnic in nw_config.pnic if pnic.device not in used_vmics] - - hosts_vmnic_facts[host.name] = host_vmnic_facts - return hosts_vmnic_facts - - -def main(): - """Main""" - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - capabilities=dict(type='bool', required=False, default=False), - directpath_io=dict(type='bool', required=False, default=False), - sriov=dict(type='bool', required=False, default=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True, - ) - - host_vmnic_mgr = HostVmnicMgr(module) - module.exit_json(changed=False, hosts_vmnics_facts=host_vmnic_mgr.gather_host_vmnic_facts()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/_vmware_local_role_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_local_role_facts.py deleted file mode 100644 index 5d5ae85ef8..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_local_role_facts.py +++ /dev/null @@ -1,143 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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': ['deprecated'], - 'supported_by': 'community' -} - - -DOCUMENTATION = ''' ---- -module: vmware_local_role_facts -deprecated: - removed_in: '2.13' - why: Deprecated in favour of C(_info) module. - alternative: Use M(vmware_local_role_info) instead. -short_description: Gather facts about local roles on an ESXi host -description: - - This module can be used to gather facts about local role facts on an ESXi host -version_added: 2.7 -author: -- Abhijeet Kasurde (@Akasurde) -notes: - - Tested on ESXi 6.5 - - Be sure that the ESXi user used for login, has the appropriate rights to view roles - - The module returns a list of dict in version 2.8 and above. -requirements: - - "python >= 2.6" - - PyVmomi -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Gather facts about local role from an ESXi - vmware_local_role_facts: - hostname: '{{ esxi_hostname }}' - username: '{{ esxi_username }}' - password: '{{ esxi_password }}' - register: fact_details - delegate_to: localhost -- name: Get Admin privileges - set_fact: - admin_priv: "{{ fact_details.local_role_facts['Admin']['privileges'] }}" -- debug: - msg: "{{ admin_priv }}" -''' - -RETURN = r''' -local_role_facts: - description: Facts about role present on ESXi host - returned: always - type: dict - sample: [ - { - "privileges": [ - "Alarm.Acknowledge", - "Alarm.Create", - "Alarm.Delete", - "Alarm.DisableActions", - ], - "role_id": -12, - "role_info_label": "Ansible User", - "role_info_summary": "Ansible Automation user", - "role_name": "AnsiUser1", - "role_system": true - }, - { - "privileges": [], - "role_id": -5, - "role_info_label": "No access", - "role_info_summary": "Used for restricting granted access", - "role_name": "NoAccess", - "role_system": true - }, - { - "privileges": [ - "System.Anonymous", - "System.View" - ], - "role_id": -3, - "role_info_label": "View", - "role_info_summary": "Visibility access (cannot be granted)", - "role_name": "View", - "role_system": true - } - ] -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec - - -class VMwareLocalRoleFacts(PyVmomi): - """Class to manage local role facts""" - def __init__(self, module): - super(VMwareLocalRoleFacts, self).__init__(module) - self.module = module - self.params = module.params - - if self.content.authorizationManager is None: - self.module.fail_json( - msg="Failed to get local authorization manager settings.", - details="It seems that '%s' is a vCenter server instead of an ESXi server" % self.params['hostname'] - ) - - def gather_local_role_facts(self): - """Gather facts about local roles""" - results = list() - for role in self.content.authorizationManager.roleList: - results.append( - dict( - role_name=role.name, - role_id=role.roleId, - privileges=[priv_name for priv_name in role.privilege], - role_system=role.system, - role_info_label=role.info.label, - role_info_summary=role.info.summary, - ) - ) - - self.module.exit_json(changed=False, local_role_facts=results) - - -def main(): - """Main""" - argument_spec = vmware_argument_spec() - module = AnsibleModule(argument_spec=argument_spec, - supports_check_mode=True) - - vmware_local_role_facts = VMwareLocalRoleFacts(module) - vmware_local_role_facts.gather_local_role_facts() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/_vmware_local_user_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_local_user_facts.py deleted file mode 100644 index 2472a13748..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_local_user_facts.py +++ /dev/null @@ -1,177 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# 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': ['deprecated'], - 'supported_by': 'community' -} - - -DOCUMENTATION = ''' ---- -module: vmware_local_user_facts -deprecated: - removed_in: '2.13' - why: Deprecated in favour of C(_info) module. - alternative: Use M(vmware_local_user_info) instead. -short_description: Gather facts about users on the given ESXi host -description: - - This module can be used to gather facts about users present on the given ESXi host system in VMware infrastructure. - - All variables and VMware object names are case sensitive. - - User must hold the 'Authorization.ModifyPermissions' privilege to invoke this module. -version_added: "2.6" -author: -- Abhijeet Kasurde (@Akasurde) -- Christian Kotte (@ckotte) -notes: - - Tested on ESXi 6.5 - - The C(full_name), C(principal), and C(user_group) properties are deprecated starting from Ansible v2.12 -requirements: - - "python >= 2.6" - - PyVmomi -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather facts about all Users on given ESXi host system - vmware_local_user_facts: - hostname: '{{ esxi_hostname }}' - username: '{{ esxi_username }}' - password: '{{ esxi_password }}' - delegate_to: localhost - register: all_user_facts -''' - -RETURN = r''' -local_user_facts: - description: metadata about all local users - returned: always - type: dict - sample: [ - { - "role": "admin", - "description": "Administrator", - "full_name": "Administrator", - "group": false, - "user_group": false, - "user_id": 0, - "user_name": "root", - "principal": "root", - "shell_access": true - }, - { - "role": "admin", - "description": "DCUI User", - "full_name": "DCUI User", - "group": false, - "user_group": false, - "user_id": 100, - "user_name": "dcui", - "principal": "dcui", - "shell_access": false - }, - ] -''' - -try: - from pyVmomi import vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec -from ansible.module_utils._text import to_native - - -class VMwareUserFactsManager(PyVmomi): - """Class to manage local user facts""" - def __init__(self, module): - super(VMwareUserFactsManager, self).__init__(module) - - if self.is_vcenter(): - self.module.fail_json( - msg="Failed to get local account manager settings.", - details="It seems that '%s' is a vCenter server instead of an ESXi server" % self.module.params['hostname'] - ) - - def gather_user_facts(self): - """Gather facts about local users""" - results = dict(changed=False, local_user_facts=[]) - search_string = '' - exact_match = False - find_users = True - find_groups = False - user_accounts = self.content.userDirectory.RetrieveUserGroups( - None, search_string, None, None, exact_match, find_users, find_groups - ) - if user_accounts: - for user in user_accounts: - temp_user = dict() - # NOTE: the properties full_name, principal, and user_group are deprecated starting from Ansible v2.12 - temp_user['full_name'] = user.fullName - temp_user['principal'] = user.principal - temp_user['user_group'] = user.group - temp_user['user_name'] = user.principal - temp_user['description'] = user.fullName - temp_user['group'] = user.group - temp_user['user_id'] = user.id - temp_user['shell_access'] = user.shellAccess - temp_user['role'] = None - try: - permissions = self.content.authorizationManager.RetrieveEntityPermissions( - entity=self.content.rootFolder, - inherited=False - ) - except vmodl.fault.ManagedObjectNotFound as not_found: - self.module.fail_json( - msg="The entity doesn't exist" % to_native(not_found) - ) - for permission in permissions: - if permission.principal == user.principal: - temp_user['role'] = self.get_role_name(permission.roleId, self.content.authorizationManager.roleList) - break - - results['local_user_facts'].append(temp_user) - self.module.exit_json(**results) - - @staticmethod - def get_role_name(role_id, role_list): - """Get role name from role ID""" - role_name = None - # Default role: No access - if role_id == -5: - role_name = 'no-access' - # Default role: Read-only - elif role_id == -2: - role_name = 'read-only' - # Default role: Administrator - elif role_id == -1: - role_name = 'admin' - # Custom roles - else: - for role in role_list: - if role.roleId == role_id: - role_name = role.name - break - return role_name - - -def main(): - """Main""" - argument_spec = vmware_argument_spec() - module = AnsibleModule(argument_spec=argument_spec, - supports_check_mode=True) - vmware_local_user_facts = VMwareUserFactsManager(module) - vmware_local_user_facts.gather_user_facts() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/_vmware_portgroup_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_portgroup_facts.py deleted file mode 100644 index 3b2241a865..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_portgroup_facts.py +++ /dev/null @@ -1,234 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# 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': ['deprecated'], - 'supported_by': 'community' -} - -DOCUMENTATION = r''' ---- -module: vmware_portgroup_facts -deprecated: - removed_in: '2.13' - why: Deprecated in favour of C(_info) module. - alternative: Use M(vmware_portgroup_info) instead. -short_description: Gathers facts about an ESXi host's Port Group configuration -description: -- This module can be used to gather facts about an ESXi host's Port Group configuration when ESXi hostname or Cluster name is given. -version_added: '2.6' -author: -- Abhijeet Kasurde (@Akasurde) -- Christian Kotte (@ckotte) -notes: -- Tested on vSphere 6.5 -- The C(vswitch_name) property is deprecated starting from Ansible v2.12 -requirements: -- python >= 2.6 -- PyVmomi -options: - policies: - description: - - Gather facts about Security, Traffic Shaping, as well as Teaming and failover. - - The property C(ts) stands for Traffic Shaping and C(lb) for Load Balancing. - type: bool - default: false - version_added: 2.8 - cluster_name: - description: - - Name of the cluster. - - Facts will be returned for all hostsystem belonging to this cluster name. - - If C(esxi_hostname) is not given, this parameter is required. - type: str - esxi_hostname: - description: - - ESXi hostname to gather facts from. - - If C(cluster_name) is not given, this parameter is required. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather portgroup facts about all ESXi Host in given Cluster - vmware_portgroup_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: '{{ cluster_name }}' - delegate_to: localhost - -- name: Gather portgroup facts about ESXi Host system - vmware_portgroup_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - delegate_to: localhost -''' - -RETURN = r''' -hosts_portgroup_facts: - description: metadata about host's portgroup configuration - returned: on success - type: dict - sample: { - "esx01": [ - { - "failback": true, - "failover_active": ["vmnic0", "vmnic1"], - "failover_standby": [], - "failure_detection": "link_status_only", - "lb": "loadbalance_srcid", - "notify": true, - "portgroup": "Management Network", - "security": [false, false, false], - "ts": "No override", - "vlan_id": 0, - "vswitch": "vSwitch0", - "vswitch_name": "vSwitch0" - }, - { - "failback": true, - "failover_active": ["vmnic2"], - "failover_standby": ["vmnic3"], - "failure_detection": "No override", - "lb": "No override", - "notify": true, - "portgroup": "vMotion", - "security": [false, false, false], - "ts": "No override", - "vlan_id": 33, - "vswitch": "vSwitch1", - "vswitch_name": "vSwitch1" - } - ] - } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class PortgroupFactsManager(PyVmomi): - """Class to manage Port Group facts""" - def __init__(self, module): - super(PortgroupFactsManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - if not self.hosts: - self.module.fail_json(msg="Failed to find host system.") - self.policies = self.params.get('policies') - - @staticmethod - def normalize_pg_info(portgroup_obj, policy_facts): - """Create Port Group information""" - pg_info_dict = dict() - spec = portgroup_obj.spec - pg_info_dict['portgroup'] = spec.name - pg_info_dict['vlan_id'] = spec.vlanId - # NOTE: the property vswitch_name is deprecated starting from Ansible v2.12 - pg_info_dict['vswitch_name'] = spec.vswitchName - pg_info_dict['vswitch'] = spec.vswitchName - - if policy_facts: - # Security facts - if spec.policy.security: - promiscuous_mode = spec.policy.security.allowPromiscuous - mac_changes = spec.policy.security.macChanges - forged_transmits = spec.policy.security.forgedTransmits - pg_info_dict['security'] = ( - ["No override" if promiscuous_mode is None else promiscuous_mode, - "No override" if mac_changes is None else mac_changes, - "No override" if forged_transmits is None else forged_transmits] - ) - else: - pg_info_dict['security'] = ["No override", "No override", "No override"] - - # Traffic Shaping facts - if spec.policy.shapingPolicy and spec.policy.shapingPolicy.enabled is not None: - pg_info_dict['ts'] = portgroup_obj.spec.policy.shapingPolicy.enabled - else: - pg_info_dict['ts'] = "No override" - - # Teaming and failover facts - if spec.policy.nicTeaming: - if spec.policy.nicTeaming.policy is None: - pg_info_dict['lb'] = "No override" - else: - pg_info_dict['lb'] = spec.policy.nicTeaming.policy - if spec.policy.nicTeaming.notifySwitches is None: - pg_info_dict['notify'] = "No override" - else: - pg_info_dict['notify'] = spec.policy.nicTeaming.notifySwitches - if spec.policy.nicTeaming.rollingOrder is None: - pg_info_dict['failback'] = "No override" - else: - pg_info_dict['failback'] = not spec.policy.nicTeaming.rollingOrder - if spec.policy.nicTeaming.nicOrder is None: - pg_info_dict['failover_active'] = "No override" - pg_info_dict['failover_standby'] = "No override" - else: - pg_info_dict['failover_active'] = spec.policy.nicTeaming.nicOrder.activeNic - pg_info_dict['failover_standby'] = spec.policy.nicTeaming.nicOrder.standbyNic - if spec.policy.nicTeaming.failureCriteria and spec.policy.nicTeaming.failureCriteria.checkBeacon is None: - pg_info_dict['failure_detection'] = "No override" - else: - if spec.policy.nicTeaming.failureCriteria.checkBeacon: - pg_info_dict['failure_detection'] = "beacon_probing" - else: - pg_info_dict['failure_detection'] = "link_status_only" - else: - pg_info_dict['lb'] = "No override" - pg_info_dict['notify'] = "No override" - pg_info_dict['failback'] = "No override" - pg_info_dict['failover_active'] = "No override" - pg_info_dict['failover_standby'] = "No override" - pg_info_dict['failure_detection'] = "No override" - - return pg_info_dict - - def gather_host_portgroup_facts(self): - """Gather Port Group facts per ESXi host""" - hosts_pg_facts = dict() - for host in self.hosts: - pgs = host.config.network.portgroup - hosts_pg_facts[host.name] = [] - for portgroup in pgs: - hosts_pg_facts[host.name].append( - self.normalize_pg_info(portgroup_obj=portgroup, policy_facts=self.policies) - ) - return hosts_pg_facts - - -def main(): - """Main""" - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - policies=dict(type='bool', required=False, default=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True - ) - - host_pg_mgr = PortgroupFactsManager(module) - module.exit_json(changed=False, hosts_portgroup_facts=host_pg_mgr.gather_host_portgroup_facts()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/_vmware_resource_pool_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_resource_pool_facts.py deleted file mode 100644 index 3910aca82b..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_resource_pool_facts.py +++ /dev/null @@ -1,144 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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': ['deprecated'], - 'supported_by': 'community' -} - -DOCUMENTATION = r''' ---- -module: vmware_resource_pool_facts -deprecated: - removed_in: '2.13' - why: Deprecated in favour of C(_info) module. - alternative: Use M(vmware_resource_pool_info) instead. -short_description: Gathers facts about resource pool information -description: -- This module can be used to gather facts about all resource configuration information. -version_added: '2.6' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather resource pool facts about all resource pools available - vmware_resource_pool_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - register: rp_facts - delegate_to: localhost -''' - -RETURN = r''' -resource_pool_facts: - description: metadata about resource pool configuration - returned: on success - type: list - sample: [ - { - "cpu_allocation_expandable_reservation": false, - "cpu_allocation_limit": 4121, - "cpu_allocation_overhead_limit": null, - "cpu_allocation_reservation": 4121, - "cpu_allocation_shares": 9000, - "cpu_allocation_shares_level": "custom", - "mem_allocation_expandable_reservation": false, - "mem_allocation_limit": 961, - "mem_allocation_overhead_limit": null, - "mem_allocation_reservation": 961, - "mem_allocation_shares": 9000, - "mem_allocation_shares_level": "custom", - "name": "Resources", - "overall_status": "green", - "owner": "DC0_H0", - "runtime_cpu_max_usage": 4121, - "runtime_cpu_overall_usage": 0, - "runtime_cpu_reservation_used": 0, - "runtime_cpu_reservation_used_vm": 0, - "runtime_cpu_unreserved_for_pool": 4121, - "runtime_cpu_unreserved_for_vm": 4121, - "runtime_memory_max_usage": 1007681536, - "runtime_memory_overall_usage": 0, - "runtime_memory_reservation_used": 0, - "runtime_memory_reservation_used_vm": 0, - "runtime_memory_unreserved_for_pool": 1007681536, - "runtime_memory_unreserved_for_vm": 1007681536 - }, - ] -''' - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi, get_all_objs - - -class ResourcePoolFactsManager(PyVmomi): - def __init__(self, module): - super(ResourcePoolFactsManager, self).__init__(module) - - def gather_rp_facts(self): - resource_pool_facts = [] - rps = get_all_objs(self.content, [vim.ResourcePool]) - for rp in rps: - tmp_facts = dict( - name=rp.name, - cpu_allocation_reservation=rp.config.cpuAllocation.reservation, - cpu_allocation_expandable_reservation=rp.config.cpuAllocation.expandableReservation, - cpu_allocation_limit=rp.config.cpuAllocation.limit, - cpu_allocation_shares=rp.config.cpuAllocation.shares.shares, - cpu_allocation_shares_level=rp.config.cpuAllocation.shares.level, - cpu_allocation_overhead_limit=rp.config.cpuAllocation.overheadLimit, - mem_allocation_reservation=rp.config.memoryAllocation.reservation, - mem_allocation_expandable_reservation=rp.config.memoryAllocation.expandableReservation, - mem_allocation_limit=rp.config.memoryAllocation.limit, - mem_allocation_shares=rp.config.memoryAllocation.shares.shares, - mem_allocation_shares_level=rp.config.memoryAllocation.shares.level, - mem_allocation_overhead_limit=rp.config.memoryAllocation.overheadLimit, - owner=rp.owner.name, - overall_status=rp.summary.runtime.overallStatus, - runtime_cpu_reservation_used=rp.summary.runtime.cpu.reservationUsed, - runtime_cpu_reservation_used_vm=rp.summary.runtime.cpu.reservationUsedForVm, - runtime_cpu_unreserved_for_pool=rp.summary.runtime.cpu.unreservedForPool, - runtime_cpu_unreserved_for_vm=rp.summary.runtime.cpu.unreservedForVm, - runtime_cpu_overall_usage=rp.summary.runtime.cpu.overallUsage, - runtime_cpu_max_usage=rp.summary.runtime.cpu.maxUsage, - runtime_memory_reservation_used=rp.summary.runtime.memory.reservationUsed, - runtime_memory_reservation_used_vm=rp.summary.runtime.memory.reservationUsedForVm, - runtime_memory_unreserved_for_pool=rp.summary.runtime.memory.unreservedForPool, - runtime_memory_unreserved_for_vm=rp.summary.runtime.memory.unreservedForVm, - runtime_memory_overall_usage=rp.summary.runtime.memory.overallUsage, - runtime_memory_max_usage=rp.summary.runtime.memory.maxUsage, - ) - - resource_pool_facts.append(tmp_facts) - return resource_pool_facts - - -def main(): - argument_spec = vmware_argument_spec() - module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) - - vmware_rp_mgr = ResourcePoolFactsManager(module) - module.exit_json(changed=False, resource_pool_facts=vmware_rp_mgr.gather_rp_facts()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/_vmware_tag_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_tag_facts.py deleted file mode 120000 index ad7e745e83..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_tag_facts.py +++ /dev/null @@ -1 +0,0 @@ -vmware_tag_info.py
\ No newline at end of file diff --git a/lib/ansible/modules/cloud/vmware/_vmware_target_canonical_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_target_canonical_facts.py deleted file mode 100644 index 629c8e82ee..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_target_canonical_facts.py +++ /dev/null @@ -1,189 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2015, Joseph Callen <jcallen () csc.com> -# Copyright: (c) 2018, Ansible Project -# 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': ['deprecated'], - 'supported_by': 'community' -} - -DOCUMENTATION = ''' ---- -module: vmware_target_canonical_facts -deprecated: - removed_in: '2.13' - why: Deprecated in favour of C(_info) module. - alternative: Use M(vmware_target_canonical_info) instead. -short_description: Return canonical (NAA) from an ESXi host system -description: - - This module can be used to gather facts about canonical (NAA) from an ESXi host based on SCSI target ID. - -version_added: "2.0" -author: -- Joseph Callen (@jcpowermac) -- Abhijeet Kasurde (@Akasurde) -notes: -requirements: - - Tested on vSphere 5.5 and 6.5 - - PyVmomi installed -options: - target_id: - description: - - The target id based on order of scsi device. - - version 2.6 onwards, this parameter is optional. - required: False - type: int - cluster_name: - description: - - Name of the cluster. - - Facts about all SCSI devices for all host system in the given cluster is returned. - - This parameter is required, if C(esxi_hostname) is not provided. - version_added: 2.6 - type: str - esxi_hostname: - description: - - Name of the ESXi host system. - - Facts about all SCSI devices for the given ESXi host system is returned. - - This parameter is required, if C(cluster_name) is not provided. - version_added: 2.6 - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Get Canonical name of particular target on particular ESXi host system - vmware_target_canonical_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - target_id: 7 - esxi_hostname: esxi_hostname - delegate_to: localhost - -- name: Get Canonical name of all target on particular ESXi host system - vmware_target_canonical_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - delegate_to: localhost - -- name: Get Canonical name of all ESXi hostname on particular Cluster - vmware_target_canonical_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: '{{ cluster_name }}' - delegate_to: localhost -''' - -RETURN = r""" -canonical: - description: metadata about SCSI Target device - returned: if host system and target id is given - type: str - sample: "mpx.vmhba0:C0:T0:L0" - -scsi_tgt_facts: - description: metadata about all SCSI Target devices - returned: if host system or cluster is given - type: dict - sample: { - "DC0_C0_H0": { - "scsilun_canonical": { - "key-vim.host.ScsiDisk-0000000000766d686261303a303a30": "mpx.vmhba0:C0:T0:L0", - "key-vim.host.ScsiLun-0005000000766d686261313a303a30": "mpx.vmhba1:C0:T0:L0" - }, - "target_lun_uuid": { - "0": "key-vim.host.ScsiDisk-0000000000766d686261303a303a30" - } - }, - "DC0_C0_H1": { - "scsilun_canonical": { - "key-vim.host.ScsiDisk-0000000000766d686261303a303a30": "mpx.vmhba0:C0:T0:L0", - "key-vim.host.ScsiLun-0005000000766d686261313a303a30": "mpx.vmhba1:C0:T0:L0" - }, - "target_lun_uuid": { - "0": "key-vim.host.ScsiDisk-0000000000766d686261303a303a30" - } - }, - } -""" - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec - - -class ScsiTargetFactsManager(PyVmomi): - def __init__(self, module): - super(ScsiTargetFactsManager, self).__init__(module) - cluster_name = self.module.params.get('cluster_name') - self.esxi_hostname = self.module.params.get('esxi_hostname') - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=self.esxi_hostname) - - def gather_scsi_device_facts(self): - """ - Function to gather facts about SCSI target devices - - """ - scsi_tgt_facts = {} - target_lun_uuid = {} - scsilun_canonical = {} - target_id = self.module.params['target_id'] - - for host in self.hosts: - # Associate the scsiLun key with the canonicalName (NAA) - for scsilun in host.config.storageDevice.scsiLun: - scsilun_canonical[scsilun.key] = scsilun.canonicalName - - # Associate target number with LUN uuid - for target in host.config.storageDevice.scsiTopology.adapter[0].target: - for lun in target.lun: - target_lun_uuid[target.target] = lun.scsiLun - - scsi_tgt_facts[host.name] = dict(scsilun_canonical=scsilun_canonical, - target_lun_uuid=target_lun_uuid) - - if target_id is not None and self.esxi_hostname is not None: - canonical = '' - temp_lun_data = scsi_tgt_facts[self.esxi_hostname]['target_lun_uuid'] - if self.esxi_hostname in scsi_tgt_facts and \ - target_id in temp_lun_data: - temp_scsi_data = scsi_tgt_facts[self.esxi_hostname]['scsilun_canonical'] - temp_target = temp_lun_data[target_id] - canonical = temp_scsi_data[temp_target] - self.module.exit_json(changed=False, canonical=canonical) - - self.module.exit_json(changed=False, scsi_tgt_facts=scsi_tgt_facts) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - dict( - target_id=dict(required=False, type='int'), - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - ) - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True, - ) - - scsi_tgt_manager = ScsiTargetFactsManager(module) - scsi_tgt_manager.gather_scsi_device_facts() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/_vmware_vm_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_vm_facts.py deleted file mode 120000 index abde079024..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_vm_facts.py +++ /dev/null @@ -1 +0,0 @@ -vmware_vm_info.py
\ No newline at end of file diff --git a/lib/ansible/modules/cloud/vmware/_vmware_vmkernel_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_vmkernel_facts.py deleted file mode 100644 index 985f5f3344..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_vmkernel_facts.py +++ /dev/null @@ -1,207 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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': ['deprecated'], - 'supported_by': 'community' -} - -DOCUMENTATION = r''' ---- -module: vmware_vmkernel_facts -deprecated: - removed_in: '2.13' - why: Deprecated in favour of C(_info) module. - alternative: Use M(vmware_vmkernel_info) instead. -short_description: Gathers VMKernel facts about an ESXi host -description: -- This module can be used to gather VMKernel facts about an ESXi host from given ESXi hostname or cluster name. -version_added: '2.5' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of the cluster. - - VMKernel facts about each ESXi server will be returned for the given cluster. - - If C(esxi_hostname) is not given, this parameter is required. - type: str - esxi_hostname: - description: - - ESXi hostname. - - VMKernel facts about this ESXi server will be returned. - - If C(cluster_name) is not given, this parameter is required. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather VMKernel facts about all ESXi Host in given Cluster - vmware_vmkernel_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: cluster_name - delegate_to: localhost - register: cluster_host_vmks - -- name: Gather VMKernel facts about ESXi Host - vmware_vmkernel_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - delegate_to: localhost - register: host_vmks -''' - -RETURN = r''' -host_vmk_facts: - description: metadata about VMKernel present on given host system - returned: success - type: dict - sample: - { - "10.76.33.208": [ - { - "device": "vmk0", - "dhcp": true, - "enable_ft": false, - "enable_management": true, - "enable_vmotion": false, - "enable_vsan": false, - "ipv4_address": "10.76.33.28", - "ipv4_subnet_mask": "255.255.255.0", - "key": "key-vim.host.VirtualNic-vmk0", - "mac": "52:54:00:12:50:ce", - "mtu": 1500, - "portgroup": "Management Network", - "stack": "defaultTcpipStack" - }, - ] - } - -''' - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi -from ansible.module_utils._text import to_native - - -class VmkernelFactsManager(PyVmomi): - def __init__(self, module): - super(VmkernelFactsManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - self.service_type_vmks = dict() - self.get_all_vmks_by_service_type() - - def get_all_vmks_by_service_type(self): - """ - Function to return information about service types and VMKernel - - """ - for host in self.hosts: - self.service_type_vmks[host.name] = dict(vmotion=[], vsan=[], management=[], faultToleranceLogging=[]) - for service_type in self.service_type_vmks[host.name].keys(): - vmks_list = self.query_service_type_for_vmks(host, service_type) - self.service_type_vmks[host.name][service_type] = vmks_list - - def query_service_type_for_vmks(self, host_system, service_type): - """ - Function to return list of VMKernels - Args: - host_system: Host system managed object - service_type: Name of service type - - Returns: List of VMKernel which belongs to that service type - - """ - vmks_list = [] - query = None - try: - query = host_system.configManager.virtualNicManager.QueryNetConfig(service_type) - except vim.fault.HostConfigFault as config_fault: - self.module.fail_json(msg="Failed to get all VMKs for service type %s due to" - " host config fault : %s" % (service_type, to_native(config_fault.msg))) - except vmodl.fault.InvalidArgument as invalid_argument: - self.module.fail_json(msg="Failed to get all VMKs for service type %s due to" - " invalid arguments : %s" % (service_type, to_native(invalid_argument.msg))) - except Exception as e: - self.module.fail_json(msg="Failed to get all VMKs for service type %s due to" - "%s" % (service_type, to_native(e))) - - if not query.selectedVnic: - return vmks_list - selected_vnics = [vnic for vnic in query.selectedVnic] - vnics_with_service_type = [vnic.device for vnic in query.candidateVnic if vnic.key in selected_vnics] - return vnics_with_service_type - - def gather_host_vmk_facts(self): - hosts_facts = {} - - for host in self.hosts: - host_vmk_facts = [] - host_network_system = host.config.network - if host_network_system: - vmks_config = host.config.network.vnic - for vmk in vmks_config: - host_vmk_facts.append(dict( - device=vmk.device, - key=vmk.key, - portgroup=vmk.portgroup, - ipv4_address=vmk.spec.ip.ipAddress, - ipv4_subnet_mask=vmk.spec.ip.subnetMask, - dhcp=vmk.spec.ip.dhcp, - mac=vmk.spec.mac, - mtu=vmk.spec.mtu, - stack=vmk.spec.netStackInstanceKey, - enable_vsan=vmk.device in self.service_type_vmks[host.name]['vsan'], - enable_vmotion=vmk.device in self.service_type_vmks[host.name]['vmotion'], - enable_management=vmk.device in self.service_type_vmks[host.name]['management'], - enable_ft=vmk.device in self.service_type_vmks[host.name]['faultToleranceLogging'], - ) - ) - hosts_facts[host.name] = host_vmk_facts - return hosts_facts - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True - ) - - vmware_vmk_config = VmkernelFactsManager(module) - module.exit_json(changed=False, host_vmk_facts=vmware_vmk_config.gather_host_vmk_facts()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/_vmware_vswitch_facts.py b/lib/ansible/modules/cloud/vmware/_vmware_vswitch_facts.py deleted file mode 100644 index eef3e7070c..0000000000 --- a/lib/ansible/modules/cloud/vmware/_vmware_vswitch_facts.py +++ /dev/null @@ -1,161 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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': ['deprecated'], - 'supported_by': 'community' -} - -DOCUMENTATION = r''' ---- -module: vmware_vswitch_facts -deprecated: - removed_in: '2.13' - why: Deprecated in favour of C(_info) module. - alternative: Use M(vmware_vswitch_info) instead. -short_description: Gathers facts about an ESXi host's vswitch configurations -description: -- This module can be used to gather facts about an ESXi host's vswitch configurations when ESXi hostname or Cluster name is given. -- The vSphere Client shows the value for the number of ports as elastic from vSphere 5.5 and above. -- Other tools like esxcli might show the number of ports as 1536 or 5632. -- See U(https://kb.vmware.com/s/article/2064511) for more details. -version_added: '2.6' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of the cluster. - - Facts about vswitch belonging to every ESXi host systems under this cluster will be returned. - - If C(esxi_hostname) is not given, this parameter is required. - type: str - esxi_hostname: - description: - - ESXi hostname to gather facts from. - - If C(cluster_name) is not given, this parameter is required. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather vswitch facts about all ESXi Host in given Cluster - vmware_vswitch_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: '{{ cluster_name }}' - delegate_to: localhost - register: all_hosts_vswitch_facts - -- name: Gather firewall facts about ESXi Host - vmware_vswitch_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - delegate_to: localhost - register: all_vswitch_facts -''' - -RETURN = r''' -hosts_vswitch_facts: - description: metadata about host's vswitch configuration - returned: on success - type: dict - sample: { - "10.76.33.218": { - "vSwitch0": { - "mtu": 1500, - "num_ports": 128, - "pnics": [ - "vmnic0" - ] - }, - "vSwitch_0011": { - "mtu": 1500, - "num_ports": 128, - "pnics": [ - "vmnic2", - "vmnic1" - ] - }, - }, - } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class VswitchFactsManager(PyVmomi): - """Class to gather vSwitch facts""" - def __init__(self, module): - super(VswitchFactsManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - if not self.hosts: - self.module.fail_json(msg="Failed to find host system.") - - @staticmethod - def serialize_pnics(vswitch_obj): - """Get pnic names""" - pnics = [] - for pnic in vswitch_obj.pnic: - # vSwitch contains all PNICs as string in format of 'key-vim.host.PhysicalNic-vmnic0' - pnics.append(pnic.split("-", 3)[-1]) - return pnics - - def gather_vswitch_facts(self): - """Gather vSwitch facts""" - hosts_vswitch_facts = dict() - for host in self.hosts: - network_manager = host.configManager.networkSystem - if network_manager: - temp_switch_dict = dict() - for available_vswitch in network_manager.networkInfo.vswitch: - temp_switch_dict[available_vswitch.name] = dict( - pnics=self.serialize_pnics(available_vswitch), - mtu=available_vswitch.mtu, - # we need to use the spec to get the ports - # otherwise, the output might be different compared to the vswitch config module - # (e.g. 5632 ports instead of 128) - num_ports=available_vswitch.spec.numPorts - ) - hosts_vswitch_facts[host.name] = temp_switch_dict - return hosts_vswitch_facts - - -def main(): - """Main""" - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True - ) - - vmware_vswitch_mgr = VswitchFactsManager(module) - module.exit_json(changed=False, hosts_vswitch_facts=vmware_vswitch_mgr.gather_vswitch_facts()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vca_fw.py b/lib/ansible/modules/cloud/vmware/vca_fw.py deleted file mode 100644 index 22acd4957f..0000000000 --- a/lib/ansible/modules/cloud/vmware/vca_fw.py +++ /dev/null @@ -1,247 +0,0 @@ -#!/usr/bin/python - -# Copyright: (c) 2015, VMware, Inc. All Rights Reserved. -# 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 = ''' ---- -module: vca_fw -short_description: add remove firewall rules in a gateway in a vca -description: - - Adds or removes firewall rules from a gateway in a vca environment -version_added: "2.0" -author: -- Peter Sprygada (@privateip) -options: - fw_rules: - description: - - A list of firewall rules to be added to the gateway, Please see examples on valid entries - required: True - default: false -extends_documentation_fragment: vca.documentation -''' - -EXAMPLES = ''' - -#Add a set of firewall rules - -- hosts: localhost - connection: local - tasks: - - vca_fw: - instance_id: 'b15ff1e5-1024-4f55-889f-ea0209726282' - vdc_name: 'benz_ansible' - state: 'absent' - fw_rules: - - description: "ben testing" - source_ip: "Any" - dest_ip: 192.0.2.23 - - description: "ben testing 2" - source_ip: 192.0.2.50 - source_port: "Any" - dest_port: "22" - dest_ip: 192.0.2.101 - is_enable: "true" - enable_logging: "false" - protocol: "Tcp" - policy: "allow" - -''' - -try: - from pyvcloud.schema.vcd.v1_5.schemas.vcloud.networkType import FirewallRuleType - from pyvcloud.schema.vcd.v1_5.schemas.vcloud.networkType import ProtocolsType -except ImportError: - # normally set a flag here but it will be caught when testing for - # the existence of pyvcloud (see module_utils/vca.py). This just - # protects against generating an exception at runtime - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vca import VcaError, vca_argument_spec, vca_login - - -VALID_PROTO = ['Tcp', 'Udp', 'Icmp', 'Other', 'Any'] -VALID_RULE_KEYS = ['policy', 'is_enable', 'enable_logging', 'description', - 'dest_ip', 'dest_port', 'source_ip', 'source_port', - 'protocol'] - - -def protocol_to_tuple(protocol): - return (protocol.get_Tcp(), - protocol.get_Udp(), - protocol.get_Icmp(), - protocol.get_Other(), - protocol.get_Any()) - - -def protocol_to_string(protocol): - protocol = protocol_to_tuple(protocol) - if protocol[0] is True: - return 'Tcp' - elif protocol[1] is True: - return 'Udp' - elif protocol[2] is True: - return 'Icmp' - elif protocol[3] is True: - return 'Other' - elif protocol[4] is True: - return 'Any' - - -def protocol_to_type(protocol): - try: - protocols = ProtocolsType() - setattr(protocols, protocol, True) - return protocols - except AttributeError: - raise VcaError("The value in protocol is not valid") - - -def validate_fw_rules(fw_rules): - for rule in fw_rules: - for k in rule.keys(): - if k not in VALID_RULE_KEYS: - raise VcaError("%s is not a valid key in fw rules, please " - "check above.." % k, valid_keys=VALID_RULE_KEYS) - - rule['dest_port'] = str(rule.get('dest_port', 'Any')).lower() - rule['dest_ip'] = rule.get('dest_ip', 'Any').lower() - rule['source_port'] = str(rule.get('source_port', 'Any')).lower() - rule['source_ip'] = rule.get('source_ip', 'Any').lower() - rule['protocol'] = rule.get('protocol', 'Any').lower() - rule['policy'] = rule.get('policy', 'allow').lower() - rule['is_enable'] = rule.get('is_enable', True) - rule['enable_logging'] = rule.get('enable_logging', False) - rule['description'] = rule.get('description', 'rule added by Ansible') - - return fw_rules - - -def fw_rules_to_dict(rules): - fw_rules = list() - for rule in rules: - fw_rules.append( - dict( - dest_port=rule.get_DestinationPortRange().lower(), - dest_ip=rule.get_DestinationIp().lower().lower(), - source_port=rule.get_SourcePortRange().lower(), - source_ip=rule.get_SourceIp().lower(), - protocol=protocol_to_string(rule.get_Protocols()).lower(), - policy=rule.get_Policy().lower(), - is_enable=rule.get_IsEnabled(), - enable_logging=rule.get_EnableLogging(), - description=rule.get_Description() - ) - ) - return fw_rules - - -def create_fw_rule(is_enable, description, policy, protocol, dest_port, - dest_ip, source_port, source_ip, enable_logging): - - return FirewallRuleType(IsEnabled=is_enable, - Description=description, - Policy=policy, - Protocols=protocol_to_type(protocol), - DestinationPortRange=dest_port, - DestinationIp=dest_ip, - SourcePortRange=source_port, - SourceIp=source_ip, - EnableLogging=enable_logging) - - -def main(): - argument_spec = vca_argument_spec() - argument_spec.update( - dict( - fw_rules=dict(required=True, type='list'), - gateway_name=dict(default='gateway'), - state=dict(default='present', choices=['present', 'absent']) - ) - ) - - module = AnsibleModule(argument_spec, supports_check_mode=True) - - fw_rules = module.params.get('fw_rules') - gateway_name = module.params.get('gateway_name') - vdc_name = module.params['vdc_name'] - - vca = vca_login(module) - - gateway = vca.get_gateway(vdc_name, gateway_name) - if not gateway: - module.fail_json(msg="Not able to find the gateway %s, please check " - "the gateway_name param" % gateway_name) - - fwservice = gateway._getFirewallService() - - rules = gateway.get_fw_rules() - current_rules = fw_rules_to_dict(rules) - - try: - desired_rules = validate_fw_rules(fw_rules) - except VcaError as e: - module.fail_json(msg=e.message) - - result = dict(changed=False) - result['current_rules'] = current_rules - result['desired_rules'] = desired_rules - - updates = list() - additions = list() - deletions = list() - - for (index, rule) in enumerate(desired_rules): - try: - if rule != current_rules[index]: - updates.append((index, rule)) - except IndexError: - additions.append(rule) - - eol = len(current_rules) - len(desired_rules) - if eol > 0: - for rule in current_rules[eol:]: - deletions.append(rule) - - for rule in additions: - if not module.check_mode: - rule['protocol'] = rule['protocol'].capitalize() - gateway.add_fw_rule(**rule) - result['changed'] = True - - for index, rule in updates: - if not module.check_mode: - rule = create_fw_rule(**rule) - fwservice.replace_FirewallRule_at(index, rule) - result['changed'] = True - - keys = ['protocol', 'dest_port', 'dest_ip', 'source_port', 'source_ip'] - for rule in deletions: - if not module.check_mode: - kwargs = dict([(k, v) for k, v in rule.items() if k in keys]) - kwargs['protocol'] = protocol_to_string(kwargs['protocol']) - gateway.delete_fw_rule(**kwargs) - result['changed'] = True - - if not module.check_mode and result['changed'] is True: - task = gateway.save_services_configuration() - if task: - vca.block_until_completed(task) - - result['rules_updated'] = len(updates) - result['rules_added'] = len(additions) - result['rules_deleted'] = len(deletions) - - return module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vca_nat.py b/lib/ansible/modules/cloud/vmware/vca_nat.py deleted file mode 100644 index 3155a0edf9..0000000000 --- a/lib/ansible/modules/cloud/vmware/vca_nat.py +++ /dev/null @@ -1,205 +0,0 @@ -#!/usr/bin/python - -# Copyright: (c) 2015, VMware, Inc. All Rights Reserved. -# 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 = ''' ---- -module: vca_nat -short_description: add remove nat rules in a gateway in a vca -description: - - Adds or removes nat rules from a gateway in a vca environment -version_added: "2.0" -author: Peter Sprygada (@privateip) -options: - purge_rules: - description: - - If set to true, it will delete all rules in the gateway that are not given as parameter to this module. - type: bool - default: false - nat_rules: - description: - - A list of rules to be added to the gateway, Please see examples on valid entries - required: True - default: false -extends_documentation_fragment: vca.documentation -''' - -EXAMPLES = ''' - -#An example for a source nat - -- hosts: localhost - connection: local - tasks: - - vca_nat: - instance_id: 'b15ff1e5-1024-4f55-889f-ea0209726282' - vdc_name: 'benz_ansible' - state: 'present' - nat_rules: - - rule_type: SNAT - original_ip: 192.0.2.42 - translated_ip: 203.0.113.23 - -#example for a DNAT -- hosts: localhost - connection: local - tasks: - - vca_nat: - instance_id: 'b15ff1e5-1024-4f55-889f-ea0209726282' - vdc_name: 'benz_ansible' - state: 'present' - nat_rules: - - rule_type: DNAT - original_ip: 203.0.113.23 - original_port: 22 - translated_ip: 192.0.2.42 - translated_port: 22 - -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vca import VcaError, vca_argument_spec, vca_login - - -VALID_RULE_KEYS = ['rule_type', 'original_ip', 'original_port', - 'translated_ip', 'translated_port', 'protocol'] - - -def validate_nat_rules(nat_rules): - for rule in nat_rules: - if not isinstance(rule, dict): - raise VcaError("nat rules must be a list of dictionaries, " - "Please check", valid_keys=VALID_RULE_KEYS) - - for k in rule.keys(): - if k not in VALID_RULE_KEYS: - raise VcaError("%s is not a valid key in nat rules, please " - "check above.." % k, valid_keys=VALID_RULE_KEYS) - - rule['original_port'] = str(rule.get('original_port', 'any')).lower() - rule['original_ip'] = rule.get('original_ip', 'any').lower() - rule['translated_ip'] = rule.get('translated_ip', 'any').lower() - rule['translated_port'] = str(rule.get('translated_port', 'any')).lower() - rule['protocol'] = rule.get('protocol', 'any').lower() - rule['rule_type'] = rule.get('rule_type', 'DNAT').lower() - - return nat_rules - - -def nat_rules_to_dict(nat_rules): - result = [] - for rule in nat_rules: - gw_rule = rule.get_GatewayNatRule() - result.append( - dict( - rule_type=rule.get_RuleType().lower(), - original_ip=gw_rule.get_OriginalIp().lower(), - original_port=(gw_rule.get_OriginalPort().lower() or 'any'), - translated_ip=gw_rule.get_TranslatedIp().lower(), - translated_port=(gw_rule.get_TranslatedPort().lower() or 'any'), - protocol=(gw_rule.get_Protocol().lower() or 'any') - ) - ) - return result - - -def rule_to_string(rule): - strings = list() - for key, value in rule.items(): - strings.append('%s=%s' % (key, value)) - return ', '.join(strings) - - -def main(): - argument_spec = vca_argument_spec() - argument_spec.update( - dict( - nat_rules=dict(type='list', default=[]), - gateway_name=dict(default='gateway'), - purge_rules=dict(default=False, type='bool'), - state=dict(default='present', choices=['present', 'absent']) - ) - ) - - module = AnsibleModule(argument_spec, supports_check_mode=True) - - vdc_name = module.params.get('vdc_name') - nat_rules = module.params['nat_rules'] - gateway_name = module.params['gateway_name'] - purge_rules = module.params['purge_rules'] - - if not purge_rules and not nat_rules: - module.fail_json(msg='Must define purge_rules or nat_rules') - - vca = vca_login(module) - - gateway = vca.get_gateway(vdc_name, gateway_name) - if not gateway: - module.fail_json(msg="Not able to find the gateway %s, please check " - "the gateway_name param" % gateway_name) - - try: - desired_rules = validate_nat_rules(nat_rules) - except VcaError as e: - module.fail_json(msg=e.message) - - rules = gateway.get_nat_rules() - - result = dict(changed=False, rules_purged=0) - - deletions = 0 - additions = 0 - - if purge_rules is True and len(rules) > 0: - result['rules_purged'] = len(rules) - deletions = result['rules_purged'] - rules = list() - if not module.check_mode: - gateway.del_all_nat_rules() - task = gateway.save_services_configuration() - vca.block_until_completed(task) - rules = gateway.get_nat_rules() - result['changed'] = True - - current_rules = nat_rules_to_dict(rules) - - result['current_rules'] = current_rules - result['desired_rules'] = desired_rules - - for rule in desired_rules: - if rule not in current_rules: - additions += 1 - if not module.check_mode: - gateway.add_nat_rule(**rule) - result['changed'] = True - result['rules_added'] = additions - - result['delete_rule'] = list() - result['delete_rule_rc'] = list() - for rule in current_rules: - if rule not in desired_rules: - deletions += 1 - if not module.check_mode: - result['delete_rule'].append(rule) - rc = gateway.del_nat_rule(**rule) - result['delete_rule_rc'].append(rc) - result['changed'] = True - result['rules_deleted'] = deletions - - if not module.check_mode and (additions > 0 or deletions > 0): - task = gateway.save_services_configuration() - vca.block_until_completed(task) - - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vca_vapp.py b/lib/ansible/modules/cloud/vmware/vca_vapp.py deleted file mode 100644 index 01a9dc7e9d..0000000000 --- a/lib/ansible/modules/cloud/vmware/vca_vapp.py +++ /dev/null @@ -1,351 +0,0 @@ -#!/usr/bin/python -# Copyright: (c) 2015, Ansible, Inc. -# 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 = ''' ---- -module: vca_vapp -short_description: Manages vCloud Air vApp instances. -description: - - This module will actively managed vCloud Air vApp instances. Instances - can be created and deleted as well as both deployed and undeployed. -version_added: "2.0" -author: -- Peter Sprygada (@privateip) -notes: -- VMware sold their vCloud Air service in Q2 2017. -- VMware made significant changes to the pyvcloud interface around this time. The C(vca_vapp) module relies on now deprecated code. -- Mileage with C(vca_vapp) may vary as vCloud Director APIs advance. -- A viable alternative maybe U(https://github.com/vmware/ansible-module-vcloud-director) -requirements: -- pyvcloud <= 18.2.2 -options: - vapp_name: - description: - - The name of the vCloud Air vApp instance - required: yes - template_name: - description: - - The name of the vApp template to use to create the vApp instance. If - the I(state) is not `absent` then the I(template_name) value must be - provided. The I(template_name) must be previously uploaded to the - catalog specified by I(catalog_name) - network_name: - description: - - The name of the network that should be attached to the virtual machine - in the vApp. The virtual network specified must already be created in - the vCloud Air VDC. If the I(state) is not 'absent' then the - I(network_name) argument must be provided. - network_mode: - description: - - Configures the mode of the network connection. - default: pool - choices: ['pool', 'dhcp', 'static'] - vm_name: - description: - - The name of the virtual machine instance in the vApp to manage. - vm_cpus: - description: - - The number of vCPUs to configure for the VM in the vApp. If the - I(vm_name) argument is provided, then this becomes a per VM setting - otherwise it is applied to all VMs in the vApp. - vm_memory: - description: - - The amount of memory in MB to allocate to VMs in the vApp. If the - I(vm_name) argument is provided, then this becomes a per VM setting - otherwise it is applied to all VMs in the vApp. - operation: - description: - - Specifies an operation to be performed on the vApp. - default: noop - choices: ['noop', 'poweron', 'poweroff', 'suspend', 'shutdown', 'reboot', 'reset'] - state: - description: - - Configures the state of the vApp. - default: present - choices: ['present', 'absent', 'deployed', 'undeployed'] - username: - description: - - The vCloud Air username to use during authentication - password: - description: - - The vCloud Air password to use during authentication - org: - description: - - The org to login to for creating vapp, mostly set when the service_type is vdc. - instance_id: - description: - - The instance id in a vchs environment to be used for creating the vapp - host: - description: - - The authentication host to be used when service type is vcd. - api_version: - description: - - The api version to be used with the vca - default: "5.7" - service_type: - description: - - The type of service we are authenticating against - default: vca - choices: [ "vca", "vchs", "vcd" ] - vdc_name: - description: - - The name of the virtual data center (VDC) where the vm should be created or contains the vAPP. -extends_documentation_fragment: vca -''' - -EXAMPLES = ''' -- name: Creates a new vApp in a VCA instance - vca_vapp: - vapp_name: tower - state: present - template_name: 'Ubuntu Server 12.04 LTS (amd64 20150127)' - vdc_name: VDC1 - instance_id: '<your instance id here>' - username: '<your username here>' - password: '<your password here>' - delegate_to: localhost -''' - -from ansible.module_utils.vca import VcaAnsibleModule, VcaError - -DEFAULT_VAPP_OPERATION = 'noop' - -VAPP_STATUS = { - 'Powered off': 'poweroff', - 'Powered on': 'poweron', - 'Suspended': 'suspend' -} - -VAPP_STATES = ['present', 'absent', 'deployed', 'undeployed'] -VAPP_OPERATIONS = ['poweron', 'poweroff', 'suspend', 'shutdown', - 'reboot', 'reset', 'noop'] - - -def get_instance(module): - vapp_name = module.params['vapp_name'] - inst = dict(vapp_name=vapp_name, state='absent') - try: - vapp = module.get_vapp(vapp_name) - if vapp: - status = module.vca.get_status(vapp.me.get_status()) - inst['status'] = VAPP_STATUS.get(status, 'unknown') - inst['state'] = 'deployed' if vapp.me.deployed else 'undeployed' - return inst - except VcaError: - return inst - - -def create(module): - vdc_name = module.params['vdc_name'] - vapp_name = module.params['vapp_name'] - template_name = module.params['template_name'] - catalog_name = module.params['catalog_name'] - network_name = module.params['network_name'] - network_mode = module.params['network_mode'] - vm_name = module.params['vm_name'] - vm_cpus = module.params['vm_cpus'] - vm_memory = module.params['vm_memory'] - deploy = module.params['state'] == 'deploy' - poweron = module.params['operation'] == 'poweron' - - task = module.vca.create_vapp(vdc_name, vapp_name, template_name, - catalog_name, network_name, 'bridged', - vm_name, vm_cpus, vm_memory, deploy, poweron) - - if task is False: - module.fail('Failed to create vapp: %s' % vapp_name) - - module.vca.block_until_completed(task) - - # Connect the network to the Vapp/VM and return assigned IP - if network_name is not None: - vm_ip = connect_to_network(module, vdc_name, vapp_name, network_name, network_mode) - return vm_ip - - -def delete(module): - vdc_name = module.params['vdc_name'] - vapp_name = module.params['vapp_name'] - module.vca.delete_vapp(vdc_name, vapp_name) - - -def do_operation(module): - vapp_name = module.params['vapp_name'] - operation = module.params['operation'] - - vm_name = module.params.get('vm_name') - vm = None - if vm_name: - vm = module.get_vm(vapp_name, vm_name) - - if operation == 'poweron': - operation = 'powerOn' - elif operation == 'poweroff': - operation = 'powerOff' - - cmd = 'power:%s' % operation - module.get_vapp(vapp_name).execute(cmd, 'post', targetVM=vm) - - -def set_state(module): - state = module.params['state'] - vapp = module.get_vapp(module.params['vapp_name']) - if state == 'deployed': - action = module.params['operation'] == 'poweron' - if not vapp.deploy(action): - module.fail('unable to deploy vapp') - elif state == 'undeployed': - action = module.params['operation'] - if action == 'poweroff': - action = 'powerOff' - elif action != 'suspend': - action = None - if not vapp.undeploy(action): - module.fail('unable to undeploy vapp') - - -def connect_to_network(module, vdc_name, vapp_name, network_name, network_mode): - nets = filter(lambda n: n.name == network_name, module.vca.get_networks(vdc_name)) - if len(nets) != 1: - module.fail_json("Unable to find network %s " % network_name) - - the_vdc = module.vca.get_vdc(vdc_name) - the_vapp = module.vca.get_vapp(the_vdc, vapp_name) - - if the_vapp and the_vapp.name != vapp_name: - module.fail_json(msg="Failed to find vapp named %s" % the_vapp.name) - - # Connect vApp - task = the_vapp.connect_to_network(nets[0].name, nets[0].href) - result = module.vca.block_until_completed(task) - - if result is None: - module.fail_json(msg="Failed to complete task") - - # Connect VM - ip_allocation_mode = None - if network_mode == 'pool': - ip_allocation_mode = 'POOL' - elif network_mode == 'dhcp': - ip_allocation_mode = 'DHCP' - - task = the_vapp.connect_vms(nets[0].name, connection_index=0, ip_allocation_mode=ip_allocation_mode) - if result is None: - module.fail_json(msg="Failed to complete task") - - result = module.vca.block_until_completed(task) - if result is None: - module.fail_json(msg="Failed to complete task") - - # Update VApp info and get VM IP - the_vapp = module.vca.get_vapp(the_vdc, vapp_name) - if the_vapp is None: - module.fail_json(msg="Failed to get vapp named %s" % vapp_name) - - return get_vm_details(module) - - -def get_vm_details(module): - vdc_name = module.params['vdc_name'] - vapp_name = module.params['vapp_name'] - vm_name = module.params['vm_name'] - the_vdc = module.vca.get_vdc(vdc_name) - the_vapp = module.vca.get_vapp(the_vdc, vapp_name) - if the_vapp and the_vapp.name != vapp_name: - module.fail_json(msg="Failed to find vapp named %s" % the_vapp.name) - the_vm_details = dict() - - for vm in the_vapp.me.Children.Vm: - sections = vm.get_Section() - - customization_section = ( - filter(lambda section: - section.__class__.__name__ == - "GuestCustomizationSectionType", - sections)[0]) - if customization_section.get_AdminPasswordEnabled(): - the_vm_details["vm_admin_password"] = customization_section.get_AdminPassword() - - virtual_hardware_section = ( - filter(lambda section: - section.__class__.__name__ == - "VirtualHardwareSection_Type", - sections)[0]) - items = virtual_hardware_section.get_Item() - ips = [] - _url = '{http://www.vmware.com/vcloud/v1.5}ipAddress' - for item in items: - if item.Connection: - for c in item.Connection: - if c.anyAttributes_.get( - _url): - ips.append(c.anyAttributes_.get( - _url)) - if len(ips) > 0: - the_vm_details["vm_ip"] = ips[0] - - return the_vm_details - - -def main(): - argument_spec = dict( - vapp_name=dict(required=True), - vdc_name=dict(required=True), - template_name=dict(), - catalog_name=dict(default='Public Catalog'), - network_name=dict(), - network_mode=dict(default='pool', choices=['dhcp', 'static', 'pool']), - vm_name=dict(), - vm_cpus=dict(), - vm_memory=dict(), - operation=dict(default=DEFAULT_VAPP_OPERATION, choices=VAPP_OPERATIONS), - state=dict(default='present', choices=VAPP_STATES) - ) - - module = VcaAnsibleModule(argument_spec=argument_spec, - supports_check_mode=True) - - state = module.params['state'] - operation = module.params['operation'] - - instance = get_instance(module) - - result = dict(changed=False) - - if instance and state == 'absent': - if not module.check_mode: - delete(module) - result['changed'] = True - - elif state != 'absent': - if instance['state'] == 'absent': - if not module.check_mode: - result['ansible_facts'] = create(module) - result['changed'] = True - - elif instance['state'] != state and state != 'present': - if not module.check_mode: - set_state(module) - result['changed'] = True - - if operation != instance.get('status') and operation != 'noop': - if not module.check_mode: - do_operation(module) - result['changed'] = True - result['ansible_facts'] = get_vm_details(module) - - return module.exit(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vcenter_extension.py b/lib/ansible/modules/cloud/vmware/vcenter_extension.py deleted file mode 100644 index 1473954f10..0000000000 --- a/lib/ansible/modules/cloud/vmware/vcenter_extension.py +++ /dev/null @@ -1,229 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Michael Tipton <mike () ibeta.org> -# 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 = ''' ---- -module: vcenter_extension -short_description: Register/deregister vCenter Extensions -description: - - This module can be used to register/deregister vCenter Extensions. -version_added: 2.8 -author: - - Michael Tipton (@castawayegr) -notes: - - Tested on vSphere 6.5 -requirements: - - "python >= 2.6" - - PyVmomi -options: - extension_key: - description: - - The extension key of the extension to install or uninstall. - required: True - type: str - version: - description: - - The version of the extension you are installing or uninstalling. - required: True - type: str - name: - description: - - Required for C(state=present). The name of the extension you are installing. - type: str - company: - description: - - Required for C(state=present). The name of the company that makes the extension. - type: str - description: - description: - - Required for C(state=present). A short description of the extension. - type: str - email: - description: - - Required for C(state=present). Administrator email to use for extension. - type: str - url: - description: - - Required for C(state=present). Link to server hosting extension zip file to install. - type: str - ssl_thumbprint: - description: - - Required for C(state=present). SSL thumbprint of the extension hosting server. - type: str - server_type: - description: - - Required for C(state=present). Type of server being used to install the extension (SOAP, REST, HTTP, etc.). - default: vsphere-client-serenity - type: str - client_type: - description: - - Required for C(state=present). Type of client the extension is (win32, .net, linux, etc.). - default: vsphere-client-serenity - type: str - visible: - description: - - Show the extension in solution manager inside vCenter. - default: True - type: bool - state: - description: - - Add or remove vCenter Extension. - choices: [absent, present] - default: present - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' - - name: Register vCenter Extension - vcenter_extension: - hostname: "{{ groups['vcsa'][0] }}" - username: "{{ vcenter_username }}" - password: "{{ site_password }}" - extension_key: "{{ extension_key }}" - version: "1.0" - company: "Acme" - name: "Acme Extension" - description: "acme management" - email: "user@example.com" - url: "https://10.0.0.1/ACME-vSphere-web-plugin-1.0.zip" - ssl_thumbprint: "{{ ssl_thumbprint }}" - state: present - delegate_to: localhost - register: register_extension - - - name: Deregister vCenter Extension - vcenter_extension: - hostname: "{{ groups['vcsa'][0] }}" - username: "{{ vcenter_username }}" - password: "{{ site_password }}" - extension_key: "{{ extension_key }}" - version: "1.0" - state: absent - delegate_to: localhost - register: deregister_extension -''' - -RETURN = """ -result: - description: information about performed operation - returned: always - type: str - sample: "'com.acme.Extension' installed." -""" - -try: - from pyVmomi import vim -except ImportError: - pass - -import datetime - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import connect_to_api, vmware_argument_spec - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update(dict( - extension_key=dict(type='str', required=True), - version=dict(type='str', required=True), - email=dict(type='str', required=False), - description=dict(type='str', required=False), - company=dict(type='str', required=False), - name=dict(type='str', required=False), - url=dict(type='str', required=False), - ssl_thumbprint=dict(type='str', required=False), - client_type=dict(type='str', default='vsphere-client-serenity', required=False), - server_type=dict(type='str', default='vsphere-client-serenity', required=False), - visible=dict(type='bool', default='True', required=False), - state=dict(type='str', default='present', choices=['absent', 'present']), - )) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=False, - required_if=[ - ['state', 'present', ['email', 'description', 'company', 'name', 'url', 'ssl_thumbprint', 'server_type', 'client_type']] - ] - ) - - state = module.params['state'] - extension_key = module.params['extension_key'] - version = module.params['version'] - email = module.params['email'] - desc = module.params['description'] - name = module.params['name'] - company = module.params['company'] - client_type = module.params['client_type'] - server_type = module.params['server_type'] - url = module.params['url'] - visible = module.params['visible'] - thumbprint = module.params['ssl_thumbprint'] - - content = connect_to_api(module, False) - em = content.extensionManager - key_check = em.FindExtension(extension_key) - results = dict(changed=False, installed=dict()) - - if state == 'present' and key_check: - results['changed'] = False - results['installed'] = "'%s' is already installed" % (extension_key) - - elif state == 'present' and not key_check: - extension = vim.Extension() - extension.key = extension_key - extension.company = company - extension.version = version - extension.lastHeartbeatTime = datetime.datetime.now() - description = vim.Description() - description.label = name - description.summary = desc - extension.description = description - extension.shownInSolutionManager = visible - - client = vim.Extension.ClientInfo() - client.company = company - client.version = version - client.description = description - client.type = client_type - client.url = url - extension.client = [client] - - server = vim.Extension.ServerInfo() - server.company = company - server.description = description - server.type = server_type - server.adminEmail = email - server.serverThumbprint = thumbprint - server.url = url - extension.server = [server] - - em.RegisterExtension(extension) - results['changed'] = True - results['installed'] = "'%s' installed." % (extension_key) - - elif state == 'absent' and key_check: - em.UnregisterExtension(extension_key) - results['changed'] = True - results['installed'] = "'%s' uninstalled." % (extension_key) - - elif state == 'absent' and not key_check: - results['changed'] = False - results['installed'] = "'%s' is not installed." % (extension_key) - - module.exit_json(**results) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vcenter_extension_info.py b/lib/ansible/modules/cloud/vmware/vcenter_extension_info.py deleted file mode 100644 index 774be5e984..0000000000 --- a/lib/ansible/modules/cloud/vmware/vcenter_extension_info.py +++ /dev/null @@ -1,115 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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: vcenter_extension_info -short_description: Gather info vCenter extensions -description: -- This module can be used to gather information about vCenter extension. -version_added: '2.9' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather info about vCenter Extensions - vcenter_extension_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - register: ext_info - delegate_to: localhost -''' - -RETURN = r''' -extension_info: - description: List of extensions - returned: success - type: list - sample: [ - { - "extension_company": "VMware, Inc.", - "extension_key": "com.vmware.vim.ls", - "extension_label": "License Services", - "extension_last_heartbeat_time": "2018-09-03T09:36:18.003768+00:00", - "extension_subject_name": "", - "extension_summary": "Provides various license services", - "extension_type": "", - "extension_version": "5.0" - }, - { - "extension_company": "VMware Inc.", - "extension_key": "com.vmware.vim.sms", - "extension_label": "VMware vCenter Storage Monitoring Service", - "extension_last_heartbeat_time": "2018-09-03T09:36:18.005730+00:00", - "extension_subject_name": "", - "extension_summary": "Storage Monitoring and Reporting", - "extension_type": "", - "extension_version": "5.5" - } - ] -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class VmwareExtManager(PyVmomi): - def __init__(self, module): - super(VmwareExtManager, self).__init__(module) - - def gather_plugin_info(self): - result = dict(changed=False, extension_info=[]) - ext_manager = self.content.extensionManager - if not ext_manager: - self.module.exit_json(**result) - - for ext in ext_manager.extensionList: - ext_info = dict( - extension_label=ext.description.label, - extension_summary=ext.description.summary, - extension_key=ext.key, - extension_company=ext.company, - extension_version=ext.version, - extension_type=ext.type if ext.type else '', - extension_subject_name=ext.subjectName if ext.subjectName else '', - extension_last_heartbeat_time=ext.lastHeartbeatTime, - ) - result['extension_info'].append(ext_info) - - self.module.exit_json(**result) - - -def main(): - argument_spec = vmware_argument_spec() - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - vcenter_extension_info_mgr = VmwareExtManager(module) - vcenter_extension_info_mgr.gather_plugin_info() - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vcenter_folder.py b/lib/ansible/modules/cloud/vmware/vcenter_folder.py deleted file mode 100644 index 6446a9710a..0000000000 --- a/lib/ansible/modules/cloud/vmware/vcenter_folder.py +++ /dev/null @@ -1,387 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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: vcenter_folder -short_description: Manage folders on given datacenter -description: -- This module can be used to create, delete, move and rename folder on then given datacenter. -- This module is only supported for vCenter. -version_added: '2.5' -author: -- Abhijeet Kasurde (@Akasurde) -- Christian Kotte (@ckotte) <christian.kotte@gmx.de> -- Jan Meerkamp (@meerkampdvv) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - datacenter: - description: - - Name of the datacenter. - required: True - aliases: ['datacenter_name'] - type: str - folder_name: - description: - - Name of folder to be managed. - - This is case sensitive parameter. - - Folder name should be under 80 characters. This is a VMware restriction. - required: True - type: str - parent_folder: - description: - - Name of the parent folder under which new folder needs to be created. - - This is case sensitive parameter. - - "If user wants to create a folder under '/DC0/vm/vm_folder', this value will be 'vm_folder'." - - "If user wants to create a folder under '/DC0/vm/folder1/folder2', this value will be 'folder1/folder2'." - required: False - type: str - folder_type: - description: - - This is type of folder. - - "If set to C(vm), then 'VM and Template Folder' is created under datacenter." - - "If set to C(host), then 'Host and Cluster Folder' is created under datacenter." - - "If set to C(datastore), then 'Storage Folder' is created under datacenter." - - "If set to C(network), then 'Network Folder' is created under datacenter." - - This parameter is required, if C(state) is set to C(present) and parent_folder is absent. - - This option is ignored, if C(parent_folder) is set. - default: vm - type: str - required: False - choices: [ datastore, host, network, vm ] - state: - description: - - State of folder. - - If set to C(present) without parent folder parameter, then folder with C(folder_type) is created. - - If set to C(present) with parent folder parameter, then folder in created under parent folder. C(folder_type) is ignored. - - If set to C(absent), then folder is unregistered and destroyed. - default: present - choices: [ present, absent ] - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Create a VM folder on given datacenter - vcenter_folder: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter_name: datacenter_name - folder_name: sample_vm_folder - folder_type: vm - state: present - register: vm_folder_creation_result - delegate_to: localhost - -- name: Create a datastore folder on given datacenter - vcenter_folder: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter_name: datacenter_name - folder_name: sample_datastore_folder - folder_type: datastore - state: present - register: datastore_folder_creation_result - delegate_to: localhost - -- name: Create a sub folder under VM folder on given datacenter - vcenter_folder: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter_name: datacenter_name - folder_name: sample_sub_folder - parent_folder: vm_folder - state: present - register: sub_folder_creation_result - delegate_to: localhost - -- name: Delete a VM folder on given datacenter - vcenter_folder: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter_name: datacenter_name - folder_name: sample_vm_folder - folder_type: vm - state: absent - register: vm_folder_deletion_result - delegate_to: localhost -''' - -RETURN = r''' -result: - description: The detail about the new folder - returned: On success - type: complex - contains: - path: - description: the full path of the new folder - type: str - msg: - description: string stating about result - type: str -''' - -try: - from pyVmomi import vim -except ImportError as import_err: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi, find_datacenter_by_name, wait_for_task, get_all_objs -from ansible.module_utils._text import to_native - - -class VmwareFolderManager(PyVmomi): - def __init__(self, module): - super(VmwareFolderManager, self).__init__(module) - datacenter_name = self.params.get('datacenter', None) - self.datacenter_obj = find_datacenter_by_name(self.content, datacenter_name=datacenter_name) - if self.datacenter_obj is None: - self.module.fail_json(msg="Failed to find datacenter %s" % datacenter_name) - - self.datacenter_folder_type = { - 'vm': self.datacenter_obj.vmFolder, - 'host': self.datacenter_obj.hostFolder, - 'datastore': self.datacenter_obj.datastoreFolder, - 'network': self.datacenter_obj.networkFolder, - } - - def ensure(self): - """ - Manage internal state management - """ - state = self.module.params.get('state') - datacenter_name = self.module.params.get('datacenter') - folder_type = self.module.params.get('folder_type') - folder_name = self.module.params.get('folder_name') - parent_folder = self.module.params.get('parent_folder', None) - results = {'changed': False, 'result': {}} - if state == 'present': - # Check if the folder already exists - p_folder_obj = None - if parent_folder: - if "/" in parent_folder: - parent_folder_parts = parent_folder.strip('/').split('/') - p_folder_obj = None - for part in parent_folder_parts: - part_folder_obj = self.get_folder(datacenter_name=datacenter_name, - folder_name=part, - folder_type=folder_type, - parent_folder=p_folder_obj) - if not part_folder_obj: - self.module.fail_json(msg="Could not find folder %s" % part) - p_folder_obj = part_folder_obj - child_folder_obj = self.get_folder(datacenter_name=datacenter_name, - folder_name=folder_name, - folder_type=folder_type, - parent_folder=p_folder_obj) - if child_folder_obj: - results['result'] = "Folder %s already exists under" \ - " parent folder %s" % (folder_name, parent_folder) - self.module.exit_json(**results) - else: - p_folder_obj = self.get_folder(datacenter_name=datacenter_name, - folder_name=parent_folder, - folder_type=folder_type) - - if not p_folder_obj: - self.module.fail_json(msg="Parent folder %s does not exist" % parent_folder) - - # Check if folder exists under parent folder - child_folder_obj = self.get_folder(datacenter_name=datacenter_name, - folder_name=folder_name, - folder_type=folder_type, - parent_folder=p_folder_obj) - if child_folder_obj: - results['result']['path'] = self.get_folder_path(child_folder_obj) - results['result'] = "Folder %s already exists under" \ - " parent folder %s" % (folder_name, parent_folder) - self.module.exit_json(**results) - else: - folder_obj = self.get_folder(datacenter_name=datacenter_name, - folder_name=folder_name, - folder_type=folder_type) - - if folder_obj: - results['result']['path'] = self.get_folder_path(folder_obj) - results['result']['msg'] = "Folder %s already exists" % folder_name - self.module.exit_json(**results) - - # Create a new folder - try: - if parent_folder and p_folder_obj: - if self.module.check_mode: - results['msg'] = "Folder '%s' of type '%s' under '%s' will be created." % \ - (folder_name, folder_type, parent_folder) - else: - new_folder = p_folder_obj.CreateFolder(folder_name) - results['result']['path'] = self.get_folder_path(new_folder) - results['result']['msg'] = "Folder '%s' of type '%s' under '%s' created" \ - " successfully." % (folder_name, folder_type, parent_folder) - results['changed'] = True - elif not parent_folder and not p_folder_obj: - if self.module.check_mode: - results['msg'] = "Folder '%s' of type '%s' will be created." % (folder_name, folder_type) - else: - new_folder = self.datacenter_folder_type[folder_type].CreateFolder(folder_name) - results['result']['msg'] = "Folder '%s' of type '%s' created successfully." % (folder_name, folder_type) - results['result']['path'] = self.get_folder_path(new_folder) - results['changed'] = True - except vim.fault.DuplicateName as duplicate_name: - # To be consistent with the other vmware modules, We decided to accept this error - # and the playbook should simply carry on with other tasks. - # User will have to take care of this exception - # https://github.com/ansible/ansible/issues/35388#issuecomment-362283078 - results['changed'] = False - results['msg'] = "Failed to create folder as another object has same name" \ - " in the same target folder : %s" % to_native(duplicate_name.msg) - except vim.fault.InvalidName as invalid_name: - self.module.fail_json(msg="Failed to create folder as folder name is not a valid " - "entity name : %s" % to_native(invalid_name.msg)) - except Exception as general_exc: - self.module.fail_json(msg="Failed to create folder due to generic" - " exception : %s " % to_native(general_exc)) - self.module.exit_json(**results) - elif state == 'absent': - # Check if the folder already exists - p_folder_obj = None - if parent_folder: - if "/" in parent_folder: - parent_folder_parts = parent_folder.strip('/').split('/') - p_folder_obj = None - for part in parent_folder_parts: - part_folder_obj = self.get_folder(datacenter_name=datacenter_name, - folder_name=part, - folder_type=folder_type, - parent_folder=p_folder_obj) - if not part_folder_obj: - self.module.fail_json(msg="Could not find folder %s" % part) - p_folder_obj = part_folder_obj - folder_obj = self.get_folder(datacenter_name=datacenter_name, - folder_name=folder_name, - folder_type=folder_type, - parent_folder=p_folder_obj) - else: - p_folder_obj = self.get_folder(datacenter_name=datacenter_name, - folder_name=parent_folder, - folder_type=folder_type) - - if not p_folder_obj: - self.module.fail_json(msg="Parent folder %s does not exist" % parent_folder) - - # Check if folder exists under parent folder - folder_obj = self.get_folder(datacenter_name=datacenter_name, - folder_name=folder_name, - folder_type=folder_type, - parent_folder=p_folder_obj) - else: - folder_obj = self.get_folder(datacenter_name=datacenter_name, - folder_name=folder_name, - folder_type=folder_type) - if folder_obj: - try: - if parent_folder: - if self.module.check_mode: - results['changed'] = True - results['msg'] = "Folder '%s' of type '%s' under '%s' will be removed." % \ - (folder_name, folder_type, parent_folder) - else: - if folder_type == 'vm': - task = folder_obj.UnregisterAndDestroy() - else: - task = folder_obj.Destroy() - results['changed'], results['msg'] = wait_for_task(task=task) - else: - if self.module.check_mode: - results['changed'] = True - results['msg'] = "Folder '%s' of type '%s' will be removed." % (folder_name, folder_type) - else: - if folder_type == 'vm': - task = folder_obj.UnregisterAndDestroy() - else: - task = folder_obj.Destroy() - results['changed'], results['msg'] = wait_for_task(task=task) - except vim.fault.ConcurrentAccess as concurrent_access: - self.module.fail_json(msg="Failed to remove folder as another client" - " modified folder before this operation : %s" % to_native(concurrent_access.msg)) - except vim.fault.InvalidState as invalid_state: - self.module.fail_json(msg="Failed to remove folder as folder is in" - " invalid state : %s" % to_native(invalid_state.msg)) - except Exception as gen_exec: - self.module.fail_json(msg="Failed to remove folder due to generic" - " exception %s " % to_native(gen_exec)) - self.module.exit_json(**results) - - def get_folder(self, datacenter_name, folder_name, folder_type, parent_folder=None): - """ - Get managed object of folder by name - Returns: Managed object of folder by name - - """ - folder_objs = get_all_objs(self.content, [vim.Folder], parent_folder) - for folder in folder_objs: - if parent_folder: - if folder.name == folder_name and \ - self.datacenter_folder_type[folder_type].childType == folder.childType: - return folder - else: - if folder.name == folder_name and \ - self.datacenter_folder_type[folder_type].childType == folder.childType and \ - folder.parent.parent.name == datacenter_name: # e.g. folder.parent.parent.name == /DC01/host/folder - return folder - - return None - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - datacenter=dict(type='str', required=True, aliases=['datacenter_name']), - folder_name=dict(type='str', required=True), - parent_folder=dict(type='str', required=False), - state=dict(type='str', - choices=['present', 'absent'], - default='present'), - folder_type=dict(type='str', - default='vm', - choices=['datastore', 'host', 'network', 'vm'], - required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - if len(module.params.get('folder_name')) > 79: - module.fail_json(msg="Failed to manage folder as folder_name can only contain 80 characters.") - - vcenter_folder_mgr = VmwareFolderManager(module) - if not vcenter_folder_mgr.is_vcenter(): - module.fail_json(msg="Module vcenter_folder is meant for vCenter, hostname %s " - "is not vCenter server." % module.params.get('hostname')) - vcenter_folder_mgr.ensure() - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vcenter_license.py b/lib/ansible/modules/cloud/vmware/vcenter_license.py deleted file mode 100644 index e3702bac4c..0000000000 --- a/lib/ansible/modules/cloud/vmware/vcenter_license.py +++ /dev/null @@ -1,275 +0,0 @@ -#!/usr/bin/python - -# Copyright: (c) 2017, Dag Wieers (@dagwieers) <dag@wieers.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: vcenter_license -short_description: Manage VMware vCenter license keys -description: -- Add and delete vCenter, ESXi server license keys. -version_added: '2.4' -author: -- Dag Wieers (@dagwieers) -requirements: -- pyVmomi -options: - labels: - description: - - The optional labels of the license key to manage in vSphere vCenter. - - This is dictionary with key/value pair. - default: { - 'source': 'ansible' - } - type: dict - license: - description: - - The license key to manage in vSphere vCenter. - required: yes - type: str - state: - description: - - Whether to add (C(present)) or remove (C(absent)) the license key. - choices: [absent, present] - default: present - type: str - esxi_hostname: - description: - - The hostname of the ESXi server to which the specified license will be assigned. - - This parameter is optional. - version_added: '2.8' - type: str - datacenter: - description: - - The datacenter name to use for the operation. - type: str - version_added: '2.9' - cluster_name: - description: - - Name of the cluster to apply vSAN license. - type: str - version_added: '2.9' -notes: -- This module will also auto-assign the current vCenter to the license key - if the product matches the license key, and vCenter us currently assigned - an evaluation license only. -- The evaluation license (00000-00000-00000-00000-00000) is not listed - when unused. -- If C(esxi_hostname) is specified, then will assign the C(license) key to - the ESXi host. -extends_documentation_fragment: vmware.vcenter_documentation -''' - -EXAMPLES = r''' -- name: Add a new vCenter license - vcenter_license: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - license: f600d-21ae3-5592b-249e0-cc341 - state: present - delegate_to: localhost - -- name: Remove an (unused) vCenter license - vcenter_license: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - license: f600d-21ae3-5592b-249e0-cc341 - state: absent - delegate_to: localhost - -- name: Add ESXi license and assign to the ESXi host - vcenter_license: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - license: f600d-21ae3-5592b-249e0-dd502 - state: present - delegate_to: localhost - -- name: Add vSAN license and assign to the given cluster - vcenter_license: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: '{{ datacenter_name }}' - cluster_name: '{{ cluster_name }}' - license: f600d-21ae3-5592b-249e0-dd502 - state: present - delegate_to: localhost -''' - -RETURN = r''' -licenses: - description: list of license keys after module executed - returned: always - type: list - sample: - - f600d-21ae3-5592b-249e0-cc341 - - 143cc-0e942-b2955-3ea12-d006f -''' - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils._text import to_native -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec, find_hostsystem_by_name - - -class VcenterLicenseMgr(PyVmomi): - def __init__(self, module): - super(VcenterLicenseMgr, self).__init__(module) - - def find_key(self, licenses, license): - for item in licenses: - if item.licenseKey == license: - return item - return None - - def list_keys(self, licenses): - keys = [] - for item in licenses: - # Filter out evaluation license key - if item.used is None: - continue - keys.append(item.licenseKey) - return keys - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update(dict( - labels=dict(type='dict', default=dict(source='ansible')), - license=dict(type='str', required=True), - state=dict(type='str', default='present', choices=['absent', 'present']), - esxi_hostname=dict(type='str'), - datacenter=dict(type='str'), - cluster_name=dict(type='str'), - )) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - license = module.params['license'] - state = module.params['state'] - - # FIXME: This does not seem to work on vCenter v6.0 - labels = [] - for k in module.params['labels']: - kv = vim.KeyValue() - kv.key = k - kv.value = module.params['labels'][k] - labels.append(kv) - - result = dict( - changed=False, - diff=dict(), - ) - - pyv = VcenterLicenseMgr(module) - if not pyv.is_vcenter(): - module.fail_json(msg="vcenter_license is meant for vCenter, hostname %s " - "is not vCenter server." % module.params.get('hostname')) - - lm = pyv.content.licenseManager - - result['licenses'] = pyv.list_keys(lm.licenses) - if module._diff: - result['diff']['before'] = '\n'.join(result['licenses']) + '\n' - - if state == 'present': - if license not in result['licenses']: - result['changed'] = True - if module.check_mode: - result['licenses'].append(license) - else: - lm.AddLicense(license, labels) - - key = pyv.find_key(lm.licenses, license) - if key is not None: - lam = lm.licenseAssignmentManager - assigned_license = None - datacenter = module.params['datacenter'] - datacenter_obj = None - if datacenter: - datacenter_obj = pyv.find_datacenter_by_name(datacenter) - if not datacenter_obj: - module.fail_json(msg="Unable to find the datacenter %(datacenter)s" % module.params) - - cluster = module.params['cluster_name'] - if cluster: - cluster_obj = pyv.find_cluster_by_name(cluster_name=cluster, datacenter_name=datacenter_obj) - if not cluster_obj: - msg = "Unable to find the cluster %(cluster_name)s" - if datacenter: - msg += " in datacenter %(datacenter)s" - module.fail_json(msg=msg % module.params) - entityId = cluster_obj._moId - # assign to current vCenter, if esxi_hostname is not specified - elif module.params['esxi_hostname'] is None: - entityId = pyv.content.about.instanceUuid - # if key name not contain "VMware vCenter Server" - if pyv.content.about.name not in key.name: - module.warn('License key "%s" (%s) is not suitable for "%s"' % (license, key.name, pyv.content.about.name)) - # assign to ESXi server - else: - esxi_host = find_hostsystem_by_name(pyv.content, module.params['esxi_hostname']) - if esxi_host is None: - module.fail_json(msg='Cannot find the specified ESXi host "%s".' % module.params['esxi_hostname']) - entityId = esxi_host._moId - # e.g., key.editionKey is "esx.enterprisePlus.cpuPackage", not sure all keys are in this format - if 'esx' not in key.editionKey: - module.warn('License key "%s" edition "%s" is not suitable for ESXi server' % (license, key.editionKey)) - - try: - assigned_license = lam.QueryAssignedLicenses(entityId=entityId) - except Exception as e: - module.fail_json(msg='Could not query vCenter "%s" assigned license info due to %s.' % (entityId, to_native(e))) - - if not assigned_license or (len(assigned_license) != 0 and assigned_license[0].assignedLicense.licenseKey != license): - try: - lam.UpdateAssignedLicense(entity=entityId, licenseKey=license) - except Exception: - module.fail_json(msg='Could not assign "%s" (%s) to vCenter.' % (license, key.name)) - result['changed'] = True - result['licenses'] = pyv.list_keys(lm.licenses) - else: - module.fail_json(msg='License "%s" is not existing or can not be added' % license) - if module._diff: - result['diff']['after'] = '\n'.join(result['licenses']) + '\n' - - elif state == 'absent' and license in result['licenses']: - - # Check if key is in use - key = pyv.find_key(lm.licenses, license) - if key.used > 0: - module.fail_json(msg='Cannot remove key "%s", still in use %s time(s).' % (license, key.used)) - - result['changed'] = True - if module.check_mode: - result['licenses'].remove(license) - else: - lm.RemoveLicense(license) - result['licenses'] = pyv.list_keys(lm.licenses) - if module._diff: - result['diff']['after'] = '\n'.join(result['licenses']) + '\n' - - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_about_info.py b/lib/ansible/modules/cloud/vmware/vmware_about_info.py deleted file mode 100644 index 5760562c6b..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_about_info.py +++ /dev/null @@ -1,126 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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_about_info -short_description: Provides information about VMware server to which user is connecting to -description: -- This module can be used to gather information about VMware server to which user is trying to connect. -version_added: '2.9' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Provide information about vCenter - vmware_about_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - delegate_to: localhost - register: vcenter_about_info - -- name: Provide information about a standalone ESXi server - vmware_about_info: - hostname: '{{ esxi_hostname }}' - username: '{{ esxi_username }}' - password: '{{ esxi_password }}' - delegate_to: localhost - register: esxi_about_info -''' - -RETURN = r''' -about_info: - description: - - dict about VMware server - returned: success - type: str - sample: - { - "api_type": "VirtualCenter", - "api_version": "6.5", - "build": "5973321", - "instance_uuid": "dbed6e0c-bd88-4ef6-b594-21283e1c677f", - "license_product_name": "VMware VirtualCenter Server", - "license_product_version": "6.0", - "locale_build": "000", - "locale_version": "INTL", - "os_type": "darwin-amd64", - "product_full_name": "VMware vCenter Server 6.5.0 build-5973321", - "product_line_id": "vpx", - "product_name": "VMware vCenter Server (govmomi simulator)", - "vendor": "VMware, Inc.", - "version": "6.5.0" - } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class VmwareAboutManager(PyVmomi): - def __init__(self, module): - super(VmwareAboutManager, self).__init__(module) - - def gather_about_info(self): - - if not self.content: - self.module.exit_json(changed=False, about_info=dict()) - - about = self.content.about - - self.module.exit_json( - changed=False, - about_info=dict( - product_name=about.name, - product_full_name=about.fullName, - vendor=about.vendor, - version=about.version, - build=about.build, - locale_version=about.localeVersion, - locale_build=about.localeBuild, - os_type=about.osType, - product_line_id=about.productLineId, - api_type=about.apiType, - api_version=about.apiVersion, - instance_uuid=about.instanceUuid, - license_product_name=about.licenseProductName, - license_product_version=about.licenseProductVersion, - ) - ) - - -def main(): - argument_spec = vmware_argument_spec() - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - vmware_about_info_mgr = VmwareAboutManager(module) - vmware_about_info_mgr.gather_about_info() - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_category.py b/lib/ansible/modules/cloud/vmware/vmware_category.py deleted file mode 100644 index e1a5d2fd99..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_category.py +++ /dev/null @@ -1,330 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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_category -short_description: Manage VMware categories -description: -- This module can be used to create / delete / update VMware categories. -- Tag feature is introduced in vSphere 6 version, so this module is not supported in the earlier versions of vSphere. -- All variables and VMware object names are case sensitive. -version_added: '2.7' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -- vSphere Automation SDK -options: - category_name: - description: - - The name of category to manage. - required: True - type: str - category_description: - description: - - The category description. - - This is required only if C(state) is set to C(present). - - This parameter is ignored, when C(state) is set to C(absent). - default: '' - type: str - category_cardinality: - description: - - The category cardinality. - - This parameter is ignored, when updating existing category. - choices: ['multiple', 'single'] - default: 'multiple' - type: str - new_category_name: - description: - - The new name for an existing category. - - This value is used while updating an existing category. - type: str - state: - description: - - The state of category. - - If set to C(present) and category does not exists, then category is created. - - If set to C(present) and category exists, then category is updated. - - If set to C(absent) and category exists, then category is deleted. - - If set to C(absent) and category does not exists, no action is taken. - - Process of updating category only allows name, description change. - default: 'present' - choices: [ 'present', 'absent' ] - type: str - associable_object_types: - description: - - List of object types that can be associated with the given category. - choices: - - All objects - - Cluster - - Content Library - - Datacenter - - Datastore - - Datastore Cluster - - Distributed Port Group - - Distributed Switch - - Folder - - Host - - Library item - - Network - - Resource Pool - - vApp - - Virtual Machine - version_added: '2.10' - type: list - elements: str -extends_documentation_fragment: vmware_rest_client.documentation -''' - -EXAMPLES = r''' -- name: Create a category - vmware_category: - hostname: "{{ vcenter_server }}" - username: "{{ vcenter_user }}" - password: "{{ vcenter_pass }}" - category_name: Sample_Cat_0001 - category_description: Sample Description - category_cardinality: 'multiple' - state: present - -- name: Rename category - vmware_category: - hostname: "{{ vcenter_server }}" - username: "{{ vcenter_user }}" - password: "{{ vcenter_pass }}" - category_name: Sample_Category_0001 - new_category_name: Sample_Category_0002 - state: present - -- name: Update category description - vmware_category: - hostname: "{{ vcenter_server }}" - username: "{{ vcenter_user }}" - password: "{{ vcenter_pass }}" - category_name: Sample_Category_0001 - category_description: Some fancy description - state: present - -- name: Delete category - vmware_category: - hostname: "{{ vcenter_server }}" - username: "{{ vcenter_user }}" - password: "{{ vcenter_pass }}" - category_name: Sample_Category_0002 - state: absent - -- name: Create category with 2 associable object types - vmware_category: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: False - category_name: 'Sample_Category_0003' - category_description: 'sample description' - associable_object_types: - - Datastore - - Cluster - state: present -''' - -RETURN = r''' -category_results: - description: dictionary of category metadata - returned: on success - type: dict - sample: { - "category_id": "urn:vmomi:InventoryServiceCategory:d7120bda-9fa5-4f92-9d71-aa1acff2e5a8:GLOBAL", - "msg": "Category NewCat_0001 updated." - } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware_rest_client import VmwareRestClient -try: - from com.vmware.cis.tagging_client import CategoryModel - from com.vmware.vapi.std.errors_client import Error -except ImportError: - pass - - -class VmwareCategory(VmwareRestClient): - def __init__(self, module): - super(VmwareCategory, self).__init__(module) - self.category_service = self.api_client.tagging.Category - self.global_categories = dict() - self.category_name = self.params.get('category_name') - self.get_all_categories() - - def ensure_state(self): - """Manage internal states of categories. """ - desired_state = self.params.get('state') - states = { - 'present': { - 'present': self.state_update_category, - 'absent': self.state_create_category, - }, - 'absent': { - 'present': self.state_delete_category, - 'absent': self.state_unchanged, - } - } - states[desired_state][self.check_category_status()]() - - def state_create_category(self): - """Create category.""" - category_spec = self.category_service.CreateSpec() - category_spec.name = self.category_name - category_spec.description = self.params.get('category_description') - - if self.params.get('category_cardinality') == 'single': - category_spec.cardinality = CategoryModel.Cardinality.SINGLE - else: - category_spec.cardinality = CategoryModel.Cardinality.MULTIPLE - - associable_object_types = self.params.get('associable_object_types') - - obj_types_set = [] - if associable_object_types: - for obj_type in associable_object_types: - if obj_type.lower() == 'all objects': - obj_types_set = [] - break - else: - obj_types_set.append(obj_type) - - category_spec.associable_types = set(obj_types_set) - - try: - category_id = self.category_service.create(category_spec) - except Error as error: - self.module.fail_json(msg="%s" % self.get_error_message(error)) - - if category_id: - self.module.exit_json(changed=True, - category_results=dict(msg="Category '%s' created." % category_spec.name, - category_id=category_id)) - self.module.exit_json(changed=False, - category_results=dict(msg="No category created", category_id='')) - - def state_unchanged(self): - """Return unchanged state.""" - self.module.exit_json(changed=False) - - def state_update_category(self): - """Update category.""" - category_id = self.global_categories[self.category_name]['category_id'] - changed = False - results = dict(msg="Category %s is unchanged." % self.category_name, - category_id=category_id) - - category_update_spec = self.category_service.UpdateSpec() - change_list = [] - old_cat_desc = self.global_categories[self.category_name]['category_description'] - new_cat_desc = self.params.get('category_description') - if new_cat_desc and new_cat_desc != old_cat_desc: - category_update_spec.description = new_cat_desc - results['msg'] = 'Category %s updated.' % self.category_name - change_list.append(True) - - new_cat_name = self.params.get('new_category_name') - if new_cat_name in self.global_categories: - self.module.fail_json(msg="Unable to rename %s as %s already" - " exists in configuration." % (self.category_name, new_cat_name)) - old_cat_name = self.global_categories[self.category_name]['category_name'] - - if new_cat_name and new_cat_name != old_cat_name: - category_update_spec.name = new_cat_name - results['msg'] = 'Category %s updated.' % self.category_name - change_list.append(True) - - if any(change_list): - try: - self.category_service.update(category_id, category_update_spec) - changed = True - except Error as error: - self.module.fail_json(msg="%s" % self.get_error_message(error)) - - self.module.exit_json(changed=changed, - category_results=results) - - def state_delete_category(self): - """Delete category.""" - category_id = self.global_categories[self.category_name]['category_id'] - try: - self.category_service.delete(category_id=category_id) - except Error as error: - self.module.fail_json(msg="%s" % self.get_error_message(error)) - self.module.exit_json(changed=True, - category_results=dict(msg="Category '%s' deleted." % self.category_name, - category_id=category_id)) - - def check_category_status(self): - """ - Check if category exists or not - Returns: 'present' if category found, else 'absent' - - """ - if self.category_name in self.global_categories: - return 'present' - else: - return 'absent' - - def get_all_categories(self): - """Retrieve all category information.""" - for category in self.category_service.list(): - category_obj = self.category_service.get(category) - self.global_categories[category_obj.name] = dict( - category_description=category_obj.description, - category_used_by=category_obj.used_by, - category_cardinality=str(category_obj.cardinality), - category_associable_types=category_obj.associable_types, - category_id=category_obj.id, - category_name=category_obj.name, - ) - - -def main(): - argument_spec = VmwareRestClient.vmware_client_argument_spec() - argument_spec.update( - category_name=dict(type='str', required=True), - category_description=dict(type='str', default='', required=False), - category_cardinality=dict(type='str', choices=["multiple", "single"], default="multiple"), - new_category_name=dict(type='str'), - state=dict(type='str', choices=['present', 'absent'], default='present'), - associable_object_types=dict( - type='list', - choices=[ - 'All objects', 'Folder', 'Cluster', - 'Datacenter', 'Datastore', 'Datastore Cluster', - 'Distributed Port Group', 'Distributed Switch', - 'Host', 'Content Library', 'Library item', 'Network', - 'Resource Pool', 'vApp', 'Virtual Machine', - ], - elements=str, - ), - ) - module = AnsibleModule(argument_spec=argument_spec) - - vmware_category = VmwareCategory(module) - vmware_category.ensure_state() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_category_info.py b/lib/ansible/modules/cloud/vmware/vmware_category_info.py deleted file mode 100644 index 1ef8529dea..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_category_info.py +++ /dev/null @@ -1,128 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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_category_info -short_description: Gather info about VMware tag categories -description: -- This module can be used to gather information about VMware tag categories. -- Tag feature is introduced in vSphere 6 version, so this module is not supported in earlier versions of vSphere. -- All variables and VMware object names are case sensitive. -version_added: '2.9' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -- vSphere Automation SDK -extends_documentation_fragment: vmware_rest_client.documentation -''' - -EXAMPLES = r''' -- name: Gather info about tag categories - vmware_category_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - delegate_to: localhost - register: all_tag_category_info - -- name: Gather category id from given tag category - vmware_category_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - delegate_to: localhost - register: tag_category_results - -- set_fact: - category_id: "{{ item.category_id }}" - loop: "{{ tag_category_results.tag_category_info|json_query(query) }}" - vars: - query: "[?category_name==`Category0001`]" -- debug: var=category_id - -''' - -RETURN = r''' -tag_category_info: - description: metadata of tag categories - returned: always - type: list - sample: [ - { - "category_associable_types": [], - "category_cardinality": "MULTIPLE", - "category_description": "awesome description", - "category_id": "urn:vmomi:InventoryServiceCategory:e785088d-6981-4b1c-9fb8-1100c3e1f742:GLOBAL", - "category_name": "Category0001", - "category_used_by": [] - }, - { - "category_associable_types": [ - "VirtualMachine" - ], - "category_cardinality": "SINGLE", - "category_description": "another awesome description", - "category_id": "urn:vmomi:InventoryServiceCategory:ae5b7c6c-e622-4671-9b96-76e93adb70f2:GLOBAL", - "category_name": "template_tag", - "category_used_by": [] - } - ] -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware_rest_client import VmwareRestClient - - -class VmwareCategoryInfoManager(VmwareRestClient): - def __init__(self, module): - super(VmwareCategoryInfoManager, self).__init__(module) - self.category_service = self.api_client.tagging.Category - - def get_all_tag_categories(self): - """Retrieve all tag category information.""" - global_tag_categories = [] - for category in self.category_service.list(): - category_obj = self.category_service.get(category) - global_tag_categories.append( - dict( - category_description=category_obj.description, - category_used_by=category_obj.used_by, - category_cardinality=str(category_obj.cardinality), - category_associable_types=category_obj.associable_types, - category_id=category_obj.id, - category_name=category_obj.name, - ) - ) - - self.module.exit_json(changed=False, tag_category_info=global_tag_categories) - - -def main(): - argument_spec = VmwareRestClient.vmware_client_argument_spec() - module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) - - vmware_category_info = VmwareCategoryInfoManager(module) - vmware_category_info.get_all_tag_categories() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_cfg_backup.py b/lib/ansible/modules/cloud/vmware/vmware_cfg_backup.py deleted file mode 100644 index 871eba8308..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_cfg_backup.py +++ /dev/null @@ -1,227 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2017, IBM Corp -# Author(s): Andreas Nafpliotis <nafpliot@de.ibm.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 = ''' ---- -module: vmware_cfg_backup -short_description: Backup / Restore / Reset ESXi host configuration -description: - - This module can be used to perform various operations related to backup, restore and reset of ESXi host configuration. -version_added: "2.5" -author: - - Andreas Nafpliotis (@nafpliot-ibm) -notes: - - Tested on ESXi 6.0 - - Works only for ESXi hosts - - For configuration load or reset, the host will be switched automatically to maintenance mode. -requirements: - - "python >= 2.6" - - PyVmomi installed -options: - esxi_hostname: - description: - - Name of ESXi server. This is required only if authentication against a vCenter is done. - required: False - type: str - dest: - description: - - The destination where the ESXi configuration bundle will be saved. The I(dest) can be a folder or a file. - - If I(dest) is a folder, the backup file will be saved in the folder with the default filename generated from the ESXi server. - - If I(dest) is a file, the backup file will be saved with that filename. The file extension will always be .tgz. - type: path - src: - description: - - The file containing the ESXi configuration that will be restored. - type: path - state: - description: - - If C(saved), the .tgz backup bundle will be saved in I(dest). - - If C(absent), the host configuration will be reset to default values. - - If C(loaded), the backup file in I(src) will be loaded to the ESXi host rewriting the hosts settings. - choices: [saved, absent, loaded] - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Save the ESXi configuration locally by authenticating directly against the ESXi host - vmware_cfg_backup: - hostname: '{{ esxi_hostname }}' - username: '{{ esxi_username }}' - password: '{{ esxi_password }}' - state: saved - dest: /tmp/ - delegate_to: localhost - -- name: Save the ESXi configuration locally by authenticating against the vCenter and selecting the ESXi host - vmware_cfg_backup: - hostname: '{{ vcenter_hostname }}' - esxi_hostname: '{{ esxi_hostname }}' - username: '{{ esxi_username }}' - password: '{{ esxi_password }}' - state: saved - dest: /tmp/ - delegate_to: localhost -''' - -RETURN = ''' -dest_file: - description: The full path of where the file holding the ESXi configurations was stored - returned: changed - type: str - sample: /tmp/configBundle-esxi.host.domain.tgz -''' - -import os -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.vmware import vmware_argument_spec, get_all_objs, wait_for_task, PyVmomi -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.urls import open_url -from ansible.module_utils.six.moves.urllib.error import HTTPError -from ansible.module_utils._text import to_native - - -class VMwareConfigurationBackup(PyVmomi): - def __init__(self, module): - super(VMwareConfigurationBackup, self).__init__(module) - self.state = self.module.params['state'] - self.dest = self.module.params['dest'] - self.src = self.module.params['src'] - self.hostname = self.module.params['hostname'] - self.username = self.module.params['username'] - self.password = self.module.params['password'] - self.validate_certs = self.module.params['validate_certs'] - self.esxi_hostname = self.module.params.get('esxi_hostname', None) - self.host = self.find_host_system() - - def find_host_system(self): - if self.esxi_hostname: - host_system_obj = self.find_hostsystem_by_name(host_name=self.esxi_hostname) - if host_system_obj: - return host_system_obj - else: - self.module.fail_json(msg="Failed to find ESXi %s" % self.esxi_hostname) - - host_system = get_all_objs(self.content, [vim.HostSystem]) - return list(host_system)[0] - - def process_state(self): - if self.state == 'saved': - self.save_configuration() - - if self.state == 'absent': - self.reset_configuration() - - if self.state == 'loaded': - self.load_configuration() - - def load_configuration(self): - if not os.path.isfile(self.src): - self.module.fail_json(msg="Source file {0} does not exist".format(self.src)) - - url = self.host.configManager.firmwareSystem.QueryFirmwareConfigUploadURL() - url = url.replace('*', self.host.name) - # find manually the url if there is a redirect because urllib2 -per RFC- doesn't do automatic redirects for PUT requests - try: - request = open_url(url=url, method='HEAD', validate_certs=self.validate_certs) - except HTTPError as e: - url = e.geturl() - - try: - with open(self.src, 'rb') as file: - data = file.read() - request = open_url(url=url, data=data, method='PUT', validate_certs=self.validate_certs, - url_username=self.username, url_password=self.password, force_basic_auth=True) - except Exception as e: - self.module.fail_json(msg=to_native(e)) - - if not self.host.runtime.inMaintenanceMode: - self.enter_maintenance() - try: - self.host.configManager.firmwareSystem.RestoreFirmwareConfiguration(force=True) - self.module.exit_json(changed=True) - except Exception as e: - self.exit_maintenance() - self.module.fail_json(msg=to_native(e)) - - def reset_configuration(self): - if not self.host.runtime.inMaintenanceMode: - self.enter_maintenance() - try: - self.host.configManager.firmwareSystem.ResetFirmwareToFactoryDefaults() - self.module.exit_json(changed=True) - except Exception as e: - self.exit_maintenance() - self.module.fail_json(msg=to_native(e)) - - def save_configuration(self): - url = self.host.configManager.firmwareSystem.BackupFirmwareConfiguration() - url = url.replace('*', self.host.name) - if os.path.isdir(self.dest): - filename = url.rsplit('/', 1)[1] - self.dest = os.path.join(self.dest, filename) - else: - filename, file_extension = os.path.splitext(self.dest) - if file_extension != ".tgz": - self.dest = filename + ".tgz" - try: - request = open_url(url=url, validate_certs=self.validate_certs) - with open(self.dest, "wb") as file: - file.write(request.read()) - self.module.exit_json(changed=True, dest_file=self.dest) - except IOError as e: - self.module.fail_json(msg="Failed to write backup file. Ensure that " - "the dest path exists and is writable. Details : %s" % to_native(e)) - except Exception as e: - self.module.fail_json(msg=to_native(e)) - - def enter_maintenance(self): - try: - task = self.host.EnterMaintenanceMode_Task(timeout=15) - success, result = wait_for_task(task) - except Exception as e: - self.module.fail_json(msg="Failed to enter maintenance mode." - " Ensure that there are no powered on machines on the host. %s" % to_native(e)) - - def exit_maintenance(self): - try: - task = self.host.ExitMaintenanceMode_Task(timeout=15) - success, result = wait_for_task(task) - except Exception as generic_exc: - self.module.fail_json(msg="Failed to exit maintenance mode due to %s" % to_native(generic_exc)) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update(dict(dest=dict(required=False, type='path'), - esxi_hostname=dict(required=False, type='str'), - src=dict(required=False, type='path'), - state=dict(required=True, choices=['saved', 'absent', 'loaded'], type='str'))) - required_if = [('state', 'saved', ['dest']), - ('state', 'loaded', ['src'])] - - module = AnsibleModule(argument_spec=argument_spec, - required_if=required_if, - supports_check_mode=False) - - vmware_cfg_backup = VMwareConfigurationBackup(module) - vmware_cfg_backup.process_state() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_cluster.py b/lib/ansible/modules/cloud/vmware/vmware_cluster.py deleted file mode 100644 index f2b5eef532..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_cluster.py +++ /dev/null @@ -1,590 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2015, Joseph Callen <jcallen () csc.com> -# Copyright: (c) 2018, Ansible Project -# -# 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_cluster -short_description: Manage VMware vSphere clusters -description: - - Adds or removes VMware vSphere clusters. - - Although this module can manage DRS, HA and VSAN related configurations, this functionality is deprecated and will be removed in 2.12. - - To manage DRS, HA and VSAN related configurations, use the new modules vmware_cluster_drs, vmware_cluster_ha and vmware_cluster_vsan. - - All values and VMware object names are case sensitive. -version_added: '2.0' -author: -- Joseph Callen (@jcpowermac) -- Abhijeet Kasurde (@Akasurde) -requirements: - - Tested on ESXi 5.5 and 6.5. - - PyVmomi installed. -options: - cluster_name: - description: - - The name of the cluster to be managed. - type: str - required: yes - datacenter: - description: - - The name of the datacenter. - type: str - required: yes - aliases: [ datacenter_name ] - ignore_drs: - description: - - If set to C(yes), DRS will not be configured; all explicit and default DRS related configurations will be ignored. - type: bool - default: 'no' - version_added: 2.9 - ignore_ha: - description: - - If set to C(yes), HA will not be configured; all explicit and default HA related configurations will be ignored. - type: bool - default: 'no' - version_added: 2.9 - ignore_vsan: - description: - - If set to C(yes), VSAN will not be configured; all explicit and default VSAN related configurations will be ignored. - type: bool - default: 'no' - version_added: 2.9 - enable_drs: - description: - - If set to C(yes), will enable DRS when the cluster is created. - type: bool - default: 'no' - drs_enable_vm_behavior_overrides: - description: - - Determines whether DRS Behavior overrides for individual virtual machines are enabled. - - If set to C(True), overrides C(drs_default_vm_behavior). - type: bool - default: True - version_added: 2.8 - drs_default_vm_behavior: - description: - - Specifies the cluster-wide default DRS behavior for virtual machines. - - If set to C(partiallyAutomated), then vCenter generate recommendations for virtual machine migration and - for the placement with a host. vCenter automatically implement placement at power on. - - If set to C(manual), then vCenter generate recommendations for virtual machine migration and - for the placement with a host. vCenter should not implement the recommendations automatically. - - If set to C(fullyAutomated), then vCenter should automate both the migration of virtual machines - and their placement with a host at power on. - default: fullyAutomated - choices: [ fullyAutomated, manual, partiallyAutomated ] - version_added: 2.8 - drs_vmotion_rate: - description: - - Threshold for generated ClusterRecommendations. - default: 3 - choices: [ 1, 2, 3, 4, 5 ] - version_added: 2.8 - enable_ha: - description: - - If set to C(yes) will enable HA when the cluster is created. - type: bool - default: 'no' - ha_host_monitoring: - description: - - Indicates whether HA restarts virtual machines after a host fails. - - If set to C(enabled), HA restarts virtual machines after a host fails. - - If set to C(disabled), HA does not restart virtual machines after a host fails. - - If C(enable_ha) is set to C(no), then this value is ignored. - choices: [ 'enabled', 'disabled' ] - default: 'enabled' - version_added: 2.8 - ha_vm_monitoring: - description: - - Indicates the state of virtual machine health monitoring service. - - If set to C(vmAndAppMonitoring), HA response to both virtual machine and application heartbeat failure. - - If set to C(vmMonitoringDisabled), virtual machine health monitoring is disabled. - - If set to C(vmMonitoringOnly), HA response to virtual machine heartbeat failure. - - If C(enable_ha) is set to C(no), then this value is ignored. - choices: ['vmAndAppMonitoring', 'vmMonitoringOnly', 'vmMonitoringDisabled'] - default: 'vmMonitoringDisabled' - version_added: 2.8 - ha_failover_level: - description: - - Number of host failures that should be tolerated, still guaranteeing sufficient resources to - restart virtual machines on available hosts. - - Accepts integer values only. - default: 2 - version_added: 2.8 - ha_admission_control_enabled: - description: - - Determines if strict admission control is enabled. - - It is recommended to set this parameter to C(True), please refer documentation for more details. - default: True - type: bool - version_added: 2.8 - ha_vm_failure_interval: - description: - - The number of seconds after which virtual machine is declared as failed - if no heartbeat has been received. - - This setting is only valid if C(ha_vm_monitoring) is set to, either C(vmAndAppMonitoring) or C(vmMonitoringOnly). - - Unit is seconds. - default: 30 - version_added: 2.8 - ha_vm_min_up_time: - description: - - The number of seconds for the virtual machine's heartbeats to stabilize after - the virtual machine has been powered on. - - This setting is only valid if C(ha_vm_monitoring) is set to, either C(vmAndAppMonitoring) or C(vmMonitoringOnly). - - Unit is seconds. - default: 120 - version_added: 2.8 - ha_vm_max_failures: - description: - - Maximum number of failures and automated resets allowed during the time - that C(ha_vm_max_failure_window) specifies. - - This setting is only valid if C(ha_vm_monitoring) is set to, either C(vmAndAppMonitoring) or C(vmMonitoringOnly). - default: 3 - version_added: 2.8 - ha_vm_max_failure_window: - description: - - The number of seconds for the window during which up to C(ha_vm_max_failures) resets - can occur before automated responses stop. - - This setting is only valid if C(ha_vm_monitoring) is set to, either C(vmAndAppMonitoring) or C(vmMonitoringOnly). - - Unit is seconds. - - Default specifies no failure window. - default: -1 - version_added: 2.8 - ha_restart_priority: - description: - - Determines the preference that HA gives to a virtual machine if sufficient capacity is not available - to power on all failed virtual machines. - - This setting is only valid if C(ha_vm_monitoring) is set to, either C(vmAndAppMonitoring) or C(vmMonitoringOnly). - - If set to C(disabled), then HA is disabled for this virtual machine. - - If set to C(high), then virtual machine with this priority have a higher chance of powering on after a failure, - when there is insufficient capacity on hosts to meet all virtual machine needs. - - If set to C(medium), then virtual machine with this priority have an intermediate chance of powering on after a failure, - when there is insufficient capacity on hosts to meet all virtual machine needs. - - If set to C(low), then virtual machine with this priority have a lower chance of powering on after a failure, - when there is insufficient capacity on hosts to meet all virtual machine needs. - default: 'medium' - version_added: 2.8 - choices: [ 'disabled', 'high', 'low', 'medium' ] - enable_vsan: - description: - - If set to C(yes) will enable vSAN when the cluster is created. - type: bool - default: 'no' - vsan_auto_claim_storage: - description: - - Determines whether the VSAN service is configured to automatically claim local storage - on VSAN-enabled hosts in the cluster. - type: bool - default: False - version_added: 2.8 - state: - description: - - Create C(present) or remove C(absent) a VMware vSphere cluster. - choices: [ absent, present ] - default: present -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r""" -- name: Create Cluster - vmware_cluster: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter_name: datacenter - cluster_name: cluster - enable_ha: yes - enable_drs: yes - enable_vsan: yes - delegate_to: localhost - -- name: Create Cluster with additional changes - vmware_cluster: - hostname: "{{ vcenter_server }}" - username: "{{ vcenter_user }}" - password: "{{ vcenter_pass }}" - validate_certs: no - datacenter_name: DC0 - cluster_name: "{{ cluster_name }}" - enable_ha: True - ha_vm_monitoring: vmMonitoringOnly - enable_drs: True - drs_default_vm_behavior: partiallyAutomated - enable_vsan: True - register: cl_result - delegate_to: localhost - -- name: Delete Cluster - vmware_cluster: - hostname: "{{ vcenter_server }}" - username: "{{ vcenter_user }}" - password: "{{ vcenter_pass }}" - datacenter_name: datacenter - cluster_name: cluster - enable_ha: yes - enable_drs: yes - enable_vsan: yes - state: absent - delegate_to: localhost -""" - -RETURN = r"""# -""" - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import (PyVmomi, TaskError, find_datacenter_by_name, - vmware_argument_spec, wait_for_task) -from ansible.module_utils._text import to_native - - -class VMwareCluster(PyVmomi): - def __init__(self, module): - super(VMwareCluster, self).__init__(module) - self.cluster_name = module.params['cluster_name'] - self.datacenter_name = module.params['datacenter'] - self.ignore_drs = module.params['ignore_drs'] - self.ignore_ha = module.params['ignore_ha'] - self.ignore_vsan = module.params['ignore_vsan'] - self.enable_drs = module.params['enable_drs'] - self.enable_ha = module.params['enable_ha'] - self.enable_vsan = module.params['enable_vsan'] - self.desired_state = module.params['state'] - self.datacenter = None - self.cluster = None - - def process_state(self): - """ - Manage internal states of cluster - """ - cluster_states = { - 'absent': { - 'present': self.state_destroy_cluster, - 'absent': self.state_exit_unchanged, - }, - 'present': { - 'present': self.state_update_cluster, - 'absent': self.state_create_cluster, - } - } - current_state = self.check_cluster_configuration() - # Based on the desired_state and the current_state call - # the appropriate method from the dictionary - cluster_states[self.desired_state][current_state]() - - def configure_ha(self): - """ - Manage HA Configuration - Returns: Cluster DAS configuration spec - - """ - msg = 'Configuring HA using vmware_cluster module is deprecated and will be removed in version 2.12. ' \ - 'Please use vmware_cluster_ha module for the new functionality.' - self.module.deprecate(msg, '2.12') - - das_config = vim.cluster.DasConfigInfo() - das_config.enabled = self.enable_ha - das_config.admissionControlPolicy = vim.cluster.FailoverLevelAdmissionControlPolicy() - das_config.admissionControlPolicy.failoverLevel = self.params.get('ha_failover_level') - - ha_vm_monitoring = self.params.get('ha_vm_monitoring') - das_vm_config = None - if ha_vm_monitoring in ['vmMonitoringOnly', 'vmAndAppMonitoring']: - vm_tool_spec = vim.cluster.VmToolsMonitoringSettings() - vm_tool_spec.enabled = True - vm_tool_spec.vmMonitoring = ha_vm_monitoring - vm_tool_spec.failureInterval = self.params.get('ha_vm_failure_interval') - vm_tool_spec.minUpTime = self.params.get('ha_vm_min_up_time') - vm_tool_spec.maxFailures = self.params.get('ha_vm_max_failures') - vm_tool_spec.maxFailureWindow = self.params.get('ha_vm_max_failure_window') - - das_vm_config = vim.cluster.DasVmSettings() - das_vm_config.restartPriority = self.params.get('ha_restart_priority') - das_vm_config.isolationResponse = None - das_vm_config.vmToolsMonitoringSettings = vm_tool_spec - - das_config.admissionControlEnabled = self.params.get('ha_admission_control_enabled') - - das_config.hostMonitoring = self.params.get('ha_host_monitoring') - das_config.vmMonitoring = ha_vm_monitoring - das_config.defaultVmSettings = das_vm_config - - return das_config - - def configure_drs(self): - """ - Manage DRS configuration - Returns: Cluster DRS configuration spec - - """ - msg = 'Configuring DRS using vmware_cluster module is deprecated and will be removed in version 2.12. ' \ - 'Please use vmware_cluster_drs module for the new functionality.' - self.module.deprecate(msg, '2.12') - - drs_config = vim.cluster.DrsConfigInfo() - - drs_config.enabled = self.enable_drs - drs_config.enableVmBehaviorOverrides = self.params.get('drs_enable_vm_behavior_overrides') - drs_config.defaultVmBehavior = self.params.get('drs_default_vm_behavior') - drs_config.vmotionRate = self.params.get('drs_vmotion_rate') - - return drs_config - - def configure_vsan(self): - """ - Manage VSAN configuration - Returns: Cluster VSAN configuration spec - - """ - msg = 'Configuring VSAN using vmware_cluster module is deprecated and will be removed in version 2.12. ' \ - 'Please use vmware_cluster_vsan module for the new functionality.' - self.module.deprecate(msg, '2.12') - - vsan_config = vim.vsan.cluster.ConfigInfo() - vsan_config.enabled = self.enable_vsan - vsan_config.defaultConfig = vim.vsan.cluster.ConfigInfo.HostDefaultInfo() - vsan_config.defaultConfig.autoClaimStorage = self.params.get('vsan_auto_claim_storage') - return vsan_config - - def state_create_cluster(self): - """ - Create cluster with given configuration - """ - try: - cluster_config_spec = vim.cluster.ConfigSpecEx() - if not self.ignore_ha: - cluster_config_spec.dasConfig = self.configure_ha() - if not self.ignore_drs: - cluster_config_spec.drsConfig = self.configure_drs() - if self.enable_vsan and not self.ignore_vsan: - cluster_config_spec.vsanConfig = self.configure_vsan() - if not self.module.check_mode: - self.datacenter.hostFolder.CreateClusterEx(self.cluster_name, cluster_config_spec) - self.module.exit_json(changed=True) - except vim.fault.DuplicateName: - # To match other vmware_* modules - pass - except vmodl.fault.InvalidArgument as invalid_args: - self.module.fail_json(msg="Cluster configuration specification" - " parameter is invalid : %s" % to_native(invalid_args.msg)) - except vim.fault.InvalidName as invalid_name: - self.module.fail_json(msg="'%s' is an invalid name for a" - " cluster : %s" % (self.cluster_name, - to_native(invalid_name.msg))) - except vmodl.fault.NotSupported as not_supported: - # This should never happen - self.module.fail_json(msg="Trying to create a cluster on an incorrect" - " folder object : %s" % to_native(not_supported.msg)) - except vmodl.RuntimeFault as runtime_fault: - self.module.fail_json(msg=to_native(runtime_fault.msg)) - except vmodl.MethodFault as method_fault: - # This should never happen either - self.module.fail_json(msg=to_native(method_fault.msg)) - except Exception as generic_exc: - self.module.fail_json(msg="Failed to create cluster" - " due to generic exception %s" % to_native(generic_exc)) - - def state_destroy_cluster(self): - """ - Destroy cluster - """ - changed, result = True, None - - try: - if not self.module.check_mode: - task = self.cluster.Destroy_Task() - changed, result = wait_for_task(task) - self.module.exit_json(changed=changed, result=result) - except vim.fault.VimFault as vim_fault: - self.module.fail_json(msg=to_native(vim_fault.msg)) - except vmodl.RuntimeFault as runtime_fault: - self.module.fail_json(msg=to_native(runtime_fault.msg)) - except vmodl.MethodFault as method_fault: - self.module.fail_json(msg=to_native(method_fault.msg)) - except Exception as generic_exc: - self.module.fail_json(msg="Failed to destroy cluster" - " due to generic exception %s" % to_native(generic_exc)) - - def state_exit_unchanged(self): - """ - Exit without any change - """ - self.module.exit_json(changed=False) - - def state_update_cluster(self): - """ - Update cluster configuration of existing cluster - """ - changed, result = False, None - cluster_config_spec = vim.cluster.ConfigSpecEx() - diff = False # Triggers Reconfigure Task only when there is a change - if self.check_ha_config_diff() and not self.ignore_ha: - cluster_config_spec.dasConfig = self.configure_ha() - diff = True - if self.check_drs_config_diff() and not self.ignore_drs: - cluster_config_spec.drsConfig = self.configure_drs() - diff = True - if self.check_vsan_config_diff() and not self.ignore_vsan: - cluster_config_spec.vsanConfig = self.configure_vsan() - diff = True - - try: - if not self.module.check_mode and diff: - task = self.cluster.ReconfigureComputeResource_Task(cluster_config_spec, True) - changed, result = wait_for_task(task) - self.module.exit_json(changed=changed, result=result) - except vmodl.RuntimeFault as runtime_fault: - self.module.fail_json(msg=to_native(runtime_fault.msg)) - except vmodl.MethodFault as method_fault: - self.module.fail_json(msg=to_native(method_fault.msg)) - except TaskError as task_e: - self.module.fail_json(msg=to_native(task_e)) - except Exception as generic_exc: - self.module.fail_json(msg="Failed to update cluster" - " due to generic exception %s" % to_native(generic_exc)) - - def check_ha_config_diff(self): - """ - Check HA configuration diff - Returns: True if there is diff, else False - - """ - das_config = self.cluster.configurationEx.dasConfig - if das_config.enabled != self.enable_ha or \ - das_config.admissionControlPolicy.failoverLevel != self.params.get('ha_failover_level') or \ - das_config.vmMonitoring != self.params.get('ha_vm_monitoring') or \ - das_config.hostMonitoring != self.params.get('ha_host_monitoring') or \ - das_config.admissionControlPolicy.failoverLevel != self.params.get('ha_failover_level') or \ - das_config.admissionControlEnabled != self.params.get('ha_admission_control_enabled') or \ - das_config.defaultVmSettings.restartPriority != self.params.get('ha_restart_priority') or \ - das_config.defaultVmSettings.vmToolsMonitoringSettings.vmMonitoring != self.params.get('ha_vm_monitoring') or \ - das_config.defaultVmSettings.vmToolsMonitoringSettings.failureInterval != self.params.get('ha_vm_failure_interval') or \ - das_config.defaultVmSettings.vmToolsMonitoringSettings.minUpTime != self.params.get('ha_vm_min_up_time') or \ - das_config.defaultVmSettings.vmToolsMonitoringSettings.maxFailures != self.params.get('ha_vm_max_failures') or \ - das_config.defaultVmSettings.vmToolsMonitoringSettings.maxFailureWindow != self.params.get('ha_vm_max_failure_window'): - return True - return False - - def check_drs_config_diff(self): - """ - Check DRS configuration diff - Returns: True if there is diff, else False - - """ - drs_config = self.cluster.configurationEx.drsConfig - - if drs_config.enabled != self.enable_drs or \ - drs_config.enableVmBehaviorOverrides != self.params.get('drs_enable_vm_behavior_overrides') or \ - drs_config.defaultVmBehavior != self.params.get('drs_default_vm_behavior') or \ - drs_config.vmotionRate != self.params.get('drs_vmotion_rate'): - return True - return False - - def check_vsan_config_diff(self): - """ - Check VSAN configuration diff - Returns: True if there is diff, else False - - """ - vsan_config = self.cluster.configurationEx.vsanConfigInfo - - if vsan_config.enabled != self.enable_vsan or \ - vsan_config.defaultConfig.autoClaimStorage != self.params.get('vsan_auto_claim_storage'): - return True - return False - - def check_cluster_configuration(self): - """ - Check cluster configuration - Returns: 'Present' if cluster exists, else 'absent' - - """ - try: - self.datacenter = find_datacenter_by_name(self.content, self.datacenter_name) - if self.datacenter is None: - self.module.fail_json(msg="Datacenter %s does not exist." % self.datacenter_name) - self.cluster = self.find_cluster_by_name(cluster_name=self.cluster_name) - - if self.cluster is None: - return 'absent' - - return 'present' - except vmodl.RuntimeFault as runtime_fault: - self.module.fail_json(msg=to_native(runtime_fault.msg)) - except vmodl.MethodFault as method_fault: - self.module.fail_json(msg=to_native(method_fault.msg)) - except Exception as generic_exc: - self.module.fail_json(msg="Failed to check configuration" - " due to generic exception %s" % to_native(generic_exc)) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update(dict( - cluster_name=dict(type='str', required=True), - datacenter=dict(type='str', required=True, aliases=['datacenter_name']), - state=dict(type='str', - default='present', - choices=['absent', 'present']), - # DRS - ignore_drs=dict(type='bool', default=False), - enable_drs=dict(type='bool', default=False), - drs_enable_vm_behavior_overrides=dict(type='bool', default=True), - drs_default_vm_behavior=dict(type='str', - choices=['fullyAutomated', 'manual', 'partiallyAutomated'], - default='fullyAutomated'), - drs_vmotion_rate=dict(type='int', - choices=range(1, 6), - default=3), - # HA - ignore_ha=dict(type='bool', default=False), - enable_ha=dict(type='bool', default=False), - ha_failover_level=dict(type='int', default=2), - ha_host_monitoring=dict(type='str', - default='enabled', - choices=['enabled', 'disabled']), - # HA VM Monitoring related parameters - ha_vm_monitoring=dict(type='str', - choices=['vmAndAppMonitoring', 'vmMonitoringOnly', 'vmMonitoringDisabled'], - default='vmMonitoringDisabled'), - ha_vm_failure_interval=dict(type='int', default=30), - ha_vm_min_up_time=dict(type='int', default=120), - ha_vm_max_failures=dict(type='int', default=3), - ha_vm_max_failure_window=dict(type='int', default=-1), - - ha_restart_priority=dict(type='str', - choices=['high', 'low', 'medium', 'disabled'], - default='medium'), - ha_admission_control_enabled=dict(type='bool', default=True), - # VSAN - ignore_vsan=dict(type='bool', default=False), - enable_vsan=dict(type='bool', default=False), - vsan_auto_claim_storage=dict(type='bool', default=False), - )) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - vmware_cluster = VMwareCluster(module) - vmware_cluster.process_state() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_cluster_drs.py b/lib/ansible/modules/cloud/vmware/vmware_cluster_drs.py deleted file mode 100644 index 6818288822..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_cluster_drs.py +++ /dev/null @@ -1,238 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2015, Joseph Callen <jcallen () csc.com> -# Copyright: (c) 2018, Ansible Project -# -# 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_cluster_drs -short_description: Manage Distributed Resource Scheduler (DRS) on VMware vSphere clusters -description: - - Manages DRS on VMware vSphere clusters. - - All values and VMware object names are case sensitive. -version_added: '2.9' -author: -- Joseph Callen (@jcpowermac) -- Abhijeet Kasurde (@Akasurde) -requirements: - - Tested on ESXi 5.5 and 6.5. - - PyVmomi installed. -options: - cluster_name: - description: - - The name of the cluster to be managed. - type: str - required: yes - datacenter: - description: - - The name of the datacenter. - type: str - required: yes - aliases: [ datacenter_name ] - enable_drs: - description: - - Whether to enable DRS. - type: bool - default: 'no' - drs_enable_vm_behavior_overrides: - description: - - Whether DRS Behavior overrides for individual virtual machines are enabled. - - If set to C(True), overrides C(drs_default_vm_behavior). - type: bool - default: True - drs_default_vm_behavior: - description: - - Specifies the cluster-wide default DRS behavior for virtual machines. - - If set to C(partiallyAutomated), vCenter generates recommendations for virtual machine migration and - for the placement with a host, then automatically implements placement recommendations at power on. - - If set to C(manual), then vCenter generates recommendations for virtual machine migration and - for the placement with a host, but does not implement the recommendations automatically. - - If set to C(fullyAutomated), then vCenter automates both the migration of virtual machines - and their placement with a host at power on. - type: str - default: fullyAutomated - choices: [ fullyAutomated, manual, partiallyAutomated ] - drs_vmotion_rate: - description: - - Threshold for generated ClusterRecommendations. - type: int - default: 3 - choices: [ 1, 2, 3, 4, 5 ] - advanced_settings: - version_added: "2.10" - description: - - A dictionary of advanced DRS settings. - default: {} - type: dict -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r""" -- name: Enable DRS - vmware_cluster_drs: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter_name: datacenter - cluster_name: cluster - enable_drs: yes - delegate_to: localhost - -- name: Enable DRS and distribute a more even number of virtual machines across hosts for availability - vmware_cluster_drs: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter_name: datacenter - cluster_name: cluster - enable_drs: yes - advanced_settings: - 'TryBalanceVmsPerHost': '1' - delegate_to: localhost - -- name: Enable DRS and set default VM behavior to partially automated - vmware_cluster_drs: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter_name: DC0 - cluster_name: "{{ cluster_name }}" - enable_drs: True - drs_default_vm_behavior: partiallyAutomated - delegate_to: localhost -""" - -RETURN = r"""# -""" - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import (PyVmomi, TaskError, find_datacenter_by_name, - vmware_argument_spec, wait_for_task, option_diff) -from ansible.module_utils._text import to_native - - -class VMwareCluster(PyVmomi): - def __init__(self, module): - super(VMwareCluster, self).__init__(module) - self.cluster_name = module.params['cluster_name'] - self.datacenter_name = module.params['datacenter'] - self.enable_drs = module.params['enable_drs'] - self.datacenter = None - self.cluster = None - - self.datacenter = find_datacenter_by_name(self.content, self.datacenter_name) - if self.datacenter is None: - self.module.fail_json(msg="Datacenter %s does not exist." % self.datacenter_name) - - self.cluster = self.find_cluster_by_name(cluster_name=self.cluster_name) - if self.cluster is None: - self.module.fail_json(msg="Cluster %s does not exist." % self.cluster_name) - - self.advanced_settings = self.params.get('advanced_settings') - if self.advanced_settings: - self.changed_advanced_settings = option_diff(self.advanced_settings, self.cluster.configurationEx.drsConfig.option) - else: - self.changed_advanced_settings = None - - def check_drs_config_diff(self): - """ - Check DRS configuration diff - Returns: True if there is diff, else False - - """ - drs_config = self.cluster.configurationEx.drsConfig - - if drs_config.enabled != self.enable_drs or \ - drs_config.enableVmBehaviorOverrides != self.params.get('drs_enable_vm_behavior_overrides') or \ - drs_config.defaultVmBehavior != self.params.get('drs_default_vm_behavior') or \ - drs_config.vmotionRate != self.params.get('drs_vmotion_rate'): - return True - - if self.changed_advanced_settings: - return True - - return False - - def configure_drs(self): - """ - Manage DRS configuration - - """ - changed, result = False, None - - if self.check_drs_config_diff(): - if not self.module.check_mode: - cluster_config_spec = vim.cluster.ConfigSpecEx() - cluster_config_spec.drsConfig = vim.cluster.DrsConfigInfo() - cluster_config_spec.drsConfig.enabled = self.enable_drs - cluster_config_spec.drsConfig.enableVmBehaviorOverrides = self.params.get('drs_enable_vm_behavior_overrides') - cluster_config_spec.drsConfig.defaultVmBehavior = self.params.get('drs_default_vm_behavior') - cluster_config_spec.drsConfig.vmotionRate = self.params.get('drs_vmotion_rate') - - if self.changed_advanced_settings: - cluster_config_spec.drsConfig.option = self.changed_advanced_settings - - try: - task = self.cluster.ReconfigureComputeResource_Task(cluster_config_spec, True) - changed, result = wait_for_task(task) - except vmodl.RuntimeFault as runtime_fault: - self.module.fail_json(msg=to_native(runtime_fault.msg)) - except vmodl.MethodFault as method_fault: - self.module.fail_json(msg=to_native(method_fault.msg)) - except TaskError as task_e: - self.module.fail_json(msg=to_native(task_e)) - except Exception as generic_exc: - self.module.fail_json(msg="Failed to update cluster" - " due to generic exception %s" % to_native(generic_exc)) - else: - changed = True - - self.module.exit_json(changed=changed, result=result) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update(dict( - cluster_name=dict(type='str', required=True), - datacenter=dict(type='str', required=True, aliases=['datacenter_name']), - # DRS - enable_drs=dict(type='bool', default=False), - drs_enable_vm_behavior_overrides=dict(type='bool', default=True), - drs_default_vm_behavior=dict(type='str', - choices=['fullyAutomated', 'manual', 'partiallyAutomated'], - default='fullyAutomated'), - drs_vmotion_rate=dict(type='int', - choices=range(1, 6), - default=3), - advanced_settings=dict(type='dict', default=dict(), required=False), - )) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - vmware_cluster_drs = VMwareCluster(module) - vmware_cluster_drs.configure_drs() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_cluster_ha.py b/lib/ansible/modules/cloud/vmware/vmware_cluster_ha.py deleted file mode 100644 index 2dd22f1621..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_cluster_ha.py +++ /dev/null @@ -1,469 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2015, Joseph Callen <jcallen () csc.com> -# Copyright: (c) 2018, Ansible Project -# -# 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_cluster_ha -short_description: Manage High Availability (HA) on VMware vSphere clusters -description: - - Manages HA configuration on VMware vSphere clusters. - - All values and VMware object names are case sensitive. -version_added: '2.9' -author: -- Joseph Callen (@jcpowermac) -- Abhijeet Kasurde (@Akasurde) -requirements: - - Tested on ESXi 5.5 and 6.5. - - PyVmomi installed. -options: - cluster_name: - description: - - The name of the cluster to be managed. - type: str - required: yes - datacenter: - description: - - The name of the datacenter. - type: str - required: yes - aliases: [ datacenter_name ] - enable_ha: - description: - - Whether to enable HA. - type: bool - default: 'no' - ha_host_monitoring: - description: - - Whether HA restarts virtual machines after a host fails. - - If set to C(enabled), HA restarts virtual machines after a host fails. - - If set to C(disabled), HA does not restart virtual machines after a host fails. - - If C(enable_ha) is set to C(no), then this value is ignored. - type: str - choices: [ 'enabled', 'disabled' ] - default: 'enabled' - ha_vm_monitoring: - description: - - State of virtual machine health monitoring service. - - If set to C(vmAndAppMonitoring), HA response to both virtual machine and application heartbeat failure. - - If set to C(vmMonitoringDisabled), virtual machine health monitoring is disabled. - - If set to C(vmMonitoringOnly), HA response to virtual machine heartbeat failure. - - If C(enable_ha) is set to C(no), then this value is ignored. - type: str - choices: ['vmAndAppMonitoring', 'vmMonitoringOnly', 'vmMonitoringDisabled'] - default: 'vmMonitoringDisabled' - host_isolation_response: - description: - - Indicates whether or VMs should be powered off if a host determines that it is isolated from the rest of the compute resource. - - If set to C(none), do not power off VMs in the event of a host network isolation. - - If set to C(powerOff), power off VMs in the event of a host network isolation. - - If set to C(shutdown), shut down VMs guest operating system in the event of a host network isolation. - type: str - choices: ['none', 'powerOff', 'shutdown'] - default: 'none' - slot_based_admission_control: - description: - - Configure slot based admission control policy. - - C(slot_based_admission_control), C(reservation_based_admission_control) and C(failover_host_admission_control) are mutually exclusive. - suboptions: - failover_level: - description: - - Number of host failures that should be tolerated. - type: int - required: true - type: dict - reservation_based_admission_control: - description: - - Configure reservation based admission control policy. - - C(slot_based_admission_control), C(reservation_based_admission_control) and C(failover_host_admission_control) are mutually exclusive. - suboptions: - failover_level: - description: - - Number of host failures that should be tolerated. - type: int - required: true - auto_compute_percentages: - description: - - By default, C(failover_level) is used to calculate C(cpu_failover_resources_percent) and C(memory_failover_resources_percent). - If a user wants to override the percentage values, he has to set this field to false. - type: bool - default: true - cpu_failover_resources_percent: - description: - - Percentage of CPU resources in the cluster to reserve for failover. - Ignored if C(auto_compute_percentages) is not set to false. - type: int - default: 50 - memory_failover_resources_percent: - description: - - Percentage of memory resources in the cluster to reserve for failover. - Ignored if C(auto_compute_percentages) is not set to false. - type: int - default: 50 - type: dict - failover_host_admission_control: - description: - - Configure dedicated failover hosts. - - C(slot_based_admission_control), C(reservation_based_admission_control) and C(failover_host_admission_control) are mutually exclusive. - suboptions: - failover_hosts: - description: - - List of dedicated failover hosts. - type: list - required: true - type: dict - ha_vm_failure_interval: - description: - - The number of seconds after which virtual machine is declared as failed - if no heartbeat has been received. - - This setting is only valid if C(ha_vm_monitoring) is set to, either C(vmAndAppMonitoring) or C(vmMonitoringOnly). - - Unit is seconds. - type: int - default: 30 - ha_vm_min_up_time: - description: - - The number of seconds for the virtual machine's heartbeats to stabilize after - the virtual machine has been powered on. - - Valid only when I(ha_vm_monitoring) is set to either C(vmAndAppMonitoring) or C(vmMonitoringOnly). - - Unit is seconds. - type: int - default: 120 - ha_vm_max_failures: - description: - - Maximum number of failures and automated resets allowed during the time - that C(ha_vm_max_failure_window) specifies. - - Valid only when I(ha_vm_monitoring) is set to either C(vmAndAppMonitoring) or C(vmMonitoringOnly). - type: int - default: 3 - ha_vm_max_failure_window: - description: - - The number of seconds for the window during which up to C(ha_vm_max_failures) resets - can occur before automated responses stop. - - Valid only when I(ha_vm_monitoring) is set to either C(vmAndAppMonitoring) or C(vmMonitoringOnly). - - Unit is seconds. - - Default specifies no failure window. - type: int - default: -1 - ha_restart_priority: - description: - - Priority HA gives to a virtual machine if sufficient capacity is not available - to power on all failed virtual machines. - - Valid only if I(ha_vm_monitoring) is set to either C(vmAndAppMonitoring) or C(vmMonitoringOnly). - - If set to C(disabled), then HA is disabled for this virtual machine. - - If set to C(high), then virtual machine with this priority have a higher chance of powering on after a failure, - when there is insufficient capacity on hosts to meet all virtual machine needs. - - If set to C(medium), then virtual machine with this priority have an intermediate chance of powering on after a failure, - when there is insufficient capacity on hosts to meet all virtual machine needs. - - If set to C(low), then virtual machine with this priority have a lower chance of powering on after a failure, - when there is insufficient capacity on hosts to meet all virtual machine needs. - type: str - default: 'medium' - choices: [ 'disabled', 'high', 'low', 'medium' ] - advanced_settings: - version_added: "2.10" - description: - - A dictionary of advanced HA settings. - default: {} - type: dict -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r""" -- name: Enable HA without admission control - vmware_cluster_ha: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter_name: datacenter - cluster_name: cluster - enable_ha: yes - delegate_to: localhost - -- name: Enable HA and VM monitoring without admission control - vmware_cluster_ha: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter_name: DC0 - cluster_name: "{{ cluster_name }}" - enable_ha: True - ha_vm_monitoring: vmMonitoringOnly - delegate_to: localhost - -- name: Enable HA with admission control reserving 50% of resources for HA - vmware_cluster_ha: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter_name: datacenter - cluster_name: cluster - enable_ha: yes - reservation_based_admission_control: - auto_compute_percentages: False - failover_level: 1 - cpu_failover_resources_percent: 50 - memory_failover_resources_percent: 50 - delegate_to: localhost -""" - -RETURN = r"""# -""" - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import (PyVmomi, TaskError, find_datacenter_by_name, - vmware_argument_spec, wait_for_task, option_diff) -from ansible.module_utils._text import to_native - - -class VMwareCluster(PyVmomi): - def __init__(self, module): - super(VMwareCluster, self).__init__(module) - self.cluster_name = module.params['cluster_name'] - self.datacenter_name = module.params['datacenter'] - self.enable_ha = module.params['enable_ha'] - self.datacenter = None - self.cluster = None - self.host_isolation_response = getattr(vim.cluster.DasVmSettings.IsolationResponse, self.params.get('host_isolation_response')) - - if self.enable_ha and ( - self.params.get('slot_based_admission_control') or - self.params.get('reservation_based_admission_control') or - self.params.get('failover_host_admission_control')): - self.ha_admission_control = True - else: - self.ha_admission_control = False - - self.datacenter = find_datacenter_by_name(self.content, self.datacenter_name) - if self.datacenter is None: - self.module.fail_json(msg="Datacenter %s does not exist." % self.datacenter_name) - - self.cluster = self.find_cluster_by_name(cluster_name=self.cluster_name) - if self.cluster is None: - self.module.fail_json(msg="Cluster %s does not exist." % self.cluster_name) - - self.advanced_settings = self.params.get('advanced_settings') - if self.advanced_settings: - self.changed_advanced_settings = option_diff(self.advanced_settings, self.cluster.configurationEx.dasConfig.option) - else: - self.changed_advanced_settings = None - - def get_failover_hosts(self): - """ - Get failover hosts for failover_host_admission_control policy - Returns: List of ESXi hosts sorted by name - - """ - policy = self.params.get('failover_host_admission_control') - hosts = [] - all_hosts = dict((h.name, h) for h in self.get_all_hosts_by_cluster(self.cluster_name)) - for host in policy.get('failover_hosts'): - if host in all_hosts: - hosts.append(all_hosts.get(host)) - else: - self.module.fail_json(msg="Host %s is not a member of cluster %s." % (host, self.cluster_name)) - hosts.sort(key=lambda h: h.name) - return hosts - - def check_ha_config_diff(self): - """ - Check HA configuration diff - Returns: True if there is diff, else False - - """ - das_config = self.cluster.configurationEx.dasConfig - if das_config.enabled != self.enable_ha: - return True - - if self.enable_ha and ( - das_config.vmMonitoring != self.params.get('ha_vm_monitoring') or - das_config.hostMonitoring != self.params.get('ha_host_monitoring') or - das_config.admissionControlEnabled != self.ha_admission_control or - das_config.defaultVmSettings.restartPriority != self.params.get('ha_restart_priority') or - das_config.defaultVmSettings.isolationResponse != self.host_isolation_response or - das_config.defaultVmSettings.vmToolsMonitoringSettings.vmMonitoring != self.params.get('ha_vm_monitoring') or - das_config.defaultVmSettings.vmToolsMonitoringSettings.failureInterval != self.params.get('ha_vm_failure_interval') or - das_config.defaultVmSettings.vmToolsMonitoringSettings.minUpTime != self.params.get('ha_vm_min_up_time') or - das_config.defaultVmSettings.vmToolsMonitoringSettings.maxFailures != self.params.get('ha_vm_max_failures') or - das_config.defaultVmSettings.vmToolsMonitoringSettings.maxFailureWindow != self.params.get('ha_vm_max_failure_window')): - return True - - if self.ha_admission_control: - if self.params.get('slot_based_admission_control'): - policy = self.params.get('slot_based_admission_control') - if not isinstance(das_config.admissionControlPolicy, vim.cluster.FailoverLevelAdmissionControlPolicy) or \ - das_config.admissionControlPolicy.failoverLevel != policy.get('failover_level'): - return True - elif self.params.get('reservation_based_admission_control'): - policy = self.params.get('reservation_based_admission_control') - auto_compute_percentages = policy.get('auto_compute_percentages') - if not isinstance(das_config.admissionControlPolicy, vim.cluster.FailoverResourcesAdmissionControlPolicy) or \ - das_config.admissionControlPolicy.autoComputePercentages != auto_compute_percentages or \ - das_config.admissionControlPolicy.failoverLevel != policy.get('failover_level'): - return True - if not auto_compute_percentages: - if das_config.admissionControlPolicy.cpuFailoverResourcesPercent != policy.get('cpu_failover_resources_percent') or \ - das_config.admissionControlPolicy.memoryFailoverResourcesPercent != policy.get('memory_failover_resources_percent'): - return True - elif self.params.get('failover_host_admission_control'): - policy = self.params.get('failover_host_admission_control') - if not isinstance(das_config.admissionControlPolicy, vim.cluster.FailoverHostAdmissionControlPolicy): - return True - das_config.admissionControlPolicy.failoverHosts.sort(key=lambda h: h.name) - if das_config.admissionControlPolicy.failoverHosts != self.get_failover_hosts(): - return True - - if self.changed_advanced_settings: - return True - - return False - - def configure_ha(self): - """ - Manage HA Configuration - - """ - changed, result = False, None - - if self.check_ha_config_diff(): - if not self.module.check_mode: - cluster_config_spec = vim.cluster.ConfigSpecEx() - cluster_config_spec.dasConfig = vim.cluster.DasConfigInfo() - cluster_config_spec.dasConfig.enabled = self.enable_ha - - if self.enable_ha: - vm_tool_spec = vim.cluster.VmToolsMonitoringSettings() - vm_tool_spec.enabled = True - vm_tool_spec.vmMonitoring = self.params.get('ha_vm_monitoring') - vm_tool_spec.failureInterval = self.params.get('ha_vm_failure_interval') - vm_tool_spec.minUpTime = self.params.get('ha_vm_min_up_time') - vm_tool_spec.maxFailures = self.params.get('ha_vm_max_failures') - vm_tool_spec.maxFailureWindow = self.params.get('ha_vm_max_failure_window') - - das_vm_config = vim.cluster.DasVmSettings() - das_vm_config.restartPriority = self.params.get('ha_restart_priority') - das_vm_config.isolationResponse = self.host_isolation_response - das_vm_config.vmToolsMonitoringSettings = vm_tool_spec - cluster_config_spec.dasConfig.defaultVmSettings = das_vm_config - - cluster_config_spec.dasConfig.admissionControlEnabled = self.ha_admission_control - - if self.ha_admission_control: - if self.params.get('slot_based_admission_control'): - cluster_config_spec.dasConfig.admissionControlPolicy = vim.cluster.FailoverLevelAdmissionControlPolicy() - policy = self.params.get('slot_based_admission_control') - cluster_config_spec.dasConfig.admissionControlPolicy.failoverLevel = policy.get('failover_level') - elif self.params.get('reservation_based_admission_control'): - cluster_config_spec.dasConfig.admissionControlPolicy = vim.cluster.FailoverResourcesAdmissionControlPolicy() - policy = self.params.get('reservation_based_admission_control') - auto_compute_percentages = policy.get('auto_compute_percentages') - cluster_config_spec.dasConfig.admissionControlPolicy.autoComputePercentages = auto_compute_percentages - cluster_config_spec.dasConfig.admissionControlPolicy.failoverLevel = policy.get('failover_level') - if not auto_compute_percentages: - cluster_config_spec.dasConfig.admissionControlPolicy.cpuFailoverResourcesPercent = \ - policy.get('cpu_failover_resources_percent') - cluster_config_spec.dasConfig.admissionControlPolicy.memoryFailoverResourcesPercent = \ - policy.get('memory_failover_resources_percent') - elif self.params.get('failover_host_admission_control'): - cluster_config_spec.dasConfig.admissionControlPolicy = vim.cluster.FailoverHostAdmissionControlPolicy() - policy = self.params.get('failover_host_admission_control') - cluster_config_spec.dasConfig.admissionControlPolicy.failoverHosts = self.get_failover_hosts() - - cluster_config_spec.dasConfig.hostMonitoring = self.params.get('ha_host_monitoring') - cluster_config_spec.dasConfig.vmMonitoring = self.params.get('ha_vm_monitoring') - - if self.changed_advanced_settings: - cluster_config_spec.dasConfig.option = self.changed_advanced_settings - - try: - task = self.cluster.ReconfigureComputeResource_Task(cluster_config_spec, True) - changed, result = wait_for_task(task) - except vmodl.RuntimeFault as runtime_fault: - self.module.fail_json(msg=to_native(runtime_fault.msg)) - except vmodl.MethodFault as method_fault: - self.module.fail_json(msg=to_native(method_fault.msg)) - except TaskError as task_e: - self.module.fail_json(msg=to_native(task_e)) - except Exception as generic_exc: - self.module.fail_json(msg="Failed to update cluster" - " due to generic exception %s" % to_native(generic_exc)) - else: - changed = True - - self.module.exit_json(changed=changed, result=result) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update(dict( - cluster_name=dict(type='str', required=True), - datacenter=dict(type='str', required=True, aliases=['datacenter_name']), - # HA - enable_ha=dict(type='bool', default=False), - ha_host_monitoring=dict(type='str', - default='enabled', - choices=['enabled', 'disabled']), - host_isolation_response=dict(type='str', - default='none', - choices=['none', 'powerOff', 'shutdown']), - advanced_settings=dict(type='dict', default=dict(), required=False), - # HA VM Monitoring related parameters - ha_vm_monitoring=dict(type='str', - choices=['vmAndAppMonitoring', 'vmMonitoringOnly', 'vmMonitoringDisabled'], - default='vmMonitoringDisabled'), - ha_vm_failure_interval=dict(type='int', default=30), - ha_vm_min_up_time=dict(type='int', default=120), - ha_vm_max_failures=dict(type='int', default=3), - ha_vm_max_failure_window=dict(type='int', default=-1), - - ha_restart_priority=dict(type='str', - choices=['high', 'low', 'medium', 'disabled'], - default='medium'), - # HA Admission Control related parameters - slot_based_admission_control=dict(type='dict', options=dict( - failover_level=dict(type='int', required=True), - )), - reservation_based_admission_control=dict(type='dict', options=dict( - auto_compute_percentages=dict(type='bool', default=True), - failover_level=dict(type='int', required=True), - cpu_failover_resources_percent=dict(type='int', default=50), - memory_failover_resources_percent=dict(type='int', default=50), - )), - failover_host_admission_control=dict(type='dict', options=dict( - failover_hosts=dict(type='list', elements='str', required=True), - )), - )) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - mutually_exclusive=[ - ['slot_based_admission_control', 'reservation_based_admission_control', 'failover_host_admission_control'] - ] - ) - - vmware_cluster_ha = VMwareCluster(module) - vmware_cluster_ha.configure_ha() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_cluster_info.py b/lib/ansible/modules/cloud/vmware/vmware_cluster_info.py deleted file mode 100644 index b441954aa2..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_cluster_info.py +++ /dev/null @@ -1,290 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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 = ''' ---- -module: vmware_cluster_info -short_description: Gather info about clusters available in given vCenter -description: - - This module can be used to gather information about clusters in VMWare infrastructure. - - All values and VMware object names are case sensitive. - - This module was called C(vmware_cluster_facts) before Ansible 2.9. The usage did not change. -version_added: '2.6' -author: - - Abhijeet Kasurde (@Akasurde) - - Christian Neugum (@digifuchsi) -notes: - - Tested on vSphere 6.5, 6.7 -requirements: - - "python >= 2.6" - - PyVmomi -options: - datacenter: - description: - - Datacenter to search for cluster/s. - - This parameter is required, if C(cluster_name) is not supplied. - required: False - type: str - cluster_name: - description: - - Name of the cluster. - - If set, information of this cluster will be returned. - - This parameter is required, if C(datacenter) is not supplied. - required: False - type: str - show_tag: - description: - - Tags related to cluster are shown if set to C(True). - default: False - type: bool - version_added: 2.9 -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Gather cluster info from given datacenter - vmware_cluster_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: ha-datacenter - validate_certs: no - delegate_to: localhost - register: cluster_info - -- name: Gather info from datacenter about specific cluster - vmware_cluster_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: DC0_C0 - delegate_to: localhost - register: cluster_info - -- name: Gather info from datacenter about specific cluster with tags - vmware_cluster_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: DC0_C0 - show_tag: True - delegate_to: localhost - register: cluster_info -''' - -RETURN = """ -clusters: - description: metadata about the available clusters - returned: always - type: dict - sample: { - "DC0_C0": { - "drs_default_vm_behavior": null, - "drs_enable_vm_behavior_overrides": null, - "drs_vmotion_rate": null, - "enable_ha": null, - "enabled_drs": true, - "enabled_vsan": false, - "ha_admission_control_enabled": null, - "ha_failover_level": null, - "ha_host_monitoring": null, - "ha_restart_priority": null, - "ha_vm_failure_interval": null, - "ha_vm_max_failure_window": null, - "ha_vm_max_failures": null, - "ha_vm_min_up_time": null, - "ha_vm_monitoring": null, - "ha_vm_tools_monitoring": null, - "vsan_auto_claim_storage": false, - "hosts": [ - { - "name": "esxi01.vsphere.local", - "folder": "/DC0/host/DC0_C0", - }, - { - "name": "esxi02.vsphere.local", - "folder": "/DC0/host/DC0_C0", - }, - { - "name": "esxi03.vsphere.local", - "folder": "/DC0/host/DC0_C0", - }, - { - "name": "esxi04.vsphere.local", - "folder": "/DC0/host/DC0_C0", - }, - ], - "tags": [ - { - "category_id": "urn:vmomi:InventoryServiceCategory:9fbf83de-7903-442e-8004-70fd3940297c:GLOBAL", - "category_name": "sample_cluster_cat_0001", - "description": "", - "id": "urn:vmomi:InventoryServiceTag:93d680db-b3a6-4834-85ad-3e9516e8fee8:GLOBAL", - "name": "sample_cluster_tag_0001" - } - ], - }, - } -""" - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec, find_datacenter_by_name, find_cluster_by_name -from ansible.module_utils.vmware_rest_client import VmwareRestClient - - -class VmwreClusterInfoManager(PyVmomi): - def __init__(self, module): - super(VmwreClusterInfoManager, self).__init__(module) - datacenter = self.params.get('datacenter') - cluster_name = self.params.get('cluster_name') - self.cluster_objs = [] - if datacenter: - datacenter_obj = find_datacenter_by_name(self.content, datacenter_name=datacenter) - if datacenter_obj is None: - self.module.fail_json(msg="Failed to find datacenter '%s'" % datacenter) - self.cluster_objs = self.get_all_cluster_objs(parent=datacenter_obj) - elif cluster_name: - cluster_obj = find_cluster_by_name(self.content, cluster_name=cluster_name) - if cluster_obj is None: - self.module.fail_json(msg="Failed to find cluster '%s'" % cluster_name) - - self.cluster_objs = [cluster_obj] - - def get_all_cluster_objs(self, parent): - """ - Get all cluster managed objects from given parent object - Args: - parent: Managed objected of datacenter or host folder - - Returns: List of host managed objects - - """ - cluster_objs = [] - if isinstance(parent, vim.Datacenter): - folder = parent.hostFolder - else: - folder = parent - - for child in folder.childEntity: - if isinstance(child, vim.Folder): - cluster_objs = cluster_objs + self.get_all_cluster_objs(child) - if isinstance(child, vim.ClusterComputeResource): - cluster_objs.append(child) - return cluster_objs - - def gather_cluster_info(self): - """ - Gather information about cluster - """ - results = dict(changed=False, clusters=dict()) - for cluster in self.cluster_objs: - # Default values - ha_failover_level = None - ha_restart_priority = None - ha_vm_tools_monitoring = None - ha_vm_min_up_time = None - ha_vm_max_failures = None - ha_vm_max_failure_window = None - ha_vm_failure_interval = None - enabled_vsan = False - vsan_auto_claim_storage = False - hosts = [] - - # Hosts - for host in cluster.host: - hosts.append({ - 'name': host.name, - 'folder': self.get_vm_path(self.content, host), - }) - - # HA - das_config = cluster.configurationEx.dasConfig - if das_config.admissionControlPolicy: - ha_failover_level = das_config.admissionControlPolicy.failoverLevel - if das_config.defaultVmSettings: - ha_restart_priority = das_config.defaultVmSettings.restartPriority, - ha_vm_tools_monitoring = das_config.defaultVmSettings.vmToolsMonitoringSettings.vmMonitoring, - ha_vm_min_up_time = das_config.defaultVmSettings.vmToolsMonitoringSettings.minUpTime, - ha_vm_max_failures = das_config.defaultVmSettings.vmToolsMonitoringSettings.maxFailures, - ha_vm_max_failure_window = das_config.defaultVmSettings.vmToolsMonitoringSettings.maxFailureWindow, - ha_vm_failure_interval = das_config.defaultVmSettings.vmToolsMonitoringSettings.failureInterval, - - # DRS - drs_config = cluster.configurationEx.drsConfig - - # VSAN - if hasattr(cluster.configurationEx, 'vsanConfig'): - vsan_config = cluster.configurationEx.vsanConfig - enabled_vsan = vsan_config.enabled, - vsan_auto_claim_storage = vsan_config.defaultConfig.autoClaimStorage, - - tag_info = [] - if self.params.get('show_tag'): - vmware_client = VmwareRestClient(self.module) - tag_info = vmware_client.get_tags_for_cluster(cluster_mid=cluster._moId) - - results['clusters'][cluster.name] = dict( - hosts=hosts, - enable_ha=das_config.enabled, - ha_failover_level=ha_failover_level, - ha_vm_monitoring=das_config.vmMonitoring, - ha_host_monitoring=das_config.hostMonitoring, - ha_admission_control_enabled=das_config.admissionControlEnabled, - ha_restart_priority=ha_restart_priority, - ha_vm_tools_monitoring=ha_vm_tools_monitoring, - ha_vm_min_up_time=ha_vm_min_up_time, - ha_vm_max_failures=ha_vm_max_failures, - ha_vm_max_failure_window=ha_vm_max_failure_window, - ha_vm_failure_interval=ha_vm_failure_interval, - enabled_drs=drs_config.enabled, - drs_enable_vm_behavior_overrides=drs_config.enableVmBehaviorOverrides, - drs_default_vm_behavior=drs_config.defaultVmBehavior, - drs_vmotion_rate=drs_config.vmotionRate, - enabled_vsan=enabled_vsan, - vsan_auto_claim_storage=vsan_auto_claim_storage, - tags=tag_info, - ) - - self.module.exit_json(**results) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - datacenter=dict(type='str'), - cluster_name=dict(type='str'), - show_tag=dict(type='bool', default=False), - ) - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'datacenter'], - ], - supports_check_mode=True, - ) - if module._name == 'vmware_cluster_facts': - module.deprecate("The 'vmware_cluster_facts' module has been renamed to 'vmware_cluster_info'", version='2.13') - - pyv = VmwreClusterInfoManager(module) - pyv.gather_cluster_info() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_cluster_vsan.py b/lib/ansible/modules/cloud/vmware/vmware_cluster_vsan.py deleted file mode 100644 index 29a304f5f9..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_cluster_vsan.py +++ /dev/null @@ -1,178 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2015, Joseph Callen <jcallen () csc.com> -# Copyright: (c) 2018, Ansible Project -# -# 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_cluster_vsan -short_description: Manages virtual storage area network (vSAN) configuration on VMware vSphere clusters -description: - - Manages vSAN on VMware vSphere clusters. - - All values and VMware object names are case sensitive. -version_added: '2.9' -author: -- Joseph Callen (@jcpowermac) -- Abhijeet Kasurde (@Akasurde) -requirements: - - Tested on ESXi 5.5 and 6.5. - - PyVmomi installed. -options: - cluster_name: - description: - - The name of the cluster to be managed. - type: str - required: yes - datacenter: - description: - - The name of the datacenter. - type: str - required: yes - aliases: [ datacenter_name ] - enable_vsan: - description: - - Whether to enable vSAN. - type: bool - default: 'no' - vsan_auto_claim_storage: - description: - - Whether the VSAN service is configured to automatically claim local storage - on VSAN-enabled hosts in the cluster. - type: bool - default: False -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r""" -- name: Enable vSAN - vmware_cluster_vsan: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter_name: datacenter - cluster_name: cluster - enable_vsan: yes - delegate_to: localhost - -- name: Enable vSAN and claim storage automatically - vmware_cluster_vsan: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter_name: DC0 - cluster_name: "{{ cluster_name }}" - enable_vsan: True - vsan_auto_claim_storage: True - delegate_to: localhost -""" - -RETURN = r"""# -""" - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import (PyVmomi, TaskError, find_datacenter_by_name, - vmware_argument_spec, wait_for_task) -from ansible.module_utils._text import to_native - - -class VMwareCluster(PyVmomi): - def __init__(self, module): - super(VMwareCluster, self).__init__(module) - self.cluster_name = module.params['cluster_name'] - self.datacenter_name = module.params['datacenter'] - self.enable_vsan = module.params['enable_vsan'] - self.datacenter = None - self.cluster = None - - self.datacenter = find_datacenter_by_name(self.content, self.datacenter_name) - if self.datacenter is None: - self.module.fail_json(msg="Datacenter %s does not exist." % self.datacenter_name) - - self.cluster = self.find_cluster_by_name(cluster_name=self.cluster_name) - if self.cluster is None: - self.module.fail_json(msg="Cluster %s does not exist." % self.cluster_name) - - def check_vsan_config_diff(self): - """ - Check VSAN configuration diff - Returns: True if there is diff, else False - - """ - vsan_config = self.cluster.configurationEx.vsanConfigInfo - - if vsan_config.enabled != self.enable_vsan or \ - vsan_config.defaultConfig.autoClaimStorage != self.params.get('vsan_auto_claim_storage'): - return True - return False - - def configure_vsan(self): - """ - Manage VSAN configuration - - """ - changed, result = False, None - - if self.check_vsan_config_diff(): - if not self.module.check_mode: - cluster_config_spec = vim.cluster.ConfigSpecEx() - cluster_config_spec.vsanConfig = vim.vsan.cluster.ConfigInfo() - cluster_config_spec.vsanConfig.enabled = self.enable_vsan - cluster_config_spec.vsanConfig.defaultConfig = vim.vsan.cluster.ConfigInfo.HostDefaultInfo() - cluster_config_spec.vsanConfig.defaultConfig.autoClaimStorage = self.params.get('vsan_auto_claim_storage') - try: - task = self.cluster.ReconfigureComputeResource_Task(cluster_config_spec, True) - changed, result = wait_for_task(task) - except vmodl.RuntimeFault as runtime_fault: - self.module.fail_json(msg=to_native(runtime_fault.msg)) - except vmodl.MethodFault as method_fault: - self.module.fail_json(msg=to_native(method_fault.msg)) - except TaskError as task_e: - self.module.fail_json(msg=to_native(task_e)) - except Exception as generic_exc: - self.module.fail_json(msg="Failed to update cluster" - " due to generic exception %s" % to_native(generic_exc)) - else: - changed = True - - self.module.exit_json(changed=changed, result=result) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update(dict( - cluster_name=dict(type='str', required=True), - datacenter=dict(type='str', required=True, aliases=['datacenter_name']), - # VSAN - enable_vsan=dict(type='bool', default=False), - vsan_auto_claim_storage=dict(type='bool', default=False), - )) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - vmware_cluster_vsan = VMwareCluster(module) - vmware_cluster_vsan.configure_vsan() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_content_deploy_template.py b/lib/ansible/modules/cloud/vmware/vmware_content_deploy_template.py deleted file mode 100644 index 8230da3b26..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_content_deploy_template.py +++ /dev/null @@ -1,273 +0,0 @@ -#!/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() diff --git a/lib/ansible/modules/cloud/vmware/vmware_content_library_info.py b/lib/ansible/modules/cloud/vmware/vmware_content_library_info.py deleted file mode 100644 index bb41e8404a..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_content_library_info.py +++ /dev/null @@ -1,154 +0,0 @@ -#!/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_library_info -short_description: Gather information about VMWare Content Library -description: -- Module to list the content libraries. -- Module to get information about specific content library. -- Content Library feature is introduced in vSphere 6.0 version, so this module is not supported in the earlier versions of vSphere. -- All variables and VMware object names are case sensitive. -version_added: '2.9' -author: -- Pavan Bidkar (@pgbidkar) -notes: -- Tested on vSphere 6.5, 6.7 -requirements: -- python >= 2.6 -- PyVmomi -- vSphere Automation SDK -options: - library_id: - description: - - content library id for which details needs to be fetched. - type: str - required: False -extends_documentation_fragment: vmware_rest_client.documentation -''' - -EXAMPLES = r''' -- name: Get List of Content Libraries - vmware_content_library_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - delegate_to: localhost - -- name: Get information about content library - vmware_content_library_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - library_id: '13b0f060-f4d3-4f84-b61f-0fe1b0c0a5a8' - validate_certs: no - delegate_to: localhost -''' - -RETURN = r''' -content_lib_details: - description: list of content library metadata - returned: on success - type: list - sample: [ - { - "library_creation_time": "2019-07-02T11:50:52.242000", - "library_description": "new description", - "library_id": "13b0f060-f4d3-4f84-b61f-0fe1b0c0a5a8", - "library_name": "demo-local-lib", - "library_publish_info": { - "authentication_method": "NONE", - "persist_json_enabled": false, - "publish_url": null, - "published": false, - "user_name": null - }, - "library_server_guid": "0fd5813b-aac7-4b92-9fb7-f18f16565613", - "library_type": "LOCAL", - "library_version": "3" - } - ] -content_libs: - description: list of content libraries - returned: on success - type: list - sample: [ - "ded9c4d5-0dcd-4837-b1d8-af7398511e33", - "36b72549-14ed-4b5f-94cb-6213fecacc02" - ] -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware_rest_client import VmwareRestClient - - -class VmwareContentLibInfo(VmwareRestClient): - def __init__(self, module): - """Constructor.""" - super(VmwareContentLibInfo, self).__init__(module) - self.content_service = self.api_client - self.library_info = [] - - def get_all_content_libs(self): - """Method to retrieve List of content libraries.""" - self.module.exit_json(changed=False, content_libs=self.content_service.content.LocalLibrary.list()) - - def get_content_lib_details(self, library_id): - """Method to retrieve Details of contentlib with library_id""" - try: - lib_details = self.content_service.content.LocalLibrary.get(library_id) - except Exception as e: - self.module.fail_json(exists=False, msg="%s" % self.get_error_message(e)) - lib_publish_info = dict( - persist_json_enabled=lib_details.publish_info.persist_json_enabled, - authentication_method=lib_details.publish_info.authentication_method, - publish_url=lib_details.publish_info.publish_url, - published=lib_details.publish_info.published, - user_name=lib_details.publish_info.user_name - ) - self.library_info.append( - dict( - library_name=lib_details.name, - library_description=lib_details.description, - library_id=lib_details.id, - library_type=lib_details.type, - library_creation_time=lib_details.creation_time, - library_server_guid=lib_details.server_guid, - library_version=lib_details.version, - library_publish_info=lib_publish_info - ) - ) - - self.module.exit_json(exists=False, changed=False, content_lib_details=self.library_info) - - -def main(): - argument_spec = VmwareRestClient.vmware_client_argument_spec() - argument_spec.update( - library_id=dict(type='str', required=False), - ) - module = AnsibleModule(argument_spec=argument_spec, - supports_check_mode=True) - - vmware_contentlib_info = VmwareContentLibInfo(module) - if module.params.get('library_id'): - vmware_contentlib_info.get_content_lib_details(module.params['library_id']) - else: - vmware_contentlib_info.get_all_content_libs() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_content_library_manager.py b/lib/ansible/modules/cloud/vmware/vmware_content_library_manager.py deleted file mode 100644 index 232742d7bf..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_content_library_manager.py +++ /dev/null @@ -1,290 +0,0 @@ -#!/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_library_manager -short_description: Create, update and delete VMware content library -description: -- Module to manage VMware content Library -- Content Library feature is introduced in vSphere 6.0 version, so this module is not supported in the earlier versions of vSphere. -- All variables and VMware object names are case sensitive. -version_added: '2.9' -author: -- Pavan Bidkar (@pgbidkar) -notes: -- Tested on vSphere 6.5, 6.7 -requirements: -- python >= 2.6 -- PyVmomi -- vSphere Automation SDK -options: - library_name: - description: - - The name of VMware content library to manage. - type: str - required: True - library_description: - description: - - The content library description. - - This is required only if C(state) is set to C(present). - - This parameter is ignored, when C(state) is set to C(absent). - - Process of updating content library only allows description change. - type: str - required: False - default: '' - library_type: - description: - - The content library type. - - This is required only if C(state) is set to C(present). - - This parameter is ignored, when C(state) is set to C(absent). - type: str - required: False - default: 'local' - choices: [ 'local', 'subscribed' ] - datastore_name: - description: - - Name of the datastore on which backing content library is created. - - This is required only if C(state) is set to C(present). - - This parameter is ignored, when C(state) is set to C(absent). - - Currently only datastore backing creation is supported. - type: str - required: False - aliases: ['datastore'] - state: - description: - - The state of content library. - - If set to C(present) and library does not exists, then content library is created. - - If set to C(present) and library exists, then content library is updated. - - If set to C(absent) and library exists, then content library is deleted. - - If set to C(absent) and library does not exists, no action is taken. - type: str - required: False - default: 'present' - choices: [ 'present', 'absent' ] -extends_documentation_fragment: vmware_rest_client.documentation -''' - -EXAMPLES = r''' -- name: Create Content Library - vmware_content_library_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - library_name: test-content-lib - library_description: 'Library with Datastore Backing' - library_type: local - datastore_name: datastore - validate_certs: False - state: present - delegate_to: localhost - -- name: Update Content Library - vmware_content_library_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - library_name: test-content-lib - library_description: 'Library with Datastore Backing' - validate_certs: no - state: present - delegate_to: localhost - -- name: Delete Content Library - vmware_content_library_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - library_name: test-content-lib - validate_certs: no - state: absent - delegate_to: localhost -''' - -RETURN = r''' -content_library_info: - description: library creation success and library_id - returned: on success - type: dict - sample: { - "library_id": "d0b92fa9-7039-4f29-8e9c-0debfcb22b72", - "library_description": 'Test description', - "library_type": 'LOCAL', - "msg": "Content Library 'demo-local-lib-4' created.", - } -''' - -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 - -HAS_VAUTOMATION_PYTHON_SDK = False -try: - from com.vmware.content_client import LibraryModel - from com.vmware.content.library_client import StorageBacking - HAS_VAUTOMATION_PYTHON_SDK = True -except ImportError: - pass - - -class VmwareContentLibCreate(VmwareRestClient): - def __init__(self, module): - """Constructor.""" - super(VmwareContentLibCreate, self).__init__(module) - self.content_service = self.api_client - self.local_libraries = dict() - self.library_name = self.params.get('library_name') - self.library_description = self.params.get('library_description') - self.library_type = self.params.get('library_type') - self.library_types = dict() - self.datastore_name = self.params.get('datastore_name') - self.get_all_libraries() - self.pyv = PyVmomi(module=module) - - def process_state(self): - """ - Manage states of Content Library - """ - self.desired_state = self.params.get('state') - library_states = { - 'absent': { - 'present': self.state_destroy_library, - 'absent': self.state_exit_unchanged, - }, - 'present': { - 'present': self.state_update_library, - 'absent': self.state_create_library, - } - } - library_states[self.desired_state][self.check_content_library_status()]() - - def get_all_libraries(self): - content_libs = self.content_service.content.LocalLibrary.list() - if content_libs: - for content_lib in content_libs: - lib_details = self.content_service.content.LocalLibrary.get(content_lib) - self.local_libraries[lib_details.name] = dict( - lib_name=lib_details.name, - lib_description=lib_details.description, - lib_id=lib_details.id, - lib_type=lib_details.type - ) - - def check_content_library_status(self): - """ - Check if Content Library exists or not - Returns: 'present' if library found, else 'absent' - - """ - ret = 'present' if self.library_name in self.local_libraries else 'absent' - return ret - - def state_create_library(self): - # Find the datastore by the given datastore name - datastore_id = self.pyv.find_datastore_by_name(datastore_name=self.datastore_name) - if not datastore_id: - self.module.fail_json(msg="Failed to find the datastore %s" % self.datastore_name) - self.datastore_id = datastore_id._moId - # Build the storage backing for the library to be created - storage_backings = [] - storage_backing = StorageBacking(type=StorageBacking.Type.DATASTORE, datastore_id=self.datastore_id) - storage_backings.append(storage_backing) - - # Build the specification for the library to be created - create_spec = LibraryModel() - create_spec.name = self.library_name - create_spec.description = self.library_description - self.library_types = {'local': create_spec.LibraryType.LOCAL, - 'subscribed': create_spec.LibraryType.SUBSCRIBED} - create_spec.type = self.library_types[self.library_type] - create_spec.storage_backings = storage_backings - - # Create a local content library backed the VC datastore - library_id = self.content_service.content.LocalLibrary.create(create_spec=create_spec, - client_token=str(uuid.uuid4())) - if library_id: - self.module.exit_json( - changed=True, - content_library_info=dict( - msg="Content Library '%s' created." % create_spec.name, - library_id=library_id, - library_description=self.library_description, - library_type=create_spec.type, - ) - ) - self.module.exit_json(changed=False, - content_library_info=dict(msg="Content Library not created. Datastore and library_type required", library_id='')) - - def state_update_library(self): - """ - Update Content Library - - """ - changed = False - library_id = self.local_libraries[self.library_name]['lib_id'] - content_library_info = dict(msg="Content Library %s is unchanged." % self.library_name, library_id=library_id) - library_update_spec = LibraryModel() - library_desc = self.local_libraries[self.library_name]['lib_description'] - desired_lib_desc = self.params.get('library_description') - if library_desc != desired_lib_desc: - library_update_spec.description = desired_lib_desc - self.content_service.content.LocalLibrary.update(library_id, library_update_spec) - content_library_info['msg'] = 'Content Library %s updated.' % self.library_name - changed = True - - self.module.exit_json(changed=changed, content_library_info=content_library_info) - - def state_destroy_library(self): - """ - Delete Content Library - - """ - library_id = self.local_libraries[self.library_name]['lib_id'] - self.content_service.content.LocalLibrary.delete(library_id=library_id) - self.module.exit_json( - changed=True, - content_library_info=dict( - msg="Content Library '%s' deleted." % self.library_name, - library_id=library_id - ) - ) - - def state_exit_unchanged(self): - """ - Return unchanged state - - """ - self.module.exit_json(changed=False) - - -def main(): - argument_spec = VmwareRestClient.vmware_client_argument_spec() - argument_spec.update( - library_name=dict(type='str', required=False), - library_description=dict(type='str', required=False), - library_type=dict(type='str', required=False, choices=['local', 'subscribed'], default='local'), - datastore_name=dict(type='str', required=False, aliases=['datastore']), - state=dict(type='str', choices=['present', 'absent'], default='present', required=False), - ) - module = AnsibleModule(argument_spec=argument_spec, - supports_check_mode=True) - - vmware_contentlib_create = VmwareContentLibCreate(module) - vmware_contentlib_create.process_state() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_datacenter.py b/lib/ansible/modules/cloud/vmware/vmware_datacenter.py deleted file mode 100644 index 1bb707e4f0..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_datacenter.py +++ /dev/null @@ -1,171 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2015, Joseph Callen <jcallen () csc.com> -# Copyright: (c) 2018, Ansible Project -# 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 = ''' ---- -module: vmware_datacenter -short_description: Manage VMware vSphere Datacenters -description: - - This module can be used to manage (create, delete) VMware vSphere Datacenters. -version_added: 2.0 -author: -- Joseph Callen (@jcpowermac) -- Kamil Szczygiel (@kamsz) -notes: - - Tested on vSphere 6.0, 6.5 -requirements: - - "python >= 2.6" - - PyVmomi -options: - datacenter_name: - description: - - The name of the datacenter the cluster will be created in. - required: True - type: str - state: - description: - - If the datacenter should be present or absent. - choices: [ present, absent ] - default: present - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Create Datacenter - vmware_datacenter: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter_name: '{{ datacenter_name }}' - state: present - delegate_to: localhost - -- name: Delete Datacenter - vmware_datacenter: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter_name: '{{ datacenter_name }}' - state: absent - delegate_to: localhost - register: datacenter_delete_result -''' - -RETURN = """# -""" - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, find_datacenter_by_name, vmware_argument_spec, wait_for_task -from ansible.module_utils._text import to_native - - -class VmwareDatacenterManager(PyVmomi): - def __init__(self, module): - super(VmwareDatacenterManager, self).__init__(module) - self.datacenter_name = self.params.get('datacenter_name') - self.datacenter_obj = self.get_datacenter() - - def ensure(self): - state = self.module.params.get('state') - - if state == 'present': - self.create_datacenter() - - if state == 'absent': - self.destroy_datacenter() - - def get_datacenter(self): - try: - datacenter_obj = find_datacenter_by_name(self.content, self.datacenter_name) - return datacenter_obj - except (vmodl.MethodFault, vmodl.RuntimeFault) as runtime_fault: - self.module.fail_json(msg="Failed to get datacenter '%s'" - " due to : %s" % (self.datacenter_name, - to_native(runtime_fault.msg))) - except Exception as generic_exc: - self.module.fail_json(msg="Failed to get datacenter" - " '%s' due to generic error: %s" % (self.datacenter_name, - to_native(generic_exc))) - - def create_datacenter(self): - folder = self.content.rootFolder - changed = False - try: - if not self.datacenter_obj and not self.module.check_mode: - changed = True - folder.CreateDatacenter(name=self.datacenter_name) - self.module.exit_json(changed=changed) - except vim.fault.DuplicateName as duplicate_name: - self.module.exit_json(changed=changed) - except vim.fault.InvalidName as invalid_name: - self.module.fail_json(msg="Specified datacenter name '%s' is an" - " invalid name : %s" % (self.datacenter_name, - to_native(invalid_name.msg))) - except vmodl.fault.NotSupported as not_supported: - # This should never happen - self.module.fail_json(msg="Trying to create a datacenter '%s' on" - " an incorrect folder object : %s" % (self.datacenter_name, - to_native(not_supported.msg))) - except (vmodl.RuntimeFault, vmodl.MethodFault) as runtime_fault: - self.module.fail_json(msg="Failed to create a datacenter" - " '%s' due to : %s" % (self.datacenter_name, - to_native(runtime_fault.msg))) - except Exception as generic_exc: - self.module.fail_json(msg="Failed to create a datacenter" - " '%s' due to generic error: %s" % (self.datacenter_name, - to_native(generic_exc))) - - def destroy_datacenter(self): - results = dict(changed=False) - try: - if self.datacenter_obj and not self.module.check_mode: - task = self.datacenter_obj.Destroy_Task() - changed, result = wait_for_task(task) - results['changed'] = changed - results['result'] = result - self.module.exit_json(**results) - except (vim.fault.VimFault, vmodl.RuntimeFault, vmodl.MethodFault) as runtime_fault: - self.module.fail_json(msg="Failed to delete a datacenter" - " '%s' due to : %s" % (self.datacenter_name, - to_native(runtime_fault.msg))) - except Exception as generic_exc: - self.module.fail_json(msg="Failed to delete a datacenter" - " '%s' due to generic error: %s" % (self.datacenter_name, - to_native(generic_exc))) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - dict( - datacenter_name=dict(required=True, type='str'), - state=dict(default='present', choices=['present', 'absent'], type='str') - ) - ) - module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) - - vmware_datacenter_mgr = VmwareDatacenterManager(module) - vmware_datacenter_mgr.ensure() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_datastore_cluster.py b/lib/ansible/modules/cloud/vmware/vmware_datastore_cluster.py deleted file mode 100644 index af2969af03..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_datastore_cluster.py +++ /dev/null @@ -1,309 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright (c) 2018, Ansible Project -# Copyright (c) 2018, Abhijeet Kasurde <akasurde@redhat.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 = ''' ---- -module: vmware_datastore_cluster -short_description: Manage VMware vSphere datastore clusters -description: - - This module can be used to add and delete datastore cluster in given VMware environment. - - All parameters and VMware object values are case sensitive. -version_added: 2.6 -author: -- Abhijeet Kasurde (@Akasurde) -notes: - - Tested on vSphere 6.0, 6.5 -requirements: - - "python >= 2.6" - - PyVmomi -options: - datacenter_name: - description: - - The name of the datacenter. - - You must specify either a C(datacenter_name) or a C(folder). - - Mutually exclusive with C(folder) parameter. - required: False - aliases: [ datacenter ] - type: str - datastore_cluster_name: - description: - - The name of the datastore cluster. - required: True - type: str - state: - description: - - If the datastore cluster should be present or absent. - choices: [ present, absent ] - default: present - type: str - folder: - description: - - Destination folder, absolute path to place datastore cluster in. - - The folder should include the datacenter. - - This parameter is case sensitive. - - You must specify either a C(folder) or a C(datacenter_name). - - 'Examples:' - - ' folder: /datacenter1/datastore' - - ' folder: datacenter1/datastore' - - ' folder: /datacenter1/datastore/folder1' - - ' folder: datacenter1/datastore/folder1' - - ' folder: /folder1/datacenter1/datastore' - - ' folder: folder1/datacenter1/datastore' - - ' folder: /folder1/datacenter1/datastore/folder2' - required: False - version_added: '2.9' - type: str - enable_sdrs: - description: - - Whether or not storage DRS is enabled. - default: False - type: bool - required: False - version_added: '2.10' - automation_level: - description: - - Run SDRS automated or manually. - choices: [ automated, manual ] - default: manual - type: str - required: False - version_added: '2.10' - keep_vmdks_together: - description: - - Specifies whether or not each VM in this datastore cluster should have its virtual disks on the same datastore by default. - default: True - type: bool - required: False - version_added: '2.10' - loadbalance_interval: - description: - - Specify the interval in minutes that storage DRS runs to load balance among datastores. - default: 480 - type: int - required: False - version_added: '2.10' - enable_io_loadbalance: - description: - - Whether or not storage DRS takes into account storage I/O workload when making load balancing and initial placement recommendations. - default: False - type: bool - required: False - version_added: '2.10' -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Create datastore cluster and enable SDRS - vmware_datastore_cluster: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter_name: '{{ datacenter_name }}' - datastore_cluster_name: '{{ datastore_cluster_name }}' - enable_sdrs: True - state: present - delegate_to: localhost - -- name: Create datastore cluster using folder - vmware_datastore_cluster: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - folder: '/{{ datacenter_name }}/datastore/ds_folder' - datastore_cluster_name: '{{ datastore_cluster_name }}' - state: present - delegate_to: localhost - -- name: Delete datastore cluster - vmware_datastore_cluster: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter_name: '{{ datacenter_name }}' - datastore_cluster_name: '{{ datastore_cluster_name }}' - state: absent - delegate_to: localhost -''' - -RETURN = """ -result: - description: information about datastore cluster operation - returned: always - type: str - sample: "Datastore cluster 'DSC2' created successfully." -""" - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec, wait_for_task -from ansible.module_utils._text import to_native - - -class VMwareDatastoreClusterManager(PyVmomi): - def __init__(self, module): - super(VMwareDatastoreClusterManager, self).__init__(module) - folder = self.params['folder'] - if folder: - self.folder_obj = self.content.searchIndex.FindByInventoryPath(folder) - if not self.folder_obj: - self.module.fail_json(msg="Failed to find the folder specified by %(folder)s" % self.params) - else: - datacenter_name = self.params.get('datacenter_name') - datacenter_obj = self.find_datacenter_by_name(datacenter_name) - if not datacenter_obj: - self.module.fail_json(msg="Failed to find datacenter '%s' required" - " for managing datastore cluster." % datacenter_name) - self.folder_obj = datacenter_obj.datastoreFolder - - self.datastore_cluster_name = self.params.get('datastore_cluster_name') - self.datastore_cluster_obj = self.find_datastore_cluster_by_name(self.datastore_cluster_name) - - def ensure(self): - """ - Manage internal state of datastore cluster - - """ - results = dict(changed=False, result='') - state = self.module.params.get('state') - enable_sdrs = self.params.get('enable_sdrs') - automation_level = self.params.get('automation_level') - keep_vmdks_together = self.params.get('keep_vmdks_together') - enable_io_loadbalance = self.params.get('enable_io_loadbalance') - loadbalance_interval = self.params.get('loadbalance_interval') - - if self.datastore_cluster_obj: - if state == 'present': - results['result'] = "Datastore cluster '%s' already available." % self.datastore_cluster_name - sdrs_spec = vim.storageDrs.ConfigSpec() - sdrs_spec.podConfigSpec = None - if enable_sdrs != self.datastore_cluster_obj.podStorageDrsEntry.storageDrsConfig.podConfig.enabled: - if not sdrs_spec.podConfigSpec: - sdrs_spec.podConfigSpec = vim.storageDrs.PodConfigSpec() - sdrs_spec.podConfigSpec.enabled = enable_sdrs - results['result'] = results['result'] + " Changed SDRS to '%s'." % enable_sdrs - if automation_level != self.datastore_cluster_obj.podStorageDrsEntry.storageDrsConfig.podConfig.defaultVmBehavior: - if not sdrs_spec.podConfigSpec: - sdrs_spec.podConfigSpec = vim.storageDrs.PodConfigSpec() - sdrs_spec.podConfigSpec.defaultVmBehavior = automation_level - results['result'] = results['result'] + " Changed automation level to '%s'." % automation_level - if keep_vmdks_together != self.datastore_cluster_obj.podStorageDrsEntry.storageDrsConfig.podConfig.defaultIntraVmAffinity: - if not sdrs_spec.podConfigSpec: - sdrs_spec.podConfigSpec = vim.storageDrs.PodConfigSpec() - sdrs_spec.podConfigSpec.defaultIntraVmAffinity = keep_vmdks_together - results['result'] = results['result'] + " Changed VMDK affinity to '%s'." % keep_vmdks_together - if enable_io_loadbalance != self.datastore_cluster_obj.podStorageDrsEntry.storageDrsConfig.podConfig.ioLoadBalanceEnabled: - if not sdrs_spec.podConfigSpec: - sdrs_spec.podConfigSpec = vim.storageDrs.PodConfigSpec() - sdrs_spec.podConfigSpec.ioLoadBalanceEnabled = enable_io_loadbalance - results['result'] = results['result'] + " Changed I/O workload balancing to '%s'." % enable_io_loadbalance - if loadbalance_interval != self.datastore_cluster_obj.podStorageDrsEntry.storageDrsConfig.podConfig.loadBalanceInterval: - if not sdrs_spec.podConfigSpec: - sdrs_spec.podConfigSpec = vim.storageDrs.PodConfigSpec() - sdrs_spec.podConfigSpec.loadBalanceInterval = loadbalance_interval - results['result'] = results['result'] + " Changed load balance interval to '%s' minutes." % loadbalance_interval - if sdrs_spec.podConfigSpec: - if not self.module.check_mode: - try: - task = self.content.storageResourceManager.ConfigureStorageDrsForPod_Task(pod=self.datastore_cluster_obj, - spec=sdrs_spec, modify=True) - changed, result = wait_for_task(task) - except Exception as generic_exc: - self.module.fail_json(msg="Failed to configure datastore cluster" - " '%s' due to %s" % (self.datastore_cluster_name, - to_native(generic_exc))) - else: - changed = True - results['changed'] = changed - elif state == 'absent': - # Delete datastore cluster - if not self.module.check_mode: - task = self.datastore_cluster_obj.Destroy_Task() - changed, result = wait_for_task(task) - else: - changed = True - if changed: - results['result'] = "Datastore cluster '%s' deleted successfully." % self.datastore_cluster_name - results['changed'] = changed - else: - self.module.fail_json(msg="Failed to delete datastore cluster '%s'." % self.datastore_cluster_name) - else: - if state == 'present': - # Create datastore cluster - if not self.module.check_mode: - try: - self.datastore_cluster_obj = self.folder_obj.CreateStoragePod(name=self.datastore_cluster_name) - except Exception as generic_exc: - self.module.fail_json(msg="Failed to create datastore cluster" - " '%s' due to %s" % (self.datastore_cluster_name, - to_native(generic_exc))) - try: - sdrs_spec = vim.storageDrs.ConfigSpec() - sdrs_spec.podConfigSpec = vim.storageDrs.PodConfigSpec() - sdrs_spec.podConfigSpec.enabled = enable_sdrs - sdrs_spec.podConfigSpec.defaultVmBehavior = automation_level - sdrs_spec.podConfigSpec.defaultIntraVmAffinity = keep_vmdks_together - sdrs_spec.podConfigSpec.ioLoadBalanceEnabled = enable_io_loadbalance - sdrs_spec.podConfigSpec.loadBalanceInterval = loadbalance_interval - task = self.content.storageResourceManager.ConfigureStorageDrsForPod_Task(pod=self.datastore_cluster_obj, spec=sdrs_spec, modify=True) - changed, result = wait_for_task(task) - except Exception as generic_exc: - self.module.fail_json(msg="Failed to configure datastore cluster" - " '%s' due to %s" % (self.datastore_cluster_name, - to_native(generic_exc))) - results['changed'] = True - results['result'] = "Datastore cluster '%s' created successfully." % self.datastore_cluster_name - elif state == 'absent': - results['result'] = "Datastore cluster '%s' not available or already deleted." % self.datastore_cluster_name - self.module.exit_json(**results) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - dict( - datacenter_name=dict(type='str', required=False, aliases=['datacenter']), - datastore_cluster_name=dict(type='str', required=True), - state=dict(default='present', choices=['present', 'absent'], type='str'), - folder=dict(type='str', required=False), - enable_sdrs=dict(type='bool', default=False, required=False), - keep_vmdks_together=dict(type='bool', default=True, required=False), - automation_level=dict(type='str', choices=['automated', 'manual'], default='manual'), - enable_io_loadbalance=dict(type='bool', default=False, required=False), - loadbalance_interval=dict(type='int', default=480, required=False) - ) - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - mutually_exclusive=[ - ['datacenter_name', 'folder'], - ], - required_one_of=[ - ['datacenter_name', 'folder'], - ] - ) - - datastore_cluster_mgr = VMwareDatastoreClusterManager(module) - datastore_cluster_mgr.ensure() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_datastore_info.py b/lib/ansible/modules/cloud/vmware/vmware_datastore_info.py deleted file mode 100644 index 3a78809536..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_datastore_info.py +++ /dev/null @@ -1,342 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2017, Tim Rightnour <thegarbledone@gmail.com> -# Copyright: (c) 2018, Ansible Project -# 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 = ''' ---- -module: vmware_datastore_info -short_description: Gather info about datastores available in given vCenter -description: - - This module can be used to gather information about datastores in VMWare infrastructure. - - All values and VMware object names are case sensitive. - - This module was called C(vmware_datastore_facts) before Ansible 2.9. The usage did not change. -version_added: 2.5 -author: - - Tim Rightnour (@garbled1) -notes: - - Tested on vSphere 5.5, 6.0 and 6.5 -requirements: - - "python >= 2.6" - - PyVmomi -options: - name: - description: - - Name of the datastore to match. - - If set, information of specific datastores are returned. - required: False - type: str - datacenter: - description: - - Datacenter to search for datastores. - - This parameter is required, if C(cluster) is not supplied. - required: False - aliases: ['datacenter_name'] - type: str - cluster: - description: - - Cluster to search for datastores. - - If set, information of datastores belonging this clusters will be returned. - - This parameter is required, if C(datacenter) is not supplied. - required: False - type: str - gather_nfs_mount_info: - description: - - Gather mount information of NFS datastores. - - Disabled per default because this slows down the execution if you have a lot of datastores. - - Only valid when C(schema) is C(summary). - type: bool - default: false - version_added: 2.8 - gather_vmfs_mount_info: - description: - - Gather mount information of VMFS datastores. - - Disabled per default because this slows down the execution if you have a lot of datastores. - - Only valid when C(schema) is C(summary). - type: bool - default: false - version_added: 2.8 - schema: - description: - - Specify the output schema desired. - - The 'summary' output schema is the legacy output from the module - - The 'vsphere' output schema is the vSphere API class definition - which requires pyvmomi>6.7.1 - choices: ['summary', 'vsphere'] - default: 'summary' - type: str - version_added: '2.10' - properties: - description: - - Specify the properties to retrieve. - - If not specified, all properties are retrieved (deeply). - - Results are returned in a structure identical to the vsphere API. - - 'Example:' - - ' properties: [' - - ' "name",' - - ' "info.vmfs.ssd",' - - ' "capability.vsanSparseSupported",' - - ' "overallStatus"' - - ' ]' - - Only valid when C(schema) is C(vsphere). - type: list - required: False - version_added: '2.10' -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Gather info from standalone ESXi server having datacenter as 'ha-datacenter' - vmware_datastore_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter_name: '{{ datacenter_name }}' - validate_certs: no - delegate_to: localhost - register: info - -- name: Gather info from datacenter about specific datastore - vmware_datastore_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter_name: '{{ datacenter_name }}' - name: datastore1 - delegate_to: localhost - register: info - -- name: Gather some info from a datastore using the vSphere API output schema - vmware_datastore_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter_name: '{{ datacenter_name }}' - schema: vsphere - properties: - - name - - info.vmfs.ssd - - capability.vsanSparseSupported - - overallStatus - delegate_to: localhost - register: info -''' - -RETURN = """ -datastores: - description: metadata about the available datastores - returned: always - type: list - sample: [ - { - "accessible": false, - "capacity": 42681237504, - "datastore_cluster": "datacluster0", - "freeSpace": 39638269952, - "maintenanceMode": "normal", - "multipleHostAccess": false, - "name": "datastore2", - "provisioned": 12289211488, - "type": "VMFS", - "uncommitted": 9246243936, - "url": "ds:///vmfs/volumes/5a69b18a-c03cd88c-36ae-5254001249ce/", - "vmfs_blockSize": 1024, - "vmfs_uuid": "5a69b18a-c03cd88c-36ae-5254001249ce", - "vmfs_version": "6.81" - }, - { - "accessible": true, - "capacity": 5497558138880, - "datastore_cluster": "datacluster0", - "freeSpace": 4279000641536, - "maintenanceMode": "normal", - "multipleHostAccess": true, - "name": "datastore3", - "nfs_path": "/vol/datastore3", - "nfs_server": "nfs_server1", - "provisioned": 1708109410304, - "type": "NFS", - "uncommitted": 489551912960, - "url": "ds:///vmfs/volumes/420b3e73-67070776/" - }, - ] -""" - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import (PyVmomi, vmware_argument_spec, get_all_objs, - find_cluster_by_name, get_parent_datacenter) - - -class VMwareHostDatastore(PyVmomi): - """ This class populates the datastore list """ - def __init__(self, module): - super(VMwareHostDatastore, self).__init__(module) - self.gather_nfs_mount_info = self.module.params['gather_nfs_mount_info'] - self.gather_vmfs_mount_info = self.module.params['gather_vmfs_mount_info'] - self.schema = self.module.params['schema'] - self.properties = self.module.params['properties'] - - def check_datastore_host(self, esxi_host, datastore): - """ Get all datastores of specified ESXi host """ - esxi = self.find_hostsystem_by_name(esxi_host) - if esxi is None: - self.module.fail_json(msg="Failed to find ESXi hostname %s " % esxi_host) - storage_system = esxi.configManager.storageSystem - host_file_sys_vol_mount_info = storage_system.fileSystemVolumeInfo.mountInfo - for host_mount_info in host_file_sys_vol_mount_info: - if host_mount_info.volume.name == datastore: - return host_mount_info - return None - - def build_datastore_list(self, datastore_list): - """ Build list with datastores """ - datastores = list() - for datastore in datastore_list: - if self.schema == 'summary': - summary = datastore.summary - datastore_summary = dict() - datastore_summary['accessible'] = summary.accessible - datastore_summary['capacity'] = summary.capacity - datastore_summary['name'] = summary.name - datastore_summary['freeSpace'] = summary.freeSpace - datastore_summary['maintenanceMode'] = summary.maintenanceMode - datastore_summary['multipleHostAccess'] = summary.multipleHostAccess - datastore_summary['type'] = summary.type - if self.gather_nfs_mount_info or self.gather_vmfs_mount_info: - if self.gather_nfs_mount_info and summary.type.startswith("NFS"): - # get mount info from the first ESXi host attached to this NFS datastore - host_mount_info = self.check_datastore_host(summary.datastore.host[0].key.name, summary.name) - datastore_summary['nfs_server'] = host_mount_info.volume.remoteHost - datastore_summary['nfs_path'] = host_mount_info.volume.remotePath - if self.gather_vmfs_mount_info and summary.type == "VMFS": - # get mount info from the first ESXi host attached to this VMFS datastore - host_mount_info = self.check_datastore_host(summary.datastore.host[0].key.name, summary.name) - datastore_summary['vmfs_blockSize'] = host_mount_info.volume.blockSize - datastore_summary['vmfs_version'] = host_mount_info.volume.version - datastore_summary['vmfs_uuid'] = host_mount_info.volume.uuid - # vcsim does not return uncommitted - if not summary.uncommitted: - summary.uncommitted = 0 - datastore_summary['uncommitted'] = summary.uncommitted - datastore_summary['url'] = summary.url - # Calculated values - datastore_summary['provisioned'] = summary.capacity - summary.freeSpace + summary.uncommitted - datastore_summary['datastore_cluster'] = 'N/A' - if isinstance(datastore.parent, vim.StoragePod): - datastore_summary['datastore_cluster'] = datastore.parent.name - - if self.module.params['name']: - if datastore_summary['name'] == self.module.params['name']: - datastores.extend([datastore_summary]) - else: - datastores.extend([datastore_summary]) - else: - if self.module.params['name']: - if datastore.name == self.module.params['name']: - datastores.extend(([self.to_json(datastore, self.properties)])) - else: - datastores.extend(([self.to_json(datastore, self.properties)])) - - return datastores - - -class PyVmomiCache(object): - """ This class caches references to objects which are requested multiples times but not modified """ - def __init__(self, content, dc_name=None): - self.content = content - self.dc_name = dc_name - self.clusters = {} - self.parent_datacenters = {} - - def get_all_objs(self, content, types, confine_to_datacenter=True): - """ Wrapper around get_all_objs to set datacenter context """ - objects = get_all_objs(content, types) - if confine_to_datacenter: - if hasattr(objects, 'items'): - # resource pools come back as a dictionary - for k, v in tuple(objects.items()): - parent_dc = get_parent_datacenter(k) - if parent_dc.name != self.dc_name: - del objects[k] - else: - # everything else should be a list - objects = [x for x in objects if get_parent_datacenter(x).name == self.dc_name] - - return objects - - -class PyVmomiHelper(PyVmomi): - """ This class gets datastores """ - def __init__(self, module): - super(PyVmomiHelper, self).__init__(module) - self.cache = PyVmomiCache(self.content, dc_name=self.params['datacenter']) - - def lookup_datastore(self, confine_to_datacenter): - """ Get datastore(s) per ESXi host or vCenter server """ - datastores = self.cache.get_all_objs(self.content, [vim.Datastore], confine_to_datacenter) - return datastores - - def lookup_datastore_by_cluster(self): - """ Get datastore(s) per cluster """ - cluster = find_cluster_by_name(self.content, self.params['cluster']) - if not cluster: - self.module.fail_json(msg='Failed to find cluster "%(cluster)s"' % self.params) - c_dc = cluster.datastore - return c_dc - - -def main(): - """ Main """ - argument_spec = vmware_argument_spec() - argument_spec.update( - name=dict(type='str'), - datacenter=dict(type='str', aliases=['datacenter_name']), - cluster=dict(type='str'), - gather_nfs_mount_info=dict(type='bool', default=False), - gather_vmfs_mount_info=dict(type='bool', default=False), - schema=dict(type='str', choices=['summary', 'vsphere'], default='summary'), - properties=dict(type='list') - ) - module = AnsibleModule(argument_spec=argument_spec, - supports_check_mode=True - ) - if module._name == 'vmware_datastore_facts': - module.deprecate("The 'vmware_datastore_facts' module has been renamed to 'vmware_datastore_info'", version='2.13') - - result = dict(changed=False) - - pyv = PyVmomiHelper(module) - - if module.params['cluster']: - dxs = pyv.lookup_datastore_by_cluster() - elif module.params['datacenter']: - dxs = pyv.lookup_datastore(confine_to_datacenter=True) - else: - dxs = pyv.lookup_datastore(confine_to_datacenter=False) - - vmware_host_datastore = VMwareHostDatastore(module) - datastores = vmware_host_datastore.build_datastore_list(dxs) - - result['datastores'] = datastores - - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_datastore_maintenancemode.py b/lib/ansible/modules/cloud/vmware/vmware_datastore_maintenancemode.py deleted file mode 100644 index a90815897a..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_datastore_maintenancemode.py +++ /dev/null @@ -1,218 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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 = ''' ---- -module: vmware_datastore_maintenancemode -short_description: Place a datastore into maintenance mode -description: - - This module can be used to manage maintenance mode of a datastore. -author: -- "Abhijeet Kasurde (@Akasurde)" -version_added: 2.6 -notes: - - Tested on vSphere 5.5, 6.0 and 6.5 -requirements: - - "python >= 2.6" - - PyVmomi -options: - datastore: - description: - - Name of datastore to manage. - - If C(datastore_cluster) or C(cluster_name) are not set, this parameter is required. - type: str - datastore_cluster: - description: - - Name of the datastore cluster from all child datastores to be managed. - - If C(datastore) or C(cluster_name) are not set, this parameter is required. - type: str - cluster_name: - description: - - Name of the cluster where datastore is connected to. - - If multiple datastores are connected to the given cluster, then all datastores will be managed by C(state). - - If C(datastore) or C(datastore_cluster) are not set, this parameter is required. - type: str - state: - description: - - If set to C(present), then enter datastore into maintenance mode. - - If set to C(present) and datastore is already in maintenance mode, then no action will be taken. - - If set to C(absent) and datastore is in maintenance mode, then exit maintenance mode. - - If set to C(absent) and datastore is not in maintenance mode, then no action will be taken. - choices: [ present, absent ] - default: present - required: False - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Enter datastore into Maintenance Mode - vmware_datastore_maintenancemode: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datastore: '{{ datastore_name }}' - state: present - delegate_to: localhost - -- name: Enter all datastores under cluster into Maintenance Mode - vmware_datastore_maintenancemode: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: '{{ cluster_name }}' - state: present - delegate_to: localhost - -- name: Enter all datastores under datastore cluster into Maintenance Mode - vmware_datastore_maintenancemode: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datastore_cluster: '{{ datastore_cluster_name }}' - state: present - delegate_to: localhost - -- name: Exit datastore into Maintenance Mode - vmware_datastore_maintenancemode: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datastore: '{{ datastore_name }}' - state: absent - delegate_to: localhost -''' - -RETURN = ''' -datastore_status: - description: Action taken for datastore - returned: always - type: dict - sample: { - "ds_226_01": "Datastore 'ds_226_01' is already in maintenance mode." - } -''' - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import (PyVmomi, vmware_argument_spec, wait_for_task, - find_cluster_by_name, get_all_objs) -from ansible.module_utils._text import to_native - - -class VmwareDatastoreMaintenanceMgr(PyVmomi): - def __init__(self, module): - super(VmwareDatastoreMaintenanceMgr, self).__init__(module) - datastore_name = self.params.get('datastore') - cluster_name = self.params.get('cluster_name') - datastore_cluster = self.params.get('datastore_cluster') - self.datastore_objs = [] - if datastore_name: - ds = self.find_datastore_by_name(datastore_name=datastore_name) - if not ds: - self.module.fail_json(msg='Failed to find datastore "%(datastore)s".' % self.params) - self.datastore_objs = [ds] - elif cluster_name: - cluster = find_cluster_by_name(self.content, cluster_name) - if not cluster: - self.module.fail_json(msg='Failed to find cluster "%(cluster_name)s".' % self.params) - self.datastore_objs = cluster.datastore - elif datastore_cluster: - datastore_cluster_obj = get_all_objs(self.content, [vim.StoragePod]) - if not datastore_cluster_obj: - self.module.fail_json(msg='Failed to find datastore cluster "%(datastore_cluster)s".' % self.params) - for datastore in datastore_cluster_obj.childEntity: - self.datastore_objs.append(datastore) - else: - self.module.fail_json(msg="Please select one of 'cluster_name', 'datastore' or 'datastore_cluster'.") - self.state = self.params.get('state') - - def ensure(self): - datastore_results = dict() - change_datastore_list = [] - for datastore in self.datastore_objs: - changed = False - if self.state == 'present' and datastore.summary.maintenanceMode != 'normal': - datastore_results[datastore.name] = "Datastore '%s' is already in maintenance mode." % datastore.name - break - elif self.state == 'absent' and datastore.summary.maintenanceMode == 'normal': - datastore_results[datastore.name] = "Datastore '%s' is not in maintenance mode." % datastore.name - break - - try: - if self.state == 'present': - storage_replacement_result = datastore.DatastoreEnterMaintenanceMode() - task = storage_replacement_result.task - else: - task = datastore.DatastoreExitMaintenanceMode_Task() - - success, result = wait_for_task(task) - - if success: - changed = True - if self.state == 'present': - datastore_results[datastore.name] = "Datastore '%s' entered in maintenance mode." % datastore.name - else: - datastore_results[datastore.name] = "Datastore '%s' exited from maintenance mode." % datastore.name - except vim.fault.InvalidState as invalid_state: - if self.state == 'present': - msg = "Unable to enter datastore '%s' in" % datastore.name - else: - msg = "Unable to exit datastore '%s' from" % datastore.name - msg += " maintenance mode due to : %s" % to_native(invalid_state.msg) - self.module.fail_json(msg=msg) - except Exception as exc: - if self.state == 'present': - msg = "Unable to enter datastore '%s' in" % datastore.name - else: - msg = "Unable to exit datastore '%s' from" % datastore.name - msg += " maintenance mode due to generic exception : %s" % to_native(exc) - self.module.fail_json(msg=msg) - change_datastore_list.append(changed) - - changed = False - if any(change_datastore_list): - changed = True - self.module.exit_json(changed=changed, datastore_status=datastore_results) - - -def main(): - spec = vmware_argument_spec() - spec.update(dict( - datastore=dict(type='str', required=False), - cluster_name=dict(type='str', required=False), - datastore_cluster=dict(type='str', required=False), - state=dict(type='str', default='present', choices=['present', 'absent']), - )) - - module = AnsibleModule( - argument_spec=spec, - required_one_of=[ - ['datastore', 'cluster_name', 'datastore_cluster'], - ], - ) - - datastore_maintenance_mgr = VmwareDatastoreMaintenanceMgr(module=module) - datastore_maintenance_mgr.ensure() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_deploy_ovf.py b/lib/ansible/modules/cloud/vmware/vmware_deploy_ovf.py deleted file mode 100644 index c8f44dc71a..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_deploy_ovf.py +++ /dev/null @@ -1,704 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2017, Matt Martz <matt@sivel.net> -# -# 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 = ''' -author: 'Matt Martz (@sivel)' -short_description: 'Deploys a VMware virtual machine from an OVF or OVA file' -description: -- 'This module can be used to deploy a VMware VM from an OVF or OVA file' -module: vmware_deploy_ovf -notes: [] -options: - allow_duplicates: - default: "yes" - description: - - Whether or not to allow duplicate VM names. ESXi allows duplicates, vCenter may not. - type: bool - datacenter: - default: ha-datacenter - description: - - Datacenter to deploy to. - type: str - cluster: - description: - - Cluster to deploy to. - type: str - datastore: - default: datastore1 - description: - - Datastore to deploy to. - - "You can also specify datastore storage cluster. version_added: 2.9" - type: str - deployment_option: - description: - - The key of the chosen deployment option. - type: str - disk_provisioning: - choices: - - flat - - eagerZeroedThick - - monolithicSparse - - twoGbMaxExtentSparse - - twoGbMaxExtentFlat - - thin - - sparse - - thick - - seSparse - - monolithicFlat - default: thin - description: - - Disk provisioning type. - type: str - fail_on_spec_warnings: - description: - - Cause the module to treat OVF Import Spec warnings as errors. - default: "no" - type: bool - folder: - description: - - Absolute path of folder to place the virtual machine. - - If not specified, defaults to the value of C(datacenter.vmFolder). - - 'Examples:' - - ' folder: /ha-datacenter/vm' - - ' folder: ha-datacenter/vm' - - ' folder: /datacenter1/vm' - - ' folder: datacenter1/vm' - - ' folder: /datacenter1/vm/folder1' - - ' folder: datacenter1/vm/folder1' - - ' folder: /folder1/datacenter1/vm' - - ' folder: folder1/datacenter1/vm' - - ' folder: /folder1/datacenter1/vm/folder2' - type: str - inject_ovf_env: - description: - - Force the given properties to be inserted into an OVF Environment and injected through VMware Tools. - version_added: "2.8" - type: bool - name: - description: - - Name of the VM to work with. - - Virtual machine names in vCenter are not necessarily unique, which may be problematic. - type: str - networks: - default: - VM Network: VM Network - description: - - 'C(key: value) mapping of OVF network name, to the vCenter network name.' - type: dict - ovf: - description: - - 'Path to OVF or OVA file to deploy.' - aliases: - - ova - power_on: - default: true - description: - - 'Whether or not to power on the virtual machine after creation.' - type: bool - properties: - description: - - The assignment of values to the properties found in the OVF as key value pairs. - type: dict - resource_pool: - default: Resources - description: - - Resource Pool to deploy to. - type: str - wait: - default: true - description: - - 'Wait for the host to power on.' - type: bool - wait_for_ip_address: - default: false - description: - - Wait until vCenter detects an IP address for the VM. - - This requires vmware-tools (vmtoolsd) to properly work after creation. - type: bool -requirements: - - pyvmomi -version_added: "2.7" -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- vmware_deploy_ovf: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - ovf: /path/to/ubuntu-16.04-amd64.ovf - wait_for_ip_address: true - delegate_to: localhost - -# Deploys a new VM named 'NewVM' in specific datacenter/cluster, with network mapping taken from variable and using ova template from an absolute path -- vmware_deploy_ovf: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: Datacenter1 - cluster: Cluster1 - datastore: vsandatastore - name: NewVM - networks: "{u'VM Network':u'{{ ProvisioningNetworkLabel }}'}" - validate_certs: no - power_on: no - ovf: /absolute/path/to/template/mytemplate.ova - delegate_to: localhost -''' - - -RETURN = r''' -instance: - description: metadata about the new virtual machine - returned: always - type: dict - sample: None -''' - -import io -import os -import sys -import tarfile -import time -import traceback - -import xml.etree.ElementTree as ET - -from threading import Thread - -from ansible.module_utils._text import to_native -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.six import string_types -from ansible.module_utils.urls import generic_urlparse, open_url, urlparse, urlunparse -from ansible.module_utils.vmware import (find_network_by_name, find_vm_by_name, PyVmomi, - gather_vm_facts, vmware_argument_spec, wait_for_task, wait_for_vm_ip) -try: - from ansible.module_utils.vmware import vim - from pyVmomi import vmodl -except ImportError: - pass - - -def path_exists(value): - if not isinstance(value, string_types): - value = str(value) - value = os.path.expanduser(os.path.expandvars(value)) - if not os.path.exists(value): - raise ValueError('%s is not a valid path' % value) - return value - - -class ProgressReader(io.FileIO): - def __init__(self, name, mode='r', closefd=True): - self.bytes_read = 0 - io.FileIO.__init__(self, name, mode=mode, closefd=closefd) - - def read(self, size=10240): - chunk = io.FileIO.read(self, size) - self.bytes_read += len(chunk) - return chunk - - -class TarFileProgressReader(tarfile.ExFileObject): - def __init__(self, *args): - self.bytes_read = 0 - tarfile.ExFileObject.__init__(self, *args) - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, traceback): - try: - self.close() - except Exception: - pass - - def read(self, size=10240): - chunk = tarfile.ExFileObject.read(self, size) - self.bytes_read += len(chunk) - return chunk - - -class VMDKUploader(Thread): - def __init__(self, vmdk, url, validate_certs=True, tarinfo=None, create=False): - Thread.__init__(self) - - self.vmdk = vmdk - - if tarinfo: - self.size = tarinfo.size - else: - self.size = os.stat(vmdk).st_size - - self.url = url - self.validate_certs = validate_certs - self.tarinfo = tarinfo - - self.f = None - self.e = None - - self._create = create - - @property - def bytes_read(self): - try: - return self.f.bytes_read - except AttributeError: - return 0 - - def _request_opts(self): - ''' - Requests for vmdk files differ from other file types. Build the request options here to handle that - ''' - headers = { - 'Content-Length': self.size, - 'Content-Type': 'application/octet-stream', - } - - if self._create: - # Non-VMDK - method = 'PUT' - headers['Overwrite'] = 't' - else: - # VMDK - method = 'POST' - headers['Content-Type'] = 'application/x-vnd.vmware-streamVmdk' - - return { - 'method': method, - 'headers': headers, - } - - def _open_url(self): - open_url(self.url, data=self.f, validate_certs=self.validate_certs, **self._request_opts()) - - def run(self): - if self.tarinfo: - try: - with TarFileProgressReader(self.vmdk, self.tarinfo) as self.f: - self._open_url() - except Exception: - self.e = sys.exc_info() - else: - try: - with ProgressReader(self.vmdk, 'rb') as self.f: - self._open_url() - except Exception: - self.e = sys.exc_info() - - -class VMwareDeployOvf(PyVmomi): - def __init__(self, module): - super(VMwareDeployOvf, self).__init__(module) - self.module = module - self.params = module.params - - self.datastore = None - self.datacenter = None - self.resource_pool = None - self.network_mappings = [] - - self.ovf_descriptor = None - self.tar = None - - self.lease = None - self.import_spec = None - self.entity = None - - def get_objects(self): - self.datacenter = self.find_datacenter_by_name(self.params['datacenter']) - if not self.datacenter: - self.module.fail_json(msg='%(datacenter)s could not be located' % self.params) - - self.datastore = None - datastore_cluster_obj = self.find_datastore_cluster_by_name(self.params['datastore']) - if datastore_cluster_obj: - datastore = None - datastore_freespace = 0 - for ds in datastore_cluster_obj.childEntity: - if isinstance(ds, vim.Datastore) and ds.summary.freeSpace > datastore_freespace: - # If datastore field is provided, filter destination datastores - if ds.summary.maintenanceMode != 'normal' or not ds.summary.accessible: - continue - datastore = ds - datastore_freespace = ds.summary.freeSpace - if datastore: - self.datastore = datastore - else: - self.datastore = self.find_datastore_by_name(self.params['datastore'], self.datacenter) - - if not self.datastore: - self.module.fail_json(msg='%(datastore)s could not be located' % self.params) - - if self.params['cluster']: - resource_pools = [] - cluster = self.find_cluster_by_name(self.params['cluster'], datacenter_name=self.datacenter) - if cluster is None: - self.module.fail_json(msg="Unable to find cluster '%(cluster)s'" % self.params) - self.resource_pool = self.find_resource_pool_by_cluster(self.params['resource_pool'], cluster=cluster) - else: - self.resource_pool = self.find_resource_pool_by_name(self.params['resource_pool']) - - if not self.resource_pool: - self.module.fail_json(msg='%(resource_pool)s could not be located' % self.params) - - for key, value in self.params['networks'].items(): - network = find_network_by_name(self.content, value) - if not network: - self.module.fail_json(msg='%(network)s could not be located' % self.params) - network_mapping = vim.OvfManager.NetworkMapping() - network_mapping.name = key - network_mapping.network = network - self.network_mappings.append(network_mapping) - - return self.datastore, self.datacenter, self.resource_pool, self.network_mappings - - def get_ovf_descriptor(self): - if tarfile.is_tarfile(self.params['ovf']): - self.tar = tarfile.open(self.params['ovf']) - ovf = None - for candidate in self.tar.getmembers(): - dummy, ext = os.path.splitext(candidate.name) - if ext.lower() == '.ovf': - ovf = candidate - break - if not ovf: - self.module.fail_json(msg='Could not locate OVF file in %(ovf)s' % self.params) - - self.ovf_descriptor = to_native(self.tar.extractfile(ovf).read()) - else: - with open(self.params['ovf']) as f: - self.ovf_descriptor = f.read() - - return self.ovf_descriptor - - def get_lease(self): - datastore, datacenter, resource_pool, network_mappings = self.get_objects() - - params = { - 'diskProvisioning': self.params['disk_provisioning'], - } - if self.params['name']: - params['entityName'] = self.params['name'] - if network_mappings: - params['networkMapping'] = network_mappings - if self.params['deployment_option']: - params['deploymentOption'] = self.params['deployment_option'] - if self.params['properties']: - params['propertyMapping'] = [] - for key, value in self.params['properties'].items(): - property_mapping = vim.KeyValue() - property_mapping.key = key - property_mapping.value = str(value) if isinstance(value, bool) else value - params['propertyMapping'].append(property_mapping) - - if self.params['folder']: - folder = self.content.searchIndex.FindByInventoryPath(self.params['folder']) - if not folder: - self.module.fail_json(msg="Unable to find the specified folder %(folder)s" % self.params) - else: - folder = datacenter.vmFolder - - spec_params = vim.OvfManager.CreateImportSpecParams(**params) - - ovf_descriptor = self.get_ovf_descriptor() - - self.import_spec = self.content.ovfManager.CreateImportSpec( - ovf_descriptor, - resource_pool, - datastore, - spec_params - ) - - errors = [to_native(e.msg) for e in getattr(self.import_spec, 'error', [])] - if self.params['fail_on_spec_warnings']: - errors.extend( - (to_native(w.msg) for w in getattr(self.import_spec, 'warning', [])) - ) - if errors: - self.module.fail_json( - msg='Failure validating OVF import spec: %s' % '. '.join(errors) - ) - - for warning in getattr(self.import_spec, 'warning', []): - self.module.warn('Problem validating OVF import spec: %s' % to_native(warning.msg)) - - if not self.params['allow_duplicates']: - name = self.import_spec.importSpec.configSpec.name - match = find_vm_by_name(self.content, name, folder=folder) - if match: - self.module.exit_json(instance=gather_vm_facts(self.content, match), changed=False) - - if self.module.check_mode: - self.module.exit_json(changed=True, instance={'hw_name': name}) - - try: - self.lease = resource_pool.ImportVApp( - self.import_spec.importSpec, - folder - ) - except vmodl.fault.SystemError as e: - self.module.fail_json( - msg='Failed to start import: %s' % to_native(e.msg) - ) - - while self.lease.state != vim.HttpNfcLease.State.ready: - time.sleep(0.1) - - self.entity = self.lease.info.entity - - return self.lease, self.import_spec - - def _normalize_url(self, url): - ''' - The hostname in URLs from vmware may be ``*`` update it accordingly - ''' - url_parts = generic_urlparse(urlparse(url)) - if url_parts.hostname == '*': - if url_parts.port: - url_parts.netloc = '%s:%d' % (self.params['hostname'], url_parts.port) - else: - url_parts.netloc = self.params['hostname'] - - return urlunparse(url_parts.as_list()) - - def upload(self): - if self.params['ovf'] is None: - self.module.fail_json(msg="OVF path is required for upload operation.") - - ovf_dir = os.path.dirname(self.params['ovf']) - - lease, import_spec = self.get_lease() - - uploaders = [] - - for file_item in import_spec.fileItem: - device_upload_url = None - for device_url in lease.info.deviceUrl: - if file_item.deviceId == device_url.importKey: - device_upload_url = self._normalize_url(device_url.url) - break - - if not device_upload_url: - lease.HttpNfcLeaseAbort( - vmodl.fault.SystemError(reason='Failed to find deviceUrl for file %s' % file_item.path) - ) - self.module.fail_json( - msg='Failed to find deviceUrl for file %s' % file_item.path - ) - - vmdk_tarinfo = None - if self.tar: - vmdk = self.tar - try: - vmdk_tarinfo = self.tar.getmember(file_item.path) - except KeyError: - lease.HttpNfcLeaseAbort( - vmodl.fault.SystemError(reason='Failed to find VMDK file %s in OVA' % file_item.path) - ) - self.module.fail_json( - msg='Failed to find VMDK file %s in OVA' % file_item.path - ) - else: - vmdk = os.path.join(ovf_dir, file_item.path) - try: - path_exists(vmdk) - except ValueError: - lease.HttpNfcLeaseAbort( - vmodl.fault.SystemError(reason='Failed to find VMDK file at %s' % vmdk) - ) - self.module.fail_json( - msg='Failed to find VMDK file at %s' % vmdk - ) - - uploaders.append( - VMDKUploader( - vmdk, - device_upload_url, - self.params['validate_certs'], - tarinfo=vmdk_tarinfo, - create=file_item.create - ) - ) - - total_size = sum(u.size for u in uploaders) - total_bytes_read = [0] * len(uploaders) - for i, uploader in enumerate(uploaders): - uploader.start() - while uploader.is_alive(): - time.sleep(0.1) - total_bytes_read[i] = uploader.bytes_read - lease.HttpNfcLeaseProgress(int(100.0 * sum(total_bytes_read) / total_size)) - - if uploader.e: - lease.HttpNfcLeaseAbort( - vmodl.fault.SystemError(reason='%s' % to_native(uploader.e[1])) - ) - self.module.fail_json( - msg='%s' % to_native(uploader.e[1]), - exception=''.join(traceback.format_tb(uploader.e[2])) - ) - - def complete(self): - self.lease.HttpNfcLeaseComplete() - - def inject_ovf_env(self): - attrib = { - 'xmlns': 'http://schemas.dmtf.org/ovf/environment/1', - 'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance', - 'xmlns:oe': 'http://schemas.dmtf.org/ovf/environment/1', - 'xmlns:ve': 'http://www.vmware.com/schema/ovfenv', - 'oe:id': '', - 've:esxId': self.entity._moId - } - env = ET.Element('Environment', **attrib) - - platform = ET.SubElement(env, 'PlatformSection') - ET.SubElement(platform, 'Kind').text = self.content.about.name - ET.SubElement(platform, 'Version').text = self.content.about.version - ET.SubElement(platform, 'Vendor').text = self.content.about.vendor - ET.SubElement(platform, 'Locale').text = 'US' - - prop_section = ET.SubElement(env, 'PropertySection') - for key, value in self.params['properties'].items(): - params = { - 'oe:key': key, - 'oe:value': str(value) if isinstance(value, bool) else value - } - ET.SubElement(prop_section, 'Property', **params) - - opt = vim.option.OptionValue() - opt.key = 'guestinfo.ovfEnv' - opt.value = '<?xml version="1.0" encoding="UTF-8"?>' + to_native(ET.tostring(env)) - - config_spec = vim.vm.ConfigSpec() - config_spec.extraConfig = [opt] - - task = self.entity.ReconfigVM_Task(config_spec) - wait_for_task(task) - - def deploy(self): - facts = {} - - if self.params['inject_ovf_env']: - self.inject_ovf_env() - - if self.params['power_on']: - task = self.entity.PowerOn() - if self.params['wait']: - wait_for_task(task) - if self.params['wait_for_ip_address']: - _facts = wait_for_vm_ip(self.content, self.entity) - if not _facts: - self.module.fail_json(msg='Waiting for IP address timed out') - facts.update(_facts) - - if not facts: - facts.update(gather_vm_facts(self.content, self.entity)) - - return facts - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update({ - 'name': {}, - 'datastore': { - 'default': 'datastore1', - }, - 'datacenter': { - 'default': 'ha-datacenter', - }, - 'cluster': { - 'default': None, - }, - 'deployment_option': { - 'default': None, - }, - 'folder': { - 'default': None, - }, - 'inject_ovf_env': { - 'default': False, - 'type': 'bool', - }, - 'resource_pool': { - 'default': 'Resources', - }, - 'networks': { - 'default': { - 'VM Network': 'VM Network', - }, - 'type': 'dict', - }, - 'ovf': { - 'type': path_exists, - 'aliases': ['ova'], - }, - 'disk_provisioning': { - 'choices': [ - 'flat', - 'eagerZeroedThick', - 'monolithicSparse', - 'twoGbMaxExtentSparse', - 'twoGbMaxExtentFlat', - 'thin', - 'sparse', - 'thick', - 'seSparse', - 'monolithicFlat' - ], - 'default': 'thin', - }, - 'power_on': { - 'type': 'bool', - 'default': True, - }, - 'properties': { - 'type': 'dict', - }, - 'wait': { - 'type': 'bool', - 'default': True, - }, - 'wait_for_ip_address': { - 'type': 'bool', - 'default': False, - }, - 'allow_duplicates': { - 'type': 'bool', - 'default': True, - }, - 'fail_on_spec_warnings': { - 'type': 'bool', - 'default': False, - }, - }) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - deploy_ovf = VMwareDeployOvf(module) - deploy_ovf.upload() - deploy_ovf.complete() - facts = deploy_ovf.deploy() - - module.exit_json(instance=facts, changed=True) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_drs_group.py b/lib/ansible/modules/cloud/vmware/vmware_drs_group.py deleted file mode 100644 index 8eb83e0690..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_drs_group.py +++ /dev/null @@ -1,584 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Karsten Kaj Jakobsen <kj@patientsky.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''' ---- -author: - - "Karsten Kaj Jakobsen (@karstenjakobsen)" -description: - - "This module can be used to create VM/Host groups in a given cluster. Creates a vm group if C(vms) is set. Creates a host group if C(hosts) is set." -extends_documentation_fragment: vmware.documentation -module: vmware_drs_group -notes: - - "Tested on vSphere 6.5 and 6.7" -options: - cluster_name: - description: - - "Cluster to create vm/host group." - required: true - type: str - datacenter: - aliases: - - datacenter_name - description: - - "Datacenter to search for given cluster. If not set, we use first cluster we encounter with C(cluster_name)." - required: false - type: str - group_name: - description: - - "The name of the group to create or remove." - required: true - type: str - hosts: - description: - - "List of hosts to create in group." - - "Required only if C(vms) is not set." - required: false - type: list - state: - choices: - - present - - absent - default: present - description: - - "If set to C(present) and the group doesn't exists then the group will be created." - - "If set to C(absent) and the group exists then the group will be deleted." - required: true - type: str - vms: - description: - - "List of vms to create in group." - - "Required only if C(hosts) is not set." - required: false - type: list -requirements: - - "python >= 2.6" - - PyVmomi -short_description: "Creates vm/host group in a given cluster." -version_added: "2.8" -''' - -EXAMPLES = r''' ---- -- name: "Create DRS VM group" - delegate_to: localhost - vmware_drs_group: - hostname: "{{ vcenter_hostname }}" - password: "{{ vcenter_password }}" - username: "{{ vcenter_username }}" - cluster_name: DC0_C0 - datacenter_name: DC0 - group_name: TEST_VM_01 - vms: - - DC0_C0_RP0_VM0 - - DC0_C0_RP0_VM1 - state: present - -- name: "Create DRS Host group" - delegate_to: localhost - vmware_drs_group: - hostname: "{{ vcenter_hostname }}" - password: "{{ vcenter_password }}" - username: "{{ vcenter_username }}" - cluster_name: DC0_C0 - datacenter_name: DC0 - group_name: TEST_HOST_01 - hosts: - - DC0_C0_H0 - - DC0_C0_H1 - - DC0_C0_H2 - state: present - -- name: "Delete DRS Host group" - delegate_to: localhost - vmware_drs_group: - hostname: "{{ vcenter_hostname }}" - password: "{{ vcenter_password }}" - username: "{{ vcenter_username }}" - cluster_name: DC0_C0 - datacenter_name: DC0 - group_name: TEST_HOST_01 - state: absent - -''' - -RETURN = r''' -drs_group_facts: - description: Metadata about DRS group created - returned: always - type: dict - sample: - "drs_group_facts": { - "changed": true, - "failed": false, - "msg": "Created host group TEST_HOST_01 successfully", - "result": { - "DC0_C0": [ - { - "group_name": "TEST_HOST_01", - "hosts": [ - "DC0_C0_H0", - "DC0_C0_H1", - "DC0_C0_H2" - ], - "type": "host" - } - ] - } - } -''' - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import (PyVmomi, vmware_argument_spec, - wait_for_task, find_cluster_by_name, - find_vm_by_id, find_datacenter_by_name, find_vm_by_name) - - -class VmwareDrsGroupManager(PyVmomi): - """ - Class to manage DRS groups - """ - - def __init__(self, module, cluster_name, group_name, state, - datacenter_name=None, vm_list=None, host_list=None): - """ - Init - """ - - super(VmwareDrsGroupManager, self).__init__(module) - - self.__datacenter_name = datacenter_name - self.__datacenter_obj = None - self.__cluster_name = cluster_name - self.__cluster_obj = None - self.__group_name = group_name - self.__group_obj = None - self.__operation = None - self.__vm_list = vm_list - self.__vm_obj_list = [] - self.__host_list = host_list - self.__host_obj_list = [] - self.__msg = 'Nothing to see here...' - self.__result = dict() - self.__changed = False - self.__state = state - - if datacenter_name is not None: - - self.__datacenter_obj = find_datacenter_by_name(self.content, self.__datacenter_name) - - if self.__datacenter_obj is None and module.check_mode is False: - raise Exception("Datacenter '%s' not found" % self.__datacenter_name) - - self.__cluster_obj = find_cluster_by_name(content=self.content, - cluster_name=self.__cluster_name, - datacenter=self.__datacenter_obj) - - # Throw error if cluster does not exist - if self.__cluster_obj is None: - if module.check_mode is False: - raise Exception("Cluster '%s' not found" % self.__cluster_name) - else: - # get group - self.__group_obj = self.__get_group_by_name() - # Set result here. If nothing is to be updated, result is already set - self.__set_result(self.__group_obj) - - # Dont populate lists if we are deleting group - if state == 'present': - - if self.__group_obj: - self.__operation = 'edit' - else: - self.__operation = 'add' - - if self.__vm_list is not None: - self.__set_vm_obj_list(vm_list=self.__vm_list) - - if self.__host_list is not None: - self.__set_host_obj_list(host_list=self.__host_list) - else: - self.__operation = 'remove' - - def get_msg(self): - """ - Returns message for Ansible result - Args: none - - Returns: string - """ - return self.__msg - - def get_result(self): - """ - Returns result for Ansible - Args: none - - Returns: dict - """ - return self.__result - - def __set_result(self, group_obj): - """ - Creates result for successful run - Args: - group_obj: group object - - Returns: None - - """ - self.__result = dict() - - if (self.__cluster_obj is not None) and (group_obj is not None): - self.__result[self.__cluster_obj.name] = [] - self.__result[self.__cluster_obj.name].append(self.__normalize_group_data(group_obj)) - - def get_changed(self): - """ - Returns if anything changed - Args: none - - Returns: boolean - """ - return self.__changed - - def __set_vm_obj_list(self, vm_list=None, cluster_obj=None): - """ - Function populate vm object list from list of vms - Args: - vm_list: List of vm names - - Returns: None - - """ - - if vm_list is None: - vm_list = self.__vm_list - - if cluster_obj is None: - cluster_obj = self.__cluster_obj - - if vm_list is not None: - - for vm in vm_list: - - if self.module.check_mode is False: - - # Get host data - vm_obj = find_vm_by_id(content=self.content, vm_id=vm, - vm_id_type='vm_name', cluster=cluster_obj) - - if vm_obj is None: - raise Exception("VM %s does not exist in cluster %s" % (vm, - self.__cluster_name)) - - self.__vm_obj_list.append(vm_obj) - - def __set_host_obj_list(self, host_list=None): - """ - Function populate host object list from list of hostnames - Args: - host_list: List of host names - - Returns: None - - """ - - if host_list is None: - host_list = self.__host_list - - if host_list is not None: - - for host in host_list: - - if self.module.check_mode is False: - - # Get host data - host_obj = self.find_hostsystem_by_name(host) - - if host_obj is None and self.module.check_mode is False: - raise Exception("ESXi host %s does not exist in cluster %s" % (host, self.__cluster_name)) - - self.__host_obj_list.append(host_obj) - - def __get_group_by_name(self, group_name=None, cluster_obj=None): - """ - Function to get group by name - Args: - group_name: Name of group - cluster_obj: vim Cluster object - - Returns: Group Object if found or None - - """ - - if group_name is None: - group_name = self.__group_name - - if cluster_obj is None: - cluster_obj = self.__cluster_obj - - # Allow for group check even if dry run - if self.module.check_mode and cluster_obj is None: - return None - - for group in cluster_obj.configurationEx.group: - if group.name == group_name: - return group - - # No group found - return None - - def __populate_vm_host_list(self, group_name=None, cluster_obj=None, host_group=False): - """ - Return all VM/Host names using given group name - Args: - group_name: group name - cluster_obj: Cluster managed object - host_group: True if we want only host name from group - - Returns: List of VM/Host names belonging to given group object - - """ - obj_name_list = [] - - if group_name is None: - group_name = self.__group_name - - if cluster_obj is None: - cluster_obj = self.__cluster_obj - - if not all([group_name, cluster_obj]): - return obj_name_list - - group = self.__group_obj - - if not host_group and isinstance(group, vim.cluster.VmGroup): - obj_name_list = [vm.name for vm in group.vm] - - elif host_group and isinstance(group, vim.cluster.HostGroup): - obj_name_list = [host.name for host in group.host] - - return obj_name_list - - def __check_if_vms_hosts_changed(self, group_name=None, cluster_obj=None, host_group=False): - """ - Function to check if VMs/Hosts changed - Args: - group_name: Name of group - cluster_obj: vim Cluster object - host_group: True if we want to check hosts, else check vms - - Returns: Bool - - """ - - if group_name is None: - group_name = self.__group_name - - if cluster_obj is None: - cluster_obj = self.__cluster_obj - - list_a = self.__host_list if host_group else self.__vm_list - list_b = self.__populate_vm_host_list(host_group=host_group) - - # By casting lists as a set, you remove duplicates and order doesn't count. Comparing sets is also much faster and more efficient than comparing lists. - if set(list_a) == set(list_b): - return False - else: - return True - - def __create_host_group(self): - - # Check if anything has changed when editing - if self.__operation == 'add' or (self.__operation == 'edit' and self.__check_if_vms_hosts_changed(host_group=True)): - - group = vim.cluster.HostGroup() - group.name = self.__group_name - group.host = self.__host_obj_list - - group_spec = vim.cluster.GroupSpec(info=group, operation=self.__operation) - config_spec = vim.cluster.ConfigSpecEx(groupSpec=[group_spec]) - - if not self.module.check_mode: - task = self.__cluster_obj.ReconfigureEx(config_spec, modify=True) - wait_for_task(task) - - # Set new result since something changed - self.__set_result(group) - self.__changed = True - - if self.__operation == 'edit': - self.__msg = "Updated host group %s successfully" % (self.__group_name) - else: - self.__msg = "Created host group %s successfully" % (self.__group_name) - - def __create_vm_group(self): - - # Check if anything has changed when editing - if self.__operation == 'add' or (self.__operation == 'edit' and self.__check_if_vms_hosts_changed()): - - group = vim.cluster.VmGroup() - - group.name = self.__group_name - group.vm = self.__vm_obj_list - - group_spec = vim.cluster.GroupSpec(info=group, operation=self.__operation) - config_spec = vim.cluster.ConfigSpecEx(groupSpec=[group_spec]) - - # Check if dry run - if not self.module.check_mode: - task = self.__cluster_obj.ReconfigureEx(config_spec, modify=True) - wait_for_task(task) - - self.__set_result(group) - self.__changed = True - - if self.__operation == 'edit': - self.__msg = "Updated vm group %s successfully" % (self.__group_name) - else: - self.__msg = "Created vm group %s successfully" % (self.__group_name) - - def __normalize_group_data(self, group_obj): - """ - Return human readable group spec - Args: - group_obj: Group object - - Returns: DRS group object fact - - """ - if not all([group_obj]): - return {} - - # Check if group is a host group - if hasattr(group_obj, 'host'): - return dict( - group_name=group_obj.name, - hosts=self.__host_list, - type="host" - ) - else: - return dict( - group_name=group_obj.name, - vms=self.__vm_list, - type="vm" - ) - - def create_drs_group(self): - """ - Function to create a DRS host/vm group - """ - - if self.__vm_list is None: - self.__create_host_group() - elif self.__host_list is None: - self.__create_vm_group() - else: - raise Exception('Failed, no hosts or vms defined') - - def delete_drs_group(self): - """ - Function to delete a DRS host/vm group - """ - - if self.__group_obj is not None: - - self.__changed = True - - # Check if dry run - if not self.module.check_mode: - - group_spec = vim.cluster.GroupSpec(removeKey=self.__group_name, operation=self.__operation) - config_spec = vim.cluster.ConfigSpecEx(groupSpec=[group_spec]) - - task = self.__cluster_obj.ReconfigureEx(config_spec, modify=True) - wait_for_task(task) - - # Dont throw error if group does not exist. Simply set changed = False - if self.__changed: - self.__msg = "Deleted group `%s` successfully" % (self.__group_name) - else: - self.__msg = "DRS group `%s` does not exists or already deleted" % (self.__group_name) - - -def main(): - """ - Main function - """ - - argument_spec = vmware_argument_spec() - - argument_spec.update( - state=dict(type='str', default='present', choices=['present', 'absent']), - datacenter=dict(type='str', required=False, aliases=['datacenter_name']), - cluster_name=dict(type='str', required=True), - group_name=dict(type='str', required=True), - vms=dict(type='list'), - hosts=dict(type='list') - ) - - required_if = [ - ['state', 'absent', ['group_name']] - ] - - module = AnsibleModule( - argument_spec=argument_spec, - required_if=required_if, - supports_check_mode=True, - mutually_exclusive=[['vms', 'hosts']], - required_one_of=[['vms', 'hosts']] - ) - - try: - # Create instance of VmwareDrsGroupManager - vmware_drs_group = VmwareDrsGroupManager(module=module, - datacenter_name=module.params.get('datacenter', None), - cluster_name=module.params['cluster_name'], - group_name=module.params['group_name'], - vm_list=module.params['vms'], - host_list=module.params['hosts'], - state=module.params['state']) - - if module.params['state'] == 'present': - # Add DRS group - vmware_drs_group.create_drs_group() - elif module.params['state'] == 'absent': - # Delete DRS group - vmware_drs_group.delete_drs_group() - - # Set results - results = dict(msg=vmware_drs_group.get_msg(), - failed=False, - changed=vmware_drs_group.get_changed(), - result=vmware_drs_group.get_result()) - - except Exception as error: - results = dict(failed=True, msg="Error: %s" % error) - - if results['failed']: - module.fail_json(**results) - else: - module.exit_json(**results) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_drs_group_info.py b/lib/ansible/modules/cloud/vmware/vmware_drs_group_info.py deleted file mode 100644 index 50e9138bfd..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_drs_group_info.py +++ /dev/null @@ -1,282 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Karsten Kaj Jakobsen <kj@patientsky.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''' ---- -author: - - "Karsten Kaj Jakobsen (@karstenjakobsen)" -description: - - "This module can be used to gather information about DRS VM/HOST groups from the given cluster." -extends_documentation_fragment: vmware.documentation -module: vmware_drs_group_info -notes: - - "Tested on vSphere 6.5 and 6.7" -options: - cluster_name: - description: - - "Cluster to search for VM/Host groups." - - "If set, information of DRS groups belonging this cluster will be returned." - - "Not needed if C(datacenter) is set." - required: false - type: str - datacenter: - aliases: - - datacenter_name - description: - - "Datacenter to search for DRS VM/Host groups." - required: true - type: str -requirements: - - "python >= 2.6" - - PyVmomi -short_description: "Gathers info about DRS VM/Host groups on the given cluster" -version_added: "2.9" -''' - -EXAMPLES = r''' ---- -- name: "Gather DRS info about given Cluster" - register: cluster_drs_group_info - vmware_drs_group_info: - hostname: "{{ vcenter_hostname }}" - password: "{{ vcenter_password }}" - username: "{{ vcenter_username }}" - cluster_name: "{{ cluster_name }}" - datacenter: "{{ datacenter }}" - delegate_to: localhost - -- name: "Gather DRS group info about all clusters in given datacenter" - register: cluster_drs_group_info - vmware_drs_group_info: - hostname: "{{ vcenter_hostname }}" - password: "{{ vcenter_password }}" - username: "{{ vcenter_username }}" - datacenter: "{{ datacenter }}" - delegate_to: localhost -''' - -RETURN = r''' -drs_group_info: - description: Metadata about DRS group from given cluster / datacenter - returned: always - type: dict - sample: - "drs_group_info": { - "DC0_C0": [ - { - "group_name": "GROUP_HOST_S01", - "hosts": [ - "vm-01.zone", - "vm-02.zone" - ], - "type": "host" - }, - { - "group_name": "GROUP_HOST_S02", - "hosts": [ - "vm-03.zone", - "vm-04.zone" - ], - "type": "host" - }, - { - "group_name": "GROUP_VM_S01", - "type": "vm", - "vms": [ - "test-node01" - ] - }, - { - "group_name": "GROUP_VM_S02", - "type": "vm", - "vms": [ - "test-node02" - ] - } - ], - "DC0_C1": [] - } -''' - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi, find_datacenter_by_name, get_all_objs - - -class VmwareDrsGroupInfoManager(PyVmomi): - - def __init__(self, module, datacenter_name, cluster_name=None): - """ - Doctring: Init - """ - - super(VmwareDrsGroupInfoManager, self).__init__(module) - - self.__datacenter_name = datacenter_name - self.__datacenter_obj = None - self.__cluster_name = cluster_name - self.__cluster_obj = None - self.__msg = 'Nothing to see here...' - self.__result = dict() - self.__changed = False - - if datacenter_name: - - datacenter_obj = find_datacenter_by_name(self.content, datacenter_name=datacenter_name) - self.cluster_obj_list = [] - - if datacenter_obj: - folder = datacenter_obj.hostFolder - self.cluster_obj_list = get_all_objs(self.content, [vim.ClusterComputeResource], folder) - else: - raise Exception("Datacenter '%s' not found" % self.__datacenter_name) - - if cluster_name: - - cluster_obj = self.find_cluster_by_name(cluster_name=self.__cluster_name) - - if cluster_obj is None: - raise Exception("Cluster '%s' not found" % self.__cluster_name) - else: - self.cluster_obj_list = [cluster_obj] - - def get_result(self): - """ - Docstring - """ - return self.__result - - def __set_result(self, result): - """ - Sets result - Args: - result: drs group result list - - Returns: None - - """ - self.__result = result - - def __get_all_from_group(self, group_obj, host_group=False): - """ - Return all VM / Host names using given group - Args: - group_obj: Group object - host_group: True if we want only host name from group - - Returns: List of VM / Host names belonging to given group object - - """ - obj_name_list = [] - - if not all([group_obj]): - return obj_name_list - - if not host_group and isinstance(group_obj, vim.cluster.VmGroup): - obj_name_list = [vm.name for vm in group_obj.vm] - elif host_group and isinstance(group_obj, vim.cluster.HostGroup): - obj_name_list = [host.name for host in group_obj.host] - - return obj_name_list - - def __normalize_group_data(self, group_obj): - """ - Return human readable group spec - Args: - group_obj: Group object - - Returns: Dictionary with DRS groups - - """ - if not all([group_obj]): - return {} - - # Check if group is a host group - if hasattr(group_obj, 'host'): - return dict( - group_name=group_obj.name, - hosts=self.__get_all_from_group(group_obj=group_obj, host_group=True), - type="host" - ) - else: - return dict( - group_name=group_obj.name, - vms=self.__get_all_from_group(group_obj=group_obj), - type="vm" - ) - - def gather_info(self): - """ - Gather DRS group information about given cluster - Returns: Dictionary of clusters with DRS groups - - """ - cluster_group_info = dict() - - for cluster_obj in self.cluster_obj_list: - - cluster_group_info[cluster_obj.name] = [] - - for drs_group in cluster_obj.configurationEx.group: - cluster_group_info[cluster_obj.name].append(self.__normalize_group_data(drs_group)) - - self.__set_result(cluster_group_info) - - -def main(): - - argument_spec = vmware_argument_spec() - - argument_spec.update( - datacenter=dict(type='str', required=False, aliases=['datacenter_name']), - cluster_name=dict(type='str', required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - required_one_of=[['cluster_name', 'datacenter']], - mutually_exclusive=[['cluster_name', 'datacenter']], - ) - - try: - # Create instance of VmwareDrsGroupManager - vmware_drs_group_info = VmwareDrsGroupInfoManager( - module=module, - datacenter_name=module.params.get('datacenter'), - cluster_name=module.params.get('cluster_name', None)) - - vmware_drs_group_info.gather_info() - - # Set results - results = dict(failed=False, - drs_group_info=vmware_drs_group_info.get_result()) - - except Exception as error: - results = dict(failed=True, msg="Error: %s" % error) - - if results['failed']: - module.fail_json(**results) - else: - module.exit_json(**results) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_drs_rule_info.py b/lib/ansible/modules/cloud/vmware/vmware_drs_rule_info.py deleted file mode 100644 index 062562d577..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_drs_rule_info.py +++ /dev/null @@ -1,262 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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_drs_rule_info -short_description: Gathers info about DRS rule on the given cluster -description: -- 'This module can be used to gather information about DRS VM-VM and VM-HOST rules from the given cluster.' -version_added: '2.9' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of the cluster. - - DRS information for the given cluster will be returned. - - This is required parameter if C(datacenter) parameter is not provided. - type: str - datacenter: - description: - - Name of the datacenter. - - DRS information for all the clusters from the given datacenter will be returned. - - This is required parameter if C(cluster_name) parameter is not provided. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather DRS info about given Cluster - vmware_drs_rule_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: '{{ cluster_name }}' - delegate_to: localhost - register: cluster_drs_info - -- name: Gather DRS info about all Clusters in given datacenter - vmware_drs_rule_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: '{{ datacenter_name }}' - delegate_to: localhost - register: datacenter_drs_info -''' - -RETURN = r''' -drs_rule_info: - description: metadata about DRS rule from given cluster / datacenter - returned: always - type: dict - sample: { - "DC0_C0": [ - { - "rule_affinity": false, - "rule_enabled": true, - "rule_key": 1, - "rule_mandatory": true, - "rule_name": "drs_rule_0001", - "rule_type": "vm_vm_rule", - "rule_uuid": "52be5061-665a-68dc-3d25-85cd2d37e114", - "rule_vms": [ - "VM_65", - "VM_146" - ] - }, - ], - "DC1_C1": [ - { - "rule_affine_host_group_name": "host_group_1", - "rule_affine_hosts": [ - "10.76.33.204" - ], - "rule_anti_affine_host_group_name": null, - "rule_anti_affine_hosts": [], - "rule_enabled": true, - "rule_key": 1, - "rule_mandatory": false, - "rule_name": "vm_host_rule_0001", - "rule_type": "vm_host_rule", - "rule_uuid": "52687108-4d3a-76f2-d29c-b708c40dbe40", - "rule_vm_group_name": "test_vm_group_1", - "rule_vms": [ - "VM_8916", - "VM_4010" - ] - } - ], - } -''' - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi, find_datacenter_by_name, get_all_objs - - -class VmwareDrsInfoManager(PyVmomi): - def __init__(self, module): - super(VmwareDrsInfoManager, self).__init__(module) - - datacenter_name = self.params.get('datacenter', None) - if datacenter_name: - datacenter_obj = find_datacenter_by_name(self.content, datacenter_name=datacenter_name) - self.cluster_obj_list = [] - if datacenter_obj: - folder = datacenter_obj.hostFolder - self.cluster_obj_list = get_all_objs(self.content, [vim.ClusterComputeResource], folder) - else: - self.module.fail_json(changed=False, msg="Datacenter '%s' not found" % datacenter_name) - - cluster_name = self.params.get('cluster_name', None) - if cluster_name: - cluster_obj = self.find_cluster_by_name(cluster_name=cluster_name) - if cluster_obj is None: - self.module.fail_json(changed=False, msg="Cluster '%s' not found" % cluster_name) - else: - self.cluster_obj_list = [cluster_obj] - - def get_all_from_group(self, group_name=None, cluster_obj=None, hostgroup=False): - """ - Return all VM / Host names using given group name - Args: - group_name: Rule name - cluster_obj: Cluster managed object - hostgroup: True if we want only host name from group - - Returns: List of VM / Host names belonging to given group object - - """ - obj_name_list = [] - if not all([group_name, cluster_obj]): - return obj_name_list - - for group in cluster_obj.configurationEx.group: - if group.name == group_name: - if not hostgroup and isinstance(group, vim.cluster.VmGroup): - obj_name_list = [vm.name for vm in group.vm] - break - elif hostgroup and isinstance(group, vim.cluster.HostGroup): - obj_name_list = [host.name for host in group.host] - break - - return obj_name_list - - @staticmethod - def normalize_vm_vm_rule_spec(rule_obj=None): - """ - Return human readable rule spec - Args: - rule_obj: Rule managed object - - Returns: Dictionary with DRS VM VM Rule info - - """ - if rule_obj is None: - return {} - return dict(rule_key=rule_obj.key, - rule_enabled=rule_obj.enabled, - rule_name=rule_obj.name, - rule_mandatory=rule_obj.mandatory, - rule_uuid=rule_obj.ruleUuid, - rule_vms=[vm.name for vm in rule_obj.vm], - rule_type="vm_vm_rule", - rule_affinity=True if isinstance(rule_obj, vim.cluster.AffinityRuleSpec) else False, - ) - - def normalize_vm_host_rule_spec(self, rule_obj=None, cluster_obj=None): - """ - Return human readable rule spec - Args: - rule_obj: Rule managed object - cluster_obj: Cluster managed object - - Returns: Dictionary with DRS VM HOST Rule info - - """ - if not all([rule_obj, cluster_obj]): - return {} - return dict(rule_key=rule_obj.key, - rule_enabled=rule_obj.enabled, - rule_name=rule_obj.name, - rule_mandatory=rule_obj.mandatory, - rule_uuid=rule_obj.ruleUuid, - rule_vm_group_name=rule_obj.vmGroupName, - rule_affine_host_group_name=rule_obj.affineHostGroupName, - rule_anti_affine_host_group_name=rule_obj.antiAffineHostGroupName, - rule_vms=self.get_all_from_group(group_name=rule_obj.vmGroupName, - cluster_obj=cluster_obj), - rule_affine_hosts=self.get_all_from_group(group_name=rule_obj.affineHostGroupName, - cluster_obj=cluster_obj, - hostgroup=True), - rule_anti_affine_hosts=self.get_all_from_group(group_name=rule_obj.antiAffineHostGroupName, - cluster_obj=cluster_obj, - hostgroup=True), - rule_type="vm_host_rule", - ) - - def gather_drs_rule_info(self): - """ - Gather DRS rule information about given cluster - Returns: Dictionary of clusters with DRS information - - """ - cluster_rule_info = dict() - for cluster_obj in self.cluster_obj_list: - cluster_rule_info[cluster_obj.name] = [] - for drs_rule in cluster_obj.configuration.rule: - if isinstance(drs_rule, vim.cluster.VmHostRuleInfo): - cluster_rule_info[cluster_obj.name].append(self.normalize_vm_host_rule_spec( - rule_obj=drs_rule, - cluster_obj=cluster_obj)) - else: - cluster_rule_info[cluster_obj.name].append(self.normalize_vm_vm_rule_spec(rule_obj=drs_rule)) - - return cluster_rule_info - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - datacenter=dict(type='str', required=False), - cluster_name=dict(type='str', required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'datacenter'], - ], - supports_check_mode=True, - ) - - vmware_drs_info = VmwareDrsInfoManager(module) - module.exit_json(changed=False, drs_rule_info=vmware_drs_info.gather_drs_rule_info()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_dvs_host.py b/lib/ansible/modules/cloud/vmware/vmware_dvs_host.py deleted file mode 100644 index 397f41b409..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_dvs_host.py +++ /dev/null @@ -1,295 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2015, Joseph Callen <jcallen () csc.com> -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# Copyright: (c) 2019, VMware Inc. -# 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 = ''' ---- -module: vmware_dvs_host -short_description: Add or remove a host from distributed virtual switch -description: - - Manage a host system from distributed virtual switch. -version_added: 2.0 -author: -- Joseph Callen (@jcpowermac) -- Abhijeet Kasurde (@Akasurde) -- Joseph Andreatta (@vmwjoseph) -notes: - - Tested on vSphere 5.5 -requirements: - - "python >= 2.7" - - PyVmomi -options: - esxi_hostname: - description: - - The ESXi hostname. - required: True - type: str - switch_name: - description: - - The name of the Distributed vSwitch. - required: True - type: str - vmnics: - description: - - The ESXi hosts vmnics to use with the Distributed vSwitch. - required: True - type: list - state: - description: - - If the host should be present or absent attached to the vSwitch. - choices: [ present, absent ] - required: True - default: 'present' - type: str - vendor_specific_config: - description: - - List of key,value dictionaries for the Vendor Specific Configuration. - - 'Element attributes are:' - - '- C(key) (str): Key of setting. (default: None)' - - '- C(value) (str): Value of setting. (default: None)' - required: False - version_added: '2.9' - type: list -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Add Host to dVS - vmware_dvs_host: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - switch_name: dvSwitch - vmnics: - - vmnic0 - - vmnic1 - state: present - delegate_to: localhost - -- name: Add Host to dVS/enable learnswitch (https://labs.vmware.com/flings/learnswitch) - vmware_dvs_host: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - switch_name: dvSwitch - vendor_specific_config: - - key: com.vmware.netoverlay.layer1 - value: learnswitch - vmnics: - - vmnic0 - - vmnic1 - state: present - delegate_to: localhost -''' - -try: - from collections import Counter - HAS_COLLECTIONS_COUNTER = True -except ImportError as e: - HAS_COLLECTIONS_COUNTER = False - -try: - from pyVmomi import vim, vmodl -except ImportError as e: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import (PyVmomi, find_dvs_by_name, find_hostsystem_by_name, - vmware_argument_spec, wait_for_task) -from ansible.module_utils._text import to_native - - -class VMwareDvsHost(PyVmomi): - def __init__(self, module): - super(VMwareDvsHost, self).__init__(module) - self.dv_switch = None - self.uplink_portgroup = None - self.host = None - self.dv_switch = None - self.nic = None - self.state = self.module.params['state'] - self.switch_name = self.module.params['switch_name'] - self.esxi_hostname = self.module.params['esxi_hostname'] - self.vmnics = self.module.params['vmnics'] - self.vendor_specific_config = self.module.params['vendor_specific_config'] - - def process_state(self): - dvs_host_states = { - 'absent': { - 'present': self.state_destroy_dvs_host, - 'absent': self.state_exit_unchanged, - }, - 'present': { - 'update': self.state_update_dvs_host, - 'present': self.state_exit_unchanged, - 'absent': self.state_create_dvs_host, - } - } - - try: - dvs_host_states[self.state][self.check_dvs_host_state()]() - except vmodl.RuntimeFault as runtime_fault: - self.module.fail_json(msg=to_native(runtime_fault.msg)) - except vmodl.MethodFault as method_fault: - self.module.fail_json(msg=to_native(method_fault.msg)) - except Exception as e: - self.module.fail_json(msg=to_native(e)) - - def find_dvs_uplink_pg(self): - # There should only always be a single uplink port group on - # a distributed virtual switch - dvs_uplink_pg = self.dv_switch.config.uplinkPortgroup[0] if len(self.dv_switch.config.uplinkPortgroup) else None - return dvs_uplink_pg - - # operation should be edit, add and remove - def modify_dvs_host(self, operation): - changed, result = False, None - spec = vim.DistributedVirtualSwitch.ConfigSpec() - spec.configVersion = self.dv_switch.config.configVersion - spec.host = [vim.dvs.HostMember.ConfigSpec()] - spec.host[0].operation = operation - spec.host[0].host = self.host - if self.vendor_specific_config: - config = list() - for item in self.vendor_specific_config: - config.append(vim.dvs.KeyedOpaqueBlob(key=item['key'], opaqueData=item['value'])) - spec.host[0].vendorSpecificConfig = config - - if operation in ("edit", "add"): - spec.host[0].backing = vim.dvs.HostMember.PnicBacking() - count = 0 - - for nic in self.vmnics: - spec.host[0].backing.pnicSpec.append(vim.dvs.HostMember.PnicSpec()) - spec.host[0].backing.pnicSpec[count].pnicDevice = nic - spec.host[0].backing.pnicSpec[count].uplinkPortgroupKey = self.uplink_portgroup.key - count += 1 - - try: - task = self.dv_switch.ReconfigureDvs_Task(spec) - changed, result = wait_for_task(task) - except vmodl.fault.NotSupported as not_supported: - self.module.fail_json(msg="Failed to configure DVS host %s as it is not" - " compatible with the VDS version." % self.esxi_hostname, - details=to_native(not_supported.msg)) - return changed, result - - def state_destroy_dvs_host(self): - operation, changed, result = ("remove", True, None) - - if not self.module.check_mode: - changed, result = self.modify_dvs_host(operation) - self.module.exit_json(changed=changed, result=to_native(result)) - - def state_exit_unchanged(self): - self.module.exit_json(changed=False) - - def state_update_dvs_host(self): - operation, changed, result = ("edit", True, None) - - if not self.module.check_mode: - changed, result = self.modify_dvs_host(operation) - self.module.exit_json(changed=changed, result=to_native(result)) - - def state_create_dvs_host(self): - operation, changed, result = ("add", True, None) - - if not self.module.check_mode: - changed, result = self.modify_dvs_host(operation) - self.module.exit_json(changed=changed, result=to_native(result)) - - def find_host_attached_dvs(self): - for dvs_host_member in self.dv_switch.config.host: - if dvs_host_member.config.host.name == self.esxi_hostname: - return dvs_host_member.config.host - - return None - - def check_uplinks(self): - pnic_device = [] - - for dvs_host_member in self.dv_switch.config.host: - if dvs_host_member.config.host == self.host: - for pnicSpec in dvs_host_member.config.backing.pnicSpec: - pnic_device.append(pnicSpec.pnicDevice) - - return Counter(pnic_device) == Counter(self.vmnics) - - def check_dvs_host_state(self): - self.dv_switch = find_dvs_by_name(self.content, self.switch_name) - - if self.dv_switch is None: - self.module.fail_json(msg="A distributed virtual switch %s " - "does not exist" % self.switch_name) - - self.uplink_portgroup = self.find_dvs_uplink_pg() - - if self.uplink_portgroup is None: - self.module.fail_json(msg="An uplink portgroup does not exist on" - " the distributed virtual switch %s" % self.switch_name) - - self.host = self.find_host_attached_dvs() - - if self.host is None: - # We still need the HostSystem object to add the host - # to the distributed vswitch - self.host = find_hostsystem_by_name(self.content, self.esxi_hostname) - if self.host is None: - self.module.fail_json(msg="The esxi_hostname %s does not exist " - "in vCenter" % self.esxi_hostname) - return 'absent' - else: - if self.check_uplinks(): - return 'present' - else: - return 'update' - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - dict( - esxi_hostname=dict(required=True, type='str'), - switch_name=dict(required=True, type='str'), - vmnics=dict(required=True, type='list'), - state=dict(default='present', choices=['present', 'absent'], type='str'), - vendor_specific_config=dict( - type='list', - elements='dict', - required=False, - options=dict( - key=dict(type='str', required=True), - value=dict(type='str', required=True), - ), - ), - ) - ) - - module = AnsibleModule(argument_spec=argument_spec, - supports_check_mode=True) - - if not HAS_COLLECTIONS_COUNTER: - module.fail_json(msg='collections.Counter from Python-2.7 is required for this module') - - vmware_dvs_host = VMwareDvsHost(module) - vmware_dvs_host.process_state() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_dvs_portgroup.py b/lib/ansible/modules/cloud/vmware/vmware_dvs_portgroup.py deleted file mode 100644 index 9336d4a30b..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_dvs_portgroup.py +++ /dev/null @@ -1,527 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2015, Joseph Callen <jcallen () csc.com> -# Copyright: (c) 2017-2018, Ansible Project -# 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 = ''' ---- -module: vmware_dvs_portgroup -short_description: Create or remove a Distributed vSwitch portgroup. -description: - - Create or remove a Distributed vSwitch portgroup. -version_added: 2.0 -author: - - Joseph Callen (@jcpowermac) - - Philippe Dellaert (@pdellaert) <philippe@dellaert.org> -notes: - - Tested on vSphere 5.5 - - Tested on vSphere 6.5 -requirements: - - "python >= 2.6" - - PyVmomi -options: - portgroup_name: - description: - - The name of the portgroup that is to be created or deleted. - required: True - type: str - switch_name: - description: - - The name of the distributed vSwitch the port group should be created on. - required: True - type: str - vlan_id: - description: - - The VLAN ID that should be configured with the portgroup, use 0 for no VLAN. - - 'If C(vlan_trunk) is configured to be I(true), this can be a combination of multiple ranges and numbers, example: 1-200, 205, 400-4094.' - - The valid C(vlan_id) range is from 0 to 4094. Overlapping ranges are allowed. - required: True - type: str - num_ports: - description: - - The number of ports the portgroup should contain. - required: True - type: int - portgroup_type: - description: - - See VMware KB 1022312 regarding portgroup types. - required: True - choices: - - 'earlyBinding' - - 'lateBinding' - - 'ephemeral' - type: str - state: - description: - - Determines if the portgroup should be present or not. - required: True - type: str - choices: - - 'present' - - 'absent' - version_added: '2.5' - vlan_trunk: - description: - - Indicates whether this is a VLAN trunk or not. - required: False - default: False - type: bool - version_added: '2.5' - network_policy: - description: - - Dictionary which configures the different security values for portgroup. - - 'Valid attributes are:' - - '- C(promiscuous) (bool): indicates whether promiscuous mode is allowed. (default: false)' - - '- C(forged_transmits) (bool): indicates whether forged transmits are allowed. (default: false)' - - '- C(mac_changes) (bool): indicates whether mac changes are allowed. (default: false)' - required: False - version_added: '2.5' - default: { - promiscuous: False, - forged_transmits: False, - mac_changes: False, - } - type: dict - teaming_policy: - description: - - Dictionary which configures the different teaming values for portgroup. - - 'Valid attributes are:' - - '- C(load_balance_policy) (string): Network adapter teaming policy. (default: loadbalance_srcid)' - - ' - choices: [ loadbalance_ip, loadbalance_srcmac, loadbalance_srcid, loadbalance_loadbased, failover_explicit]' - - ' - "loadbalance_loadbased" is available from version 2.6 and onwards' - - '- C(inbound_policy) (bool): Indicate whether or not the teaming policy is applied to inbound frames as well. (default: False)' - - '- C(notify_switches) (bool): Indicate whether or not to notify the physical switch if a link fails. (default: True)' - - '- C(rolling_order) (bool): Indicate whether or not to use a rolling policy when restoring links. (default: False)' - required: False - version_added: '2.5' - default: { - 'notify_switches': True, - 'load_balance_policy': 'loadbalance_srcid', - 'inbound_policy': False, - 'rolling_order': False - } - type: dict - port_policy: - description: - - Dictionary which configures the advanced policy settings for the portgroup. - - 'Valid attributes are:' - - '- C(block_override) (bool): indicates if the block policy can be changed per port. (default: true)' - - '- C(ipfix_override) (bool): indicates if the ipfix policy can be changed per port. (default: false)' - - '- C(live_port_move) (bool): indicates if a live port can be moved in or out of the portgroup. (default: false)' - - '- C(network_rp_override) (bool): indicates if the network resource pool can be changed per port. (default: false)' - - '- C(port_config_reset_at_disconnect) (bool): indicates if the configuration of a port is reset automatically after disconnect. (default: true)' - - '- C(security_override) (bool): indicates if the security policy can be changed per port. (default: false)' - - '- C(shaping_override) (bool): indicates if the shaping policy can be changed per port. (default: false)' - - '- C(traffic_filter_override) (bool): indicates if the traffic filter can be changed per port. (default: false)' - - '- C(uplink_teaming_override) (bool): indicates if the uplink teaming policy can be changed per port. (default: false)' - - '- C(vendor_config_override) (bool): indicates if the vendor config can be changed per port. (default: false)' - - '- C(vlan_override) (bool): indicates if the vlan can be changed per port. (default: false)' - required: False - version_added: '2.5' - default: { - 'traffic_filter_override': False, - 'network_rp_override': False, - 'live_port_move': False, - 'security_override': False, - 'vendor_config_override': False, - 'port_config_reset_at_disconnect': True, - 'uplink_teaming_override': False, - 'block_override': True, - 'shaping_override': False, - 'vlan_override': False, - 'ipfix_override': False - } - type: dict - -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Create vlan portgroup - vmware_dvs_portgroup: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - portgroup_name: vlan-123-portrgoup - switch_name: dvSwitch - vlan_id: 123 - num_ports: 120 - portgroup_type: earlyBinding - state: present - delegate_to: localhost - -- name: Create vlan trunk portgroup - vmware_dvs_portgroup: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - portgroup_name: vlan-trunk-portrgoup - switch_name: dvSwitch - vlan_id: 1-1000, 1005, 1100-1200 - vlan_trunk: True - num_ports: 120 - portgroup_type: earlyBinding - state: present - delegate_to: localhost - -- name: Create no-vlan portgroup - vmware_dvs_portgroup: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - portgroup_name: no-vlan-portrgoup - switch_name: dvSwitch - vlan_id: 0 - num_ports: 120 - portgroup_type: earlyBinding - state: present - delegate_to: localhost - -- name: Create vlan portgroup with all security and port policies - vmware_dvs_portgroup: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - portgroup_name: vlan-123-portrgoup - switch_name: dvSwitch - vlan_id: 123 - num_ports: 120 - portgroup_type: earlyBinding - state: present - network_policy: - promiscuous: yes - forged_transmits: yes - mac_changes: yes - port_policy: - block_override: yes - ipfix_override: yes - live_port_move: yes - network_rp_override: yes - port_config_reset_at_disconnect: yes - security_override: yes - shaping_override: yes - traffic_filter_override: yes - uplink_teaming_override: yes - vendor_config_override: yes - vlan_override: yes - delegate_to: localhost -''' - -try: - from pyVmomi import vim, vmodl -except ImportError as e: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import (PyVmomi, find_dvs_by_name, find_dvspg_by_name, - vmware_argument_spec, wait_for_task) - - -class VMwareDvsPortgroup(PyVmomi): - def __init__(self, module): - super(VMwareDvsPortgroup, self).__init__(module) - self.dvs_portgroup = None - self.dv_switch = None - - def create_vlan_list(self): - vlan_id_list = [] - for vlan_id_splitted in self.module.params['vlan_id'].split(','): - vlans = vlan_id_splitted.split('-') - if len(vlans) > 2: - self.module.fail_json(msg="Invalid VLAN range %s." % vlan_id_splitted) - if len(vlans) == 2: - vlan_id_start = vlans[0].strip() - vlan_id_end = vlans[1].strip() - if not vlan_id_start.isdigit(): - self.module.fail_json(msg="Invalid VLAN %s." % vlan_id_start) - if not vlan_id_end.isdigit(): - self.module.fail_json(msg="Invalid VLAN %s." % vlan_id_end) - vlan_id_start = int(vlan_id_start) - vlan_id_end = int(vlan_id_end) - if vlan_id_start not in range(0, 4095) or vlan_id_end not in range(0, 4095): - self.module.fail_json(msg="vlan_id range %s specified is incorrect. The valid vlan_id range is from 0 to 4094." % vlan_id_splitted) - vlan_id_list.append((vlan_id_start, vlan_id_end)) - else: - vlan_id = vlans[0].strip() - if not vlan_id.isdigit(): - self.module.fail_json(msg="Invalid VLAN %s." % vlan_id) - vlan_id = int(vlan_id) - vlan_id_list.append((vlan_id, vlan_id)) - - vlan_id_list.sort() - - return vlan_id_list - - def build_config(self): - config = vim.dvs.DistributedVirtualPortgroup.ConfigSpec() - - # Basic config - config.name = self.module.params['portgroup_name'] - config.numPorts = self.module.params['num_ports'] - - # Default port config - config.defaultPortConfig = vim.dvs.VmwareDistributedVirtualSwitch.VmwarePortConfigPolicy() - if self.module.params['vlan_trunk']: - config.defaultPortConfig.vlan = vim.dvs.VmwareDistributedVirtualSwitch.TrunkVlanSpec() - config.defaultPortConfig.vlan.vlanId = list(map(lambda x: vim.NumericRange(start=x[0], end=x[1]), self.create_vlan_list())) - else: - config.defaultPortConfig.vlan = vim.dvs.VmwareDistributedVirtualSwitch.VlanIdSpec() - config.defaultPortConfig.vlan.vlanId = int(self.module.params['vlan_id']) - config.defaultPortConfig.vlan.inherited = False - config.defaultPortConfig.securityPolicy = vim.dvs.VmwareDistributedVirtualSwitch.SecurityPolicy() - config.defaultPortConfig.securityPolicy.allowPromiscuous = vim.BoolPolicy(value=self.module.params['network_policy']['promiscuous']) - config.defaultPortConfig.securityPolicy.forgedTransmits = vim.BoolPolicy(value=self.module.params['network_policy']['forged_transmits']) - config.defaultPortConfig.securityPolicy.macChanges = vim.BoolPolicy(value=self.module.params['network_policy']['mac_changes']) - - # Teaming Policy - teamingPolicy = vim.dvs.VmwareDistributedVirtualSwitch.UplinkPortTeamingPolicy() - teamingPolicy.policy = vim.StringPolicy(value=self.module.params['teaming_policy']['load_balance_policy']) - teamingPolicy.reversePolicy = vim.BoolPolicy(value=self.module.params['teaming_policy']['inbound_policy']) - teamingPolicy.notifySwitches = vim.BoolPolicy(value=self.module.params['teaming_policy']['notify_switches']) - teamingPolicy.rollingOrder = vim.BoolPolicy(value=self.module.params['teaming_policy']['rolling_order']) - config.defaultPortConfig.uplinkTeamingPolicy = teamingPolicy - - # PG policy (advanced_policy) - config.policy = vim.dvs.VmwareDistributedVirtualSwitch.VMwarePortgroupPolicy() - config.policy.blockOverrideAllowed = self.module.params['port_policy']['block_override'] - config.policy.ipfixOverrideAllowed = self.module.params['port_policy']['ipfix_override'] - config.policy.livePortMovingAllowed = self.module.params['port_policy']['live_port_move'] - config.policy.networkResourcePoolOverrideAllowed = self.module.params['port_policy']['network_rp_override'] - config.policy.portConfigResetAtDisconnect = self.module.params['port_policy']['port_config_reset_at_disconnect'] - config.policy.securityPolicyOverrideAllowed = self.module.params['port_policy']['security_override'] - config.policy.shapingOverrideAllowed = self.module.params['port_policy']['shaping_override'] - config.policy.trafficFilterOverrideAllowed = self.module.params['port_policy']['traffic_filter_override'] - config.policy.uplinkTeamingOverrideAllowed = self.module.params['port_policy']['uplink_teaming_override'] - config.policy.vendorConfigOverrideAllowed = self.module.params['port_policy']['vendor_config_override'] - config.policy.vlanOverrideAllowed = self.module.params['port_policy']['vlan_override'] - - # PG Type - config.type = self.module.params['portgroup_type'] - - return config - - def process_state(self): - dvspg_states = { - 'absent': { - 'present': self.state_destroy_dvspg, - 'absent': self.state_exit_unchanged, - }, - 'present': { - 'update': self.state_update_dvspg, - 'present': self.state_exit_unchanged, - 'absent': self.state_create_dvspg, - } - } - try: - dvspg_states[self.module.params['state']][self.check_dvspg_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 update_port_group(self): - config = self.build_config() - config.configVersion = self.dvs_portgroup.config.configVersion - task = self.dvs_portgroup.ReconfigureDVPortgroup_Task(config) - changed, result = wait_for_task(task) - return changed, result - - def create_port_group(self): - config = self.build_config() - task = self.dv_switch.AddDVPortgroup_Task([config]) - changed, result = wait_for_task(task) - return changed, result - - def state_destroy_dvspg(self): - changed = True - result = None - - if not self.module.check_mode: - task = self.dvs_portgroup.Destroy_Task() - changed, result = wait_for_task(task) - self.module.exit_json(changed=changed, result=str(result)) - - def state_exit_unchanged(self): - self.module.exit_json(changed=False) - - def state_update_dvspg(self): - changed = True - result = None - - if not self.module.check_mode: - changed, result = self.update_port_group() - self.module.exit_json(changed=changed, result=str(result)) - - def state_create_dvspg(self): - changed = True - result = None - - if not self.module.check_mode: - changed, result = self.create_port_group() - self.module.exit_json(changed=changed, result=str(result)) - - def check_dvspg_state(self): - self.dv_switch = find_dvs_by_name(self.content, self.module.params['switch_name']) - - if self.dv_switch is None: - self.module.fail_json(msg="A distributed virtual switch with name %s does not exist" % self.module.params['switch_name']) - self.dvs_portgroup = find_dvspg_by_name(self.dv_switch, self.module.params['portgroup_name']) - - if self.dvs_portgroup is None: - return 'absent' - - # Check config - # Basic config - if self.dvs_portgroup.config.numPorts != self.module.params['num_ports']: - return 'update' - - # Default port config - defaultPortConfig = self.dvs_portgroup.config.defaultPortConfig - if self.module.params['vlan_trunk']: - if not isinstance(defaultPortConfig.vlan, vim.dvs.VmwareDistributedVirtualSwitch.TrunkVlanSpec): - return 'update' - if map(lambda x: (x.start, x.end), defaultPortConfig.vlan.vlanId) != self.create_vlan_list(): - return 'update' - else: - if not isinstance(defaultPortConfig.vlan, vim.dvs.VmwareDistributedVirtualSwitch.VlanIdSpec): - return 'update' - if defaultPortConfig.vlan.vlanId != int(self.module.params['vlan_id']): - return 'update' - - if defaultPortConfig.securityPolicy.allowPromiscuous.value != self.module.params['network_policy']['promiscuous'] or \ - defaultPortConfig.securityPolicy.forgedTransmits.value != self.module.params['network_policy']['forged_transmits'] or \ - defaultPortConfig.securityPolicy.macChanges.value != self.module.params['network_policy']['mac_changes']: - return 'update' - - # Teaming Policy - teamingPolicy = self.dvs_portgroup.config.defaultPortConfig.uplinkTeamingPolicy - if teamingPolicy.policy.value != self.module.params['teaming_policy']['load_balance_policy'] or \ - teamingPolicy.reversePolicy.value != self.module.params['teaming_policy']['inbound_policy'] or \ - teamingPolicy.notifySwitches.value != self.module.params['teaming_policy']['notify_switches'] or \ - teamingPolicy.rollingOrder.value != self.module.params['teaming_policy']['rolling_order']: - return 'update' - - # PG policy (advanced_policy) - policy = self.dvs_portgroup.config.policy - if policy.blockOverrideAllowed != self.module.params['port_policy']['block_override'] or \ - policy.ipfixOverrideAllowed != self.module.params['port_policy']['ipfix_override'] or \ - policy.livePortMovingAllowed != self.module.params['port_policy']['live_port_move'] or \ - policy.networkResourcePoolOverrideAllowed != self.module.params['port_policy']['network_rp_override'] or \ - policy.portConfigResetAtDisconnect != self.module.params['port_policy']['port_config_reset_at_disconnect'] or \ - policy.securityPolicyOverrideAllowed != self.module.params['port_policy']['security_override'] or \ - policy.shapingOverrideAllowed != self.module.params['port_policy']['shaping_override'] or \ - policy.trafficFilterOverrideAllowed != self.module.params['port_policy']['traffic_filter_override'] or \ - policy.uplinkTeamingOverrideAllowed != self.module.params['port_policy']['uplink_teaming_override'] or \ - policy.vendorConfigOverrideAllowed != self.module.params['port_policy']['vendor_config_override'] or \ - policy.vlanOverrideAllowed != self.module.params['port_policy']['vlan_override']: - return 'update' - - # PG Type - if self.dvs_portgroup.config.type != self.module.params['portgroup_type']: - return 'update' - - return 'present' - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - dict( - portgroup_name=dict(required=True, type='str'), - switch_name=dict(required=True, type='str'), - vlan_id=dict(required=True, type='str'), - num_ports=dict(required=True, type='int'), - portgroup_type=dict(required=True, choices=['earlyBinding', 'lateBinding', 'ephemeral'], type='str'), - state=dict(required=True, choices=['present', 'absent'], type='str'), - vlan_trunk=dict(type='bool', default=False), - network_policy=dict( - type='dict', - options=dict( - promiscuous=dict(type='bool', default=False), - forged_transmits=dict(type='bool', default=False), - mac_changes=dict(type='bool', default=False) - ), - default=dict( - promiscuous=False, - forged_transmits=False, - mac_changes=False - ) - ), - teaming_policy=dict( - type='dict', - options=dict( - inbound_policy=dict(type='bool', default=False), - notify_switches=dict(type='bool', default=True), - rolling_order=dict(type='bool', default=False), - load_balance_policy=dict(type='str', - default='loadbalance_srcid', - choices=[ - 'loadbalance_ip', - 'loadbalance_srcmac', - 'loadbalance_srcid', - 'loadbalance_loadbased', - 'failover_explicit', - ], - ) - ), - default=dict( - inbound_policy=False, - notify_switches=True, - rolling_order=False, - load_balance_policy='loadbalance_srcid', - ), - ), - port_policy=dict( - type='dict', - options=dict( - block_override=dict(type='bool', default=True), - ipfix_override=dict(type='bool', default=False), - live_port_move=dict(type='bool', default=False), - network_rp_override=dict(type='bool', default=False), - port_config_reset_at_disconnect=dict(type='bool', default=True), - security_override=dict(type='bool', default=False), - shaping_override=dict(type='bool', default=False), - traffic_filter_override=dict(type='bool', default=False), - uplink_teaming_override=dict(type='bool', default=False), - vendor_config_override=dict(type='bool', default=False), - vlan_override=dict(type='bool', default=False) - ), - default=dict( - block_override=True, - ipfix_override=False, - live_port_move=False, - network_rp_override=False, - port_config_reset_at_disconnect=True, - security_override=False, - shaping_override=False, - traffic_filter_override=False, - uplink_teaming_override=False, - vendor_config_override=False, - vlan_override=False - ) - ) - ) - ) - - module = AnsibleModule(argument_spec=argument_spec, - supports_check_mode=True) - - vmware_dvs_portgroup = VMwareDvsPortgroup(module) - vmware_dvs_portgroup.process_state() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_dvs_portgroup_find.py b/lib/ansible/modules/cloud/vmware/vmware_dvs_portgroup_find.py deleted file mode 100644 index a5d3005dbc..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_dvs_portgroup_find.py +++ /dev/null @@ -1,213 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# 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_dvs_portgroup_find -short_description: Find portgroup(s) in a VMware environment -description: -- Find portgroup(s) based on different criteria such as distributed vSwitch, VLAN id or a string in the name. -version_added: 2.9 -author: -- David Martinez (@dx0xm) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.7 -- PyVmomi -options: - dvswitch: - description: - - Name of a distributed vSwitch to look for. - type: str - vlanid: - description: - - VLAN id can be any number between 1 and 4094. - - This search criteria will looks into VLAN ranges to find possible matches. - required: false - type: int - name: - description: - - string to check inside the name of the portgroup. - - Basic containment check using python C(in) operation. - type: str - show_uplink: - description: - - Show or hide uplink portgroups. - - Only relevant when C(vlanid) is supplied. - type: bool - default: False -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Get all portgroups in dvswitch vDS - vmware_dvs_portgroup_find: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - dvswitch: 'vDS' - validate_certs: no - delegate_to: localhost - -- name: Confirm if vlan 15 is present - vmware_dvs_portgroup_find: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - vlanid: '15' - validate_certs: no - delegate_to: localhost -''' - -RETURN = r''' -dvs_portgroups: - description: basic details of portgroups found - returned: on success - type: list - sample: [ - { - "dvswitch": "vDS", - "name": "N-51", - "pvlan": true, - "trunk": true, - "vlan_id": "0" - } - ] -''' - -try: - from pyVmomi import vim -except ImportError as e: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi, find_dvs_by_name - - -class DVSPortgroupFindManager(PyVmomi): - def __init__(self, module): - super(DVSPortgroupFindManager, self).__init__(module) - self.dvs_name = self.params['dvswitch'] - self.vlan = self.params['vlanid'] - self.cmp_vlans = True if self.vlan else False - self.pgs = self.find_portgroups_by_name(self.content, self.module.params['name']) - - if self.dvs_name: - self.pgs = self.find_portgroups_by_dvs(self.pgs, self.dvs_name) - - def find_portgroups_by_name(self, content, name=None): - vimtype = [vim.dvs.DistributedVirtualPortgroup] - container = content.viewManager.CreateContainerView(content.rootFolder, vimtype, True) - if not name: - obj = container.view - else: - obj = [] - for c in container.view: - if name in c.name: - obj.append(c) - - return obj - - def find_portgroups_by_dvs(self, pgl, dvs): - obj = [] - for c in pgl: - if dvs in c.config.distributedVirtualSwitch.name: - obj.append(c) - - return obj - - def vlan_match(self, pgup, userup, vlanlst): - res = False - if pgup and userup: - return True - - for ln in vlanlst: - if '-' in ln: - arr = ln.split('-') - if arr[0] < self.vlan and self.vlan < arr[1]: - res = True - elif ln == str(self.vlan): - res = True - - return res - - def get_dvs_portgroup(self): - pgroups = self.pgs - - pglist = [] - for pg in pgroups: - trunk = False - pvlan = False - vlanInfo = pg.config.defaultPortConfig.vlan - cl1 = vim.dvs.VmwareDistributedVirtualSwitch.TrunkVlanSpec - cl2 = vim.dvs.VmwareDistributedVirtualSwitch.PvlanSpec - vlan_id_list = [] - if isinstance(vlanInfo, cl1): - trunk = True - for item in vlanInfo.vlanId: - if item.start == item.end: - vlan_id_list.append(str(item.start)) - else: - vlan_id_list.append(str(item.start) + '-' + str(item.end)) - elif isinstance(vlanInfo, cl2): - pvlan = True - vlan_id_list.append(str(vlanInfo.pvlanId)) - else: - vlan_id_list.append(str(vlanInfo.vlanId)) - - if self.cmp_vlans: - if self.vlan_match(pg.config.uplink, self.module.params['show_uplink'], vlan_id_list): - pglist.append(dict( - name=pg.name, - trunk=trunk, - pvlan=pvlan, - vlan_id=','.join(vlan_id_list), - dvswitch=pg.config.distributedVirtualSwitch.name)) - else: - pglist.append(dict( - name=pg.name, - trunk=trunk, - pvlan=pvlan, - vlan_id=','.join(vlan_id_list), - dvswitch=pg.config.distributedVirtualSwitch.name)) - - return pglist - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - dvswitch=dict(type='str', required=False), - vlanid=dict(type='int', required=False), - name=dict(type='str', required=False), - show_uplink=dict(type='bool', default=False), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - required_if=[ - ['show_uplink', 'True', 'vlanid'] - ] - ) - - dvs_pg_mgr = DVSPortgroupFindManager(module) - module.exit_json(changed=False, - dvs_portgroups=dvs_pg_mgr.get_dvs_portgroup()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_dvs_portgroup_info.py b/lib/ansible/modules/cloud/vmware/vmware_dvs_portgroup_info.py deleted file mode 100644 index 6e2afc8332..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_dvs_portgroup_info.py +++ /dev/null @@ -1,275 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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_dvs_portgroup_info -short_description: Gathers info DVS portgroup configurations -description: -- This module can be used to gather information about DVS portgroup configurations. -version_added: '2.9' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - datacenter: - description: - - Name of the datacenter. - required: true - type: str - dvswitch: - description: - - Name of a dvswitch to look for. - required: false - type: str - version_added: "2.9" - show_network_policy: - description: - - Show or hide network policies of DVS portgroup. - type: bool - default: True - show_port_policy: - description: - - Show or hide port policies of DVS portgroup. - type: bool - default: True - show_teaming_policy: - description: - - Show or hide teaming policies of DVS portgroup. - type: bool - default: True - show_vlan_info: - description: - - Show or hide vlan information of the DVS portgroup. - type: bool - default: False - version_added: "2.9" -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Get info about DVPG - vmware_dvs_portgroup_info: - hostname: "{{ vcenter_server }}" - username: "{{ vcenter_user }}" - password: "{{ vcenter_pass }}" - validate_certs: no - datacenter: "{{ datacenter_name }}" - register: dvpg_info - -- name: Get number of ports for portgroup 'dvpg_001' in 'dvs_001' - debug: - msg: "{{ item.num_ports }}" - with_items: - - "{{ dvpg_info.dvs_portgroup_info['dvs_001'] | json_query(query) }}" - vars: - query: "[?portgroup_name=='dvpg_001']" -''' - -RETURN = r''' -dvs_portgroup_info: - description: metadata about DVS portgroup configuration - returned: on success - type: dict - sample: { - "dvs_0":[ - { - "description": null, - "dvswitch_name": "dvs_001", - "network_policy": { - "forged_transmits": false, - "mac_changes": false, - "promiscuous": false - }, - "num_ports": 8, - "port_policy": { - "block_override": true, - "ipfix_override": false, - "live_port_move": false, - "network_rp_override": false, - "port_config_reset_at_disconnect": true, - "security_override": false, - "shaping_override": false, - "traffic_filter_override": false, - "uplink_teaming_override": false, - "vendor_config_override": false, - "vlan_override": false - }, - "portgroup_name": "dvpg_001", - "teaming_policy": { - "inbound_policy": true, - "notify_switches": true, - "policy": "loadbalance_srcid", - "rolling_order": false - }, - "vlan_info": { - "trunk": false, - "pvlan": false, - "vlan_id": 0 - }, - "type": "earlyBinding" - }, - ] - } -''' - -try: - from pyVmomi import vim -except ImportError as e: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi, get_all_objs, find_dvs_by_name - - -class DVSPortgroupInfoManager(PyVmomi): - def __init__(self, module): - super(DVSPortgroupInfoManager, self).__init__(module) - self.dc_name = self.params['datacenter'] - self.dvs_name = self.params['dvswitch'] - - datacenter = self.find_datacenter_by_name(self.dc_name) - if datacenter is None: - self.module.fail_json(msg="Failed to find the datacenter %s" % self.dc_name) - if self.dvs_name: - # User specified specific dvswitch name to gather information - dvsn = find_dvs_by_name(self.content, self.dvs_name) - if dvsn is None: - self.module.fail_json(msg="Failed to find the dvswitch %s" % self.dvs_name) - - self.dvsls = [dvsn] - else: - # default behaviour, gather information about all dvswitches - self.dvsls = get_all_objs(self.content, [vim.DistributedVirtualSwitch], folder=datacenter.networkFolder) - - def get_vlan_info(self, vlan_obj=None): - """ - Return vlan information from given object - Args: - vlan_obj: vlan managed object - Returns: Dict of vlan details of the specific object - """ - - vdret = dict() - if not vlan_obj: - return vdret - - if isinstance(vlan_obj, vim.dvs.VmwareDistributedVirtualSwitch.TrunkVlanSpec): - vlan_id_list = [] - for vli in vlan_obj.vlanId: - if vli.start == vli.end: - vlan_id_list.append(str(vli.start)) - else: - vlan_id_list.append(str(vli.start) + "-" + str(vli.end)) - vdret = dict(trunk=True, pvlan=False, vlan_id=vlan_id_list) - elif isinstance(vlan_obj, vim.dvs.VmwareDistributedVirtualSwitch.PvlanSpec): - vdret = dict(trunk=False, pvlan=True, vlan_id=str(vlan_obj.pvlanId)) - else: - vdret = dict(trunk=False, pvlan=False, vlan_id=str(vlan_obj.vlanId)) - - return vdret - - def gather_dvs_portgroup_info(self): - dvs_lists = self.dvsls - result = dict() - for dvs in dvs_lists: - result[dvs.name] = list() - for dvs_pg in dvs.portgroup: - network_policy = dict() - teaming_policy = dict() - port_policy = dict() - vlan_info = dict() - - if self.module.params['show_network_policy'] and dvs_pg.config.defaultPortConfig.securityPolicy: - network_policy = dict( - forged_transmits=dvs_pg.config.defaultPortConfig.securityPolicy.forgedTransmits.value, - promiscuous=dvs_pg.config.defaultPortConfig.securityPolicy.allowPromiscuous.value, - mac_changes=dvs_pg.config.defaultPortConfig.securityPolicy.macChanges.value - ) - if self.module.params['show_teaming_policy']: - # govcsim does not have uplinkTeamingPolicy, remove this check once - # PR https://github.com/vmware/govmomi/pull/1524 merged. - if dvs_pg.config.defaultPortConfig.uplinkTeamingPolicy: - teaming_policy = dict( - policy=dvs_pg.config.defaultPortConfig.uplinkTeamingPolicy.policy.value, - inbound_policy=dvs_pg.config.defaultPortConfig.uplinkTeamingPolicy.reversePolicy.value, - notify_switches=dvs_pg.config.defaultPortConfig.uplinkTeamingPolicy.notifySwitches.value, - rolling_order=dvs_pg.config.defaultPortConfig.uplinkTeamingPolicy.rollingOrder.value, - ) - - if self.params['show_port_policy']: - # govcsim does not have port policy - if dvs_pg.config.policy: - port_policy = dict( - block_override=dvs_pg.config.policy.blockOverrideAllowed, - ipfix_override=dvs_pg.config.policy.ipfixOverrideAllowed, - live_port_move=dvs_pg.config.policy.livePortMovingAllowed, - network_rp_override=dvs_pg.config.policy.networkResourcePoolOverrideAllowed, - port_config_reset_at_disconnect=dvs_pg.config.policy.portConfigResetAtDisconnect, - security_override=dvs_pg.config.policy.securityPolicyOverrideAllowed, - shaping_override=dvs_pg.config.policy.shapingOverrideAllowed, - traffic_filter_override=dvs_pg.config.policy.trafficFilterOverrideAllowed, - uplink_teaming_override=dvs_pg.config.policy.uplinkTeamingOverrideAllowed, - vendor_config_override=dvs_pg.config.policy.vendorConfigOverrideAllowed, - vlan_override=dvs_pg.config.policy.vlanOverrideAllowed - ) - - if self.params['show_vlan_info']: - vlan_info = self.get_vlan_info(dvs_pg.config.defaultPortConfig.vlan) - - dvpg_details = dict( - portgroup_name=dvs_pg.name, - num_ports=dvs_pg.config.numPorts, - dvswitch_name=dvs_pg.config.distributedVirtualSwitch.name, - description=dvs_pg.config.description, - type=dvs_pg.config.type, - teaming_policy=teaming_policy, - port_policy=port_policy, - network_policy=network_policy, - vlan_info=vlan_info, - ) - result[dvs.name].append(dvpg_details) - - return result - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - datacenter=dict(type='str', required=True), - show_network_policy=dict(type='bool', default=True), - show_teaming_policy=dict(type='bool', default=True), - show_port_policy=dict(type='bool', default=True), - dvswitch=dict(), - show_vlan_info=dict(type='bool', default=False), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - dvs_pg_mgr = DVSPortgroupInfoManager(module) - module.exit_json(changed=False, - dvs_portgroup_info=dvs_pg_mgr.gather_dvs_portgroup_info()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_dvswitch.py b/lib/ansible/modules/cloud/vmware/vmware_dvswitch.py deleted file mode 100644 index 4124596027..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_dvswitch.py +++ /dev/null @@ -1,754 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright: (c) 2015, Joseph Callen <jcallen () csc.com> -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# Copyright: (c) 2018, Ansible Project -# -# 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 = ''' ---- -module: vmware_dvswitch -short_description: Create or remove a Distributed Switch -description: - - This module can be used to create, remove a Distributed Switch. -version_added: 2.0 -author: -- Joseph Callen (@jcpowermac) -- Abhijeet Kasurde (@Akasurde) -- Christian Kotte (@ckotte) -notes: - - Tested on vSphere 6.5 and 6.7 -requirements: - - "python >= 2.6" - - PyVmomi -options: - datacenter_name: - description: - - The name of the datacenter that will contain the Distributed Switch. - - This parameter is optional, if C(folder) is provided. - - Mutually exclusive with C(folder) parameter. - required: False - aliases: ['datacenter'] - type: str - switch_name: - description: - - The name of the distribute vSwitch to create or remove. - required: True - aliases: ['switch', 'dvswitch'] - type: str - switch_version: - description: - - The version of the Distributed Switch to create. - - Can be 6.0.0, 5.5.0, 5.1.0, 5.0.0 with a vCenter running vSphere 6.0 and 6.5. - - Can be 6.6.0, 6.5.0, 6.0.0 with a vCenter running vSphere 6.7. - - The version must match the version of the ESXi hosts you want to connect. - - The version of the vCenter server is used if not specified. - - Required only if C(state) is set to C(present). - version_added: 2.5 - choices: ['5.0.0', '5.1.0', '5.5.0', '6.0.0', '6.5.0', '6.6.0'] - aliases: ['version'] - type: str - mtu: - description: - - The switch maximum transmission unit. - - Required parameter for C(state) both C(present) and C(absent), before Ansible 2.6 version. - - Required only if C(state) is set to C(present), for Ansible 2.6 and onwards. - - Accepts value between 1280 to 9000 (both inclusive). - type: int - default: 1500 - multicast_filtering_mode: - description: - - The multicast filtering mode. - - 'C(basic) mode: multicast traffic for virtual machines is forwarded according to the destination MAC address of the multicast group.' - - 'C(snooping) mode: the Distributed Switch provides IGMP and MLD snooping according to RFC 4541.' - type: str - choices: ['basic', 'snooping'] - default: 'basic' - version_added: 2.8 - uplink_quantity: - description: - - Quantity of uplink per ESXi host added to the Distributed Switch. - - The uplink quantity can be increased or decreased, but a decrease will only be successfull if the uplink isn't used by a portgroup. - - Required parameter for C(state) both C(present) and C(absent), before Ansible 2.6 version. - - Required only if C(state) is set to C(present), for Ansible 2.6 and onwards. - type: int - uplink_prefix: - description: - - The prefix used for the naming of the uplinks. - - Only valid if the Distributed Switch will be created. Not used if the Distributed Switch is already present. - - Uplinks are created as Uplink 1, Uplink 2, etc. pp. by default. - default: 'Uplink ' - version_added: 2.8 - type: str - discovery_proto: - description: - - Link discovery protocol between Cisco and Link Layer discovery. - - Required parameter for C(state) both C(present) and C(absent), before Ansible 2.6 version. - - Required only if C(state) is set to C(present), for Ansible 2.6 and onwards. - - 'C(cdp): Use Cisco Discovery Protocol (CDP).' - - 'C(lldp): Use Link Layer Discovery Protocol (LLDP).' - - 'C(disabled): Do not use a discovery protocol.' - choices: ['cdp', 'lldp', 'disabled'] - default: 'cdp' - aliases: [ 'discovery_protocol' ] - type: str - discovery_operation: - description: - - Select the discovery operation. - - Required parameter for C(state) both C(present) and C(absent), before Ansible 2.6 version. - - Required only if C(state) is set to C(present), for Ansible 2.6 and onwards. - choices: ['both', 'advertise', 'listen'] - default: 'listen' - type: str - contact: - description: - - Dictionary which configures administrator contact name and description for the Distributed Switch. - - 'Valid attributes are:' - - '- C(name) (str): Administrator name.' - - '- C(description) (str): Description or other details.' - type: dict - version_added: 2.8 - description: - description: - - Description of the Distributed Switch. - type: str - version_added: 2.8 - health_check: - description: - - Dictionary which configures Health Check for the Distributed Switch. - - 'Valid attributes are:' - - '- C(vlan_mtu) (bool): VLAN and MTU health check. (default: False)' - - '- C(teaming_failover) (bool): Teaming and failover health check. (default: False)' - - '- C(vlan_mtu_interval) (int): VLAN and MTU health check interval (minutes). (default: 0)' - - '- The default for C(vlan_mtu_interval) is 1 in the vSphere Client if the VLAN and MTU health check is enabled.' - - '- C(teaming_failover_interval) (int): Teaming and failover health check interval (minutes). (default: 0)' - - '- The default for C(teaming_failover_interval) is 1 in the vSphere Client if the Teaming and failover health check is enabled.' - type: dict - default: { - vlan_mtu: False, - teaming_failover: False, - vlan_mtu_interval: 0, - teaming_failover_interval: 0, - } - version_added: 2.8 - state: - description: - - If set to C(present) and the Distributed Switch doesn't exists then the Distributed Switch will be created. - - If set to C(absent) and the Distributed Switch exists then the Distributed Switch will be deleted. - default: 'present' - choices: ['present', 'absent'] - type: str - folder: - description: - - Destination folder, absolute path to place dvswitch in. - - The folder should include the datacenter. - - This parameter is case sensitive. - - This parameter is optional, if C(datacenter) is provided. - - 'Examples:' - - ' folder: /datacenter1/network' - - ' folder: datacenter1/network' - - ' folder: /datacenter1/network/folder1' - - ' folder: datacenter1/network/folder1' - - ' folder: /folder1/datacenter1/network' - - ' folder: folder1/datacenter1/network' - - ' folder: /folder1/datacenter1/network/folder2' - required: False - type: str - version_added: 2.9 -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Create dvSwitch - vmware_dvswitch: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: '{{ datacenter }}' - switch: dvSwitch - version: 6.0.0 - mtu: 9000 - uplink_quantity: 2 - discovery_protocol: lldp - discovery_operation: both - state: present - delegate_to: localhost - -- name: Create dvSwitch with all options - vmware_dvswitch: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: '{{ datacenter }}' - switch: dvSwitch - version: 6.5.0 - mtu: 9000 - uplink_quantity: 2 - uplink_prefix: 'Uplink_' - discovery_protocol: cdp - discovery_operation: both - multicast_filtering_mode: snooping - health_check: - vlan_mtu: true - vlan_mtu_interval: 1 - teaming_failover: true - teaming_failover_interval: 1 - state: present - delegate_to: localhost - -- name: Delete dvSwitch - vmware_dvswitch: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: '{{ datacenter }}' - switch: dvSwitch - state: absent - delegate_to: localhost -''' - -RETURN = """ -result: - description: information about performed operation - returned: always - type: str - sample: { - "changed": false, - "contact": null, - "contact_details": null, - "description": null, - "discovery_operation": "both", - "discovery_protocol": "cdp", - "dvswitch": "test", - "health_check_teaming": false, - "health_check_teaming_interval": 0, - "health_check_vlan": false, - "health_check_vlan_interval": 0, - "mtu": 9000, - "multicast_filtering_mode": "basic", - "result": "DVS already configured properly", - "uplink_quantity": 2, - "uplinks": [ - "Uplink_1", - "Uplink_2" - ], - "version": "6.6.0" - } -""" - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils._text import to_native -from ansible.module_utils.vmware import ( - PyVmomi, TaskError, find_dvs_by_name, vmware_argument_spec, wait_for_task -) - - -class VMwareDvSwitch(PyVmomi): - """Class to manage a Distributed Virtual Switch""" - def __init__(self, module): - super(VMwareDvSwitch, self).__init__(module) - self.dvs = None - - self.switch_name = self.module.params['switch_name'] - self.switch_version = self.module.params['switch_version'] - if self.content.about.version == '6.7.0': - self.vcenter_switch_version = '6.6.0' - else: - self.vcenter_switch_version = self.content.about.version - folder = self.params['folder'] - if folder: - self.folder_obj = self.content.searchIndex.FindByInventoryPath(folder) - if not self.folder_obj: - self.module.fail_json(msg="Failed to find the folder specified by %(folder)s" % self.params) - else: - datacenter_name = self.params.get('datacenter_name') - datacenter_obj = self.find_datacenter_by_name(datacenter_name) - if not datacenter_obj: - self.module.fail_json(msg="Failed to find datacenter '%s' required" - " for managing distributed vSwitch." % datacenter_name) - self.folder_obj = datacenter_obj.networkFolder - - self.mtu = self.module.params['mtu'] - # MTU sanity check - if not 1280 <= self.mtu <= 9000: - self.module.fail_json( - msg="MTU value should be between 1280 and 9000 (both inclusive), provided %d." % self.mtu - ) - self.multicast_filtering_mode = self.module.params['multicast_filtering_mode'] - self.uplink_quantity = self.module.params['uplink_quantity'] - self.uplink_prefix = self.module.params['uplink_prefix'] - self.discovery_protocol = self.module.params['discovery_proto'] - self.discovery_operation = self.module.params['discovery_operation'] - # TODO: add port mirroring - self.health_check_vlan = self.params['health_check'].get('vlan_mtu') - self.health_check_vlan_interval = self.params['health_check'].get('vlan_mtu_interval') - self.health_check_teaming = self.params['health_check'].get('teaming_failover') - self.health_check_teaming_interval = self.params['health_check'].get('teaming_failover_interval') - if self.params['contact']: - self.contact_name = self.params['contact'].get('name') - self.contact_details = self.params['contact'].get('details') - else: - self.contact_name = None - self.contact_details = None - self.description = self.module.params['description'] - self.state = self.module.params['state'] - - def process_state(self): - """Process the current state of the DVS""" - dvs_states = { - 'absent': { - 'present': self.destroy_dvswitch, - 'absent': self.exit_unchanged, - }, - 'present': { - 'present': self.update_dvswitch, - 'absent': self.create_dvswitch, - } - } - - try: - dvs_states[self.state][self.check_dvs()]() - except vmodl.RuntimeFault as runtime_fault: - self.module.fail_json(msg=to_native(runtime_fault.msg)) - except vmodl.MethodFault as method_fault: - self.module.fail_json(msg=to_native(method_fault.msg)) - except Exception as e: - self.module.fail_json(msg=to_native(e)) - - def check_dvs(self): - """Check if DVS is present""" - self.dvs = find_dvs_by_name(self.content, self.switch_name, folder=self.folder_obj) - if self.dvs is None: - return 'absent' - return 'present' - - def create_dvswitch(self): - """Create a DVS""" - changed = True - results = dict(changed=changed) - - spec = vim.DistributedVirtualSwitch.CreateSpec() - spec.configSpec = vim.dvs.VmwareDistributedVirtualSwitch.ConfigSpec() - # Name - results['dvswitch'] = self.switch_name - spec.configSpec.name = self.switch_name - # MTU - results['mtu'] = self.mtu - spec.configSpec.maxMtu = self.mtu - # Discovery Protocol type and operation - results['discovery_protocol'] = self.discovery_protocol - results['discovery_operation'] = self.discovery_operation - spec.configSpec.linkDiscoveryProtocolConfig = self.create_ldp_spec() - # Administrator contact - results['contact'] = self.contact_name - results['contact_details'] = self.contact_details - if self.contact_name or self.contact_details: - spec.contact = self.create_contact_spec() - # Description - results['description'] = self.description - if self.description: - spec.description = self.description - # Uplinks - results['uplink_quantity'] = self.uplink_quantity - spec.configSpec.uplinkPortPolicy = vim.DistributedVirtualSwitch.NameArrayUplinkPortPolicy() - for count in range(1, self.uplink_quantity + 1): - spec.configSpec.uplinkPortPolicy.uplinkPortName.append("%s%d" % (self.uplink_prefix, count)) - results['uplinks'] = spec.configSpec.uplinkPortPolicy.uplinkPortName - # Version - results['version'] = self.switch_version - if self.switch_version: - spec.productInfo = self.create_product_spec(self.switch_version) - - if self.module.check_mode: - result = "DVS would be created" - else: - # Create DVS - network_folder = self.folder_obj - task = network_folder.CreateDVS_Task(spec) - try: - wait_for_task(task) - except TaskError as invalid_argument: - self.module.fail_json( - msg="Failed to create DVS : %s" % to_native(invalid_argument) - ) - # Find new DVS - self.dvs = find_dvs_by_name(self.content, self.switch_name) - changed_multicast = False - spec = vim.dvs.VmwareDistributedVirtualSwitch.ConfigSpec() - # Use the same version in the new spec; The version will be increased by one by the API automatically - spec.configVersion = self.dvs.config.configVersion - # Set multicast filtering mode - results['multicast_filtering_mode'] = self.multicast_filtering_mode - multicast_filtering_mode = self.get_api_mc_filtering_mode(self.multicast_filtering_mode) - if self.dvs.config.multicastFilteringMode != multicast_filtering_mode: - changed_multicast = True - spec.multicastFilteringMode = multicast_filtering_mode - spec.multicastFilteringMode = self.get_api_mc_filtering_mode(self.multicast_filtering_mode) - if changed_multicast: - self.update_dvs_config(self.dvs, spec) - # Set Health Check config - results['health_check_vlan'] = self.health_check_vlan - results['health_check_teaming'] = self.health_check_teaming - result = self.check_health_check_config(self.dvs.config.healthCheckConfig) - changed_health_check = result[1] - if changed_health_check: - self.update_health_check_config(self.dvs, result[0]) - result = "DVS created" - self.module.exit_json(changed=changed, result=to_native(result)) - - def create_ldp_spec(self): - """Create Link Discovery Protocol config spec""" - ldp_config_spec = vim.host.LinkDiscoveryProtocolConfig() - if self.discovery_protocol == 'disabled': - ldp_config_spec.protocol = 'cdp' - ldp_config_spec.operation = 'none' - else: - ldp_config_spec.protocol = self.discovery_protocol - ldp_config_spec.operation = self.discovery_operation - return ldp_config_spec - - def create_product_spec(self, switch_version): - """Create product info spec""" - product_info_spec = vim.dvs.ProductSpec() - product_info_spec.version = switch_version - return product_info_spec - - @staticmethod - def get_api_mc_filtering_mode(mode): - """Get Multicast filtering mode""" - if mode == 'basic': - return 'legacyFiltering' - return 'snooping' - - def create_contact_spec(self): - """Create contact info spec""" - contact_info_spec = vim.DistributedVirtualSwitch.ContactInfo() - contact_info_spec.name = self.contact_name - contact_info_spec.contact = self.contact_details - return contact_info_spec - - def update_dvs_config(self, switch_object, spec): - """Update DVS config""" - try: - task = switch_object.ReconfigureDvs_Task(spec) - wait_for_task(task) - except TaskError as invalid_argument: - self.module.fail_json( - msg="Failed to update DVS : %s" % to_native(invalid_argument) - ) - - def check_health_check_config(self, health_check_config): - """Check Health Check config""" - changed = changed_vlan = changed_vlan_interval = changed_teaming = changed_teaming_interval = False - vlan_previous = teaming_previous = None - vlan_interval_previous = teaming_interval_previous = 0 - for config in health_check_config: - if isinstance(config, vim.dvs.VmwareDistributedVirtualSwitch.VlanMtuHealthCheckConfig): - if config.enable != self.health_check_vlan: - changed = changed_vlan = True - vlan_previous = config.enable - config.enable = self.health_check_vlan - if config.enable and config.interval != self.health_check_vlan_interval: - changed = changed_vlan_interval = True - vlan_interval_previous = config.interval - config.interval = self.health_check_vlan_interval - if isinstance(config, vim.dvs.VmwareDistributedVirtualSwitch.TeamingHealthCheckConfig): - if config.enable != self.health_check_teaming: - changed = changed_teaming = True - teaming_previous = config.enable - config.enable = self.health_check_teaming - if config.enable and config.interval != self.health_check_teaming_interval: - changed = changed_teaming_interval = True - teaming_interval_previous = config.interval - config.interval = self.health_check_teaming_interval - return (health_check_config, changed, changed_vlan, vlan_previous, changed_vlan_interval, vlan_interval_previous, - changed_teaming, teaming_previous, changed_teaming_interval, teaming_interval_previous) - - def update_health_check_config(self, switch_object, health_check_config): - """Update Health Check config""" - try: - task = switch_object.UpdateDVSHealthCheckConfig_Task(healthCheckConfig=health_check_config) - except vim.fault.DvsFault as dvs_fault: - self.module.fail_json(msg="Update failed due to DVS fault : %s" % to_native(dvs_fault)) - except vmodl.fault.NotSupported as not_supported: - self.module.fail_json(msg="Health check not supported on the switch : %s" % to_native(not_supported)) - except TaskError as invalid_argument: - self.module.fail_json(msg="Failed to configure health check : %s" % to_native(invalid_argument)) - try: - wait_for_task(task) - except TaskError as invalid_argument: - self.module.fail_json(msg="Failed to update health check config : %s" % to_native(invalid_argument)) - - def exit_unchanged(self): - """Exit with status message""" - changed = False - results = dict(changed=changed) - results['dvswitch'] = self.switch_name - results['result'] = "DVS not present" - self.module.exit_json(**results) - - def destroy_dvswitch(self): - """Delete a DVS""" - changed = True - results = dict(changed=changed) - results['dvswitch'] = self.switch_name - if self.module.check_mode: - results['result'] = "DVS would be deleted" - else: - try: - task = self.dvs.Destroy_Task() - except vim.fault.VimFault as vim_fault: - self.module.fail_json(msg="Failed to deleted DVS : %s" % to_native(vim_fault)) - wait_for_task(task) - results['result'] = "DVS deleted" - self.module.exit_json(**results) - - def update_dvswitch(self): - """Check and update DVS settings""" - changed = changed_settings = changed_ldp = changed_version = changed_health_check = False - results = dict(changed=changed) - results['dvswitch'] = self.switch_name - changed_list = [] - - config_spec = vim.dvs.VmwareDistributedVirtualSwitch.ConfigSpec() - # Use the same version in the new spec; The version will be increased by one by the API automatically - config_spec.configVersion = self.dvs.config.configVersion - - # Check MTU - results['mtu'] = self.mtu - if self.dvs.config.maxMtu != self.mtu: - changed = changed_settings = True - changed_list.append("mtu") - results['mtu_previous'] = config_spec.maxMtu - config_spec.maxMtu = self.mtu - - # Check Discovery Protocol type and operation - ldp_protocol = self.dvs.config.linkDiscoveryProtocolConfig.protocol - ldp_operation = self.dvs.config.linkDiscoveryProtocolConfig.operation - if self.discovery_protocol == 'disabled': - results['discovery_protocol'] = self.discovery_protocol - results['discovery_operation'] = 'n/a' - if ldp_protocol != 'cdp' or ldp_operation != 'none': - changed_ldp = True - results['discovery_protocol_previous'] = ldp_protocol - results['discovery_operation_previous'] = ldp_operation - else: - results['discovery_protocol'] = self.discovery_protocol - results['discovery_operation'] = self.discovery_operation - if ldp_protocol != self.discovery_protocol or ldp_operation != self.discovery_operation: - changed_ldp = True - if ldp_protocol != self.discovery_protocol: - results['discovery_protocol_previous'] = ldp_protocol - if ldp_operation != self.discovery_operation: - results['discovery_operation_previous'] = ldp_operation - if changed_ldp: - changed = changed_settings = True - changed_list.append("discovery protocol") - config_spec.linkDiscoveryProtocolConfig = self.create_ldp_spec() - - # Check Multicast filtering mode - results['multicast_filtering_mode'] = self.multicast_filtering_mode - multicast_filtering_mode = self.get_api_mc_filtering_mode(self.multicast_filtering_mode) - if self.dvs.config.multicastFilteringMode != multicast_filtering_mode: - changed = changed_settings = True - changed_list.append("multicast filtering") - results['multicast_filtering_mode_previous'] = self.dvs.config.multicastFilteringMode - config_spec.multicastFilteringMode = multicast_filtering_mode - - # Check administrator contact - results['contact'] = self.contact_name - results['contact_details'] = self.contact_details - if self.dvs.config.contact.name != self.contact_name or self.dvs.config.contact.contact != self.contact_details: - changed = changed_settings = True - changed_list.append("contact") - results['contact_previous'] = self.dvs.config.contact.name - results['contact_details_previous'] = self.dvs.config.contact.contact - config_spec.contact = self.create_contact_spec() - - # Check description - results['description'] = self.description - if self.dvs.config.description != self.description: - changed = changed_settings = True - changed_list.append("description") - results['description_previous'] = self.dvs.config.description - if self.description is None: - # need to use empty string; will be set to None by API - config_spec.description = '' - else: - config_spec.description = self.description - - # Check uplinks - results['uplink_quantity'] = self.uplink_quantity - if len(self.dvs.config.uplinkPortPolicy.uplinkPortName) != self.uplink_quantity: - changed = changed_settings = True - changed_list.append("uplink quantity") - results['uplink_quantity_previous'] = len(self.dvs.config.uplinkPortPolicy.uplinkPortName) - config_spec.uplinkPortPolicy = vim.DistributedVirtualSwitch.NameArrayUplinkPortPolicy() - # just replace the uplink array if uplinks need to be added - if len(self.dvs.config.uplinkPortPolicy.uplinkPortName) < self.uplink_quantity: - for count in range(1, self.uplink_quantity + 1): - config_spec.uplinkPortPolicy.uplinkPortName.append("%s%d" % (self.uplink_prefix, count)) - # just replace the uplink array if uplinks need to be removed - if len(self.dvs.config.uplinkPortPolicy.uplinkPortName) > self.uplink_quantity: - for count in range(1, self.uplink_quantity + 1): - config_spec.uplinkPortPolicy.uplinkPortName.append("%s%d" % (self.uplink_prefix, count)) - results['uplinks'] = config_spec.uplinkPortPolicy.uplinkPortName - results['uplinks_previous'] = self.dvs.config.uplinkPortPolicy.uplinkPortName - else: - # No uplink name check; uplink names can't be changed easily if they are used by a portgroup - results['uplinks'] = self.dvs.config.uplinkPortPolicy.uplinkPortName - - # Check Health Check - results['health_check_vlan'] = self.health_check_vlan - results['health_check_teaming'] = self.health_check_teaming - results['health_check_vlan_interval'] = self.health_check_vlan_interval - results['health_check_teaming_interval'] = self.health_check_teaming_interval - (health_check_config, changed_health_check, changed_vlan, vlan_previous, - changed_vlan_interval, vlan_interval_previous, changed_teaming, teaming_previous, - changed_teaming_interval, teaming_interval_previous) = \ - self.check_health_check_config(self.dvs.config.healthCheckConfig) - if changed_health_check: - changed = True - changed_list.append("health check") - if changed_vlan: - results['health_check_vlan_previous'] = vlan_previous - if changed_vlan_interval: - results['health_check_vlan_interval_previous'] = vlan_interval_previous - if changed_teaming: - results['health_check_teaming_previous'] = teaming_previous - if changed_teaming_interval: - results['health_check_teaming_interval_previous'] = teaming_interval_previous - - # Check switch version - if self.switch_version: - results['version'] = self.switch_version - if self.dvs.config.productInfo.version != self.switch_version: - changed_version = True - spec_product = self.create_product_spec(self.switch_version) - else: - results['version'] = self.vcenter_switch_version - if self.dvs.config.productInfo.version != self.vcenter_switch_version: - changed_version = True - spec_product = self.create_product_spec(self.vcenter_switch_version) - if changed_version: - changed = True - changed_list.append("switch version") - results['version_previous'] = self.dvs.config.productInfo.version - - if changed: - if self.module.check_mode: - changed_suffix = ' would be changed' - else: - changed_suffix = ' changed' - if len(changed_list) > 2: - message = ', '.join(changed_list[:-1]) + ', and ' + str(changed_list[-1]) - elif len(changed_list) == 2: - message = ' and '.join(changed_list) - elif len(changed_list) == 1: - message = changed_list[0] - message += changed_suffix - if not self.module.check_mode: - if changed_settings: - self.update_dvs_config(self.dvs, config_spec) - if changed_health_check: - self.update_health_check_config(self.dvs, health_check_config) - if changed_version: - task = self.dvs.PerformDvsProductSpecOperation_Task("upgrade", spec_product) - try: - wait_for_task(task) - except TaskError as invalid_argument: - self.module.fail_json(msg="Failed to update DVS version : %s" % to_native(invalid_argument)) - else: - message = "DVS already configured properly" - results['changed'] = changed - results['result'] = message - - self.module.exit_json(**results) - - -def main(): - """Main""" - argument_spec = vmware_argument_spec() - argument_spec.update( - dict( - datacenter_name=dict(aliases=['datacenter']), - folder=dict(), - switch_name=dict(required=True, aliases=['switch', 'dvswitch']), - mtu=dict(type='int', default=1500), - multicast_filtering_mode=dict(type='str', default='basic', choices=['basic', 'snooping']), - switch_version=dict( - choices=['5.0.0', '5.1.0', '5.5.0', '6.0.0', '6.5.0', '6.6.0'], - aliases=['version'], - default=None - ), - uplink_quantity=dict(type='int'), - uplink_prefix=dict(type='str', default='Uplink '), - discovery_proto=dict( - type='str', choices=['cdp', 'lldp', 'disabled'], default='cdp', aliases=['discovery_protocol'] - ), - discovery_operation=dict(type='str', choices=['both', 'advertise', 'listen'], default='listen'), - health_check=dict( - type='dict', - options=dict( - vlan_mtu=dict(type='bool', default=False), - teaming_failover=dict(type='bool', default=False), - vlan_mtu_interval=dict(type='int', default=0), - teaming_failover_interval=dict(type='int', default=0), - ), - default=dict( - vlan_mtu=False, - teaming_failover=False, - vlan_mtu_interval=0, - teaming_failover_interval=0, - ), - ), - contact=dict( - type='dict', - options=dict( - name=dict(type='str'), - description=dict(type='str'), - ), - ), - description=dict(type='str'), - state=dict(default='present', choices=['present', 'absent']), - ) - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_if=[ - ('state', 'present', - ['uplink_quantity']), - ], - required_one_of=[ - ['folder', 'datacenter_name'], - ], - mutually_exclusive=[ - ['folder', 'datacenter_name'], - ], - supports_check_mode=True, - ) - - vmware_dvswitch = VMwareDvSwitch(module) - vmware_dvswitch.process_state() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_dvswitch_lacp.py b/lib/ansible/modules/cloud/vmware/vmware_dvswitch_lacp.py deleted file mode 100644 index 5e1b821a6a..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_dvswitch_lacp.py +++ /dev/null @@ -1,404 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# -# 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 = ''' ---- -module: vmware_dvswitch_lacp -short_description: Manage LACP configuration on a Distributed Switch -description: - - This module can be used to configure Link Aggregation Control Protocol (LACP) support mode and Link Aggregation Groups (LAGs). -version_added: 2.8 -author: -- Christian Kotte (@ckotte) -notes: - - Tested on vSphere 6.7 - - You need to run the task two times if you want to remove all LAGs and change the support mode to 'basic' -requirements: - - "python >= 2.6" - - PyVmomi -options: - switch: - description: - - The name of the Distributed Switch to manage. - required: True - aliases: ['dvswitch'] - type: str - support_mode: - description: - - The LACP support mode. - - 'C(basic): One Link Aggregation Control Protocol group in the switch (singleLag).' - - 'C(enhanced): Multiple Link Aggregation Control Protocol groups in the switch (multipleLag).' - type: str - default: 'basic' - choices: ['basic', 'enhanced'] - link_aggregation_groups: - description: - - Can only be used if C(lacp_support) is set to C(enhanced). - - 'The following parameters are required:' - - '- C(name) (string): Name of the LAG.' - - '- C(uplink_number) (int): Number of uplinks. Can 1 to 30.' - - '- C(mode) (string): The negotiating state of the uplinks/ports.' - - ' - choices: [ active, passive ]' - - '- C(load_balancing_mode) (string): Load balancing algorithm.' - - ' - Valid attributes are:' - - ' - srcTcpUdpPort: Source TCP/UDP port number.' - - ' - srcDestIpTcpUdpPortVlan: Source and destination IP, source and destination TCP/UDP port number and VLAN.' - - ' - srcIpVlan: Source IP and VLAN.' - - ' - srcDestTcpUdpPort: Source and destination TCP/UDP port number.' - - ' - srcMac: Source MAC address.' - - ' - destIp: Destination IP.' - - ' - destMac: Destination MAC address.' - - ' - vlan: VLAN only.' - - ' - srcDestIp: Source and Destination IP.' - - ' - srcIpTcpUdpPortVlan: Source IP, TCP/UDP port number and VLAN.' - - ' - srcDestIpTcpUdpPort: Source and destination IP and TCP/UDP port number.' - - ' - srcDestMac: Source and destination MAC address.' - - ' - destIpTcpUdpPort: Destination IP and TCP/UDP port number.' - - ' - srcPortId: Source Virtual Port Id.' - - ' - srcIp: Source IP.' - - ' - srcIpTcpUdpPort: Source IP and TCP/UDP port number.' - - ' - destIpTcpUdpPortVlan: Destination IP, TCP/UDP port number and VLAN.' - - ' - destTcpUdpPort: Destination TCP/UDP port number.' - - ' - destIpVlan: Destination IP and VLAN.' - - ' - srcDestIpVlan: Source and destination IP and VLAN.' - - ' - The default load balancing mode in the vSphere Client is srcDestIpTcpUdpPortVlan.' - - Please see examples for more information. - type: list -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Enable enhanced mode on a Distributed Switch - vmware_dvswitch_lacp: - hostname: '{{ inventory_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - switch: dvSwitch - support_mode: enhanced - validate_certs: "{{ validate_vcenter_certs }}" - delegate_to: localhost - loop_control: - label: "{{ item.name }}" - with_items: "{{ vcenter_distributed_switches }}" - -- name: Enable enhanced mode and create two LAGs on a Distributed Switch - vmware_dvswitch_lacp: - hostname: '{{ inventory_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - switch: dvSwitch - support_mode: enhanced - link_aggregation_groups: - - name: lag1 - uplink_number: 2 - mode: active - load_balancing_mode: srcDestIpTcpUdpPortVlan - - name: lag2 - uplink_number: 2 - mode: passive - load_balancing_mode: srcDestIp - validate_certs: "{{ validate_vcenter_certs }}" - delegate_to: localhost - loop_control: - label: "{{ item.name }}" - with_items: "{{ vcenter_distributed_switches }}" -''' - -RETURN = """ -result: - description: information about performed operation - returned: always - type: str - sample: { - "changed": true, - "dvswitch": "dvSwitch", - "link_aggregation_groups": [ - {"load_balancing_mode": "srcDestIpTcpUdpPortVlan", "mode": "active", "name": "lag1", "uplink_number": 2}, - {"load_balancing_mode": "srcDestIp", "mode": "active", "name": "lag2", "uplink_number": 2} - ], - "link_aggregation_groups_previous": [], - "support_mode": "enhanced", - "result": "lacp lags changed" - } -""" - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils._text import to_native -from ansible.module_utils.vmware import ( - PyVmomi, TaskError, find_dvs_by_name, vmware_argument_spec, wait_for_task -) - - -class VMwareDvSwitchLacp(PyVmomi): - """Class to manage a LACP on a Distributed Virtual Switch""" - def __init__(self, module): - super(VMwareDvSwitchLacp, self).__init__(module) - self.switch_name = self.module.params['switch'] - self.support_mode = self.module.params['support_mode'] - self.link_aggregation_groups = self.module.params['link_aggregation_groups'] - if self.support_mode == 'basic' and ( - self.link_aggregation_groups and not ( - len(self.link_aggregation_groups) == 1 and self.link_aggregation_groups[0] == '')): - self.module.fail_json( - msg="LAGs can only be configured if 'support_mode' is set to 'enhanced'!" - ) - self.dvs = find_dvs_by_name(self.content, self.switch_name) - if self.dvs is None: - self.module.fail_json(msg="Failed to find DVS %s" % self.switch_name) - - def ensure(self): - """Manage LACP configuration""" - changed = changed_support_mode = changed_lags = False - results = dict(changed=changed) - results['dvswitch'] = self.switch_name - changed_list = [] - - spec = vim.dvs.VmwareDistributedVirtualSwitch.ConfigSpec() - spec.configVersion = self.dvs.config.configVersion - - # Check support mode - results['support_mode'] = self.support_mode - lacp_support_mode = self.get_lacp_support_mode(self.support_mode) - if self.dvs.config.lacpApiVersion != lacp_support_mode: - changed = changed_support_mode = True - changed_list.append("support mode") - results['support_mode_previous'] = self.get_lacp_support_mode(self.dvs.config.lacpApiVersion) - spec.lacpApiVersion = lacp_support_mode - - # Check LAGs - results['link_aggregation_groups'] = self.link_aggregation_groups - if self.link_aggregation_groups and not ( - len(self.link_aggregation_groups) == 1 and self.link_aggregation_groups[0] == ''): - if self.dvs.config.lacpGroupConfig: - lacp_lag_list = [] - # Check if desired LAGs are configured - for lag in self.link_aggregation_groups: - lag_name, lag_mode, lag_uplink_number, lag_load_balancing_mode = self.get_lacp_lag_options(lag) - lag_found = False - for lacp_group in self.dvs.config.lacpGroupConfig: - if lacp_group.name == lag_name: - lag_found = True - if (lag_mode != lacp_group.mode or - lag_uplink_number != lacp_group.uplinkNum or - lag_load_balancing_mode != lacp_group.loadbalanceAlgorithm): - changed = changed_lags = True - lacp_lag_list.append( - self.create_lacp_group_spec( - 'edit', - lacp_group.key, lag_name, lag_uplink_number, lag_mode, lag_load_balancing_mode - ) - ) - break - if lag_found is False: - changed = changed_lags = True - lacp_lag_list.append( - self.create_lacp_group_spec( - 'add', None, lag_name, lag_uplink_number, lag_mode, lag_load_balancing_mode - ) - ) - # Check if LAGs need to be removed - for lacp_group in self.dvs.config.lacpGroupConfig: - lag_found = False - for lag in self.link_aggregation_groups: - result = self.get_lacp_lag_options(lag) - if lacp_group.name == result[0]: - lag_found = True - break - if lag_found is False: - changed = changed_lags = True - lacp_lag_list.append( - self.create_lacp_group_spec('remove', lacp_group.key, lacp_group.name, None, None, None) - ) - else: - changed = changed_lags = True - lacp_lag_list = [] - for lag in self.link_aggregation_groups: - lag_name, lag_mode, lag_uplink_number, lag_load_balancing_mode = self.get_lacp_lag_options(lag) - lacp_lag_list.append( - self.create_lacp_group_spec( - 'add', None, lag_name, lag_uplink_number, lag_mode, lag_load_balancing_mode - ) - ) - else: - if self.dvs.config.lacpGroupConfig: - changed = changed_lags = True - lacp_lag_list = [] - for lacp_group in self.dvs.config.lacpGroupConfig: - lacp_lag_list.append( - self.create_lacp_group_spec('remove', lacp_group.key, lacp_group.name, None, None, None) - ) - if changed_lags: - changed_list.append("link aggregation groups") - current_lags_list = [] - for lacp_group in self.dvs.config.lacpGroupConfig: - temp_lag = dict() - temp_lag['name'] = lacp_group.name - temp_lag['uplink_number'] = lacp_group.uplinkNum - temp_lag['mode'] = lacp_group.mode - temp_lag['load_balancing_mode'] = lacp_group.loadbalanceAlgorithm - current_lags_list.append(temp_lag) - results['link_aggregation_groups_previous'] = current_lags_list - - if changed: - if self.module.check_mode: - changed_suffix = ' would be changed' - else: - changed_suffix = ' changed' - if len(changed_list) > 2: - message = ', '.join(changed_list[:-1]) + ', and ' + str(changed_list[-1]) - elif len(changed_list) == 2: - message = ' and '.join(changed_list) - elif len(changed_list) == 1: - message = changed_list[0] - message += changed_suffix - if not self.module.check_mode: - if changed_support_mode and self.support_mode == 'basic' and changed_lags: - self.update_lacp_group_config(self.dvs, lacp_lag_list) - # NOTE: You need to run the task again to change the support mode to 'basic' as well - # No matter how long you sleep, you will always get the following error in vCenter: - # 'Cannot complete operation due to concurrent modification by another operation.' - # self.update_dvs_config(self.dvs, spec) - else: - if changed_support_mode: - self.update_dvs_config(self.dvs, spec) - if changed_lags: - self.update_lacp_group_config(self.dvs, lacp_lag_list) - else: - message = "LACP already configured properly" - results['changed'] = changed - results['result'] = message - - self.module.exit_json(**results) - - @staticmethod - def get_lacp_support_mode(mode): - """Get LACP support mode""" - return_mode = None - if mode == 'basic': - return_mode = 'singleLag' - elif mode == 'enhanced': - return_mode = 'multipleLag' - elif mode == 'singleLag': - return_mode = 'basic' - elif mode == 'multipleLag': - return_mode = 'enhanced' - return return_mode - - def get_lacp_lag_options(self, lag): - """Get and check LACP LAG options""" - lag_name = lag.get('name', None) - if lag_name is None: - self.module.fail_json(msg="Please specify name in lag options as it's a required parameter") - lag_mode = lag.get('mode', None) - if lag_mode is None: - self.module.fail_json(msg="Please specify mode in lag options as it's a required parameter") - lag_uplink_number = lag.get('uplink_number', None) - if lag_uplink_number is None: - self.module.fail_json(msg="Please specify uplink_number in lag options as it's a required parameter") - elif lag_uplink_number > 30: - self.module.fail_json(msg="More than 30 uplinks are not supported in a single LAG!") - lag_load_balancing_mode = lag.get('load_balancing_mode', None) - supported_lb_modes = ['srcTcpUdpPort', 'srcDestIpTcpUdpPortVlan', 'srcIpVlan', 'srcDestTcpUdpPort', - 'srcMac', 'destIp', 'destMac', 'vlan', 'srcDestIp', 'srcIpTcpUdpPortVlan', - 'srcDestIpTcpUdpPort', 'srcDestMac', 'destIpTcpUdpPort', 'srcPortId', 'srcIp', - 'srcIpTcpUdpPort', 'destIpTcpUdpPortVlan', 'destTcpUdpPort', 'destIpVlan', 'srcDestIpVlan'] - if lag_load_balancing_mode is None: - self.module.fail_json(msg="Please specify load_balancing_mode in lag options as it's a required parameter") - elif lag_load_balancing_mode not in supported_lb_modes: - self.module.fail_json(msg="The specified load balancing mode '%s' isn't supported!" % lag_load_balancing_mode) - return lag_name, lag_mode, lag_uplink_number, lag_load_balancing_mode - - @staticmethod - def create_lacp_group_spec(operation, key, name, uplink_number, mode, load_balancing_mode): - """ - Create LACP group spec - operation: add, edit, or remove - Returns: LACP group spec - """ - lacp_spec = vim.dvs.VmwareDistributedVirtualSwitch.LacpGroupSpec() - lacp_spec.operation = operation - lacp_spec.lacpGroupConfig = vim.dvs.VmwareDistributedVirtualSwitch.LacpGroupConfig() - lacp_spec.lacpGroupConfig.name = name - if operation in ('edit', 'remove'): - lacp_spec.lacpGroupConfig.key = key - if not operation == 'remove': - lacp_spec.lacpGroupConfig.uplinkNum = uplink_number - lacp_spec.lacpGroupConfig.mode = mode - lacp_spec.lacpGroupConfig.loadbalanceAlgorithm = load_balancing_mode - # greyed out in vSphere Client!? - # lacp_spec.vlan = vim.dvs.VmwareDistributedVirtualSwitch.LagVlanConfig() - # lacp_spec.vlan.vlanId = [vim.NumericRange(...)] - # lacp_spec.ipfix = vim.dvs.VmwareDistributedVirtualSwitch.LagIpfixConfig() - # lacp_spec.ipfix.ipfixEnabled = True/False - return lacp_spec - - def update_dvs_config(self, switch_object, spec): - """Update DVS config""" - try: - task = switch_object.ReconfigureDvs_Task(spec) - result = wait_for_task(task) - except TaskError as invalid_argument: - self.module.fail_json( - msg="Failed to update DVS : %s" % to_native(invalid_argument) - ) - return result - - def update_lacp_group_config(self, switch_object, lacp_group_spec): - """Update LACP group config""" - try: - task = switch_object.UpdateDVSLacpGroupConfig_Task(lacpGroupSpec=lacp_group_spec) - result = wait_for_task(task) - except vim.fault.DvsFault as dvs_fault: - self.module.fail_json(msg="Update failed due to DVS fault : %s" % to_native(dvs_fault)) - except vmodl.fault.NotSupported as not_supported: - self.module.fail_json( - msg="Multiple Link Aggregation Control Protocol groups not supported on the switch : %s" % - to_native(not_supported) - ) - except TaskError as invalid_argument: - self.module.fail_json( - msg="Failed to update Link Aggregation Group : %s" % to_native(invalid_argument) - ) - return result - - -def main(): - """Main""" - argument_spec = vmware_argument_spec() - argument_spec.update( - dict( - switch=dict(required=True, aliases=['dvswitch']), - support_mode=dict(default='basic', choices=['basic', 'enhanced']), - link_aggregation_groups=dict(default=[], type='list'), - ) - ) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - vmware_dvswitch_lacp = VMwareDvSwitchLacp(module) - vmware_dvswitch_lacp.ensure() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_dvswitch_nioc.py b/lib/ansible/modules/cloud/vmware/vmware_dvswitch_nioc.py deleted file mode 100644 index cf35be12f6..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_dvswitch_nioc.py +++ /dev/null @@ -1,399 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2018, VMware, Inc. -# Copyright: (c) 2019, Abhijeet Kasurde <akasurde@redhat.com> -# SPDX-License-Identifier: GPL-3.0-or-later -# 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 = ''' ---- -module: vmware_dvswitch_nioc -short_description: Manage distributed switch Network IO Control -description: - - This module can be used to manage distributed switch Network IO Control configurations. -version_added: "2.9" -author: - - Joseph Andreatta (@vmwjoseph) -notes: - - Tested on vSphere 6.7 -requirements: - - "python >= 2.6" - - PyVmomi -options: - switch: - description: - - The name of the distributed switch. - required: True - aliases: ['dvswitch'] - type: str - version: - description: - - Network IO control version. - choices: - - 'version2' - - 'version3' - required: False - type: str - state: - description: - - Enable or disable NIOC on the distributed switch. - default: 'present' - choices: ['present', 'absent'] - required: False - type: str - resources: - description: - - 'List of dicts containing - { name: Resource name is one of the following: "faultTolerance", "hbr", "iSCSI", "management", "nfs", "vdp", - "virtualMachine", "vmotion", "vsan" - limit: The maximum allowed usage for a traffic class belonging to this resource pool per host physical NIC. - reservation: (Ignored if NIOC version is set to version2) Amount of bandwidth resource that is - guaranteed available to the host infrastructure traffic class. If the utilization is less than the - reservation, the extra bandwidth is used for other host infrastructure traffic class types. - Reservation is not allowed to exceed the value of limit, if limit is set. Unit is Mbits/sec. - shares_level: The allocation level ("low", "normal", "high", "custom"). The level is a simplified view - of shares. Levels map to a pre-determined set of numeric values for shares. - shares: Ignored unless shares_level is "custom". The number of shares allocated. - reservation: Ignored unless version is "version3". Amount of bandwidth resource that is guaranteed - available to the host infrastructure traffic class. - }' - required: False - type: list -extends_documentation_fragment: vmware.documentation -''' - -RETURN = r''' -dvswitch_nioc_status: - description: - - result of the changes - returned: success - type: str -resources_changed: - description: - - list of resources which were changed - returned: success - type: list - sample: [ "vmotion", "vsan" ] -''' - -EXAMPLES = ''' -- name: Enable NIOC - vmware_dvswitch_nioc: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - switch: dvSwitch - version: version3 - resources: - - name: vmotion - limit: -1 - reservation: 128 - shares_level: normal - - name: vsan - limit: -1 - shares_level: custom - shares: 99 - reservation: 256 - state: present - delegate_to: localhost - -- name: Disable NIOC - vmware_dvswitch_nioc: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - switch: dvSwitch - state: absent - delegate_to: localhost -''' - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils._text import to_native -from ansible.module_utils.vmware import PyVmomi, find_datacenter_by_name, find_dvs_by_name, vmware_argument_spec, wait_for_task - - -class VMwareDVSwitchNIOC(PyVmomi): - - def __init__(self, module): - super(VMwareDVSwitchNIOC, self).__init__(module) - self.dvs = None - self.resource_changes = list() - self.switch = module.params['switch'] - self.version = module.params.get('version') - self.state = module.params['state'] - self.resources = module.params.get('resources') - self.result = { - 'changed': False, - 'dvswitch_nioc_status': 'Unchanged', - 'resources_changed': list(), - } - - def process_state(self): - nioc_states = { - 'absent': { - 'present': self.state_disable_nioc, - 'absent': self.state_exit, - }, - 'present': { - 'version': self.state_update_nioc_version, - 'update': self.state_update_nioc_resources, - 'present': self.state_exit, - 'absent': self.state_enable_nioc, - } - } - nioc_states[self.state][self.check_nioc_state()]() - self.state_exit() - - def state_exit(self): - self.module.exit_json(**self.result) - - def state_disable_nioc(self): - self.result['changed'] = True - if not self.module.check_mode: - self.set_nioc_enabled(False) - self.result['dvswitch_nioc_status'] = 'Disabled NIOC' - - def state_enable_nioc(self): - self.result['changed'] = True - if not self.module.check_mode: - self.set_nioc_enabled(True) - self.set_nioc_version() - self.result['dvswitch_nioc_status'] = "Enabled NIOC with version %s" % self.version - - # Check resource state and apply all required changes - if self.check_resources() == 'update': - self.set_nioc_resources(self.resource_changes) - - def state_update_nioc_version(self): - self.result['changed'] = True - if not self.module.check_mode: - self.set_nioc_version() - self.result['dvswitch_nioc_status'] = "Set NIOC to version %s" % self.version - - # Check resource state and apply all required changes - if self.check_resources() == 'update': - self.set_nioc_resources(self.resource_changes) - - def state_update_nioc_resources(self): - self.result['changed'] = True - if not self.module.check_mode: - self.result['dvswitch_nioc_status'] = "Resource configuration modified" - self.set_nioc_resources(self.resource_changes) - - def set_nioc_enabled(self, state): - try: - self.dvs.EnableNetworkResourceManagement(enable=state) - except vim.fault.DvsFault as dvs_fault: - self.module.fail_json(msg='DvsFault while setting NIOC enabled=%r: %s' % (state, to_native(dvs_fault.msg))) - except vim.fault.DvsNotAuthorized as auth_fault: - self.module.fail_json(msg='Not authorized to set NIOC enabled=%r: %s' % (state, to_native(auth_fault.msg))) - except vmodl.fault.NotSupported as support_fault: - self.module.fail_json(msg='NIOC not supported by DVS: %s' % to_native(support_fault.msg)) - except vmodl.RuntimeFault as runtime_fault: - self.module.fail_json(msg='RuntimeFault while setting NIOC enabled=%r: %s' % (state, to_native(runtime_fault.msg))) - - def set_nioc_version(self): - upgrade_spec = vim.DistributedVirtualSwitch.ConfigSpec() - upgrade_spec.configVersion = self.dvs.config.configVersion - if not self.version: - self.version = 'version2' - upgrade_spec.networkResourceControlVersion = self.version - - try: - task = self.dvs.ReconfigureDvs_Task(spec=upgrade_spec) - wait_for_task(task) - except vmodl.RuntimeFault as runtime_fault: - self.module.fail_json(msg="RuntimeFault when setting NIOC version: %s " % to_native(runtime_fault.msg)) - - def check_nioc_state(self): - self.dvs = find_dvs_by_name(self.content, self.switch) - - if self.dvs is None: - self.module.fail_json(msg='DVS %s was not found.' % self.switch) - else: - if not self.dvs.config.networkResourceManagementEnabled: - return 'absent' - if self.version and self.dvs.config.networkResourceControlVersion != self.version: - return 'version' - - # NIOC is enabled and the correct version, so return the state of the resources - return self.check_resources() - - def check_resources(self): - self.dvs = find_dvs_by_name(self.content, self.switch) - if self.dvs is None: - self.module.fail_json(msg="DVS named '%s' was not found" % self.switch) - - for resource in self.resources: - if self.check_resource_state(resource) == 'update': - self.resource_changes.append(resource) - self.result['resources_changed'].append(resource['name']) - - if len(self.resource_changes) > 0: - return 'update' - return 'present' - - def check_resource_state(self, resource): - resource_cfg = self.find_netioc_by_key(resource['name']) - if resource_cfg is None: - self.module.fail_json(msg="NetIOC resource named '%s' was not found" % resource['name']) - - rc = { - "limit": resource_cfg.allocationInfo.limit, - "shares_level": resource_cfg.allocationInfo.shares.level - } - if resource_cfg.allocationInfo.shares.level == 'custom': - rc["shares"] = resource_cfg.allocationInfo.shares.shares - if self.dvs.config.networkResourceControlVersion == "version3": - rc["reservation"] = resource_cfg.allocationInfo.reservation - - for k, v in rc.items(): - if k in resource and v != resource[k]: - return 'update' - return 'valid' - - def set_nioc_resources(self, resources): - if self.dvs.config.networkResourceControlVersion == 'version3': - self._update_version3_resources(resources) - elif self.dvs.config.networkResourceControlVersion == 'version2': - self._update_version2_resources(resources) - - def _update_version3_resources(self, resources): - allocations = list() - - for resource in resources: - allocation = vim.DistributedVirtualSwitch.HostInfrastructureTrafficResource() - allocation.allocationInfo = vim.DistributedVirtualSwitch.HostInfrastructureTrafficResource.ResourceAllocation() - allocation.key = resource['name'] - if 'limit' in resource: - allocation.allocationInfo.limit = resource['limit'] - if 'reservation' in resource: - allocation.allocationInfo.reservation = resource['reservation'] - if 'shares_level' in resource: - allocation.allocationInfo.shares = vim.SharesInfo() - allocation.allocationInfo.shares.level = resource['shares_level'] - if 'shares' in resource and resource['shares_level'] == 'custom': - allocation.allocationInfo.shares.shares = resource['shares'] - elif resource['shares_level'] == 'custom': - self.module.fail_json( - msg="Resource %s, shares_level set to custom but shares not specified" % resource['name'] - ) - - allocations.append(allocation) - - spec = vim.DistributedVirtualSwitch.ConfigSpec() - spec.configVersion = self.dvs.config.configVersion - spec.infrastructureTrafficResourceConfig = allocations - - task = self.dvs.ReconfigureDvs_Task(spec) - wait_for_task(task) - - def _update_version2_resources(self, resources): - allocations = list() - - for resource in resources: - resource_cfg = self.find_netioc_by_key(resource['name']) - allocation = vim.DVSNetworkResourcePoolConfigSpec() - allocation.allocationInfo = vim.DVSNetworkResourcePoolAllocationInfo() - allocation.key = resource['name'] - allocation.configVersion = resource_cfg.configVersion - if 'limit' in resource: - allocation.allocationInfo.limit = resource['limit'] - if 'shares_level' in resource: - allocation.allocationInfo.shares = vim.SharesInfo() - allocation.allocationInfo.shares.level = resource['shares_level'] - if 'shares' in resource and resource['shares_level'] == 'custom': - allocation.allocationInfo.shares.shares = resource['shares'] - - allocations.append(allocation) - - self.dvs.UpdateNetworkResourcePool(allocations) - - def find_netioc_by_key(self, resource_name): - config = None - if self.dvs.config.networkResourceControlVersion == "version3": - config = self.dvs.config.infrastructureTrafficResourceConfig - elif self.dvs.config.networkResourceControlVersion == "version2": - config = self.dvs.networkResourcePool - - for obj in config: - if obj.key == resource_name: - return obj - return None - - -def main(): - argument_spec = vmware_argument_spec() - - argument_spec.update( - dict( - switch=dict(required=True, type='str', aliases=['dvswitch']), - version=dict(type='str', choices=['version2', 'version3']), - state=dict(default='present', choices=['present', 'absent'], type='str'), - resources=dict( - type='list', - default=list(), - elements='dict', - options=dict( - name=dict( - type='str', - required=True, - choices=[ - 'faultTolerance', - 'hbr', - 'iSCSI', - 'management', - 'nfs', - 'vdp', - 'virtualMachine', - 'vmotion', - 'vsan' - ] - ), - limit=dict(type='int', default=-1), - shares_level=dict( - type='str', - required=False, - choices=[ - 'low', - 'normal', - 'high', - 'custom' - ] - ), - shares=dict(type='int', required=False), - reservation=dict(type='int', default=0) - ) - ), - ) - ) - - module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) - - try: - vmware_dvswitch_nioc = VMwareDVSwitchNIOC(module) - vmware_dvswitch_nioc.process_state() - except vmodl.RuntimeFault as runtime_fault: - module.fail_json(msg=to_native(runtime_fault.msg)) - except vmodl.MethodFault as method_fault: - module.fail_json(msg=to_native(method_fault.msg)) - except Exception as e: - module.fail_json(msg=to_native(e)) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_dvswitch_pvlans.py b/lib/ansible/modules/cloud/vmware/vmware_dvswitch_pvlans.py deleted file mode 100644 index 4b395c3c51..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_dvswitch_pvlans.py +++ /dev/null @@ -1,533 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# -# 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 = ''' ---- -module: vmware_dvswitch_pvlans -short_description: Manage Private VLAN configuration of a Distributed Switch -description: - - This module can be used to configure Private VLANs (PVLANs) on a Distributed Switch. -version_added: 2.8 -author: -- Christian Kotte (@ckotte) -notes: - - Tested on vSphere 6.5 and 6.7 -requirements: - - "python >= 2.6" - - PyVmomi -options: - switch: - description: - - The name of the Distributed Switch. - type: str - required: True - aliases: ['dvswitch'] - primary_pvlans: - description: - - A list of VLAN IDs that should be configured as Primary PVLANs. - - If C(primary_pvlans) isn't specified, all PVLANs will be deleted if present. - - Each member of the list requires primary_pvlan_id (int) set. - - The secondary promiscuous PVLAN will be created automatically. - - If C(secondary_pvlans) isn't specified, the primary PVLANs and each secondary promiscuous PVLAN will be created. - - Please see examples for more information. - type: list - default: [] - secondary_pvlans: - description: - - A list of VLAN IDs that should be configured as Secondary PVLANs. - - 'C(primary_pvlans) need to be specified to create any Secondary PVLAN.' - - If C(primary_pvlans) isn't specified, all PVLANs will be deleted if present. - - Each member of the list requires primary_pvlan_id (int), secondary_pvlan_id (int), and pvlan_type (str) to be set. - - The type of the secondary PVLAN can be isolated or community. The secondary promiscuous PVLAN will be created automatically. - - Please see examples for more information. - type: list - default: [] -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Create PVLANs on a Distributed Switch - vmware_dvswitch_pvlans: - hostname: '{{ inventory_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - switch: dvSwitch - primary_pvlans: - - primary_pvlan_id: 1 - - primary_pvlan_id: 4 - secondary_pvlans: - - primary_pvlan_id: 1 - secondary_pvlan_id: 2 - pvlan_type: isolated - - primary_pvlan_id: 1 - secondary_pvlan_id: 3 - pvlan_type: community - - primary_pvlan_id: 4 - secondary_pvlan_id: 5 - pvlan_type: community - delegate_to: localhost - -- name: Create primary PVLAN and secondary promiscuous PVLAN on a Distributed Switch - vmware_dvswitch_pvlans: - hostname: '{{ inventory_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - switch: dvSwitch - primary_pvlans: - - primary_pvlan_id: 1 - delegate_to: localhost - -- name: Remove all PVLANs from a Distributed Switch - vmware_dvswitch_pvlans: - hostname: '{{ inventory_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - switch: dvSwitch - primary_pvlans: [] - secondary_pvlans: [] - delegate_to: localhost -''' - -RETURN = """ -result: - description: information about performed operation - returned: always - type: str - sample: { - "changed": true, - "dvswitch": "dvSwitch", - "private_vlans": [ - { - "primary_pvlan_id": 1, - "pvlan_type": "promiscuous", - "secondary_pvlan_id": 1 - }, - { - "primary_pvlan_id": 1, - "pvlan_type": "isolated", - "secondary_pvlan_id": 2 - }, - { - "primary_pvlan_id": 1, - "pvlan_type": "community", - "secondary_pvlan_id": 3 - } - ], - "private_vlans_previous": [], - "result": "All private VLANs added" - } -""" - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils._text import to_native -from ansible.module_utils.vmware import ( - PyVmomi, TaskError, find_dvs_by_name, vmware_argument_spec, wait_for_task -) - - -class VMwareDvSwitchPvlans(PyVmomi): - """Class to manage Private VLANs on a Distributed Virtual Switch""" - - def __init__(self, module): - super(VMwareDvSwitchPvlans, self).__init__(module) - self.switch_name = self.module.params['switch'] - if self.module.params['primary_pvlans']: - self.primary_pvlans = self.module.params['primary_pvlans'] - if self.module.params['secondary_pvlans']: - self.secondary_pvlans = self.module.params['secondary_pvlans'] - else: - self.secondary_pvlans = None - self.do_pvlan_sanity_checks() - else: - self.primary_pvlans = None - self.secondary_pvlans = None - self.dvs = find_dvs_by_name(self.content, self.switch_name) - if self.dvs is None: - self.module.fail_json(msg="Failed to find DVS %s" % self.switch_name) - - def do_pvlan_sanity_checks(self): - """Do sanity checks for primary and secondary PVLANs""" - # Check if primary PVLANs are unique - for primary_vlan in self.primary_pvlans: - count = 0 - primary_pvlan_id = self.get_primary_pvlan_option(primary_vlan) - for primary_vlan_2 in self.primary_pvlans: - primary_pvlan_id_2 = self.get_primary_pvlan_option(primary_vlan_2) - if primary_pvlan_id == primary_pvlan_id_2: - count += 1 - if count > 1: - self.module.fail_json( - msg="The primary PVLAN ID '%s' must be unique!" % primary_pvlan_id - ) - if self.secondary_pvlans: - # Check if secondary PVLANs are unique - for secondary_pvlan in self.secondary_pvlans: - count = 0 - result = self.get_secondary_pvlan_options(secondary_pvlan) - for secondary_pvlan_2 in self.secondary_pvlans: - result_2 = self.get_secondary_pvlan_options(secondary_pvlan_2) - if result[0] == result_2[0]: - count += 1 - if count > 1: - self.module.fail_json( - msg="The secondary PVLAN ID '%s' must be unique!" % result[0] - ) - # Check if secondary PVLANs are already used as primary PVLANs - for primary_vlan in self.primary_pvlans: - primary_pvlan_id = self.get_primary_pvlan_option(primary_vlan) - for secondary_pvlan in self.secondary_pvlans: - result = self.get_secondary_pvlan_options(secondary_pvlan) - if primary_pvlan_id == result[0]: - self.module.fail_json( - msg="The secondary PVLAN ID '%s' is already used as a primary PVLAN!" % - result[0] - ) - # Check if a primary PVLAN is present for every secondary PVLANs - for secondary_pvlan in self.secondary_pvlans: - primary_pvlan_found = False - result = self.get_secondary_pvlan_options(secondary_pvlan) - for primary_vlan in self.primary_pvlans: - primary_pvlan_id = self.get_primary_pvlan_option(primary_vlan) - if result[1] == primary_pvlan_id: - primary_pvlan_found = True - break - if not primary_pvlan_found: - self.module.fail_json( - msg="The primary PVLAN ID '%s' isn't defined for the secondary PVLAN ID '%s'!" % - (result[1], result[0]) - ) - - def ensure(self): - """Manage Private VLANs""" - changed = False - results = dict(changed=changed) - results['dvswitch'] = self.switch_name - changed_list_add = [] - changed_list_remove = [] - - config_spec = vim.dvs.VmwareDistributedVirtualSwitch.ConfigSpec() - # Use the same version in the new spec; The version will be increased by one by the API automatically - config_spec.configVersion = self.dvs.config.configVersion - - # Check Private VLANs - results['private_vlans'] = None - if self.primary_pvlans: - desired_pvlan_list = [] - for primary_vlan in self.primary_pvlans: - primary_pvlan_id = self.get_primary_pvlan_option(primary_vlan) - temp_pvlan = dict() - temp_pvlan['primary_pvlan_id'] = primary_pvlan_id - temp_pvlan['secondary_pvlan_id'] = primary_pvlan_id - temp_pvlan['pvlan_type'] = 'promiscuous' - desired_pvlan_list.append(temp_pvlan) - if self.secondary_pvlans: - for secondary_pvlan in self.secondary_pvlans: - (secondary_pvlan_id, - secondary_vlan_primary_vlan_id, - pvlan_type) = self.get_secondary_pvlan_options(secondary_pvlan) - temp_pvlan = dict() - temp_pvlan['primary_pvlan_id'] = secondary_vlan_primary_vlan_id - temp_pvlan['secondary_pvlan_id'] = secondary_pvlan_id - temp_pvlan['pvlan_type'] = pvlan_type - desired_pvlan_list.append(temp_pvlan) - results['private_vlans'] = desired_pvlan_list - if self.dvs.config.pvlanConfig: - pvlan_spec_list = [] - # Check if desired PVLANs are configured - for primary_vlan in self.primary_pvlans: - primary_pvlan_id = self.get_primary_pvlan_option(primary_vlan) - promiscuous_found = other_found = False - for pvlan_object in self.dvs.config.pvlanConfig: - if pvlan_object.primaryVlanId == primary_pvlan_id and pvlan_object.pvlanType == 'promiscuous': - promiscuous_found = True - break - if not promiscuous_found: - changed = True - changed_list_add.append('promiscuous (%s, %s)' % (primary_pvlan_id, primary_pvlan_id)) - pvlan_spec_list.append( - self.create_pvlan_config_spec( - operation='add', - primary_pvlan_id=primary_pvlan_id, - secondary_pvlan_id=primary_pvlan_id, - pvlan_type='promiscuous' - ) - ) - if self.secondary_pvlans: - for secondary_pvlan in self.secondary_pvlans: - (secondary_pvlan_id, - secondary_vlan_primary_vlan_id, - pvlan_type) = self.get_secondary_pvlan_options(secondary_pvlan) - if primary_pvlan_id == secondary_vlan_primary_vlan_id: - for pvlan_object_2 in self.dvs.config.pvlanConfig: - if (pvlan_object_2.primaryVlanId == secondary_vlan_primary_vlan_id - and pvlan_object_2.secondaryVlanId == secondary_pvlan_id - and pvlan_object_2.pvlanType == pvlan_type): - other_found = True - break - if not other_found: - changed = True - changed_list_add.append( - '%s (%s, %s)' % (pvlan_type, primary_pvlan_id, secondary_pvlan_id) - ) - pvlan_spec_list.append( - self.create_pvlan_config_spec( - operation='add', - primary_pvlan_id=primary_pvlan_id, - secondary_pvlan_id=secondary_pvlan_id, - pvlan_type=pvlan_type - ) - ) - # Check if a PVLAN needs to be removed - for pvlan_object in self.dvs.config.pvlanConfig: - promiscuous_found = other_found = False - if (pvlan_object.primaryVlanId == pvlan_object.secondaryVlanId - and pvlan_object.pvlanType == 'promiscuous'): - for primary_vlan in self.primary_pvlans: - primary_pvlan_id = self.get_primary_pvlan_option(primary_vlan) - if pvlan_object.primaryVlanId == primary_pvlan_id and pvlan_object.pvlanType == 'promiscuous': - promiscuous_found = True - break - if not promiscuous_found: - changed = True - changed_list_remove.append( - 'promiscuous (%s, %s)' % (pvlan_object.primaryVlanId, pvlan_object.secondaryVlanId) - ) - pvlan_spec_list.append( - self.create_pvlan_config_spec( - operation='remove', - primary_pvlan_id=pvlan_object.primaryVlanId, - secondary_pvlan_id=pvlan_object.secondaryVlanId, - pvlan_type='promiscuous' - ) - ) - elif self.secondary_pvlans: - for secondary_pvlan in self.secondary_pvlans: - (secondary_pvlan_id, - secondary_vlan_primary_vlan_id, - pvlan_type) = self.get_secondary_pvlan_options(secondary_pvlan) - if (pvlan_object.primaryVlanId == secondary_vlan_primary_vlan_id - and pvlan_object.secondaryVlanId == secondary_pvlan_id - and pvlan_object.pvlanType == pvlan_type): - other_found = True - break - if not other_found: - changed = True - changed_list_remove.append( - '%s (%s, %s)' % ( - pvlan_object.pvlanType, pvlan_object.primaryVlanId, pvlan_object.secondaryVlanId - ) - ) - pvlan_spec_list.append( - self.create_pvlan_config_spec( - operation='remove', - primary_pvlan_id=pvlan_object.primaryVlanId, - secondary_pvlan_id=pvlan_object.secondaryVlanId, - pvlan_type=pvlan_object.pvlanType - ) - ) - else: - changed = True - changed_list_remove.append( - '%s (%s, %s)' % ( - pvlan_object.pvlanType, pvlan_object.primaryVlanId, pvlan_object.secondaryVlanId - ) - ) - pvlan_spec_list.append( - self.create_pvlan_config_spec( - operation='remove', - primary_pvlan_id=pvlan_object.primaryVlanId, - secondary_pvlan_id=pvlan_object.secondaryVlanId, - pvlan_type=pvlan_object.pvlanType - ) - ) - else: - changed = True - changed_list_add.append('All private VLANs') - pvlan_spec_list = [] - for primary_vlan in self.primary_pvlans: - # the first secondary VLAN's type is always promiscuous - primary_pvlan_id = self.get_primary_pvlan_option(primary_vlan) - pvlan_spec_list.append( - self.create_pvlan_config_spec( - operation='add', - primary_pvlan_id=primary_pvlan_id, - secondary_pvlan_id=primary_pvlan_id, - pvlan_type='promiscuous' - ) - ) - if self.secondary_pvlans: - for secondary_pvlan in self.secondary_pvlans: - (secondary_pvlan_id, - secondary_vlan_primary_vlan_id, - pvlan_type) = self.get_secondary_pvlan_options(secondary_pvlan) - if primary_pvlan_id == secondary_vlan_primary_vlan_id: - pvlan_spec_list.append( - self.create_pvlan_config_spec( - operation='add', - primary_pvlan_id=primary_pvlan_id, - secondary_pvlan_id=secondary_pvlan_id, - pvlan_type=pvlan_type - ) - ) - else: - # Remove PVLAN configuration if present - if self.dvs.config.pvlanConfig: - changed = True - changed_list_remove.append('All private VLANs') - pvlan_spec_list = [] - for pvlan_object in self.dvs.config.pvlanConfig: - pvlan_spec_list.append( - self.create_pvlan_config_spec( - operation='remove', - primary_pvlan_id=pvlan_object.primaryVlanId, - secondary_pvlan_id=pvlan_object.secondaryVlanId, - pvlan_type=pvlan_object.pvlanType - ) - ) - - if changed: - message_add = message_remove = None - if changed_list_add: - message_add = self.build_change_message('add', changed_list_add) - if changed_list_remove: - message_remove = self.build_change_message('remove', changed_list_remove) - if message_add and message_remove: - message = message_add + '. ' + message_remove + '.' - elif message_add: - message = message_add - elif message_remove: - message = message_remove - current_pvlan_list = [] - for pvlan_object in self.dvs.config.pvlanConfig: - temp_pvlan = dict() - temp_pvlan['primary_pvlan_id'] = pvlan_object.primaryVlanId - temp_pvlan['secondary_pvlan_id'] = pvlan_object.secondaryVlanId - temp_pvlan['pvlan_type'] = pvlan_object.pvlanType - current_pvlan_list.append(temp_pvlan) - results['private_vlans_previous'] = current_pvlan_list - config_spec.pvlanConfigSpec = pvlan_spec_list - if not self.module.check_mode: - try: - task = self.dvs.ReconfigureDvs_Task(config_spec) - wait_for_task(task) - except TaskError as invalid_argument: - self.module.fail_json( - msg="Failed to update DVS : %s" % to_native(invalid_argument) - ) - else: - message = "PVLANs already configured properly" - results['changed'] = changed - results['result'] = message - - self.module.exit_json(**results) - - def get_primary_pvlan_option(self, primary_vlan): - """Get Primary PVLAN option""" - primary_pvlan_id = primary_vlan.get('primary_pvlan_id', None) - if primary_pvlan_id is None: - self.module.fail_json( - msg="Please specify primary_pvlan_id in primary_pvlans options as it's a required parameter" - ) - if primary_pvlan_id in (0, 4095): - self.module.fail_json(msg="The VLAN IDs of 0 and 4095 are reserved and cannot be used as a primary PVLAN.") - return primary_pvlan_id - - def get_secondary_pvlan_options(self, secondary_pvlan): - """Get Secondary PVLAN option""" - secondary_pvlan_id = secondary_pvlan.get('secondary_pvlan_id', None) - if secondary_pvlan_id is None: - self.module.fail_json( - msg="Please specify secondary_pvlan_id in secondary_pvlans options as it's a required parameter" - ) - primary_pvlan_id = secondary_pvlan.get('primary_pvlan_id', None) - if primary_pvlan_id is None: - self.module.fail_json( - msg="Please specify primary_pvlan_id in secondary_pvlans options as it's a required parameter" - ) - if secondary_pvlan_id in (0, 4095) or primary_pvlan_id in (0, 4095): - self.module.fail_json( - msg="The VLAN IDs of 0 and 4095 are reserved and cannot be used as a primary or secondary PVLAN." - ) - pvlan_type = secondary_pvlan.get('pvlan_type', None) - supported_pvlan_types = ['isolated', 'community'] - if pvlan_type is None: - self.module.fail_json(msg="Please specify pvlan_type in secondary_pvlans options as it's a required parameter") - elif pvlan_type not in supported_pvlan_types: - self.module.fail_json(msg="The specified PVLAN type '%s' isn't supported!" % pvlan_type) - return secondary_pvlan_id, primary_pvlan_id, pvlan_type - - @staticmethod - def create_pvlan_config_spec(operation, primary_pvlan_id, secondary_pvlan_id, pvlan_type): - """ - Create PVLAN config spec - operation: add, edit, or remove - Returns: PVLAN config spec - """ - pvlan_spec = vim.dvs.VmwareDistributedVirtualSwitch.PvlanConfigSpec() - pvlan_spec.operation = operation - pvlan_spec.pvlanEntry = vim.dvs.VmwareDistributedVirtualSwitch.PvlanMapEntry() - pvlan_spec.pvlanEntry.primaryVlanId = primary_pvlan_id - pvlan_spec.pvlanEntry.secondaryVlanId = secondary_pvlan_id - pvlan_spec.pvlanEntry.pvlanType = pvlan_type - return pvlan_spec - - def build_change_message(self, operation, changed_list): - """Build the changed message""" - if operation == 'add': - changed_operation = 'added' - elif operation == 'remove': - changed_operation = 'removed' - if self.module.check_mode: - changed_suffix = ' would be %s' % changed_operation - else: - changed_suffix = ' %s' % changed_operation - if len(changed_list) > 2: - message = ', '.join(changed_list[:-1]) + ', and ' + str(changed_list[-1]) - elif len(changed_list) == 2: - message = ' and '.join(changed_list) - elif len(changed_list) == 1: - message = changed_list[0] - message += changed_suffix - return message - - -def main(): - """Main""" - argument_spec = vmware_argument_spec() - argument_spec.update( - dict( - switch=dict(required=True, aliases=['dvswitch']), - primary_pvlans=dict(type='list', default=list(), required=False), - secondary_pvlans=dict(type='list', default=list(), required=False), - ) - ) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - vmware_dvswitch_pvlans = VMwareDvSwitchPvlans(module) - vmware_dvswitch_pvlans.ensure() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_dvswitch_uplink_pg.py b/lib/ansible/modules/cloud/vmware/vmware_dvswitch_uplink_pg.py deleted file mode 100644 index 9f50933c6c..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_dvswitch_uplink_pg.py +++ /dev/null @@ -1,480 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# -# 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 = ''' ---- -module: vmware_dvswitch_uplink_pg -short_description: Manage uplink portproup configuration of a Distributed Switch -description: - - This module can be used to configure the uplink portgroup of a Distributed Switch. -version_added: 2.8 -author: -- Christian Kotte (@ckotte) -notes: - - Tested on vSphere 6.5 and 6.7 -requirements: - - "python >= 2.6" - - PyVmomi -options: - switch: - description: - - The name of the Distributed Switch. - type: str - required: True - aliases: ['dvswitch'] - name: - description: - - The name of the uplink portgroup. - - The current name will be used if not specified. - type: str - description: - description: - - The description of the uplink portgroup. - type: str - advanced: - description: - - Dictionary which configures the advanced policy settings for the uplink portgroup. - - 'Valid attributes are:' - - '- C(port_config_reset_at_disconnect) (bool): indicates if the configuration of a port is reset automatically after disconnect. (default: true)' - - '- C(block_override) (bool): indicates if the block policy can be changed per port. (default: true)' - - '- C(netflow_override) (bool): indicates if the NetFlow policy can be changed per port. (default: false)' - - '- C(traffic_filter_override) (bool): indicates if the traffic filter can be changed per port. (default: false)' - - '- C(vendor_config_override) (bool): indicates if the vendor config can be changed per port. (default: false)' - - '- C(vlan_override) (bool): indicates if the vlan can be changed per port. (default: false)' - required: False - default: { - port_config_reset_at_disconnect: True, - block_override: True, - vendor_config_override: False, - vlan_override: False, - netflow_override: False, - traffic_filter_override: False, - } - aliases: ['port_policy'] - type: dict - vlan_trunk_range: - description: - - The VLAN trunk range that should be configured with the uplink portgroup. - - 'This can be a combination of multiple ranges and numbers, example: [ 2-3967, 4049-4092 ].' - type: list - default: [ '0-4094' ] - lacp: - description: - - Dictionary which configures the LACP settings for the uplink portgroup. - - The options are only used if the LACP support mode is set to 'basic'. - - 'The following parameters are required:' - - '- C(status) (str): Indicates if LACP is enabled. (default: disabled)' - - '- C(mode) (str): The negotiating state of the uplinks/ports. (default: passive)' - required: False - default: { - status: 'disabled', - mode: 'passive', - } - type: dict - netflow_enabled: - description: - - Indicates if NetFlow is enabled on the uplink portgroup. - type: bool - default: False - block_all_ports: - description: - - Indicates if all ports are blocked on the uplink portgroup. - type: bool - default: False -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Configure Uplink portgroup - vmware_dvswitch_uplink_pg: - hostname: '{{ inventory_hostname }}' - username: '{{ vcsa_username }}' - password: '{{ vcsa_password }}' - switch: dvSwitch - name: dvSwitch-DVUplinks - advanced: - port_config_reset_at_disconnect: True - block_override: True - vendor_config_override: False - vlan_override: False - netflow_override: False - traffic_filter_override: False - vlan_trunk_range: - - '0-4094' - netflow_enabled: False - block_all_ports: False - delegate_to: localhost - -- name: Enabled LACP on Uplink portgroup - vmware_dvswitch_uplink_pg: - hostname: '{{ inventory_hostname }}' - username: '{{ vcsa_username }}' - password: '{{ vcsa_password }}' - switch: dvSwitch - lacp: - status: enabled - mode: active - delegate_to: localhost -''' - -RETURN = """ -result: - description: information about performed operation - returned: always - type: str - sample: { - "adv_block_ports": true, - "adv_netflow": false, - "adv_reset_at_disconnect": true, - "adv_traffic_filtering": false, - "adv_vendor_conf": false, - "adv_vlan": false, - "block_all_ports": false, - "changed": false, - "description": null, - "dvswitch": "dvSwitch", - "lacp_status": "disabled", - "lacp_status_previous": "enabled", - "name": "dvSwitch-DVUplinks", - "netflow_enabled": false, - "result": "Uplink portgroup already configured properly", - "vlan_trunk_range": [ - "2-3967", - "4049-4092" - ] - } -""" - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils._text import to_native -from ansible.module_utils.vmware import ( - PyVmomi, TaskError, find_dvs_by_name, vmware_argument_spec, wait_for_task -) - - -class VMwareDvSwitchUplinkPortgroup(PyVmomi): - """Class to manage a uplink portgroup on a Distributed Virtual Switch""" - - def __init__(self, module): - super(VMwareDvSwitchUplinkPortgroup, self).__init__(module) - self.switch_name = self.module.params['switch'] - self.uplink_pg_name = self.params['name'] - self.uplink_pg_description = self.params['description'] - self.uplink_pg_reset = self.params['advanced'].get('port_config_reset_at_disconnect') - self.uplink_pg_block_ports = self.params['advanced'].get('block_override') - self.uplink_pg_vendor_conf = self.params['advanced'].get('vendor_config_override') - self.uplink_pg_vlan = self.params['advanced'].get('vlan_override') - self.uplink_pg_netflow = self.params['advanced'].get('netflow_override') - self.uplink_pg_tf = self.params['advanced'].get('traffic_filter_override') - self.uplink_pg_vlan_trunk_range = self.params['vlan_trunk_range'] - self.uplink_pg_netflow_enabled = self.params['netflow_enabled'] - self.uplink_pg_block_all_ports = self.params['block_all_ports'] - self.lacp_status = self.params['lacp'].get('status') - self.lacp_mode = self.params['lacp'].get('mode') - self.dvs = find_dvs_by_name(self.content, self.switch_name) - if self.dvs is None: - self.module.fail_json(msg="Failed to find DVS %s" % self.switch_name) - self.support_mode = self.dvs.config.lacpApiVersion - - def ensure(self): - """Manage uplink portgroup""" - changed = changed_uplink_pg_policy = changed_vlan_trunk_range = changed_lacp = False - results = dict(changed=changed) - results['dvswitch'] = self.switch_name - changed_list = [] - - uplink_pg_spec = vim.dvs.DistributedVirtualPortgroup.ConfigSpec() - # Use the same version in the new spec; The version will be increased by one by the API automatically - uplink_pg_spec.configVersion = self.dvs.config.uplinkPortgroup[0].config.configVersion - uplink_pg_config = self.dvs.config.uplinkPortgroup[0].config - - # Check name - if self.uplink_pg_name: - results['name'] = self.uplink_pg_name - if uplink_pg_config.name != self.uplink_pg_name: - changed = True - changed_list.append("name") - results['name_previous'] = uplink_pg_config.name - uplink_pg_spec.name = self.uplink_pg_name - else: - results['name'] = uplink_pg_config.name - - # Check description - results['description'] = self.uplink_pg_description - if uplink_pg_config.description != self.uplink_pg_description: - changed = True - changed_list.append("description") - results['description_previous'] = uplink_pg_config.description - uplink_pg_spec.description = self.uplink_pg_description - - # Check port policies - results['adv_reset_at_disconnect'] = self.uplink_pg_reset - results['adv_block_ports'] = self.uplink_pg_block_ports - results['adv_vendor_conf'] = self.uplink_pg_vendor_conf - results['adv_vlan'] = self.uplink_pg_vlan - results['adv_netflow'] = self.uplink_pg_netflow - results['adv_traffic_filtering'] = self.uplink_pg_tf - uplink_pg_policy_spec = vim.dvs.VmwareDistributedVirtualSwitch.VMwarePortgroupPolicy() - uplink_pg_policy_spec.portConfigResetAtDisconnect = self.uplink_pg_reset - uplink_pg_policy_spec.blockOverrideAllowed = self.uplink_pg_block_ports - uplink_pg_policy_spec.vendorConfigOverrideAllowed = self.uplink_pg_vendor_conf - uplink_pg_policy_spec.vlanOverrideAllowed = self.uplink_pg_vlan - uplink_pg_policy_spec.ipfixOverrideAllowed = self.uplink_pg_netflow - uplink_pg_policy_spec.trafficFilterOverrideAllowed = self.uplink_pg_tf - # There's no information available if the following option are deprecated, but - # they aren't visible in the vSphere Client - uplink_pg_policy_spec.shapingOverrideAllowed = False - uplink_pg_policy_spec.livePortMovingAllowed = False - uplink_pg_policy_spec.uplinkTeamingOverrideAllowed = False - uplink_pg_policy_spec.securityPolicyOverrideAllowed = False - uplink_pg_policy_spec.networkResourcePoolOverrideAllowed = False - # Check policies - if uplink_pg_config.policy.portConfigResetAtDisconnect != self.uplink_pg_reset: - changed_uplink_pg_policy = True - results['adv_reset_at_disconnect_previous'] = uplink_pg_config.policy.portConfigResetAtDisconnect - if uplink_pg_config.policy.blockOverrideAllowed != self.uplink_pg_block_ports: - changed_uplink_pg_policy = True - results['adv_block_ports_previous'] = uplink_pg_config.policy.blockOverrideAllowed - if uplink_pg_config.policy.vendorConfigOverrideAllowed != self.uplink_pg_vendor_conf: - changed_uplink_pg_policy = True - results['adv_vendor_conf_previous'] = uplink_pg_config.policy.vendorConfigOverrideAllowed - if uplink_pg_config.policy.vlanOverrideAllowed != self.uplink_pg_vlan: - changed_uplink_pg_policy = True - results['adv_vlan_previous'] = uplink_pg_config.policy.vlanOverrideAllowed - if uplink_pg_config.policy.ipfixOverrideAllowed != self.uplink_pg_netflow: - changed_uplink_pg_policy = True - results['adv_netflow_previous'] = uplink_pg_config.policy.ipfixOverrideAllowed - if uplink_pg_config.policy.trafficFilterOverrideAllowed != self.uplink_pg_tf: - changed_uplink_pg_policy = True - results['adv_traffic_filtering_previous'] = uplink_pg_config.policy.trafficFilterOverrideAllowed - if changed_uplink_pg_policy: - changed = True - changed_list.append("advanced") - uplink_pg_spec.policy = uplink_pg_policy_spec - - uplink_pg_spec.defaultPortConfig = vim.dvs.VmwareDistributedVirtualSwitch.VmwarePortConfigPolicy() - - # Check VLAN trunk - results['vlan_trunk_range'] = self.uplink_pg_vlan_trunk_range - vlan_id_ranges = self.uplink_pg_vlan_trunk_range - trunk_vlan_spec = vim.dvs.VmwareDistributedVirtualSwitch.TrunkVlanSpec() - vlan_id_list = [] - for vlan_id_range in vlan_id_ranges: - vlan_id_range_found = False - vlan_id_start, vlan_id_end = self.get_vlan_ids_from_range(vlan_id_range) - # Check if range is already configured - for current_vlan_id_range in uplink_pg_config.defaultPortConfig.vlan.vlanId: - if current_vlan_id_range.start == int(vlan_id_start) and current_vlan_id_range.end == int(vlan_id_end): - vlan_id_range_found = True - break - if vlan_id_range_found is False: - changed_vlan_trunk_range = True - vlan_id_list.append( - vim.NumericRange(start=int(vlan_id_start), end=int(vlan_id_end)) - ) - # Check if range needs to be removed - for current_vlan_id_range in uplink_pg_config.defaultPortConfig.vlan.vlanId: - vlan_id_range_found = False - for vlan_id_range in vlan_id_ranges: - vlan_id_start, vlan_id_end = self.get_vlan_ids_from_range(vlan_id_range) - if (current_vlan_id_range.start == int(vlan_id_start) - and current_vlan_id_range.end == int(vlan_id_end)): - vlan_id_range_found = True - break - if vlan_id_range_found is False: - changed_vlan_trunk_range = True - trunk_vlan_spec.vlanId = vlan_id_list - if changed_vlan_trunk_range: - changed = True - changed_list.append("vlan trunk range") - current_vlan_id_list = [] - for current_vlan_id_range in uplink_pg_config.defaultPortConfig.vlan.vlanId: - if current_vlan_id_range.start == current_vlan_id_range.end: - current_vlan_id_range_string = current_vlan_id_range.start - else: - current_vlan_id_range_string = '-'.join( - [str(current_vlan_id_range.start), str(current_vlan_id_range.end)] - ) - current_vlan_id_list.append(current_vlan_id_range_string) - results['vlan_trunk_range_previous'] = current_vlan_id_list - uplink_pg_spec.defaultPortConfig.vlan = trunk_vlan_spec - - # Check LACP - lacp_support_mode = self.get_lacp_support_mode(self.support_mode) - if lacp_support_mode == 'basic': - results['lacp_status'] = self.lacp_status - lacp_spec = vim.dvs.VmwareDistributedVirtualSwitch.UplinkLacpPolicy() - lacp_enabled = False - if self.lacp_status == 'enabled': - lacp_enabled = True - if uplink_pg_config.defaultPortConfig.lacpPolicy.enable.value != lacp_enabled: - changed_lacp = True - changed_list.append("lacp status") - if uplink_pg_config.defaultPortConfig.lacpPolicy.enable.value: - results['lacp_status_previous'] = 'enabled' - else: - results['lacp_status_previous'] = 'disabled' - lacp_spec.enable = vim.BoolPolicy() - lacp_spec.enable.inherited = False - lacp_spec.enable.value = lacp_enabled - if lacp_enabled and uplink_pg_config.defaultPortConfig.lacpPolicy.mode.value != self.lacp_mode: - results['lacp_mode'] = self.lacp_mode - changed_lacp = True - changed_list.append("lacp mode") - results['lacp_mode_previous'] = uplink_pg_config.defaultPortConfig.lacpPolicy.mode.value - lacp_spec.mode = vim.StringPolicy() - lacp_spec.mode.inherited = False - lacp_spec.mode.value = self.lacp_mode - if changed_lacp: - changed = True - uplink_pg_spec.defaultPortConfig.lacpPolicy = lacp_spec - - # Check NetFlow - results['netflow_enabled'] = self.uplink_pg_netflow_enabled - netflow_enabled_spec = vim.BoolPolicy() - netflow_enabled_spec.inherited = False - netflow_enabled_spec.value = self.uplink_pg_netflow_enabled - if uplink_pg_config.defaultPortConfig.ipfixEnabled.value != self.uplink_pg_netflow_enabled: - changed = True - results['netflow_enabled_previous'] = uplink_pg_config.defaultPortConfig.ipfixEnabled.value - changed_list.append("netflow") - uplink_pg_spec.defaultPortConfig.ipfixEnabled = netflow_enabled_spec - - # TODO: Check Traffic filtering and marking - - # Check Block all ports - results['block_all_ports'] = self.uplink_pg_block_all_ports - block_all_ports_spec = vim.BoolPolicy() - block_all_ports_spec.inherited = False - block_all_ports_spec.value = self.uplink_pg_block_all_ports - if uplink_pg_config.defaultPortConfig.blocked.value != self.uplink_pg_block_all_ports: - changed = True - changed_list.append("block all ports") - results['block_all_ports_previous'] = uplink_pg_config.defaultPortConfig.blocked.value - uplink_pg_spec.defaultPortConfig.blocked = block_all_ports_spec - - if changed: - if self.module.check_mode: - changed_suffix = ' would be changed' - else: - changed_suffix = ' changed' - if len(changed_list) > 2: - message = ', '.join(changed_list[:-1]) + ', and ' + str(changed_list[-1]) - elif len(changed_list) == 2: - message = ' and '.join(changed_list) - elif len(changed_list) == 1: - message = changed_list[0] - message += changed_suffix - if not self.module.check_mode: - try: - task = self.dvs.config.uplinkPortgroup[0].ReconfigureDVPortgroup_Task(uplink_pg_spec) - wait_for_task(task) - except TaskError as invalid_argument: - self.module.fail_json(msg="Failed to update uplink portgroup : %s" % to_native(invalid_argument)) - else: - message = "Uplink portgroup already configured properly" - results['changed'] = changed - results['result'] = message - - self.module.exit_json(**results) - - @staticmethod - def get_vlan_ids_from_range(vlan_id_range): - """Get start and end VLAN ID from VLAN ID range""" - try: - vlan_id_start, vlan_id_end = vlan_id_range.split('-') - except (AttributeError, TypeError): - vlan_id_start = vlan_id_end = vlan_id_range - except ValueError: - vlan_id_start = vlan_id_end = vlan_id_range.strip() - return vlan_id_start, vlan_id_end - - @staticmethod - def get_lacp_support_mode(mode): - """Get LACP support mode""" - return_mode = None - if mode == 'basic': - return_mode = 'singleLag' - elif mode == 'enhanced': - return_mode = 'multipleLag' - elif mode == 'singleLag': - return_mode = 'basic' - elif mode == 'multipleLag': - return_mode = 'enhanced' - return return_mode - - -def main(): - """Main""" - argument_spec = vmware_argument_spec() - argument_spec.update( - dict( - switch=dict(required=True, aliases=['dvswitch']), - name=dict(type='str'), - description=dict(type='str'), - advanced=dict( - type='dict', - options=dict( - port_config_reset_at_disconnect=dict(type='bool', default=True), - block_override=dict(type='bool', default=True), - vendor_config_override=dict(type='bool', default=False), - vlan_override=dict(type='bool', default=False), - netflow_override=dict(type='bool', default=False), - traffic_filter_override=dict(type='bool', default=False), - ), - default=dict( - port_config_reset_at_disconnect=True, - block_override=True, - vendor_config_override=False, - vlan_override=False, - netflow_override=False, - traffic_filter_override=False, - ), - aliases=['port_policy'], - ), - lacp=dict( - type='dict', - options=dict( - status=dict(type='str', choices=['enabled', 'disabled'], default=['disabled']), - mode=dict(type='str', choices=['active', 'passive'], default=['passive']), - ), - default=dict( - status='disabled', - mode='passive', - ), - ), - vlan_trunk_range=dict(type='list', default=['0-4094']), - netflow_enabled=dict(type='bool', default=False), - block_all_ports=dict(type='bool', default=False), - ) - ) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - vmware_dvswitch_uplink_pg = VMwareDvSwitchUplinkPortgroup(module) - vmware_dvswitch_uplink_pg.ensure() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_evc_mode.py b/lib/ansible/modules/cloud/vmware/vmware_evc_mode.py deleted file mode 100644 index 935d356e3a..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_evc_mode.py +++ /dev/null @@ -1,232 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2019, Michael Tipton <mike () ibeta.org> -# 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 = ''' ---- -module: vmware_evc_mode -short_description: Enable/Disable EVC mode on vCenter -description: - - This module can be used to enable/disable EVC mode on vCenter. -version_added: 2.9 -author: - - Michael Tipton (@castawayegr) -notes: - - Tested on vSphere 6.7 -requirements: - - "python >= 2.6" - - PyVmomi -options: - datacenter_name: - description: - - The name of the datacenter the cluster belongs to that you want to enable or disable EVC mode on. - required: True - type: str - cluster_name: - description: - - The name of the cluster to enable or disable EVC mode on. - required: True - type: str - evc_mode: - description: - - Required for C(state=present). - - The EVC mode to enable or disable on the cluster. (intel-broadwell, intel-nehalem, intel-merom, etc.). - required: True - type: str - state: - description: - - Add or remove EVC mode. - choices: [absent, present] - default: present - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' - - name: Enable EVC Mode - vmware_evc_mode: - hostname: "{{ groups['vcsa'][0] }}" - username: "{{ vcenter_username }}" - password: "{{ site_password }}" - datacenter_name: "{{ datacenter_name }}" - cluster_name: "{{ cluster_name }}" - evc_mode: "intel-broadwell" - state: present - delegate_to: localhost - register: enable_evc - - - name: Disable EVC Mode - vmware_evc_mode: - hostname: "{{ groups['vcsa'][0] }}" - username: "{{ vcenter_username }}" - password: "{{ site_password }}" - datacenter_name: "{{ datacenter_name }}" - cluster_name: "{{ cluster_name }}" - state: absent - delegate_to: localhost - register: disable_evc -''' - -RETURN = """ -result: - description: information about performed operation - returned: always - type: str - sample: "EVC Mode for 'intel-broadwell' has been enabled." -""" - -try: - from pyVmomi import vim -except ImportError: - pass - - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils._text import to_native -from ansible.module_utils.vmware import (PyVmomi, find_datacenter_by_name, find_cluster_by_name, - vmware_argument_spec, wait_for_task, TaskError) - - -class VMwareEVC(PyVmomi): - def __init__(self, module): - super(VMwareEVC, self).__init__(module) - self.cluster_name = module.params['cluster_name'] - self.evc_mode = module.params['evc_mode'] - self.datacenter_name = module.params['datacenter_name'] - self.desired_state = module.params['state'] - self.datacenter = None - self.cluster = None - - def process_state(self): - """ - Manage internal states of evc - """ - evc_states = { - 'absent': { - 'present': self.state_disable_evc, - 'absent': self.state_exit_unchanged, - }, - 'present': { - 'present': self.state_update_evc, - 'absent': self.state_enable_evc, - } - } - current_state = self.check_evc_configuration() - # Based on the desired_state and the current_state call - # the appropriate method from the dictionary - evc_states[self.desired_state][current_state]() - - def check_evc_configuration(self): - """ - Check evc configuration - Returns: 'Present' if evc enabled, else 'absent' - """ - try: - self.datacenter = find_datacenter_by_name(self.content, self.datacenter_name) - if self.datacenter is None: - self.module.fail_json(msg="Datacenter '%s' does not exist." % self.datacenter_name) - self.cluster = self.find_cluster_by_name(cluster_name=self.cluster_name, datacenter_name=self.datacenter) - - if self.cluster is None: - self.module.fail_json(msg="Cluster '%s' does not exist." % self.cluster_name) - self.evcm = self.cluster.EvcManager() - - if not self.evcm: - self.module.fail_json(msg="Unable to get EVC manager for cluster '%s'." % self.cluster_name) - self.evc_state = self.evcm.evcState - self.current_evc_mode = self.evc_state.currentEVCModeKey - - if not self.current_evc_mode: - return 'absent' - - return 'present' - except Exception as generic_exc: - self.module.fail_json(msg="Failed to check configuration" - " due to generic exception %s" % to_native(generic_exc)) - - def state_exit_unchanged(self): - """ - Exit without any change - """ - self.module.exit_json(changed=False, msg="EVC Mode is already disabled on cluster '%s'." % self.cluster_name) - - def state_update_evc(self): - """ - Update EVC Mode - """ - changed, result = False, None - try: - if not self.module.check_mode and self.current_evc_mode != self.evc_mode: - evc_task = self.evcm.ConfigureEvcMode_Task(self.evc_mode) - changed, result = wait_for_task(evc_task) - if self.module.check_mode and self.current_evc_mode != self.evc_mode: - changed, result = True, None - if self.current_evc_mode == self.evc_mode: - self.module.exit_json(changed=changed, msg="EVC Mode is already set to '%(evc_mode)s' on '%(cluster_name)s'." % self.params) - self.module.exit_json(changed=changed, msg="EVC Mode has been updated to '%(evc_mode)s' on '%(cluster_name)s'." % self.params) - except TaskError as invalid_argument: - self.module.fail_json(msg="Failed to update EVC mode: %s" % to_native(invalid_argument)) - - def state_enable_evc(self): - """ - Enable EVC Mode - """ - changed, result = False, None - try: - if not self.module.check_mode: - evc_task = self.evcm.ConfigureEvcMode_Task(self.evc_mode) - changed, result = wait_for_task(evc_task) - if self.module.check_mode: - changed, result = True, None - self.module.exit_json(changed=changed, msg="EVC Mode for '%(evc_mode)s' has been enabled on '%(cluster_name)s'." % self.params) - except TaskError as invalid_argument: - self.module.fail_json(msg="Failed to enable EVC mode: %s" % to_native(invalid_argument)) - - def state_disable_evc(self): - """ - Disable EVC Mode - """ - changed, result = False, None - try: - if not self.module.check_mode: - evc_task = self.evcm.DisableEvcMode_Task() - changed, result = wait_for_task(evc_task) - if self.module.check_mode: - changed, result = True, None - self.module.exit_json(changed=changed, msg="EVC Mode has been disabled on cluster '%s'." % self.cluster_name) - except TaskError as invalid_argument: - self.module.fail_json(msg="Failed to disable EVC mode: %s" % to_native(invalid_argument)) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update(dict( - cluster_name=dict(type='str', required=True), - datacenter_name=dict(type='str', required=True), - evc_mode=dict(type='str', required=True), - state=dict(type='str', default='present', choices=['absent', 'present']), - )) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - required_if=[ - ['state', 'present', ['cluster_name', 'datacenter_name', 'evc_mode']] - ] - ) - - vmware_evc = VMwareEVC(module) - vmware_evc.process_state() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_export_ovf.py b/lib/ansible/modules/cloud/vmware/vmware_export_ovf.py deleted file mode 100644 index 1dc177bd6a..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_export_ovf.py +++ /dev/null @@ -1,357 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Diane Wang <dianew@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_export_ovf -short_description: Exports a VMware virtual machine to an OVF file, device files and a manifest file -description: > - This module can be used to export a VMware virtual machine to OVF template from vCenter server or ESXi host. -version_added: '2.8' -author: -- Diane Wang (@Tomorrow9) <dianew@vmware.com> -requirements: -- python >= 2.6 -- PyVmomi -notes: [] -options: - name: - description: - - Name of the virtual machine to export. - - This is a required parameter, if parameter C(uuid) or C(moid) is not supplied. - type: str - uuid: - description: - - Uuid of the virtual machine to export. - - This is a required parameter, if parameter C(name) or C(moid) is not supplied. - type: str - moid: - description: - - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. - - This is required if C(name) or C(uuid) is not supplied. - version_added: '2.9' - type: str - datacenter: - default: ha-datacenter - description: - - Datacenter name of the virtual machine to export. - - This parameter is case sensitive. - type: str - folder: - description: - - Destination folder, absolute path to find the specified guest. - - The folder should include the datacenter. ESX's datacenter is ha-datacenter. - - This parameter is case sensitive. - - 'If multiple machines are found with same name, this parameter is used to identify - uniqueness of the virtual machine. version_added 2.5' - - 'Examples:' - - ' folder: /ha-datacenter/vm' - - ' folder: ha-datacenter/vm' - - ' folder: /datacenter1/vm' - - ' folder: datacenter1/vm' - - ' folder: /datacenter1/vm/folder1' - - ' folder: datacenter1/vm/folder1' - - ' folder: /folder1/datacenter1/vm' - - ' folder: folder1/datacenter1/vm' - - ' folder: /folder1/datacenter1/vm/folder2' - type: str - export_dir: - description: - - Absolute path to place the exported files on the server running this task, must have write permission. - - If folder not exist will create it, also create a folder under this path named with VM name. - required: yes - type: path - export_with_images: - default: false - description: - - Export an ISO image of the media mounted on the CD/DVD Drive within the virtual machine. - type: bool - download_timeout: - description: - - The user defined timeout in second of exporting file. - - If the vmdk file is too large, you can increase the value. - default: 30 - type: int - version_added: '2.9' -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- vmware_export_ovf: - validate_certs: false - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - name: '{{ vm_name }}' - export_with_images: true - export_dir: /path/to/ovf_template/ - delegate_to: localhost -''' - -RETURN = r''' -instance: - description: list of the exported files, if exported from vCenter server, device file is not named with vm name - returned: always - type: dict - sample: None -''' - -import os -import hashlib -from time import sleep -from threading import Thread -from ansible.module_utils.urls import open_url -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils._text import to_text, to_bytes -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi -try: - from pyVmomi import vim - from pyVim import connect -except ImportError: - pass - - -class LeaseProgressUpdater(Thread): - def __init__(self, http_nfc_lease, update_interval): - Thread.__init__(self) - self._running = True - self.httpNfcLease = http_nfc_lease - self.updateInterval = update_interval - self.progressPercent = 0 - - def set_progress_percent(self, progress_percent): - self.progressPercent = progress_percent - - def stop(self): - self._running = False - - def run(self): - while self._running: - try: - if self.httpNfcLease.state == vim.HttpNfcLease.State.done: - return - self.httpNfcLease.HttpNfcLeaseProgress(self.progressPercent) - sleep_sec = 0 - while True: - if self.httpNfcLease.state == vim.HttpNfcLease.State.done or self.httpNfcLease.state == vim.HttpNfcLease.State.error: - return - sleep_sec += 1 - sleep(1) - if sleep_sec == self.updateInterval: - break - except Exception: - return - - -class VMwareExportVmOvf(PyVmomi): - def __init__(self, module): - super(VMwareExportVmOvf, self).__init__(module) - self.mf_file = '' - self.ovf_dir = '' - # set read device content chunk size to 2 MB - self.chunk_size = 2 * 2 ** 20 - # set lease progress update interval to 15 seconds - self.lease_interval = 15 - self.facts = {'device_files': []} - self.download_timeout = None - - def create_export_dir(self, vm_obj): - self.ovf_dir = os.path.join(self.params['export_dir'], vm_obj.name) - if not os.path.exists(self.ovf_dir): - try: - os.makedirs(self.ovf_dir) - except OSError as err: - self.module.fail_json(msg='Exception caught when create folder %s, with error %s' - % (self.ovf_dir, to_text(err))) - self.mf_file = os.path.join(self.ovf_dir, vm_obj.name + '.mf') - - def download_device_files(self, headers, temp_target_disk, device_url, lease_updater, total_bytes_written, - total_bytes_to_write): - mf_content = 'SHA256(' + os.path.basename(temp_target_disk) + ')= ' - sha256_hash = hashlib.sha256() - response = None - - with open(self.mf_file, 'a') as mf_handle: - with open(temp_target_disk, 'wb') as handle: - try: - response = open_url(device_url, headers=headers, validate_certs=False, timeout=self.download_timeout) - except Exception as err: - lease_updater.httpNfcLease.HttpNfcLeaseAbort() - lease_updater.stop() - self.module.fail_json(msg='Exception caught when getting %s, %s' % (device_url, to_text(err))) - if not response: - lease_updater.httpNfcLease.HttpNfcLeaseAbort() - lease_updater.stop() - self.module.fail_json(msg='Getting %s failed' % device_url) - if response.getcode() >= 400: - lease_updater.httpNfcLease.HttpNfcLeaseAbort() - lease_updater.stop() - self.module.fail_json(msg='Getting %s return code %d' % (device_url, response.getcode())) - current_bytes_written = 0 - block = response.read(self.chunk_size) - while block: - handle.write(block) - sha256_hash.update(block) - handle.flush() - os.fsync(handle.fileno()) - current_bytes_written += len(block) - block = response.read(self.chunk_size) - written_percent = ((current_bytes_written + total_bytes_written) * 100) / total_bytes_to_write - lease_updater.progressPercent = int(written_percent) - mf_handle.write(mf_content + sha256_hash.hexdigest() + '\n') - self.facts['device_files'].append(temp_target_disk) - return current_bytes_written - - def export_to_ovf_files(self, vm_obj): - self.create_export_dir(vm_obj=vm_obj) - export_with_iso = False - if 'export_with_images' in self.params and self.params['export_with_images']: - export_with_iso = True - self.download_timeout = self.params['download_timeout'] - - ovf_files = [] - # get http nfc lease firstly - http_nfc_lease = vm_obj.ExportVm() - # create a thread to track file download progress - lease_updater = LeaseProgressUpdater(http_nfc_lease, self.lease_interval) - total_bytes_written = 0 - # total storage space occupied by the virtual machine across all datastores - total_bytes_to_write = vm_obj.summary.storage.unshared - # new deployed VM with no OS installed - if total_bytes_to_write == 0: - total_bytes_to_write = vm_obj.summary.storage.committed - if total_bytes_to_write == 0: - http_nfc_lease.HttpNfcLeaseAbort() - self.module.fail_json(msg='Total storage space occupied by the VM is 0.') - headers = {'Accept': 'application/x-vnd.vmware-streamVmdk'} - cookies = connect.GetStub().cookie - if cookies: - headers['Cookie'] = cookies - lease_updater.start() - try: - while True: - if http_nfc_lease.state == vim.HttpNfcLease.State.ready: - for deviceUrl in http_nfc_lease.info.deviceUrl: - file_download = False - if deviceUrl.targetId and deviceUrl.disk: - file_download = True - elif deviceUrl.url.split('/')[-1].split('.')[-1] == 'iso': - if export_with_iso: - file_download = True - elif deviceUrl.url.split('/')[-1].split('.')[-1] == 'nvram': - if self.host_version_at_least(version=(6, 7, 0), vm_obj=vm_obj): - file_download = True - else: - continue - device_file_name = deviceUrl.url.split('/')[-1] - # device file named disk-0.iso, disk-1.vmdk, disk-2.vmdk, replace 'disk' with vm name - if device_file_name.split('.')[0][0:5] == "disk-": - device_file_name = device_file_name.replace('disk', vm_obj.name) - temp_target_disk = os.path.join(self.ovf_dir, device_file_name) - device_url = deviceUrl.url - # if export from ESXi host, replace * with hostname in url - # e.g., https://*/ha-nfc/5289bf27-da99-7c0e-3978-8853555deb8c/disk-1.vmdk - if '*' in device_url: - device_url = device_url.replace('*', self.params['hostname']) - if file_download: - current_bytes_written = self.download_device_files(headers=headers, - temp_target_disk=temp_target_disk, - device_url=device_url, - lease_updater=lease_updater, - total_bytes_written=total_bytes_written, - total_bytes_to_write=total_bytes_to_write) - total_bytes_written += current_bytes_written - ovf_file = vim.OvfManager.OvfFile() - ovf_file.deviceId = deviceUrl.key - ovf_file.path = device_file_name - ovf_file.size = current_bytes_written - ovf_files.append(ovf_file) - break - elif http_nfc_lease.state == vim.HttpNfcLease.State.initializing: - sleep(2) - continue - elif http_nfc_lease.state == vim.HttpNfcLease.State.error: - lease_updater.stop() - self.module.fail_json(msg='Get HTTP NFC lease error %s.' % http_nfc_lease.state.error[0].fault) - - # generate ovf file - ovf_manager = self.content.ovfManager - ovf_descriptor_name = vm_obj.name - ovf_parameters = vim.OvfManager.CreateDescriptorParams() - ovf_parameters.name = ovf_descriptor_name - ovf_parameters.ovfFiles = ovf_files - vm_descriptor_result = ovf_manager.CreateDescriptor(obj=vm_obj, cdp=ovf_parameters) - if vm_descriptor_result.error: - http_nfc_lease.HttpNfcLeaseAbort() - lease_updater.stop() - self.module.fail_json(msg='Create VM descriptor file error %s.' % vm_descriptor_result.error) - else: - vm_descriptor = vm_descriptor_result.ovfDescriptor - ovf_descriptor_path = os.path.join(self.ovf_dir, ovf_descriptor_name + '.ovf') - sha256_hash = hashlib.sha256() - with open(self.mf_file, 'a') as mf_handle: - with open(ovf_descriptor_path, 'w') as handle: - handle.write(vm_descriptor) - sha256_hash.update(to_bytes(vm_descriptor)) - mf_handle.write('SHA256(' + os.path.basename(ovf_descriptor_path) + ')= ' + sha256_hash.hexdigest() + '\n') - http_nfc_lease.HttpNfcLeaseProgress(100) - # self.facts = http_nfc_lease.HttpNfcLeaseGetManifest() - http_nfc_lease.HttpNfcLeaseComplete() - lease_updater.stop() - self.facts.update({'manifest': self.mf_file, 'ovf_file': ovf_descriptor_path}) - except Exception as err: - kwargs = { - 'changed': False, - 'failed': True, - 'msg': "get exception: %s" % to_text(err), - } - http_nfc_lease.HttpNfcLeaseAbort() - lease_updater.stop() - return kwargs - return {'changed': True, 'failed': False, 'instance': self.facts} - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - name=dict(type='str'), - uuid=dict(type='str'), - moid=dict(type='str'), - folder=dict(type='str'), - datacenter=dict(type='str', default='ha-datacenter'), - export_dir=dict(type='path', required=True), - export_with_images=dict(type='bool', default=False), - download_timeout=dict(type='int', default=30), - ) - - module = AnsibleModule(argument_spec=argument_spec, - supports_check_mode=True, - required_one_of=[ - ['name', 'uuid', 'moid'], - ], - ) - pyv = VMwareExportVmOvf(module) - vm = pyv.get_vm() - if vm: - vm_facts = pyv.gather_facts(vm) - vm_power_state = vm_facts['hw_power_status'].lower() - if vm_power_state != 'poweredoff': - module.fail_json(msg='VM state should be poweredoff to export') - results = pyv.export_to_ovf_files(vm_obj=vm) - module.exit_json(**results) - else: - module.fail_json(msg='The specified virtual machine not found') - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_folder_info.py b/lib/ansible/modules/cloud/vmware/vmware_folder_info.py deleted file mode 100644 index 14f2ba3fd3..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_folder_info.py +++ /dev/null @@ -1,164 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright: (c) 2019, David Hewitt <davidmhewitt@gmail.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_folder_info -short_description: Provides information about folders in a datacenter -description: -- The module can be used to gather a hierarchical view of the folders that exist within a datacenter -version_added: 2.9 -author: -- David Hewitt (@davidmhewitt) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - datacenter: - description: - - Name of the datacenter. - required: true - type: str - aliases: ['datacenter_name'] -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Provide information about vCenter folders - vmware_folder_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: datacenter_name - delegate_to: localhost - register: vcenter_folder_info -''' - -RETURN = r''' -folder_info: - description: - - dict about folders - returned: success - type: str - sample: - { - "datastoreFolders": { - "path": "/DC01/datastore", - "subfolders": { - "Local Datastores": { - "path": "/DC01/datastore/Local Datastores", - "subfolders": {} - } - } - }, - "hostFolders": { - "path": "/DC01/host", - "subfolders": {} - }, - "networkFolders": { - "path": "/DC01/network", - "subfolders": {} - }, - "vmFolders": { - "path": "/DC01/vm", - "subfolders": { - "Core Infrastructure Servers": { - "path": "/DC01/vm/Core Infrastructure Servers", - "subfolders": { - "Staging Network Services": { - "path": "/DC01/vm/Core Infrastructure Servers/Staging Network Services", - "subfolders": {} - }, - "VMware": { - "path": "/DC01/vm/Core Infrastructure Servers/VMware", - "subfolders": {} - } - } - } - } - } - } -''' - -try: - from pyVmomi import vim -except ImportError as import_err: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class VmwareFolderInfoManager(PyVmomi): - def __init__(self, module): - super(VmwareFolderInfoManager, self).__init__(module) - self.dc_name = self.params['datacenter'] - - def gather_folder_info(self): - datacenter = self.find_datacenter_by_name(self.dc_name) - if datacenter is None: - self.module.fail_json(msg="Failed to find the datacenter %s" % self.dc_name) - - folder_trees = {} - folder_trees['vmFolders'] = self.build_folder_tree(datacenter.vmFolder, "/%s/vm" % self.dc_name) - folder_trees['hostFolders'] = self.build_folder_tree(datacenter.hostFolder, "/%s/host" % self.dc_name) - folder_trees['networkFolders'] = self.build_folder_tree(datacenter.networkFolder, "/%s/network" % self.dc_name) - folder_trees['datastoreFolders'] = self.build_folder_tree(datacenter.datastoreFolder, "/%s/datastore" % self.dc_name) - - self.module.exit_json( - changed=False, - folder_info=folder_trees - ) - - def build_folder_tree(self, folder, path): - tree = { - 'path': path, - 'subfolders': {} - } - - children = None - if hasattr(folder, 'childEntity'): - children = folder.childEntity - - if children: - for child in children: - if child == folder: - continue - if isinstance(child, vim.Folder): - ctree = self.build_folder_tree(child, "%s/%s" % (path, child.name)) - tree['subfolders'][child.name] = dict.copy(ctree) - return tree - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - datacenter=dict(type='str', required=True, aliases=['datacenter_name']) - ) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - vmware_folder_info_mgr = VmwareFolderInfoManager(module) - vmware_folder_info_mgr.gather_folder_info() - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest.py b/lib/ansible/modules/cloud/vmware/vmware_guest.py deleted file mode 100644 index df9f695be5..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_guest.py +++ /dev/null @@ -1,2914 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# This module is also sponsored by E.T.A.I. (www.etai.fr) -# 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_guest -short_description: Manages virtual machines in vCenter -description: > - This module can be used to create new virtual machines from templates or other virtual machines, - manage power state of virtual machine such as power on, power off, suspend, shutdown, reboot, restart etc., - modify various virtual machine components like network, disk, customization etc., - rename a virtual machine and remove a virtual machine with associated components. -version_added: '2.2' -author: -- Loic Blot (@nerzhul) <loic.blot@unix-experience.fr> -- Philippe Dellaert (@pdellaert) <philippe@dellaert.org> -- Abhijeet Kasurde (@Akasurde) <akasurde@redhat.com> -requirements: -- python >= 2.6 -- PyVmomi -notes: - - Please make sure that the user used for M(vmware_guest) has the correct level of privileges. - - For example, following is the list of minimum privileges required by users to create virtual machines. - - " DataStore > Allocate Space" - - " Virtual Machine > Configuration > Add New Disk" - - " Virtual Machine > Configuration > Add or Remove Device" - - " Virtual Machine > Inventory > Create New" - - " Network > Assign Network" - - " Resource > Assign Virtual Machine to Resource Pool" - - "Module may require additional privileges as well, which may be required for gathering facts - e.g. ESXi configurations." - - Tested on vSphere 5.5, 6.0, 6.5 and 6.7. - - Use SCSI disks instead of IDE when you want to expand online disks by specifying a SCSI controller. - - Uses SysPrep for Windows VM (depends on 'guest_id' parameter match 'win') with PyVmomi. - - In order to change the VM's parameters (e.g. number of CPUs), the VM must be powered off unless the hot-add - support is enabled and the C(state=present) must be used to apply the changes. - - "For additional information please visit Ansible VMware community wiki - U(https://github.com/ansible/community/wiki/VMware)." -options: - state: - description: - - Specify the state the virtual machine should be in. - - 'If C(state) is set to C(present) and virtual machine exists, ensure the virtual machine - configurations conforms to task arguments.' - - 'If C(state) is set to C(absent) and virtual machine exists, then the specified virtual machine - is removed with its associated components.' - - 'If C(state) is set to one of the following C(poweredon), C(poweredoff), C(present), C(restarted), C(suspended) - and virtual machine does not exists, then virtual machine is deployed with given parameters.' - - 'If C(state) is set to C(poweredon) and virtual machine exists with powerstate other than powered on, - then the specified virtual machine is powered on.' - - 'If C(state) is set to C(poweredoff) and virtual machine exists with powerstate other than powered off, - then the specified virtual machine is powered off.' - - 'If C(state) is set to C(restarted) and virtual machine exists, then the virtual machine is restarted.' - - 'If C(state) is set to C(suspended) and virtual machine exists, then the virtual machine is set to suspended mode.' - - 'If C(state) is set to C(shutdownguest) and virtual machine exists, then the virtual machine is shutdown.' - - 'If C(state) is set to C(rebootguest) and virtual machine exists, then the virtual machine is rebooted.' - default: present - choices: [ present, absent, poweredon, poweredoff, restarted, suspended, shutdownguest, rebootguest ] - name: - description: - - Name of the virtual machine to work with. - - Virtual machine names in vCenter are not necessarily unique, which may be problematic, see C(name_match). - - 'If multiple virtual machines with same name exists, then C(folder) is required parameter to - identify uniqueness of the virtual machine.' - - This parameter is required, if C(state) is set to C(poweredon), C(poweredoff), C(present), C(restarted), C(suspended) - and virtual machine does not exists. - - This parameter is case sensitive. - required: yes - name_match: - description: - - If multiple virtual machines matching the name, use the first or last found. - default: 'first' - choices: [ first, last ] - uuid: - description: - - UUID of the virtual machine to manage if known, this is VMware's unique identifier. - - This is required if C(name) is not supplied. - - If virtual machine does not exists, then this parameter is ignored. - - Please note that a supplied UUID will be ignored on virtual machine creation, as VMware creates the UUID internally. - use_instance_uuid: - description: - - Whether to use the VMware instance UUID rather than the BIOS UUID. - default: no - type: bool - version_added: '2.8' - template: - description: - - Template or existing virtual machine used to create new virtual machine. - - If this value is not set, virtual machine is created without using a template. - - If the virtual machine already exists, this parameter will be ignored. - - This parameter is case sensitive. - - You can also specify template or VM UUID for identifying source. version_added 2.8. Use C(hw_product_uuid) from M(vmware_guest_facts) as UUID value. - - From version 2.8 onwards, absolute path to virtual machine or template can be used. - aliases: [ 'template_src' ] - is_template: - description: - - Flag the instance as a template. - - This will mark the given virtual machine as template. - default: 'no' - type: bool - version_added: '2.3' - folder: - description: - - Destination folder, absolute path to find an existing guest or create the new guest. - - The folder should include the datacenter. ESX's datacenter is ha-datacenter. - - This parameter is case sensitive. - - This parameter is required, while deploying new virtual machine. version_added 2.5. - - 'If multiple machines are found with same name, this parameter is used to identify - uniqueness of the virtual machine. version_added 2.5' - - 'Examples:' - - ' folder: /ha-datacenter/vm' - - ' folder: ha-datacenter/vm' - - ' folder: /datacenter1/vm' - - ' folder: datacenter1/vm' - - ' folder: /datacenter1/vm/folder1' - - ' folder: datacenter1/vm/folder1' - - ' folder: /folder1/datacenter1/vm' - - ' folder: folder1/datacenter1/vm' - - ' folder: /folder1/datacenter1/vm/folder2' - hardware: - description: - - Manage virtual machine's hardware attributes. - - All parameters case sensitive. - - 'Valid attributes are:' - - ' - C(hotadd_cpu) (boolean): Allow virtual CPUs to be added while the virtual machine is running.' - - ' - C(hotremove_cpu) (boolean): Allow virtual CPUs to be removed while the virtual machine is running. - version_added: 2.5' - - ' - C(hotadd_memory) (boolean): Allow memory to be added while the virtual machine is running.' - - ' - C(memory_mb) (integer): Amount of memory in MB.' - - ' - C(nested_virt) (bool): Enable nested virtualization. version_added: 2.5' - - ' - C(num_cpus) (integer): Number of CPUs.' - - ' - C(num_cpu_cores_per_socket) (integer): Number of Cores Per Socket.' - - " C(num_cpus) must be a multiple of C(num_cpu_cores_per_socket). - For example to create a VM with 2 sockets of 4 cores, specify C(num_cpus): 8 and C(num_cpu_cores_per_socket): 4" - - ' - C(scsi) (string): Valid values are C(buslogic), C(lsilogic), C(lsilogicsas) and C(paravirtual) (default).' - - " - C(memory_reservation_lock) (boolean): If set true, memory resource reservation for the virtual machine - will always be equal to the virtual machine's memory size. version_added: 2.5" - - ' - C(max_connections) (integer): Maximum number of active remote display connections for the virtual machines. - version_added: 2.5.' - - ' - C(mem_limit) (integer): The memory utilization of a virtual machine will not exceed this limit. Unit is MB. - version_added: 2.5' - - ' - C(mem_reservation) (integer): The amount of memory resource that is guaranteed available to the virtual - machine. Unit is MB. C(memory_reservation) is alias to this. version_added: 2.5' - - ' - C(cpu_limit) (integer): The CPU utilization of a virtual machine will not exceed this limit. Unit is MHz. - version_added: 2.5' - - ' - C(cpu_reservation) (integer): The amount of CPU resource that is guaranteed available to the virtual machine. - Unit is MHz. version_added: 2.5' - - ' - C(version) (integer): The Virtual machine hardware versions. Default is 10 (ESXi 5.5 and onwards). - If value specified as C(latest), version is set to the most current virtual hardware supported on the host. - C(latest) is added in version 2.10. - Please check VMware documentation for correct virtual machine hardware version. - Incorrect hardware version may lead to failure in deployment. If hardware version is already equal to the given - version then no action is taken. version_added: 2.6' - - ' - C(boot_firmware) (string): Choose which firmware should be used to boot the virtual machine. - Allowed values are "bios" and "efi". version_added: 2.7' - - ' - C(virt_based_security) (bool): Enable Virtualization Based Security feature for Windows 10. - (Support from Virtual machine hardware version 14, Guest OS Windows 10 64 bit, Windows Server 2016)' - - guest_id: - description: - - Set the guest ID. - - This parameter is case sensitive. - - 'Examples:' - - " virtual machine with RHEL7 64 bit, will be 'rhel7_64Guest'" - - " virtual machine with CentOS 64 bit, will be 'centos64Guest'" - - " virtual machine with Ubuntu 64 bit, will be 'ubuntu64Guest'" - - This field is required when creating a virtual machine, not required when creating from the template. - - > - Valid values are referenced here: - U(https://code.vmware.com/apis/358/doc/vim.vm.GuestOsDescriptor.GuestOsIdentifier.html) - version_added: '2.3' - disk: - description: - - A list of disks to add. - - This parameter is case sensitive. - - Shrinking disks is not supported. - - Removing existing disks of the virtual machine is not supported. - - 'Valid attributes are:' - - ' - C(size_[tb,gb,mb,kb]) (integer): Disk storage size in specified unit.' - - ' - C(type) (string): Valid values are:' - - ' - C(thin) thin disk' - - ' - C(eagerzeroedthick) eagerzeroedthick disk, added in version 2.5' - - ' Default: C(None) thick disk, no eagerzero.' - - ' - C(datastore) (string): The name of datastore which will be used for the disk. If C(autoselect_datastore) is set to True, - then will select the less used datastore whose name contains this "disk.datastore" string.' - - ' - C(filename) (string): Existing disk image to be used. Filename must already exist on the datastore.' - - ' Specify filename string in C([datastore_name] path/to/file.vmdk) format. Added in version 2.8.' - - ' - C(autoselect_datastore) (bool): select the less used datastore. "disk.datastore" and "disk.autoselect_datastore" - will not be used if C(datastore) is specified outside this C(disk) configuration.' - - ' - C(disk_mode) (string): Type of disk mode. Added in version 2.6' - - ' - Available options are :' - - ' - C(persistent): Changes are immediately and permanently written to the virtual disk. This is default.' - - ' - C(independent_persistent): Same as persistent, but not affected by snapshots.' - - ' - C(independent_nonpersistent): Changes to virtual disk are made to a redo log and discarded at power off, but not affected by snapshots.' - cdrom: - description: - - A CD-ROM configuration for the virtual machine. - - Or a list of CD-ROMs configuration for the virtual machine. Added in version 2.9. - - 'Parameters C(controller_type), C(controller_number), C(unit_number), C(state) are added for a list of CD-ROMs - configuration support.' - - 'Valid attributes are:' - - ' - C(type) (string): The type of CD-ROM, valid options are C(none), C(client) or C(iso). With C(none) the CD-ROM - will be disconnected but present.' - - ' - C(iso_path) (string): The datastore path to the ISO file to use, in the form of C([datastore1] path/to/file.iso). - Required if type is set C(iso).' - - ' - C(controller_type) (string): Default value is C(ide). Only C(ide) controller type for CD-ROM is supported for - now, will add SATA controller type in the future.' - - ' - C(controller_number) (int): For C(ide) controller, valid value is 0 or 1.' - - ' - C(unit_number) (int): For CD-ROM device attach to C(ide) controller, valid value is 0 or 1. - C(controller_number) and C(unit_number) are mandatory attributes.' - - ' - C(state) (string): Valid value is C(present) or C(absent). Default is C(present). If set to C(absent), then - the specified CD-ROM will be removed. For C(ide) controller, hot-add or hot-remove CD-ROM is not supported.' - version_added: '2.5' - resource_pool: - description: - - Use the given resource pool for virtual machine operation. - - This parameter is case sensitive. - - Resource pool should be child of the selected host parent. - version_added: '2.3' - wait_for_ip_address: - description: - - Wait until vCenter detects an IP address for the virtual machine. - - This requires vmware-tools (vmtoolsd) to properly work after creation. - - "vmware-tools needs to be installed on the given virtual machine in order to work with this parameter." - default: 'no' - type: bool - wait_for_ip_address_timeout: - description: - - Define a timeout (in seconds) for the wait_for_ip_address parameter. - default: '300' - type: int - version_added: '2.10' - wait_for_customization_timeout: - description: - - Define a timeout (in seconds) for the wait_for_customization parameter. - - Be careful when setting this value since the time guest customization took may differ among guest OSes. - default: '3600' - type: int - version_added: '2.10' - wait_for_customization: - description: - - Wait until vCenter detects all guest customizations as successfully completed. - - When enabled, the VM will automatically be powered on. - - "If vCenter does not detect guest customization start or succeed, failed events after time - C(wait_for_customization_timeout) parameter specified, warning message will be printed and task result is fail." - default: 'no' - type: bool - version_added: '2.8' - state_change_timeout: - description: - - If the C(state) is set to C(shutdownguest), by default the module will return immediately after sending the shutdown signal. - - If this argument is set to a positive integer, the module will instead wait for the virtual machine to reach the poweredoff state. - - The value sets a timeout in seconds for the module to wait for the state change. - default: 0 - version_added: '2.6' - snapshot_src: - description: - - Name of the existing snapshot to use to create a clone of a virtual machine. - - This parameter is case sensitive. - - While creating linked clone using C(linked_clone) parameter, this parameter is required. - version_added: '2.4' - linked_clone: - description: - - Whether to create a linked clone from the snapshot specified. - - If specified, then C(snapshot_src) is required parameter. - default: 'no' - type: bool - version_added: '2.4' - force: - description: - - Ignore warnings and complete the actions. - - This parameter is useful while removing virtual machine which is powered on state. - - 'This module reflects the VMware vCenter API and UI workflow, as such, in some cases the `force` flag will - be mandatory to perform the action to ensure you are certain the action has to be taken, no matter what the consequence. - This is specifically the case for removing a powered on the virtual machine when C(state) is set to C(absent).' - default: 'no' - type: bool - delete_from_inventory: - description: - - Whether to delete Virtual machine from inventory or delete from disk. - default: False - type: bool - version_added: '2.10' - datacenter: - description: - - Destination datacenter for the deploy operation. - - This parameter is case sensitive. - default: ha-datacenter - cluster: - description: - - The cluster name where the virtual machine will run. - - This is a required parameter, if C(esxi_hostname) is not set. - - C(esxi_hostname) and C(cluster) are mutually exclusive parameters. - - This parameter is case sensitive. - version_added: '2.3' - esxi_hostname: - description: - - The ESXi hostname where the virtual machine will run. - - This is a required parameter, if C(cluster) is not set. - - C(esxi_hostname) and C(cluster) are mutually exclusive parameters. - - This parameter is case sensitive. - annotation: - description: - - A note or annotation to include in the virtual machine. - version_added: '2.3' - customvalues: - description: - - Define a list of custom values to set on virtual machine. - - A custom value object takes two fields C(key) and C(value). - - Incorrect key and values will be ignored. - version_added: '2.3' - networks: - description: - - A list of networks (in the order of the NICs). - - Removing NICs is not allowed, while reconfiguring the virtual machine. - - All parameters and VMware object names are case sensitive. - - 'One of the below parameters is required per entry:' - - ' - C(name) (string): Name of the portgroup or distributed virtual portgroup for this interface. - When specifying distributed virtual portgroup make sure given C(esxi_hostname) or C(cluster) is associated with it.' - - ' - C(vlan) (integer): VLAN number for this interface.' - - 'Optional parameters per entry (used for virtual hardware):' - - ' - C(device_type) (string): Virtual network device (one of C(e1000), C(e1000e), C(pcnet32), C(vmxnet2), C(vmxnet3) (default), C(sriov)).' - - ' - C(mac) (string): Customize MAC address.' - - ' - C(dvswitch_name) (string): Name of the distributed vSwitch. - This value is required if multiple distributed portgroups exists with the same name. version_added 2.7' - - ' - C(start_connected) (bool): Indicates that virtual network adapter starts with associated virtual machine powers on. version_added: 2.5' - - 'Optional parameters per entry (used for OS customization):' - - ' - C(type) (string): Type of IP assignment (either C(dhcp) or C(static)). C(dhcp) is default.' - - ' - C(ip) (string): Static IP address (implies C(type: static)).' - - ' - C(netmask) (string): Static netmask required for C(ip).' - - ' - C(gateway) (string): Static gateway.' - - ' - C(dns_servers) (string): DNS servers for this network interface (Windows).' - - ' - C(domain) (string): Domain name for this network interface (Windows).' - - ' - C(wake_on_lan) (bool): Indicates if wake-on-LAN is enabled on this virtual network adapter. version_added: 2.5' - - ' - C(allow_guest_control) (bool): Enables guest control over whether the connectable device is connected. version_added: 2.5' - version_added: '2.3' - customization: - description: - - Parameters for OS customization when cloning from the template or the virtual machine, or apply to the existing virtual machine directly. - - Not all operating systems are supported for customization with respective vCenter version, - please check VMware documentation for respective OS customization. - - For supported customization operating system matrix, (see U(http://partnerweb.vmware.com/programs/guestOS/guest-os-customization-matrix.pdf)) - - All parameters and VMware object names are case sensitive. - - Linux based OSes requires Perl package to be installed for OS customizations. - - 'Common parameters (Linux/Windows):' - - ' - C(existing_vm) (bool): If set to C(True), do OS customization on the specified virtual machine directly. - If set to C(False) or not specified, do OS customization when cloning from the template or the virtual machine. version_added: 2.8' - - ' - C(dns_servers) (list): List of DNS servers to configure.' - - ' - C(dns_suffix) (list): List of domain suffixes, also known as DNS search path (default: C(domain) parameter).' - - ' - C(domain) (string): DNS domain name to use.' - - ' - C(hostname) (string): Computer hostname (default: shorted C(name) parameter). Allowed characters are alphanumeric (uppercase and lowercase) - and minus, rest of the characters are dropped as per RFC 952.' - - 'Parameters related to Linux customization:' - - ' - C(timezone) (string): Timezone (See List of supported time zones for different vSphere versions in Linux/Unix - systems (2145518) U(https://kb.vmware.com/s/article/2145518)). version_added: 2.9' - - ' - C(hwclockUTC) (bool): Specifies whether the hardware clock is in UTC or local time. - True when the hardware clock is in UTC, False when the hardware clock is in local time. version_added: 2.9' - - 'Parameters related to Windows customization:' - - ' - C(autologon) (bool): Auto logon after virtual machine customization (default: False).' - - ' - C(autologoncount) (int): Number of autologon after reboot (default: 1).' - - ' - C(domainadmin) (string): User used to join in AD domain (mandatory with C(joindomain)).' - - ' - C(domainadminpassword) (string): Password used to join in AD domain (mandatory with C(joindomain)).' - - ' - C(fullname) (string): Server owner name (default: Administrator).' - - ' - C(joindomain) (string): AD domain to join (Not compatible with C(joinworkgroup)).' - - ' - C(joinworkgroup) (string): Workgroup to join (Not compatible with C(joindomain), default: WORKGROUP).' - - ' - C(orgname) (string): Organisation name (default: ACME).' - - ' - C(password) (string): Local administrator password.' - - ' - C(productid) (string): Product ID.' - - ' - C(runonce) (list): List of commands to run at first user logon.' - - ' - C(timezone) (int): Timezone (See U(https://msdn.microsoft.com/en-us/library/ms912391.aspx)).' - version_added: '2.3' - vapp_properties: - description: - - A list of vApp properties. - - 'For full list of attributes and types refer to:' - - 'U(https://vdc-download.vmware.com/vmwb-repository/dcr-public/6b586ed2-655c-49d9-9029-bc416323cb22/ - fa0b429a-a695-4c11-b7d2-2cbc284049dc/doc/vim.vApp.PropertyInfo.html)' - - 'Basic attributes are:' - - ' - C(id) (string): Property id - required.' - - ' - C(value) (string): Property value.' - - ' - C(type) (string): Value type, string type by default.' - - ' - C(operation): C(remove): This attribute is required only when removing properties.' - version_added: '2.6' - customization_spec: - description: - - Unique name identifying the requested customization specification. - - This parameter is case sensitive. - - If set, then overrides C(customization) parameter values. - version_added: '2.6' - datastore: - description: - - Specify datastore or datastore cluster to provision virtual machine. - - 'This parameter takes precedence over "disk.datastore" parameter.' - - 'This parameter can be used to override datastore or datastore cluster setting of the virtual machine when deployed - from the template.' - - Please see example for more usage. - version_added: '2.7' - convert: - description: - - Specify convert disk type while cloning template or virtual machine. - choices: [ thin, thick, eagerzeroedthick ] - version_added: '2.8' -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Create a virtual machine on given ESXi hostname - vmware_guest: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - folder: /DC1/vm/ - name: test_vm_0001 - state: poweredon - guest_id: centos64Guest - # This is hostname of particular ESXi server on which user wants VM to be deployed - esxi_hostname: "{{ esxi_hostname }}" - disk: - - size_gb: 10 - type: thin - datastore: datastore1 - hardware: - memory_mb: 512 - num_cpus: 4 - scsi: paravirtual - networks: - - name: VM Network - mac: aa:bb:dd:aa:00:14 - ip: 10.10.10.100 - netmask: 255.255.255.0 - device_type: vmxnet3 - wait_for_ip_address: yes - wait_for_ip_address_timeout: 600 - delegate_to: localhost - register: deploy_vm - -- name: Create a virtual machine from a template - vmware_guest: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - folder: /testvms - name: testvm_2 - state: poweredon - template: template_el7 - disk: - - size_gb: 10 - type: thin - datastore: g73_datastore - # Add another disk from an existing VMDK - - filename: "[datastore1] testvms/testvm_2_1/testvm_2_1.vmdk" - hardware: - memory_mb: 512 - num_cpus: 6 - num_cpu_cores_per_socket: 3 - scsi: paravirtual - memory_reservation_lock: True - mem_limit: 8096 - mem_reservation: 4096 - cpu_limit: 8096 - cpu_reservation: 4096 - max_connections: 5 - hotadd_cpu: True - hotremove_cpu: True - hotadd_memory: False - version: 12 # Hardware version of virtual machine - boot_firmware: "efi" - cdrom: - type: iso - iso_path: "[datastore1] livecd.iso" - networks: - - name: VM Network - mac: aa:bb:dd:aa:00:14 - wait_for_ip_address: yes - delegate_to: localhost - register: deploy - -- name: Clone a virtual machine from Windows template and customize - vmware_guest: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: datacenter1 - cluster: cluster - name: testvm-2 - template: template_windows - networks: - - name: VM Network - ip: 192.168.1.100 - netmask: 255.255.255.0 - gateway: 192.168.1.1 - mac: aa:bb:dd:aa:00:14 - domain: my_domain - dns_servers: - - 192.168.1.1 - - 192.168.1.2 - - vlan: 1234 - type: dhcp - customization: - autologon: yes - dns_servers: - - 192.168.1.1 - - 192.168.1.2 - domain: my_domain - password: new_vm_password - runonce: - - powershell.exe -ExecutionPolicy Unrestricted -File C:\Windows\Temp\ConfigureRemotingForAnsible.ps1 -ForceNewSSLCert -EnableCredSSP - delegate_to: localhost - -- name: Clone a virtual machine from Linux template and customize - vmware_guest: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ datacenter }}" - state: present - folder: /DC1/vm - template: "{{ template }}" - name: "{{ vm_name }}" - cluster: DC1_C1 - networks: - - name: VM Network - ip: 192.168.10.11 - netmask: 255.255.255.0 - wait_for_ip_address: True - customization: - domain: "{{ guest_domain }}" - dns_servers: - - 8.9.9.9 - - 7.8.8.9 - dns_suffix: - - example.com - - example2.com - delegate_to: localhost - -- name: Rename a virtual machine (requires the virtual machine's uuid) - vmware_guest: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - uuid: "{{ vm_uuid }}" - name: new_name - state: present - delegate_to: localhost - -- name: Remove a virtual machine by uuid - vmware_guest: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - uuid: "{{ vm_uuid }}" - state: absent - delegate_to: localhost - -- name: Remove a virtual machine from inventory - vmware_guest: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - name: vm_name - delete_from_inventory: True - state: absent - delegate_to: localhost - -- name: Manipulate vApp properties - vmware_guest: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - name: vm_name - state: present - vapp_properties: - - id: remoteIP - category: Backup - label: Backup server IP - type: string - value: 10.10.10.1 - - id: old_property - operation: remove - delegate_to: localhost - -- name: Set powerstate of a virtual machine to poweroff by using UUID - vmware_guest: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - uuid: "{{ vm_uuid }}" - state: poweredoff - delegate_to: localhost - -- name: Deploy a virtual machine in a datastore different from the datastore of the template - vmware_guest: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "{{ vm_name }}" - state: present - template: "{{ template_name }}" - # Here datastore can be different which holds template - datastore: "{{ virtual_machine_datastore }}" - hardware: - memory_mb: 512 - num_cpus: 2 - scsi: paravirtual - delegate_to: localhost - -- name: Create a diskless VM - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - state: poweredoff - cluster: "{{ ccr1 }}" - name: diskless_vm - folder: /Asia-Datacenter1/vm - guest_id: centos64Guest - datastore: "{{ ds1 }}" - hardware: - memory_mb: 1024 - num_cpus: 2 - num_cpu_cores_per_socket: 1 -''' - -RETURN = r''' -instance: - description: metadata about the new virtual machine - returned: always - type: dict - sample: None -''' - -import re -import time -import string - -HAS_PYVMOMI = False -try: - from pyVmomi import vim, vmodl, VmomiSupport - HAS_PYVMOMI = True -except ImportError: - pass - -from random import randint -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.common.network import is_mac -from ansible.module_utils._text import to_text, to_native -from ansible.module_utils.vmware import (find_obj, gather_vm_facts, get_all_objs, - compile_folder_path_for_object, serialize_spec, - vmware_argument_spec, set_vm_power_state, PyVmomi, - find_dvs_by_name, find_dvspg_by_name, wait_for_vm_ip, - wait_for_task, TaskError, quote_obj_name) - - -def list_or_dict(value): - if isinstance(value, list) or isinstance(value, dict): - return value - else: - raise ValueError("'%s' is not valid, valid type is 'list' or 'dict'." % value) - - -class PyVmomiDeviceHelper(object): - """ This class is a helper to create easily VMware Objects for PyVmomiHelper """ - - def __init__(self, module): - self.module = module - self.next_disk_unit_number = 0 - self.scsi_device_type = { - 'lsilogic': vim.vm.device.VirtualLsiLogicController, - 'paravirtual': vim.vm.device.ParaVirtualSCSIController, - 'buslogic': vim.vm.device.VirtualBusLogicController, - 'lsilogicsas': vim.vm.device.VirtualLsiLogicSASController, - } - - def create_scsi_controller(self, scsi_type): - scsi_ctl = vim.vm.device.VirtualDeviceSpec() - scsi_ctl.operation = vim.vm.device.VirtualDeviceSpec.Operation.add - scsi_device = self.scsi_device_type.get(scsi_type, vim.vm.device.ParaVirtualSCSIController) - scsi_ctl.device = scsi_device() - scsi_ctl.device.busNumber = 0 - # While creating a new SCSI controller, temporary key value - # should be unique negative integers - scsi_ctl.device.key = -randint(1000, 9999) - scsi_ctl.device.hotAddRemove = True - scsi_ctl.device.sharedBus = 'noSharing' - scsi_ctl.device.scsiCtlrUnitNumber = 7 - - return scsi_ctl - - def is_scsi_controller(self, device): - return isinstance(device, tuple(self.scsi_device_type.values())) - - @staticmethod - def create_ide_controller(bus_number=0): - ide_ctl = vim.vm.device.VirtualDeviceSpec() - ide_ctl.operation = vim.vm.device.VirtualDeviceSpec.Operation.add - ide_ctl.device = vim.vm.device.VirtualIDEController() - ide_ctl.device.deviceInfo = vim.Description() - # While creating a new IDE controller, temporary key value - # should be unique negative integers - ide_ctl.device.key = -randint(200, 299) - ide_ctl.device.busNumber = bus_number - - return ide_ctl - - @staticmethod - def create_cdrom(ide_device, cdrom_type, iso_path=None, unit_number=0): - cdrom_spec = vim.vm.device.VirtualDeviceSpec() - cdrom_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.add - cdrom_spec.device = vim.vm.device.VirtualCdrom() - cdrom_spec.device.controllerKey = ide_device.key - cdrom_spec.device.key = -randint(3000, 3999) - cdrom_spec.device.unitNumber = unit_number - cdrom_spec.device.connectable = vim.vm.device.VirtualDevice.ConnectInfo() - cdrom_spec.device.connectable.allowGuestControl = True - cdrom_spec.device.connectable.startConnected = (cdrom_type != "none") - if cdrom_type in ["none", "client"]: - cdrom_spec.device.backing = vim.vm.device.VirtualCdrom.RemotePassthroughBackingInfo() - elif cdrom_type == "iso": - cdrom_spec.device.backing = vim.vm.device.VirtualCdrom.IsoBackingInfo(fileName=iso_path) - - return cdrom_spec - - @staticmethod - def is_equal_cdrom(vm_obj, cdrom_device, cdrom_type, iso_path): - if cdrom_type == "none": - return (isinstance(cdrom_device.backing, vim.vm.device.VirtualCdrom.RemotePassthroughBackingInfo) and - cdrom_device.connectable.allowGuestControl and - not cdrom_device.connectable.startConnected and - (vm_obj.runtime.powerState != vim.VirtualMachinePowerState.poweredOn or not cdrom_device.connectable.connected)) - elif cdrom_type == "client": - return (isinstance(cdrom_device.backing, vim.vm.device.VirtualCdrom.RemotePassthroughBackingInfo) and - cdrom_device.connectable.allowGuestControl and - cdrom_device.connectable.startConnected and - (vm_obj.runtime.powerState != vim.VirtualMachinePowerState.poweredOn or cdrom_device.connectable.connected)) - elif cdrom_type == "iso": - return (isinstance(cdrom_device.backing, vim.vm.device.VirtualCdrom.IsoBackingInfo) and - cdrom_device.backing.fileName == iso_path and - cdrom_device.connectable.allowGuestControl and - cdrom_device.connectable.startConnected and - (vm_obj.runtime.powerState != vim.VirtualMachinePowerState.poweredOn or cdrom_device.connectable.connected)) - - @staticmethod - def update_cdrom_config(vm_obj, cdrom_spec, cdrom_device, iso_path=None): - # Updating an existing CD-ROM - if cdrom_spec["type"] in ["client", "none"]: - cdrom_device.backing = vim.vm.device.VirtualCdrom.RemotePassthroughBackingInfo() - elif cdrom_spec["type"] == "iso" and iso_path is not None: - cdrom_device.backing = vim.vm.device.VirtualCdrom.IsoBackingInfo(fileName=iso_path) - cdrom_device.connectable = vim.vm.device.VirtualDevice.ConnectInfo() - cdrom_device.connectable.allowGuestControl = True - cdrom_device.connectable.startConnected = (cdrom_spec["type"] != "none") - if vm_obj and vm_obj.runtime.powerState == vim.VirtualMachinePowerState.poweredOn: - cdrom_device.connectable.connected = (cdrom_spec["type"] != "none") - - def remove_cdrom(self, cdrom_device): - cdrom_spec = vim.vm.device.VirtualDeviceSpec() - cdrom_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.remove - cdrom_spec.device = cdrom_device - - return cdrom_spec - - def create_scsi_disk(self, scsi_ctl, disk_index=None): - diskspec = vim.vm.device.VirtualDeviceSpec() - diskspec.operation = vim.vm.device.VirtualDeviceSpec.Operation.add - diskspec.device = vim.vm.device.VirtualDisk() - diskspec.device.backing = vim.vm.device.VirtualDisk.FlatVer2BackingInfo() - diskspec.device.controllerKey = scsi_ctl.device.key - - if self.next_disk_unit_number == 7: - raise AssertionError() - if disk_index == 7: - raise AssertionError() - """ - Configure disk unit number. - """ - if disk_index is not None: - diskspec.device.unitNumber = disk_index - self.next_disk_unit_number = disk_index + 1 - else: - diskspec.device.unitNumber = self.next_disk_unit_number - self.next_disk_unit_number += 1 - - # unit number 7 is reserved to SCSI controller, increase next index - if self.next_disk_unit_number == 7: - self.next_disk_unit_number += 1 - - return diskspec - - def get_device(self, device_type, name): - nic_dict = dict(pcnet32=vim.vm.device.VirtualPCNet32(), - vmxnet2=vim.vm.device.VirtualVmxnet2(), - vmxnet3=vim.vm.device.VirtualVmxnet3(), - e1000=vim.vm.device.VirtualE1000(), - e1000e=vim.vm.device.VirtualE1000e(), - sriov=vim.vm.device.VirtualSriovEthernetCard(), - ) - if device_type in nic_dict: - return nic_dict[device_type] - else: - self.module.fail_json(msg='Invalid device_type "%s"' - ' for network "%s"' % (device_type, name)) - - def create_nic(self, device_type, device_label, device_infos): - nic = vim.vm.device.VirtualDeviceSpec() - nic.device = self.get_device(device_type, device_infos['name']) - nic.device.wakeOnLanEnabled = bool(device_infos.get('wake_on_lan', True)) - nic.device.deviceInfo = vim.Description() - nic.device.deviceInfo.label = device_label - nic.device.deviceInfo.summary = device_infos['name'] - nic.device.connectable = vim.vm.device.VirtualDevice.ConnectInfo() - nic.device.connectable.startConnected = bool(device_infos.get('start_connected', True)) - nic.device.connectable.allowGuestControl = bool(device_infos.get('allow_guest_control', True)) - nic.device.connectable.connected = True - if 'mac' in device_infos and is_mac(device_infos['mac']): - nic.device.addressType = 'manual' - nic.device.macAddress = device_infos['mac'] - else: - nic.device.addressType = 'generated' - - return nic - - def integer_value(self, input_value, name): - """ - Function to return int value for given input, else return error - Args: - input_value: Input value to retrieve int value from - name: Name of the Input value (used to build error message) - Returns: (int) if integer value can be obtained, otherwise will send a error message. - """ - if isinstance(input_value, int): - return input_value - elif isinstance(input_value, str) and input_value.isdigit(): - return int(input_value) - else: - self.module.fail_json(msg='"%s" attribute should be an' - ' integer value.' % name) - - -class PyVmomiCache(object): - """ This class caches references to objects which are requested multiples times but not modified """ - - def __init__(self, content, dc_name=None): - self.content = content - self.dc_name = dc_name - self.networks = {} - self.clusters = {} - self.esx_hosts = {} - self.parent_datacenters = {} - - def find_obj(self, content, types, name, confine_to_datacenter=True): - """ Wrapper around find_obj to set datacenter context """ - result = find_obj(content, types, name) - if result and confine_to_datacenter: - if to_text(self.get_parent_datacenter(result).name) != to_text(self.dc_name): - result = None - objects = self.get_all_objs(content, types, confine_to_datacenter=True) - for obj in objects: - if name is None or to_text(obj.name) == to_text(name): - return obj - return result - - def get_all_objs(self, content, types, confine_to_datacenter=True): - """ Wrapper around get_all_objs to set datacenter context """ - objects = get_all_objs(content, types) - if confine_to_datacenter: - if hasattr(objects, 'items'): - # resource pools come back as a dictionary - # make a copy - for k, v in tuple(objects.items()): - parent_dc = self.get_parent_datacenter(k) - if parent_dc.name != self.dc_name: - del objects[k] - else: - # everything else should be a list - objects = [x for x in objects if self.get_parent_datacenter(x).name == self.dc_name] - - return objects - - def get_network(self, network): - network = quote_obj_name(network) - - if network not in self.networks: - self.networks[network] = self.find_obj(self.content, [vim.Network], network) - - return self.networks[network] - - def get_cluster(self, cluster): - if cluster not in self.clusters: - self.clusters[cluster] = self.find_obj(self.content, [vim.ClusterComputeResource], cluster) - - return self.clusters[cluster] - - def get_esx_host(self, host): - if host not in self.esx_hosts: - self.esx_hosts[host] = self.find_obj(self.content, [vim.HostSystem], host) - - return self.esx_hosts[host] - - def get_parent_datacenter(self, obj): - """ Walk the parent tree to find the objects datacenter """ - if isinstance(obj, vim.Datacenter): - return obj - if obj in self.parent_datacenters: - return self.parent_datacenters[obj] - datacenter = None - while True: - if not hasattr(obj, 'parent'): - break - obj = obj.parent - if isinstance(obj, vim.Datacenter): - datacenter = obj - break - self.parent_datacenters[obj] = datacenter - return datacenter - - -class PyVmomiHelper(PyVmomi): - def __init__(self, module): - super(PyVmomiHelper, self).__init__(module) - self.device_helper = PyVmomiDeviceHelper(self.module) - self.configspec = None - self.relospec = None - self.change_detected = False # a change was detected and needs to be applied through reconfiguration - self.change_applied = False # a change was applied meaning at least one task succeeded - self.customspec = None - self.cache = PyVmomiCache(self.content, dc_name=self.params['datacenter']) - - def gather_facts(self, vm): - return gather_vm_facts(self.content, vm) - - def remove_vm(self, vm, delete_from_inventory=False): - # https://www.vmware.com/support/developer/converter-sdk/conv60_apireference/vim.ManagedEntity.html#destroy - if vm.summary.runtime.powerState.lower() == 'poweredon': - self.module.fail_json(msg="Virtual machine %s found in 'powered on' state, " - "please use 'force' parameter to remove or poweroff VM " - "and try removing VM again." % vm.name) - # Delete VM from Inventory - if delete_from_inventory: - try: - vm.UnregisterVM() - except (vim.fault.TaskInProgress, - vmodl.RuntimeFault) as e: - return {'changed': self.change_applied, 'failed': True, 'msg': e.msg, 'op': 'UnregisterVM'} - self.change_applied = True - return {'changed': self.change_applied, 'failed': False} - # Delete VM from Disk - task = vm.Destroy() - self.wait_for_task(task) - if task.info.state == 'error': - return {'changed': self.change_applied, 'failed': True, 'msg': task.info.error.msg, 'op': 'destroy'} - else: - return {'changed': self.change_applied, 'failed': False} - - def configure_guestid(self, vm_obj, vm_creation=False): - # guest_id is not required when using templates - if self.params['template']: - return - - # guest_id is only mandatory on VM creation - if vm_creation and self.params['guest_id'] is None: - self.module.fail_json(msg="guest_id attribute is mandatory for VM creation") - - if self.params['guest_id'] and \ - (vm_obj is None or self.params['guest_id'].lower() != vm_obj.summary.config.guestId.lower()): - self.change_detected = True - self.configspec.guestId = self.params['guest_id'] - - def configure_resource_alloc_info(self, vm_obj): - """ - Function to configure resource allocation information about virtual machine - :param vm_obj: VM object in case of reconfigure, None in case of deploy - :return: None - """ - rai_change_detected = False - memory_allocation = vim.ResourceAllocationInfo() - cpu_allocation = vim.ResourceAllocationInfo() - - if 'hardware' in self.params: - if 'mem_limit' in self.params['hardware']: - mem_limit = None - try: - mem_limit = int(self.params['hardware'].get('mem_limit')) - except ValueError: - self.module.fail_json(msg="hardware.mem_limit attribute should be an integer value.") - memory_allocation.limit = mem_limit - if vm_obj is None or memory_allocation.limit != vm_obj.config.memoryAllocation.limit: - rai_change_detected = True - - if 'mem_reservation' in self.params['hardware'] or 'memory_reservation' in self.params['hardware']: - mem_reservation = self.params['hardware'].get('mem_reservation') - if mem_reservation is None: - mem_reservation = self.params['hardware'].get('memory_reservation') - try: - mem_reservation = int(mem_reservation) - except ValueError: - self.module.fail_json(msg="hardware.mem_reservation or hardware.memory_reservation should be an integer value.") - - memory_allocation.reservation = mem_reservation - if vm_obj is None or \ - memory_allocation.reservation != vm_obj.config.memoryAllocation.reservation: - rai_change_detected = True - - if 'cpu_limit' in self.params['hardware']: - cpu_limit = None - try: - cpu_limit = int(self.params['hardware'].get('cpu_limit')) - except ValueError: - self.module.fail_json(msg="hardware.cpu_limit attribute should be an integer value.") - cpu_allocation.limit = cpu_limit - if vm_obj is None or cpu_allocation.limit != vm_obj.config.cpuAllocation.limit: - rai_change_detected = True - - if 'cpu_reservation' in self.params['hardware']: - cpu_reservation = None - try: - cpu_reservation = int(self.params['hardware'].get('cpu_reservation')) - except ValueError: - self.module.fail_json(msg="hardware.cpu_reservation should be an integer value.") - cpu_allocation.reservation = cpu_reservation - if vm_obj is None or \ - cpu_allocation.reservation != vm_obj.config.cpuAllocation.reservation: - rai_change_detected = True - - if rai_change_detected: - self.configspec.memoryAllocation = memory_allocation - self.configspec.cpuAllocation = cpu_allocation - self.change_detected = True - - def configure_cpu_and_memory(self, vm_obj, vm_creation=False): - # set cpu/memory/etc - if 'hardware' in self.params: - if 'num_cpus' in self.params['hardware']: - try: - num_cpus = int(self.params['hardware']['num_cpus']) - except ValueError: - self.module.fail_json(msg="hardware.num_cpus attribute should be an integer value.") - # check VM power state and cpu hot-add/hot-remove state before re-config VM - if vm_obj and vm_obj.runtime.powerState == vim.VirtualMachinePowerState.poweredOn: - if not vm_obj.config.cpuHotRemoveEnabled and num_cpus < vm_obj.config.hardware.numCPU: - self.module.fail_json(msg="Configured cpu number is less than the cpu number of the VM, " - "cpuHotRemove is not enabled") - if not vm_obj.config.cpuHotAddEnabled and num_cpus > vm_obj.config.hardware.numCPU: - self.module.fail_json(msg="Configured cpu number is more than the cpu number of the VM, " - "cpuHotAdd is not enabled") - - if 'num_cpu_cores_per_socket' in self.params['hardware']: - try: - num_cpu_cores_per_socket = int(self.params['hardware']['num_cpu_cores_per_socket']) - except ValueError: - self.module.fail_json(msg="hardware.num_cpu_cores_per_socket attribute " - "should be an integer value.") - if num_cpus % num_cpu_cores_per_socket != 0: - self.module.fail_json(msg="hardware.num_cpus attribute should be a multiple " - "of hardware.num_cpu_cores_per_socket") - self.configspec.numCoresPerSocket = num_cpu_cores_per_socket - if vm_obj is None or self.configspec.numCoresPerSocket != vm_obj.config.hardware.numCoresPerSocket: - self.change_detected = True - self.configspec.numCPUs = num_cpus - if vm_obj is None or self.configspec.numCPUs != vm_obj.config.hardware.numCPU: - self.change_detected = True - # num_cpu is mandatory for VM creation - elif vm_creation and not self.params['template']: - self.module.fail_json(msg="hardware.num_cpus attribute is mandatory for VM creation") - - if 'memory_mb' in self.params['hardware']: - try: - memory_mb = int(self.params['hardware']['memory_mb']) - except ValueError: - self.module.fail_json(msg="Failed to parse hardware.memory_mb value." - " Please refer the documentation and provide" - " correct value.") - # check VM power state and memory hotadd state before re-config VM - if vm_obj and vm_obj.runtime.powerState == vim.VirtualMachinePowerState.poweredOn: - if vm_obj.config.memoryHotAddEnabled and memory_mb < vm_obj.config.hardware.memoryMB: - self.module.fail_json(msg="Configured memory is less than memory size of the VM, " - "operation is not supported") - elif not vm_obj.config.memoryHotAddEnabled and memory_mb != vm_obj.config.hardware.memoryMB: - self.module.fail_json(msg="memoryHotAdd is not enabled") - self.configspec.memoryMB = memory_mb - if vm_obj is None or self.configspec.memoryMB != vm_obj.config.hardware.memoryMB: - self.change_detected = True - # memory_mb is mandatory for VM creation - elif vm_creation and not self.params['template']: - self.module.fail_json(msg="hardware.memory_mb attribute is mandatory for VM creation") - - if 'hotadd_memory' in self.params['hardware']: - if vm_obj and vm_obj.runtime.powerState == vim.VirtualMachinePowerState.poweredOn and \ - vm_obj.config.memoryHotAddEnabled != bool(self.params['hardware']['hotadd_memory']): - self.module.fail_json(msg="Configure hotadd memory operation is not supported when VM is power on") - self.configspec.memoryHotAddEnabled = bool(self.params['hardware']['hotadd_memory']) - if vm_obj is None or self.configspec.memoryHotAddEnabled != vm_obj.config.memoryHotAddEnabled: - self.change_detected = True - - if 'hotadd_cpu' in self.params['hardware']: - if vm_obj and vm_obj.runtime.powerState == vim.VirtualMachinePowerState.poweredOn and \ - vm_obj.config.cpuHotAddEnabled != bool(self.params['hardware']['hotadd_cpu']): - self.module.fail_json(msg="Configure hotadd cpu operation is not supported when VM is power on") - self.configspec.cpuHotAddEnabled = bool(self.params['hardware']['hotadd_cpu']) - if vm_obj is None or self.configspec.cpuHotAddEnabled != vm_obj.config.cpuHotAddEnabled: - self.change_detected = True - - if 'hotremove_cpu' in self.params['hardware']: - if vm_obj and vm_obj.runtime.powerState == vim.VirtualMachinePowerState.poweredOn and \ - vm_obj.config.cpuHotRemoveEnabled != bool(self.params['hardware']['hotremove_cpu']): - self.module.fail_json(msg="Configure hotremove cpu operation is not supported when VM is power on") - self.configspec.cpuHotRemoveEnabled = bool(self.params['hardware']['hotremove_cpu']) - if vm_obj is None or self.configspec.cpuHotRemoveEnabled != vm_obj.config.cpuHotRemoveEnabled: - self.change_detected = True - - if 'memory_reservation_lock' in self.params['hardware']: - self.configspec.memoryReservationLockedToMax = bool(self.params['hardware']['memory_reservation_lock']) - if vm_obj is None or self.configspec.memoryReservationLockedToMax != vm_obj.config.memoryReservationLockedToMax: - self.change_detected = True - - if 'boot_firmware' in self.params['hardware']: - # boot firmware re-config can cause boot issue - if vm_obj is not None: - return - boot_firmware = self.params['hardware']['boot_firmware'].lower() - if boot_firmware not in ('bios', 'efi'): - self.module.fail_json(msg="hardware.boot_firmware value is invalid [%s]." - " Need one of ['bios', 'efi']." % boot_firmware) - self.configspec.firmware = boot_firmware - self.change_detected = True - - def sanitize_cdrom_params(self): - # cdroms {'ide': [{num: 0, cdrom: []}, {}], 'sata': [{num: 0, cdrom: []}, {}, ...]} - cdroms = {'ide': [], 'sata': []} - expected_cdrom_spec = self.params.get('cdrom') - if expected_cdrom_spec: - for cdrom_spec in expected_cdrom_spec: - cdrom_spec['controller_type'] = cdrom_spec.get('controller_type', 'ide').lower() - if cdrom_spec['controller_type'] not in ['ide', 'sata']: - self.module.fail_json(msg="Invalid cdrom.controller_type: %s, valid value is 'ide' or 'sata'." - % cdrom_spec['controller_type']) - - cdrom_spec['state'] = cdrom_spec.get('state', 'present').lower() - if cdrom_spec['state'] not in ['present', 'absent']: - self.module.fail_json(msg="Invalid cdrom.state: %s, valid value is 'present', 'absent'." - % cdrom_spec['state']) - - if cdrom_spec['state'] == 'present': - if 'type' in cdrom_spec and cdrom_spec.get('type') not in ['none', 'client', 'iso']: - self.module.fail_json(msg="Invalid cdrom.type: %s, valid value is 'none', 'client' or 'iso'." - % cdrom_spec.get('type')) - if cdrom_spec.get('type') == 'iso' and not cdrom_spec.get('iso_path'): - self.module.fail_json(msg="cdrom.iso_path is mandatory when cdrom.type is set to iso.") - - if cdrom_spec['controller_type'] == 'ide' and \ - (cdrom_spec.get('controller_number') not in [0, 1] or cdrom_spec.get('unit_number') not in [0, 1]): - self.module.fail_json(msg="Invalid cdrom.controller_number: %s or cdrom.unit_number: %s, valid" - " values are 0 or 1 for IDE controller." % (cdrom_spec.get('controller_number'), cdrom_spec.get('unit_number'))) - - if cdrom_spec['controller_type'] == 'sata' and \ - (cdrom_spec.get('controller_number') not in range(0, 4) or cdrom_spec.get('unit_number') not in range(0, 30)): - self.module.fail_json(msg="Invalid cdrom.controller_number: %s or cdrom.unit_number: %s," - " valid controller_number value is 0-3, valid unit_number is 0-29" - " for SATA controller." % (cdrom_spec.get('controller_number'), cdrom_spec.get('unit_number'))) - - ctl_exist = False - for exist_spec in cdroms.get(cdrom_spec['controller_type']): - if exist_spec['num'] == cdrom_spec['controller_number']: - ctl_exist = True - exist_spec['cdrom'].append(cdrom_spec) - break - if not ctl_exist: - cdroms.get(cdrom_spec['controller_type']).append({'num': cdrom_spec['controller_number'], 'cdrom': [cdrom_spec]}) - - return cdroms - - def configure_cdrom(self, vm_obj): - # Configure the VM CD-ROM - if self.params.get('cdrom'): - if vm_obj and vm_obj.config.template: - # Changing CD-ROM settings on a template is not supported - return - - if isinstance(self.params.get('cdrom'), dict): - self.configure_cdrom_dict(vm_obj) - elif isinstance(self.params.get('cdrom'), list): - self.configure_cdrom_list(vm_obj) - - def configure_cdrom_dict(self, vm_obj): - if self.params["cdrom"].get('type') not in ['none', 'client', 'iso']: - self.module.fail_json(msg="cdrom.type is mandatory. Options are 'none', 'client', and 'iso'.") - if self.params["cdrom"]['type'] == 'iso' and not self.params["cdrom"].get('iso_path'): - self.module.fail_json(msg="cdrom.iso_path is mandatory when cdrom.type is set to iso.") - - cdrom_spec = None - cdrom_devices = self.get_vm_cdrom_devices(vm=vm_obj) - iso_path = self.params["cdrom"].get("iso_path") - if len(cdrom_devices) == 0: - # Creating new CD-ROM - ide_devices = self.get_vm_ide_devices(vm=vm_obj) - if len(ide_devices) == 0: - # Creating new IDE device - ide_ctl = self.device_helper.create_ide_controller() - ide_device = ide_ctl.device - self.change_detected = True - self.configspec.deviceChange.append(ide_ctl) - else: - ide_device = ide_devices[0] - if len(ide_device.device) > 3: - self.module.fail_json(msg="hardware.cdrom specified for a VM or template which already has 4" - " IDE devices of which none are a cdrom") - - cdrom_spec = self.device_helper.create_cdrom(ide_device=ide_device, cdrom_type=self.params["cdrom"]["type"], - iso_path=iso_path) - if vm_obj and vm_obj.runtime.powerState == vim.VirtualMachinePowerState.poweredOn: - cdrom_spec.device.connectable.connected = (self.params["cdrom"]["type"] != "none") - - elif not self.device_helper.is_equal_cdrom(vm_obj=vm_obj, cdrom_device=cdrom_devices[0], - cdrom_type=self.params["cdrom"]["type"], iso_path=iso_path): - self.device_helper.update_cdrom_config(vm_obj, self.params["cdrom"], cdrom_devices[0], iso_path=iso_path) - cdrom_spec = vim.vm.device.VirtualDeviceSpec() - cdrom_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.edit - cdrom_spec.device = cdrom_devices[0] - - if cdrom_spec: - self.change_detected = True - self.configspec.deviceChange.append(cdrom_spec) - - def configure_cdrom_list(self, vm_obj): - configured_cdroms = self.sanitize_cdrom_params() - cdrom_devices = self.get_vm_cdrom_devices(vm=vm_obj) - # configure IDE CD-ROMs - if configured_cdroms['ide']: - ide_devices = self.get_vm_ide_devices(vm=vm_obj) - for expected_cdrom_spec in configured_cdroms['ide']: - ide_device = None - for device in ide_devices: - if device.busNumber == expected_cdrom_spec['num']: - ide_device = device - break - # if not find the matched ide controller or no existing ide controller - if not ide_device: - ide_ctl = self.device_helper.create_ide_controller(bus_number=expected_cdrom_spec['num']) - ide_device = ide_ctl.device - self.change_detected = True - self.configspec.deviceChange.append(ide_ctl) - - for cdrom in expected_cdrom_spec['cdrom']: - cdrom_device = None - iso_path = cdrom.get('iso_path') - unit_number = cdrom.get('unit_number') - for target_cdrom in cdrom_devices: - if target_cdrom.controllerKey == ide_device.key and target_cdrom.unitNumber == unit_number: - cdrom_device = target_cdrom - break - # create new CD-ROM - if not cdrom_device and cdrom.get('state') != 'absent': - if vm_obj and vm_obj.runtime.powerState == vim.VirtualMachinePowerState.poweredOn: - self.module.fail_json(msg='CD-ROM attach to IDE controller not support hot-add.') - if len(ide_device.device) == 2: - self.module.fail_json(msg='Maximum number of CD-ROMs attached to IDE controller is 2.') - cdrom_spec = self.device_helper.create_cdrom(ide_device=ide_device, cdrom_type=cdrom['type'], - iso_path=iso_path, unit_number=unit_number) - self.change_detected = True - self.configspec.deviceChange.append(cdrom_spec) - # re-configure CD-ROM - elif cdrom_device and cdrom.get('state') != 'absent' and \ - not self.device_helper.is_equal_cdrom(vm_obj=vm_obj, cdrom_device=cdrom_device, - cdrom_type=cdrom['type'], iso_path=iso_path): - self.device_helper.update_cdrom_config(vm_obj, cdrom, cdrom_device, iso_path=iso_path) - cdrom_spec = vim.vm.device.VirtualDeviceSpec() - cdrom_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.edit - cdrom_spec.device = cdrom_device - self.change_detected = True - self.configspec.deviceChange.append(cdrom_spec) - # delete CD-ROM - elif cdrom_device and cdrom.get('state') == 'absent': - if vm_obj and vm_obj.runtime.powerState != vim.VirtualMachinePowerState.poweredOff: - self.module.fail_json(msg='CD-ROM attach to IDE controller not support hot-remove.') - cdrom_spec = self.device_helper.remove_cdrom(cdrom_device) - self.change_detected = True - self.configspec.deviceChange.append(cdrom_spec) - # configure SATA CD-ROMs is not supported yet - if configured_cdroms['sata']: - pass - - def configure_hardware_params(self, vm_obj): - """ - Function to configure hardware related configuration of virtual machine - Args: - vm_obj: virtual machine object - """ - if 'hardware' in self.params: - if 'max_connections' in self.params['hardware']: - # maxMksConnections == max_connections - self.configspec.maxMksConnections = int(self.params['hardware']['max_connections']) - if vm_obj is None or self.configspec.maxMksConnections != vm_obj.config.maxMksConnections: - self.change_detected = True - - if 'nested_virt' in self.params['hardware']: - self.configspec.nestedHVEnabled = bool(self.params['hardware']['nested_virt']) - if vm_obj is None or self.configspec.nestedHVEnabled != bool(vm_obj.config.nestedHVEnabled): - self.change_detected = True - - if 'version' in self.params['hardware']: - hw_version_check_failed = False - temp_version = self.params['hardware'].get('version', 10) - if isinstance(temp_version, str) and temp_version.lower() == 'latest': - # Check is to make sure vm_obj is not of type template - if vm_obj and not vm_obj.config.template: - try: - task = vm_obj.UpgradeVM_Task() - self.wait_for_task(task) - if task.info.state == 'error': - return {'changed': self.change_applied, 'failed': True, 'msg': task.info.error.msg, 'op': 'upgrade'} - except vim.fault.AlreadyUpgraded: - # Don't fail if VM is already upgraded. - pass - else: - try: - temp_version = int(temp_version) - except ValueError: - hw_version_check_failed = True - - if temp_version not in range(3, 16): - hw_version_check_failed = True - - if hw_version_check_failed: - self.module.fail_json(msg="Failed to set hardware.version '%s' value as valid" - " values range from 3 (ESX 2.x) to 14 (ESXi 6.5 and greater)." % temp_version) - # Hardware version is denoted as "vmx-10" - version = "vmx-%02d" % temp_version - self.configspec.version = version - if vm_obj is None or self.configspec.version != vm_obj.config.version: - self.change_detected = True - # Check is to make sure vm_obj is not of type template - if vm_obj and not vm_obj.config.template: - # VM exists and we need to update the hardware version - current_version = vm_obj.config.version - # current_version = "vmx-10" - version_digit = int(current_version.split("-", 1)[-1]) - if temp_version < version_digit: - self.module.fail_json(msg="Current hardware version '%d' which is greater than the specified" - " version '%d'. Downgrading hardware version is" - " not supported. Please specify version greater" - " than the current version." % (version_digit, - temp_version)) - new_version = "vmx-%02d" % temp_version - try: - task = vm_obj.UpgradeVM_Task(new_version) - self.wait_for_task(task) - if task.info.state == 'error': - return {'changed': self.change_applied, 'failed': True, 'msg': task.info.error.msg, 'op': 'upgrade'} - except vim.fault.AlreadyUpgraded: - # Don't fail if VM is already upgraded. - pass - - if 'virt_based_security' in self.params['hardware']: - host_version = self.select_host().summary.config.product.version - if int(host_version.split('.')[0]) < 6 or (int(host_version.split('.')[0]) == 6 and int(host_version.split('.')[1]) < 7): - self.module.fail_json(msg="ESXi version %s not support VBS." % host_version) - guest_ids = ['windows9_64Guest', 'windows9Server64Guest'] - if vm_obj is None: - guestid = self.configspec.guestId - else: - guestid = vm_obj.summary.config.guestId - if guestid not in guest_ids: - self.module.fail_json(msg="Guest '%s' not support VBS." % guestid) - if (vm_obj is None and int(self.configspec.version.split('-')[1]) >= 14) or \ - (vm_obj and int(vm_obj.config.version.split('-')[1]) >= 14 and (vm_obj.runtime.powerState == vim.VirtualMachinePowerState.poweredOff)): - self.configspec.flags = vim.vm.FlagInfo() - self.configspec.flags.vbsEnabled = bool(self.params['hardware']['virt_based_security']) - if bool(self.params['hardware']['virt_based_security']): - self.configspec.flags.vvtdEnabled = True - self.configspec.nestedHVEnabled = True - if (vm_obj is None and self.configspec.firmware == 'efi') or \ - (vm_obj and vm_obj.config.firmware == 'efi'): - self.configspec.bootOptions = vim.vm.BootOptions() - self.configspec.bootOptions.efiSecureBootEnabled = True - else: - self.module.fail_json(msg="Not support VBS when firmware is BIOS.") - if vm_obj is None or self.configspec.flags.vbsEnabled != vm_obj.config.flags.vbsEnabled: - self.change_detected = True - - def get_device_by_type(self, vm=None, type=None): - device_list = [] - if vm is None or type is None: - return device_list - for device in vm.config.hardware.device: - if isinstance(device, type): - device_list.append(device) - - return device_list - - def get_vm_cdrom_devices(self, vm=None): - return self.get_device_by_type(vm=vm, type=vim.vm.device.VirtualCdrom) - - def get_vm_ide_devices(self, vm=None): - return self.get_device_by_type(vm=vm, type=vim.vm.device.VirtualIDEController) - - def get_vm_network_interfaces(self, vm=None): - device_list = [] - if vm is None: - return device_list - - nw_device_types = (vim.vm.device.VirtualPCNet32, vim.vm.device.VirtualVmxnet2, - vim.vm.device.VirtualVmxnet3, vim.vm.device.VirtualE1000, - vim.vm.device.VirtualE1000e, vim.vm.device.VirtualSriovEthernetCard) - for device in vm.config.hardware.device: - if isinstance(device, nw_device_types): - device_list.append(device) - - return device_list - - def sanitize_network_params(self): - """ - Sanitize user provided network provided params - - Returns: A sanitized list of network params, else fails - - """ - network_devices = list() - # Clean up user data here - for network in self.params['networks']: - if 'name' not in network and 'vlan' not in network: - self.module.fail_json(msg="Please specify at least a network name or" - " a VLAN name under VM network list.") - - if 'name' in network and self.cache.get_network(network['name']) is None: - self.module.fail_json(msg="Network '%(name)s' does not exist." % network) - elif 'vlan' in network: - dvps = self.cache.get_all_objs(self.content, [vim.dvs.DistributedVirtualPortgroup]) - for dvp in dvps: - if hasattr(dvp.config.defaultPortConfig, 'vlan') and \ - isinstance(dvp.config.defaultPortConfig.vlan.vlanId, int) and \ - str(dvp.config.defaultPortConfig.vlan.vlanId) == str(network['vlan']): - network['name'] = dvp.config.name - break - if 'dvswitch_name' in network and \ - dvp.config.distributedVirtualSwitch.name == network['dvswitch_name'] and \ - dvp.config.name == network['vlan']: - network['name'] = dvp.config.name - break - - if dvp.config.name == network['vlan']: - network['name'] = dvp.config.name - break - else: - self.module.fail_json(msg="VLAN '%(vlan)s' does not exist." % network) - - if 'type' in network: - if network['type'] not in ['dhcp', 'static']: - self.module.fail_json(msg="Network type '%(type)s' is not a valid parameter." - " Valid parameters are ['dhcp', 'static']." % network) - if network['type'] != 'static' and ('ip' in network or 'netmask' in network): - self.module.fail_json(msg='Static IP information provided for network "%(name)s",' - ' but "type" is set to "%(type)s".' % network) - else: - # Type is optional parameter, if user provided IP or Subnet assume - # network type as 'static' - if 'ip' in network or 'netmask' in network: - network['type'] = 'static' - else: - # User wants network type as 'dhcp' - network['type'] = 'dhcp' - - if network.get('type') == 'static': - if 'ip' in network and 'netmask' not in network: - self.module.fail_json(msg="'netmask' is required if 'ip' is" - " specified under VM network list.") - if 'ip' not in network and 'netmask' in network: - self.module.fail_json(msg="'ip' is required if 'netmask' is" - " specified under VM network list.") - - validate_device_types = ['pcnet32', 'vmxnet2', 'vmxnet3', 'e1000', 'e1000e', 'sriov'] - if 'device_type' in network and network['device_type'] not in validate_device_types: - self.module.fail_json(msg="Device type specified '%s' is not valid." - " Please specify correct device" - " type from ['%s']." % (network['device_type'], - "', '".join(validate_device_types))) - - if 'mac' in network and not is_mac(network['mac']): - self.module.fail_json(msg="Device MAC address '%s' is invalid." - " Please provide correct MAC address." % network['mac']) - - network_devices.append(network) - - return network_devices - - def configure_network(self, vm_obj): - # Ignore empty networks, this permits to keep networks when deploying a template/cloning a VM - if len(self.params['networks']) == 0: - return - - network_devices = self.sanitize_network_params() - - # List current device for Clone or Idempotency - current_net_devices = self.get_vm_network_interfaces(vm=vm_obj) - if len(network_devices) < len(current_net_devices): - self.module.fail_json(msg="Given network device list is lesser than current VM device list (%d < %d). " - "Removing interfaces is not allowed" - % (len(network_devices), len(current_net_devices))) - - for key in range(0, len(network_devices)): - nic_change_detected = False - network_name = network_devices[key]['name'] - if key < len(current_net_devices) and (vm_obj or self.params['template']): - # We are editing existing network devices, this is either when - # are cloning from VM or Template - nic = vim.vm.device.VirtualDeviceSpec() - nic.operation = vim.vm.device.VirtualDeviceSpec.Operation.edit - - nic.device = current_net_devices[key] - if ('wake_on_lan' in network_devices[key] and - nic.device.wakeOnLanEnabled != network_devices[key].get('wake_on_lan')): - nic.device.wakeOnLanEnabled = network_devices[key].get('wake_on_lan') - nic_change_detected = True - if ('start_connected' in network_devices[key] and - nic.device.connectable.startConnected != network_devices[key].get('start_connected')): - nic.device.connectable.startConnected = network_devices[key].get('start_connected') - nic_change_detected = True - if ('allow_guest_control' in network_devices[key] and - nic.device.connectable.allowGuestControl != network_devices[key].get('allow_guest_control')): - nic.device.connectable.allowGuestControl = network_devices[key].get('allow_guest_control') - nic_change_detected = True - - if nic.device.deviceInfo.summary != network_name: - nic.device.deviceInfo.summary = network_name - nic_change_detected = True - if 'device_type' in network_devices[key]: - device = self.device_helper.get_device(network_devices[key]['device_type'], network_name) - device_class = type(device) - if not isinstance(nic.device, device_class): - self.module.fail_json(msg="Changing the device type is not possible when interface is already present. " - "The failing device type is %s" % network_devices[key]['device_type']) - # Changing mac address has no effect when editing interface - if 'mac' in network_devices[key] and nic.device.macAddress != current_net_devices[key].macAddress: - self.module.fail_json(msg="Changing MAC address has not effect when interface is already present. " - "The failing new MAC address is %s" % nic.device.macAddress) - - else: - # Default device type is vmxnet3, VMware best practice - device_type = network_devices[key].get('device_type', 'vmxnet3') - nic = self.device_helper.create_nic(device_type, - 'Network Adapter %s' % (key + 1), - network_devices[key]) - nic.operation = vim.vm.device.VirtualDeviceSpec.Operation.add - nic_change_detected = True - - if hasattr(self.cache.get_network(network_name), 'portKeys'): - # VDS switch - - pg_obj = None - if 'dvswitch_name' in network_devices[key]: - dvs_name = network_devices[key]['dvswitch_name'] - dvs_obj = find_dvs_by_name(self.content, dvs_name) - if dvs_obj is None: - self.module.fail_json(msg="Unable to find distributed virtual switch %s" % dvs_name) - pg_obj = find_dvspg_by_name(dvs_obj, network_name) - if pg_obj is None: - self.module.fail_json(msg="Unable to find distributed port group %s" % network_name) - else: - pg_obj = self.cache.find_obj(self.content, [vim.dvs.DistributedVirtualPortgroup], network_name) - - # TODO: (akasurde) There is no way to find association between resource pool and distributed virtual portgroup - # For now, check if we are able to find distributed virtual switch - if not pg_obj.config.distributedVirtualSwitch: - self.module.fail_json(msg="Failed to find distributed virtual switch which is associated with" - " distributed virtual portgroup '%s'. Make sure hostsystem is associated with" - " the given distributed virtual portgroup. Also, check if user has correct" - " permission to access distributed virtual switch in the given portgroup." % pg_obj.name) - if (nic.device.backing and - (not hasattr(nic.device.backing, 'port') or - (nic.device.backing.port.portgroupKey != pg_obj.key or - nic.device.backing.port.switchUuid != pg_obj.config.distributedVirtualSwitch.uuid))): - nic_change_detected = True - - dvs_port_connection = vim.dvs.PortConnection() - dvs_port_connection.portgroupKey = pg_obj.key - # If user specifies distributed port group without associating to the hostsystem on which - # virtual machine is going to be deployed then we get error. We can infer that there is no - # association between given distributed port group and host system. - host_system = self.params.get('esxi_hostname') - if host_system and host_system not in [host.config.host.name for host in pg_obj.config.distributedVirtualSwitch.config.host]: - self.module.fail_json(msg="It seems that host system '%s' is not associated with distributed" - " virtual portgroup '%s'. Please make sure host system is associated" - " with given distributed virtual portgroup" % (host_system, pg_obj.name)) - dvs_port_connection.switchUuid = pg_obj.config.distributedVirtualSwitch.uuid - nic.device.backing = vim.vm.device.VirtualEthernetCard.DistributedVirtualPortBackingInfo() - nic.device.backing.port = dvs_port_connection - - elif isinstance(self.cache.get_network(network_name), vim.OpaqueNetwork): - # NSX-T Logical Switch - nic.device.backing = vim.vm.device.VirtualEthernetCard.OpaqueNetworkBackingInfo() - network_id = self.cache.get_network(network_name).summary.opaqueNetworkId - nic.device.backing.opaqueNetworkType = 'nsx.LogicalSwitch' - nic.device.backing.opaqueNetworkId = network_id - nic.device.deviceInfo.summary = 'nsx.LogicalSwitch: %s' % network_id - nic_change_detected = True - else: - # vSwitch - if not isinstance(nic.device.backing, vim.vm.device.VirtualEthernetCard.NetworkBackingInfo): - nic.device.backing = vim.vm.device.VirtualEthernetCard.NetworkBackingInfo() - nic_change_detected = True - - net_obj = self.cache.get_network(network_name) - if nic.device.backing.network != net_obj: - nic.device.backing.network = net_obj - nic_change_detected = True - - if nic.device.backing.deviceName != network_name: - nic.device.backing.deviceName = network_name - nic_change_detected = True - - if nic_change_detected: - # Change to fix the issue found while configuring opaque network - # VMs cloned from a template with opaque network will get disconnected - # Replacing deprecated config parameter with relocation Spec - if isinstance(self.cache.get_network(network_name), vim.OpaqueNetwork): - self.relospec.deviceChange.append(nic) - else: - self.configspec.deviceChange.append(nic) - self.change_detected = True - - def configure_vapp_properties(self, vm_obj): - if len(self.params['vapp_properties']) == 0: - return - - for x in self.params['vapp_properties']: - if not x.get('id'): - self.module.fail_json(msg="id is required to set vApp property") - - new_vmconfig_spec = vim.vApp.VmConfigSpec() - - if vm_obj: - # VM exists - # This is primarily for vcsim/integration tests, unset vAppConfig was not seen on my deployments - orig_spec = vm_obj.config.vAppConfig if vm_obj.config.vAppConfig else new_vmconfig_spec - - vapp_properties_current = dict((x.id, x) for x in orig_spec.property) - vapp_properties_to_change = dict((x['id'], x) for x in self.params['vapp_properties']) - - # each property must have a unique key - # init key counter with max value + 1 - all_keys = [x.key for x in orig_spec.property] - new_property_index = max(all_keys) + 1 if all_keys else 0 - - for property_id, property_spec in vapp_properties_to_change.items(): - is_property_changed = False - new_vapp_property_spec = vim.vApp.PropertySpec() - - if property_id in vapp_properties_current: - if property_spec.get('operation') == 'remove': - new_vapp_property_spec.operation = 'remove' - new_vapp_property_spec.removeKey = vapp_properties_current[property_id].key - is_property_changed = True - else: - # this is 'edit' branch - new_vapp_property_spec.operation = 'edit' - new_vapp_property_spec.info = vapp_properties_current[property_id] - try: - for property_name, property_value in property_spec.items(): - - if property_name == 'operation': - # operation is not an info object property - # if set to anything other than 'remove' we don't fail - continue - - # Updating attributes only if needed - if getattr(new_vapp_property_spec.info, property_name) != property_value: - setattr(new_vapp_property_spec.info, property_name, property_value) - is_property_changed = True - - except Exception as e: - msg = "Failed to set vApp property field='%s' and value='%s'. Error: %s" % (property_name, property_value, to_text(e)) - self.module.fail_json(msg=msg) - else: - if property_spec.get('operation') == 'remove': - # attempt to delete non-existent property - continue - - # this is add new property branch - new_vapp_property_spec.operation = 'add' - - property_info = vim.vApp.PropertyInfo() - property_info.classId = property_spec.get('classId') - property_info.instanceId = property_spec.get('instanceId') - property_info.id = property_spec.get('id') - property_info.category = property_spec.get('category') - property_info.label = property_spec.get('label') - property_info.type = property_spec.get('type', 'string') - property_info.userConfigurable = property_spec.get('userConfigurable', True) - property_info.defaultValue = property_spec.get('defaultValue') - property_info.value = property_spec.get('value', '') - property_info.description = property_spec.get('description') - - new_vapp_property_spec.info = property_info - new_vapp_property_spec.info.key = new_property_index - new_property_index += 1 - is_property_changed = True - - if is_property_changed: - new_vmconfig_spec.property.append(new_vapp_property_spec) - else: - # New VM - all_keys = [x.key for x in new_vmconfig_spec.property] - new_property_index = max(all_keys) + 1 if all_keys else 0 - vapp_properties_to_change = dict((x['id'], x) for x in self.params['vapp_properties']) - is_property_changed = False - - for property_id, property_spec in vapp_properties_to_change.items(): - new_vapp_property_spec = vim.vApp.PropertySpec() - # this is add new property branch - new_vapp_property_spec.operation = 'add' - - property_info = vim.vApp.PropertyInfo() - property_info.classId = property_spec.get('classId') - property_info.instanceId = property_spec.get('instanceId') - property_info.id = property_spec.get('id') - property_info.category = property_spec.get('category') - property_info.label = property_spec.get('label') - property_info.type = property_spec.get('type', 'string') - property_info.userConfigurable = property_spec.get('userConfigurable', True) - property_info.defaultValue = property_spec.get('defaultValue') - property_info.value = property_spec.get('value', '') - property_info.description = property_spec.get('description') - - new_vapp_property_spec.info = property_info - new_vapp_property_spec.info.key = new_property_index - new_property_index += 1 - is_property_changed = True - - if is_property_changed: - new_vmconfig_spec.property.append(new_vapp_property_spec) - - if new_vmconfig_spec.property: - self.configspec.vAppConfig = new_vmconfig_spec - self.change_detected = True - - def customize_customvalues(self, vm_obj, config_spec): - if len(self.params['customvalues']) == 0: - return - - vm_custom_spec = config_spec - vm_custom_spec.extraConfig = [] - - changed = False - facts = self.gather_facts(vm_obj) - for kv in self.params['customvalues']: - if 'key' not in kv or 'value' not in kv: - self.module.exit_json(msg="customvalues items required both 'key' and 'value' fields.") - - # If kv is not kv fetched from facts, change it - if kv['key'] not in facts['customvalues'] or facts['customvalues'][kv['key']] != kv['value']: - option = vim.option.OptionValue() - option.key = kv['key'] - option.value = kv['value'] - - vm_custom_spec.extraConfig.append(option) - changed = True - - if changed: - self.change_detected = True - - def customize_vm(self, vm_obj): - - # User specified customization specification - custom_spec_name = self.params.get('customization_spec') - if custom_spec_name: - cc_mgr = self.content.customizationSpecManager - if cc_mgr.DoesCustomizationSpecExist(name=custom_spec_name): - temp_spec = cc_mgr.GetCustomizationSpec(name=custom_spec_name) - self.customspec = temp_spec.spec - return - else: - self.module.fail_json(msg="Unable to find customization specification" - " '%s' in given configuration." % custom_spec_name) - - # Network settings - adaptermaps = [] - for network in self.params['networks']: - - guest_map = vim.vm.customization.AdapterMapping() - guest_map.adapter = vim.vm.customization.IPSettings() - - if 'ip' in network and 'netmask' in network: - guest_map.adapter.ip = vim.vm.customization.FixedIp() - guest_map.adapter.ip.ipAddress = str(network['ip']) - guest_map.adapter.subnetMask = str(network['netmask']) - elif 'type' in network and network['type'] == 'dhcp': - guest_map.adapter.ip = vim.vm.customization.DhcpIpGenerator() - - if 'gateway' in network: - guest_map.adapter.gateway = network['gateway'] - - # On Windows, DNS domain and DNS servers can be set by network interface - # https://pubs.vmware.com/vi3/sdk/ReferenceGuide/vim.vm.customization.IPSettings.html - if 'domain' in network: - guest_map.adapter.dnsDomain = network['domain'] - elif 'domain' in self.params['customization']: - guest_map.adapter.dnsDomain = self.params['customization']['domain'] - - if 'dns_servers' in network: - guest_map.adapter.dnsServerList = network['dns_servers'] - elif 'dns_servers' in self.params['customization']: - guest_map.adapter.dnsServerList = self.params['customization']['dns_servers'] - - adaptermaps.append(guest_map) - - # Global DNS settings - globalip = vim.vm.customization.GlobalIPSettings() - if 'dns_servers' in self.params['customization']: - globalip.dnsServerList = self.params['customization']['dns_servers'] - - # TODO: Maybe list the different domains from the interfaces here by default ? - if 'dns_suffix' in self.params['customization']: - dns_suffix = self.params['customization']['dns_suffix'] - if isinstance(dns_suffix, list): - globalip.dnsSuffixList = " ".join(dns_suffix) - else: - globalip.dnsSuffixList = dns_suffix - elif 'domain' in self.params['customization']: - globalip.dnsSuffixList = self.params['customization']['domain'] - - if self.params['guest_id']: - guest_id = self.params['guest_id'] - else: - guest_id = vm_obj.summary.config.guestId - - # For windows guest OS, use SysPrep - # https://pubs.vmware.com/vi3/sdk/ReferenceGuide/vim.vm.customization.Sysprep.html#field_detail - if 'win' in guest_id: - ident = vim.vm.customization.Sysprep() - - ident.userData = vim.vm.customization.UserData() - - # Setting hostName, orgName and fullName is mandatory, so we set some default when missing - ident.userData.computerName = vim.vm.customization.FixedName() - # computer name will be truncated to 15 characters if using VM name - default_name = self.params['name'].replace(' ', '') - punctuation = string.punctuation.replace('-', '') - default_name = ''.join([c for c in default_name if c not in punctuation]) - ident.userData.computerName.name = str(self.params['customization'].get('hostname', default_name[0:15])) - ident.userData.fullName = str(self.params['customization'].get('fullname', 'Administrator')) - ident.userData.orgName = str(self.params['customization'].get('orgname', 'ACME')) - - if 'productid' in self.params['customization']: - ident.userData.productId = str(self.params['customization']['productid']) - - ident.guiUnattended = vim.vm.customization.GuiUnattended() - - if 'autologon' in self.params['customization']: - ident.guiUnattended.autoLogon = self.params['customization']['autologon'] - ident.guiUnattended.autoLogonCount = self.params['customization'].get('autologoncount', 1) - - if 'timezone' in self.params['customization']: - # Check if timezone value is a int before proceeding. - ident.guiUnattended.timeZone = self.device_helper.integer_value( - self.params['customization']['timezone'], - 'customization.timezone') - - ident.identification = vim.vm.customization.Identification() - - if self.params['customization'].get('password', '') != '': - ident.guiUnattended.password = vim.vm.customization.Password() - ident.guiUnattended.password.value = str(self.params['customization']['password']) - ident.guiUnattended.password.plainText = True - - if 'joindomain' in self.params['customization']: - if 'domainadmin' not in self.params['customization'] or 'domainadminpassword' not in self.params['customization']: - self.module.fail_json(msg="'domainadmin' and 'domainadminpassword' entries are mandatory in 'customization' section to use " - "joindomain feature") - - ident.identification.domainAdmin = str(self.params['customization']['domainadmin']) - ident.identification.joinDomain = str(self.params['customization']['joindomain']) - ident.identification.domainAdminPassword = vim.vm.customization.Password() - ident.identification.domainAdminPassword.value = str(self.params['customization']['domainadminpassword']) - ident.identification.domainAdminPassword.plainText = True - - elif 'joinworkgroup' in self.params['customization']: - ident.identification.joinWorkgroup = str(self.params['customization']['joinworkgroup']) - - if 'runonce' in self.params['customization']: - ident.guiRunOnce = vim.vm.customization.GuiRunOnce() - ident.guiRunOnce.commandList = self.params['customization']['runonce'] - - else: - # FIXME: We have no clue whether this non-Windows OS is actually Linux, hence it might fail! - - # For Linux guest OS, use LinuxPrep - # https://pubs.vmware.com/vi3/sdk/ReferenceGuide/vim.vm.customization.LinuxPrep.html - ident = vim.vm.customization.LinuxPrep() - - # TODO: Maybe add domain from interface if missing ? - if 'domain' in self.params['customization']: - ident.domain = str(self.params['customization']['domain']) - - ident.hostName = vim.vm.customization.FixedName() - hostname = str(self.params['customization'].get('hostname', self.params['name'].split('.')[0])) - # Remove all characters except alphanumeric and minus which is allowed by RFC 952 - valid_hostname = re.sub(r"[^a-zA-Z0-9\-]", "", hostname) - ident.hostName.name = valid_hostname - - # List of supported time zones for different vSphere versions in Linux/Unix systems - # https://kb.vmware.com/s/article/2145518 - if 'timezone' in self.params['customization']: - ident.timeZone = str(self.params['customization']['timezone']) - if 'hwclockUTC' in self.params['customization']: - ident.hwClockUTC = self.params['customization']['hwclockUTC'] - - self.customspec = vim.vm.customization.Specification() - self.customspec.nicSettingMap = adaptermaps - self.customspec.globalIPSettings = globalip - self.customspec.identity = ident - - def get_vm_scsi_controller(self, vm_obj): - # If vm_obj doesn't exist there is no SCSI controller to find - if vm_obj is None: - return None - - for device in vm_obj.config.hardware.device: - if self.device_helper.is_scsi_controller(device): - scsi_ctl = vim.vm.device.VirtualDeviceSpec() - scsi_ctl.device = device - return scsi_ctl - - return None - - def get_configured_disk_size(self, expected_disk_spec): - # what size is it? - if [x for x in expected_disk_spec.keys() if x.startswith('size_') or x == 'size']: - # size, size_tb, size_gb, size_mb, size_kb - if 'size' in expected_disk_spec: - size_regex = re.compile(r'(\d+(?:\.\d+)?)([tgmkTGMK][bB])') - disk_size_m = size_regex.match(expected_disk_spec['size']) - try: - if disk_size_m: - expected = disk_size_m.group(1) - unit = disk_size_m.group(2) - else: - raise ValueError - - if re.match(r'\d+\.\d+', expected): - # We found float value in string, let's typecast it - expected = float(expected) - else: - # We found int value in string, let's typecast it - expected = int(expected) - - if not expected or not unit: - raise ValueError - - except (TypeError, ValueError, NameError): - # Common failure - self.module.fail_json(msg="Failed to parse disk size please review value" - " provided using documentation.") - else: - param = [x for x in expected_disk_spec.keys() if x.startswith('size_')][0] - unit = param.split('_')[-1].lower() - expected = [x[1] for x in expected_disk_spec.items() if x[0].startswith('size_')][0] - expected = int(expected) - - disk_units = dict(tb=3, gb=2, mb=1, kb=0) - if unit in disk_units: - unit = unit.lower() - return expected * (1024 ** disk_units[unit]) - else: - self.module.fail_json(msg="%s is not a supported unit for disk size." - " Supported units are ['%s']." % (unit, - "', '".join(disk_units.keys()))) - - # No size found but disk, fail - self.module.fail_json( - msg="No size, size_kb, size_mb, size_gb or size_tb attribute found into disk configuration") - - def add_existing_vmdk(self, vm_obj, expected_disk_spec, diskspec, scsi_ctl): - """ - Adds vmdk file described by expected_disk_spec['filename'], retrieves the file - information and adds the correct spec to self.configspec.deviceChange. - """ - filename = expected_disk_spec['filename'] - # If this is a new disk, or the disk file names are different - if (vm_obj and diskspec.device.backing.fileName != filename) or vm_obj is None: - diskspec.device.backing.fileName = filename - diskspec.device.key = -1 - self.change_detected = True - self.configspec.deviceChange.append(diskspec) - - def configure_disks(self, vm_obj): - # Ignore empty disk list, this permits to keep disks when deploying a template/cloning a VM - if len(self.params['disk']) == 0: - return - - scsi_ctl = self.get_vm_scsi_controller(vm_obj) - - # Create scsi controller only if we are deploying a new VM, not a template or reconfiguring - if vm_obj is None or scsi_ctl is None: - scsi_ctl = self.device_helper.create_scsi_controller(self.get_scsi_type()) - self.change_detected = True - self.configspec.deviceChange.append(scsi_ctl) - - disks = [x for x in vm_obj.config.hardware.device if isinstance(x, vim.vm.device.VirtualDisk)] \ - if vm_obj is not None else None - - if disks is not None and self.params.get('disk') and len(self.params.get('disk')) < len(disks): - self.module.fail_json(msg="Provided disks configuration has less disks than " - "the target object (%d vs %d)" % (len(self.params.get('disk')), len(disks))) - - disk_index = 0 - for expected_disk_spec in self.params.get('disk'): - disk_modified = False - # If we are manipulating and existing objects which has disks and disk_index is in disks - if vm_obj is not None and disks is not None and disk_index < len(disks): - diskspec = vim.vm.device.VirtualDeviceSpec() - # set the operation to edit so that it knows to keep other settings - diskspec.operation = vim.vm.device.VirtualDeviceSpec.Operation.edit - diskspec.device = disks[disk_index] - else: - diskspec = self.device_helper.create_scsi_disk(scsi_ctl, disk_index) - disk_modified = True - - # increment index for next disk search - disk_index += 1 - # index 7 is reserved to SCSI controller - if disk_index == 7: - disk_index += 1 - - if 'disk_mode' in expected_disk_spec: - disk_mode = expected_disk_spec.get('disk_mode', 'persistent').lower() - valid_disk_mode = ['persistent', 'independent_persistent', 'independent_nonpersistent'] - if disk_mode not in valid_disk_mode: - self.module.fail_json(msg="disk_mode specified is not valid." - " Should be one of ['%s']" % "', '".join(valid_disk_mode)) - - if (vm_obj and diskspec.device.backing.diskMode != disk_mode) or (vm_obj is None): - diskspec.device.backing.diskMode = disk_mode - disk_modified = True - else: - diskspec.device.backing.diskMode = "persistent" - - # is it thin? - if 'type' in expected_disk_spec: - disk_type = expected_disk_spec.get('type', '').lower() - if disk_type == 'thin': - diskspec.device.backing.thinProvisioned = True - elif disk_type == 'eagerzeroedthick': - diskspec.device.backing.eagerlyScrub = True - - if 'filename' in expected_disk_spec and expected_disk_spec['filename'] is not None: - self.add_existing_vmdk(vm_obj, expected_disk_spec, diskspec, scsi_ctl) - continue - elif vm_obj is None or self.params['template']: - # We are creating new VM or from Template - # Only create virtual device if not backed by vmdk in original template - if diskspec.device.backing.fileName == '': - diskspec.fileOperation = vim.vm.device.VirtualDeviceSpec.FileOperation.create - - # which datastore? - if expected_disk_spec.get('datastore'): - # TODO: This is already handled by the relocation spec, - # but it needs to eventually be handled for all the - # other disks defined - pass - - kb = self.get_configured_disk_size(expected_disk_spec) - # VMware doesn't allow to reduce disk sizes - if kb < diskspec.device.capacityInKB: - self.module.fail_json( - msg="Given disk size is smaller than found (%d < %d). Reducing disks is not allowed." % - (kb, diskspec.device.capacityInKB)) - - if kb != diskspec.device.capacityInKB or disk_modified: - diskspec.device.capacityInKB = kb - self.configspec.deviceChange.append(diskspec) - - self.change_detected = True - - def select_host(self): - hostsystem = self.cache.get_esx_host(self.params['esxi_hostname']) - if not hostsystem: - self.module.fail_json(msg='Failed to find ESX host "%(esxi_hostname)s"' % self.params) - if hostsystem.runtime.connectionState != 'connected' or hostsystem.runtime.inMaintenanceMode: - self.module.fail_json(msg='ESXi "%(esxi_hostname)s" is in invalid state or in maintenance mode.' % self.params) - return hostsystem - - def autoselect_datastore(self): - datastore = None - datastores = self.cache.get_all_objs(self.content, [vim.Datastore]) - - if datastores is None or len(datastores) == 0: - self.module.fail_json(msg="Unable to find a datastore list when autoselecting") - - datastore_freespace = 0 - for ds in datastores: - if not self.is_datastore_valid(datastore_obj=ds): - continue - - if ds.summary.freeSpace > datastore_freespace: - datastore = ds - datastore_freespace = ds.summary.freeSpace - - return datastore - - def get_recommended_datastore(self, datastore_cluster_obj=None): - """ - Function to return Storage DRS recommended datastore from datastore cluster - Args: - datastore_cluster_obj: datastore cluster managed object - - Returns: Name of recommended datastore from the given datastore cluster - - """ - if datastore_cluster_obj is None: - return None - # Check if Datastore Cluster provided by user is SDRS ready - sdrs_status = datastore_cluster_obj.podStorageDrsEntry.storageDrsConfig.podConfig.enabled - if sdrs_status: - # We can get storage recommendation only if SDRS is enabled on given datastorage cluster - pod_sel_spec = vim.storageDrs.PodSelectionSpec() - pod_sel_spec.storagePod = datastore_cluster_obj - storage_spec = vim.storageDrs.StoragePlacementSpec() - storage_spec.podSelectionSpec = pod_sel_spec - storage_spec.type = 'create' - - try: - rec = self.content.storageResourceManager.RecommendDatastores(storageSpec=storage_spec) - rec_action = rec.recommendations[0].action[0] - return rec_action.destination.name - except Exception: - # There is some error so we fall back to general workflow - pass - datastore = None - datastore_freespace = 0 - for ds in datastore_cluster_obj.childEntity: - if isinstance(ds, vim.Datastore) and ds.summary.freeSpace > datastore_freespace: - # If datastore field is provided, filter destination datastores - if not self.is_datastore_valid(datastore_obj=ds): - continue - - datastore = ds - datastore_freespace = ds.summary.freeSpace - if datastore: - return datastore.name - return None - - def select_datastore(self, vm_obj=None): - datastore = None - datastore_name = None - - if len(self.params['disk']) != 0: - # TODO: really use the datastore for newly created disks - if 'autoselect_datastore' in self.params['disk'][0] and self.params['disk'][0]['autoselect_datastore']: - datastores = [] - - if self.params['cluster']: - cluster = self.find_cluster_by_name(self.params['cluster'], self.content) - - for host in cluster.host: - for mi in host.configManager.storageSystem.fileSystemVolumeInfo.mountInfo: - if mi.volume.type == "VMFS": - datastores.append(self.cache.find_obj(self.content, [vim.Datastore], mi.volume.name)) - elif self.params['esxi_hostname']: - host = self.find_hostsystem_by_name(self.params['esxi_hostname']) - - for mi in host.configManager.storageSystem.fileSystemVolumeInfo.mountInfo: - if mi.volume.type == "VMFS": - datastores.append(self.cache.find_obj(self.content, [vim.Datastore], mi.volume.name)) - else: - datastores = self.cache.get_all_objs(self.content, [vim.Datastore]) - datastores = [x for x in datastores if self.cache.get_parent_datacenter(x).name == self.params['datacenter']] - - datastore_freespace = 0 - for ds in datastores: - if not self.is_datastore_valid(datastore_obj=ds): - continue - - if (ds.summary.freeSpace > datastore_freespace) or (ds.summary.freeSpace == datastore_freespace and not datastore): - # If datastore field is provided, filter destination datastores - if 'datastore' in self.params['disk'][0] and \ - isinstance(self.params['disk'][0]['datastore'], str) and \ - ds.name.find(self.params['disk'][0]['datastore']) < 0: - continue - - datastore = ds - datastore_name = datastore.name - datastore_freespace = ds.summary.freeSpace - - elif 'datastore' in self.params['disk'][0]: - datastore_name = self.params['disk'][0]['datastore'] - # Check if user has provided datastore cluster first - datastore_cluster = self.cache.find_obj(self.content, [vim.StoragePod], datastore_name) - if datastore_cluster: - # If user specified datastore cluster so get recommended datastore - datastore_name = self.get_recommended_datastore(datastore_cluster_obj=datastore_cluster) - # Check if get_recommended_datastore or user specified datastore exists or not - datastore = self.cache.find_obj(self.content, [vim.Datastore], datastore_name) - else: - self.module.fail_json(msg="Either datastore or autoselect_datastore should be provided to select datastore") - - if not datastore and self.params['template']: - # use the template's existing DS - disks = [x for x in vm_obj.config.hardware.device if isinstance(x, vim.vm.device.VirtualDisk)] - if disks: - datastore = disks[0].backing.datastore - datastore_name = datastore.name - # validation - if datastore: - dc = self.cache.get_parent_datacenter(datastore) - if dc.name != self.params['datacenter']: - datastore = self.autoselect_datastore() - datastore_name = datastore.name - - if not datastore: - if len(self.params['disk']) != 0 or self.params['template'] is None: - self.module.fail_json(msg="Unable to find the datastore with given parameters." - " This could mean, %s is a non-existent virtual machine and module tried to" - " deploy it as new virtual machine with no disk. Please specify disks parameter" - " or specify template to clone from." % self.params['name']) - self.module.fail_json(msg="Failed to find a matching datastore") - - return datastore, datastore_name - - def obj_has_parent(self, obj, parent): - if obj is None and parent is None: - raise AssertionError() - current_parent = obj - - while True: - if current_parent.name == parent.name: - return True - - # Check if we have reached till root folder - moid = current_parent._moId - if moid in ['group-d1', 'ha-folder-root']: - return False - - current_parent = current_parent.parent - if current_parent is None: - return False - - def get_scsi_type(self): - disk_controller_type = "paravirtual" - # set cpu/memory/etc - if 'hardware' in self.params: - if 'scsi' in self.params['hardware']: - if self.params['hardware']['scsi'] in ['buslogic', 'paravirtual', 'lsilogic', 'lsilogicsas']: - disk_controller_type = self.params['hardware']['scsi'] - else: - self.module.fail_json(msg="hardware.scsi attribute should be 'paravirtual' or 'lsilogic'") - return disk_controller_type - - def find_folder(self, searchpath): - """ Walk inventory objects one position of the searchpath at a time """ - - # split the searchpath so we can iterate through it - paths = [x.replace('/', '') for x in searchpath.split('/')] - paths_total = len(paths) - 1 - position = 0 - - # recursive walk while looking for next element in searchpath - root = self.content.rootFolder - while root and position <= paths_total: - change = False - if hasattr(root, 'childEntity'): - for child in root.childEntity: - if child.name == paths[position]: - root = child - position += 1 - change = True - break - elif isinstance(root, vim.Datacenter): - if hasattr(root, 'vmFolder'): - if root.vmFolder.name == paths[position]: - root = root.vmFolder - position += 1 - change = True - else: - root = None - - if not change: - root = None - - return root - - def get_resource_pool(self, cluster=None, host=None, resource_pool=None): - """ Get a resource pool, filter on cluster, esxi_hostname or resource_pool if given """ - - cluster_name = cluster or self.params.get('cluster', None) - host_name = host or self.params.get('esxi_hostname', None) - resource_pool_name = resource_pool or self.params.get('resource_pool', None) - - # get the datacenter object - datacenter = find_obj(self.content, [vim.Datacenter], self.params['datacenter']) - if not datacenter: - self.module.fail_json(msg='Unable to find datacenter "%s"' % self.params['datacenter']) - - # if cluster is given, get the cluster object - if cluster_name: - cluster = find_obj(self.content, [vim.ComputeResource], cluster_name, folder=datacenter) - if not cluster: - self.module.fail_json(msg='Unable to find cluster "%s"' % cluster_name) - # if host is given, get the cluster object using the host - elif host_name: - host = find_obj(self.content, [vim.HostSystem], host_name, folder=datacenter) - if not host: - self.module.fail_json(msg='Unable to find host "%s"' % host_name) - cluster = host.parent - else: - cluster = None - - # get resource pools limiting search to cluster or datacenter - resource_pool = find_obj(self.content, [vim.ResourcePool], resource_pool_name, folder=cluster or datacenter) - if not resource_pool: - if resource_pool_name: - self.module.fail_json(msg='Unable to find resource_pool "%s"' % resource_pool_name) - else: - self.module.fail_json(msg='Unable to find resource pool, need esxi_hostname, resource_pool, or cluster') - return resource_pool - - def deploy_vm(self): - # https://github.com/vmware/pyvmomi-community-samples/blob/master/samples/clone_vm.py - # https://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/vim.vm.CloneSpec.html - # https://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/vim.vm.ConfigSpec.html - # https://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.vm.RelocateSpec.html - - # FIXME: - # - static IPs - - self.folder = self.params.get('folder', None) - if self.folder is None: - self.module.fail_json(msg="Folder is required parameter while deploying new virtual machine") - - # Prepend / if it was missing from the folder path, also strip trailing slashes - if not self.folder.startswith('/'): - self.folder = '/%(folder)s' % self.params - self.folder = self.folder.rstrip('/') - - datacenter = self.cache.find_obj(self.content, [vim.Datacenter], self.params['datacenter']) - if datacenter is None: - self.module.fail_json(msg='No datacenter named %(datacenter)s was found' % self.params) - - dcpath = compile_folder_path_for_object(datacenter) - - # Nested folder does not have trailing / - if not dcpath.endswith('/'): - dcpath += '/' - - # Check for full path first in case it was already supplied - if (self.folder.startswith(dcpath + self.params['datacenter'] + '/vm') or - self.folder.startswith(dcpath + '/' + self.params['datacenter'] + '/vm')): - fullpath = self.folder - elif self.folder.startswith('/vm/') or self.folder == '/vm': - fullpath = "%s%s%s" % (dcpath, self.params['datacenter'], self.folder) - elif self.folder.startswith('/'): - fullpath = "%s%s/vm%s" % (dcpath, self.params['datacenter'], self.folder) - else: - fullpath = "%s%s/vm/%s" % (dcpath, self.params['datacenter'], self.folder) - - f_obj = self.content.searchIndex.FindByInventoryPath(fullpath) - - # abort if no strategy was successful - if f_obj is None: - # Add some debugging values in failure. - details = { - 'datacenter': datacenter.name, - 'datacenter_path': dcpath, - 'folder': self.folder, - 'full_search_path': fullpath, - } - self.module.fail_json(msg='No folder %s matched in the search path : %s' % (self.folder, fullpath), - details=details) - - destfolder = f_obj - - if self.params['template']: - vm_obj = self.get_vm_or_template(template_name=self.params['template']) - if vm_obj is None: - self.module.fail_json(msg="Could not find a template named %(template)s" % self.params) - else: - vm_obj = None - - # always get a resource_pool - resource_pool = self.get_resource_pool() - - # set the destination datastore for VM & disks - if self.params['datastore']: - # Give precedence to datastore value provided by user - # User may want to deploy VM to specific datastore. - datastore_name = self.params['datastore'] - # Check if user has provided datastore cluster first - datastore_cluster = self.cache.find_obj(self.content, [vim.StoragePod], datastore_name) - if datastore_cluster: - # If user specified datastore cluster so get recommended datastore - datastore_name = self.get_recommended_datastore(datastore_cluster_obj=datastore_cluster) - # Check if get_recommended_datastore or user specified datastore exists or not - datastore = self.cache.find_obj(self.content, [vim.Datastore], datastore_name) - else: - (datastore, datastore_name) = self.select_datastore(vm_obj) - - self.configspec = vim.vm.ConfigSpec() - self.configspec.deviceChange = [] - # create the relocation spec - self.relospec = vim.vm.RelocateSpec() - self.relospec.deviceChange = [] - self.configure_guestid(vm_obj=vm_obj, vm_creation=True) - self.configure_cpu_and_memory(vm_obj=vm_obj, vm_creation=True) - self.configure_hardware_params(vm_obj=vm_obj) - self.configure_resource_alloc_info(vm_obj=vm_obj) - self.configure_vapp_properties(vm_obj=vm_obj) - self.configure_disks(vm_obj=vm_obj) - self.configure_network(vm_obj=vm_obj) - self.configure_cdrom(vm_obj=vm_obj) - - # Find if we need network customizations (find keys in dictionary that requires customizations) - network_changes = False - for nw in self.params['networks']: - for key in nw: - # We don't need customizations for these keys - if key == 'type' and nw['type'] == 'dhcp': - network_changes = True - break - if key not in ('device_type', 'mac', 'name', 'vlan', 'type', 'start_connected', 'dvswitch_name'): - network_changes = True - break - - if len(self.params['customization']) > 0 or network_changes or self.params.get('customization_spec') is not None: - self.customize_vm(vm_obj=vm_obj) - - clonespec = None - clone_method = None - try: - if self.params['template']: - # Only select specific host when ESXi hostname is provided - if self.params['esxi_hostname']: - self.relospec.host = self.select_host() - self.relospec.datastore = datastore - - # Convert disk present in template if is set - if self.params['convert']: - for device in vm_obj.config.hardware.device: - if isinstance(device, vim.vm.device.VirtualDisk): - disk_locator = vim.vm.RelocateSpec.DiskLocator() - disk_locator.diskBackingInfo = vim.vm.device.VirtualDisk.FlatVer2BackingInfo() - if self.params['convert'] in ['thin']: - disk_locator.diskBackingInfo.thinProvisioned = True - if self.params['convert'] in ['eagerzeroedthick']: - disk_locator.diskBackingInfo.eagerlyScrub = True - if self.params['convert'] in ['thick']: - disk_locator.diskBackingInfo.diskMode = "persistent" - disk_locator.diskId = device.key - disk_locator.datastore = datastore - self.relospec.disk.append(disk_locator) - - # https://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.vm.RelocateSpec.html - # > pool: For a clone operation from a template to a virtual machine, this argument is required. - self.relospec.pool = resource_pool - linked_clone = self.params.get('linked_clone') - snapshot_src = self.params.get('snapshot_src', None) - if linked_clone: - if snapshot_src is not None: - self.relospec.diskMoveType = vim.vm.RelocateSpec.DiskMoveOptions.createNewChildDiskBacking - else: - self.module.fail_json(msg="Parameter 'linked_src' and 'snapshot_src' are" - " required together for linked clone operation.") - - clonespec = vim.vm.CloneSpec(template=self.params['is_template'], location=self.relospec) - if self.customspec: - clonespec.customization = self.customspec - - if snapshot_src is not None: - if vm_obj.snapshot is None: - self.module.fail_json(msg="No snapshots present for virtual machine or template [%(template)s]" % self.params) - snapshot = self.get_snapshots_by_name_recursively(snapshots=vm_obj.snapshot.rootSnapshotList, - snapname=snapshot_src) - if len(snapshot) != 1: - self.module.fail_json(msg='virtual machine "%(template)s" does not contain' - ' snapshot named "%(snapshot_src)s"' % self.params) - - clonespec.snapshot = snapshot[0].snapshot - - clonespec.config = self.configspec - clone_method = 'Clone' - try: - task = vm_obj.Clone(folder=destfolder, name=self.params['name'], spec=clonespec) - except vim.fault.NoPermission as e: - self.module.fail_json(msg="Failed to clone virtual machine %s to folder %s " - "due to permission issue: %s" % (self.params['name'], - destfolder, - to_native(e.msg))) - self.change_detected = True - else: - # ConfigSpec require name for VM creation - self.configspec.name = self.params['name'] - self.configspec.files = vim.vm.FileInfo(logDirectory=None, - snapshotDirectory=None, - suspendDirectory=None, - vmPathName="[" + datastore_name + "]") - - clone_method = 'CreateVM_Task' - try: - task = destfolder.CreateVM_Task(config=self.configspec, pool=resource_pool) - except vmodl.fault.InvalidRequest as e: - self.module.fail_json(msg="Failed to create virtual machine due to invalid configuration " - "parameter %s" % to_native(e.msg)) - except vim.fault.RestrictedVersion as e: - self.module.fail_json(msg="Failed to create virtual machine due to " - "product versioning restrictions: %s" % to_native(e.msg)) - self.change_detected = True - self.wait_for_task(task) - except TypeError as e: - self.module.fail_json(msg="TypeError was returned, please ensure to give correct inputs. %s" % to_text(e)) - - if task.info.state == 'error': - # https://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=2021361 - # https://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=2173 - - # provide these to the user for debugging - clonespec_json = serialize_spec(clonespec) - configspec_json = serialize_spec(self.configspec) - kwargs = { - 'changed': self.change_applied, - 'failed': True, - 'msg': task.info.error.msg, - 'clonespec': clonespec_json, - 'configspec': configspec_json, - 'clone_method': clone_method - } - - return kwargs - else: - # set annotation - vm = task.info.result - if self.params['annotation']: - annotation_spec = vim.vm.ConfigSpec() - annotation_spec.annotation = str(self.params['annotation']) - task = vm.ReconfigVM_Task(annotation_spec) - self.wait_for_task(task) - if task.info.state == 'error': - return {'changed': self.change_applied, 'failed': True, 'msg': task.info.error.msg, 'op': 'annotation'} - - if self.params['customvalues']: - vm_custom_spec = vim.vm.ConfigSpec() - self.customize_customvalues(vm_obj=vm, config_spec=vm_custom_spec) - task = vm.ReconfigVM_Task(vm_custom_spec) - self.wait_for_task(task) - if task.info.state == 'error': - return {'changed': self.change_applied, 'failed': True, 'msg': task.info.error.msg, 'op': 'customvalues'} - - if self.params['wait_for_ip_address'] or self.params['wait_for_customization'] or self.params['state'] in ['poweredon', 'restarted']: - set_vm_power_state(self.content, vm, 'poweredon', force=False) - - if self.params['wait_for_ip_address']: - wait_for_vm_ip(self.content, vm, self.params['wait_for_ip_address_timeout']) - - if self.params['wait_for_customization']: - is_customization_ok = self.wait_for_customization(vm=vm, timeout=self.params['wait_for_customization_timeout']) - if not is_customization_ok: - vm_facts = self.gather_facts(vm) - return {'changed': self.change_applied, 'failed': True, 'instance': vm_facts, 'op': 'customization'} - - vm_facts = self.gather_facts(vm) - return {'changed': self.change_applied, 'failed': False, 'instance': vm_facts} - - def get_snapshots_by_name_recursively(self, snapshots, snapname): - snap_obj = [] - for snapshot in snapshots: - if snapshot.name == snapname: - snap_obj.append(snapshot) - else: - snap_obj = snap_obj + self.get_snapshots_by_name_recursively(snapshot.childSnapshotList, snapname) - return snap_obj - - def reconfigure_vm(self): - self.configspec = vim.vm.ConfigSpec() - self.configspec.deviceChange = [] - # create the relocation spec - self.relospec = vim.vm.RelocateSpec() - self.relospec.deviceChange = [] - self.configure_guestid(vm_obj=self.current_vm_obj) - self.configure_cpu_and_memory(vm_obj=self.current_vm_obj) - self.configure_hardware_params(vm_obj=self.current_vm_obj) - self.configure_disks(vm_obj=self.current_vm_obj) - self.configure_network(vm_obj=self.current_vm_obj) - self.configure_cdrom(vm_obj=self.current_vm_obj) - self.customize_customvalues(vm_obj=self.current_vm_obj, config_spec=self.configspec) - self.configure_resource_alloc_info(vm_obj=self.current_vm_obj) - self.configure_vapp_properties(vm_obj=self.current_vm_obj) - - if self.params['annotation'] and self.current_vm_obj.config.annotation != self.params['annotation']: - self.configspec.annotation = str(self.params['annotation']) - self.change_detected = True - - if self.params['resource_pool']: - self.relospec.pool = self.get_resource_pool() - - if self.relospec.pool != self.current_vm_obj.resourcePool: - task = self.current_vm_obj.RelocateVM_Task(spec=self.relospec) - self.wait_for_task(task) - if task.info.state == 'error': - return {'changed': self.change_applied, 'failed': True, 'msg': task.info.error.msg, 'op': 'relocate'} - - # Only send VMware task if we see a modification - if self.change_detected: - task = None - try: - task = self.current_vm_obj.ReconfigVM_Task(spec=self.configspec) - except vim.fault.RestrictedVersion as e: - self.module.fail_json(msg="Failed to reconfigure virtual machine due to" - " product versioning restrictions: %s" % to_native(e.msg)) - self.wait_for_task(task) - if task.info.state == 'error': - return {'changed': self.change_applied, 'failed': True, 'msg': task.info.error.msg, 'op': 'reconfig'} - - # Rename VM - if self.params['uuid'] and self.params['name'] and self.params['name'] != self.current_vm_obj.config.name: - task = self.current_vm_obj.Rename_Task(self.params['name']) - self.wait_for_task(task) - if task.info.state == 'error': - return {'changed': self.change_applied, 'failed': True, 'msg': task.info.error.msg, 'op': 'rename'} - - # Mark VM as Template - if self.params['is_template'] and not self.current_vm_obj.config.template: - try: - self.current_vm_obj.MarkAsTemplate() - self.change_applied = True - except vmodl.fault.NotSupported as e: - self.module.fail_json(msg="Failed to mark virtual machine [%s] " - "as template: %s" % (self.params['name'], e.msg)) - - # Mark Template as VM - elif not self.params['is_template'] and self.current_vm_obj.config.template: - resource_pool = self.get_resource_pool() - kwargs = dict(pool=resource_pool) - - if self.params.get('esxi_hostname', None): - host_system_obj = self.select_host() - kwargs.update(host=host_system_obj) - - try: - self.current_vm_obj.MarkAsVirtualMachine(**kwargs) - self.change_applied = True - except vim.fault.InvalidState as invalid_state: - self.module.fail_json(msg="Virtual machine is not marked" - " as template : %s" % to_native(invalid_state.msg)) - except vim.fault.InvalidDatastore as invalid_ds: - self.module.fail_json(msg="Converting template to virtual machine" - " operation cannot be performed on the" - " target datastores: %s" % to_native(invalid_ds.msg)) - except vim.fault.CannotAccessVmComponent as cannot_access: - self.module.fail_json(msg="Failed to convert template to virtual machine" - " as operation unable access virtual machine" - " component: %s" % to_native(cannot_access.msg)) - except vmodl.fault.InvalidArgument as invalid_argument: - self.module.fail_json(msg="Failed to convert template to virtual machine" - " due to : %s" % to_native(invalid_argument.msg)) - except Exception as generic_exc: - self.module.fail_json(msg="Failed to convert template to virtual machine" - " due to generic error : %s" % to_native(generic_exc)) - - # Automatically update VMware UUID when converting template to VM. - # This avoids an interactive prompt during VM startup. - uuid_action = [x for x in self.current_vm_obj.config.extraConfig if x.key == "uuid.action"] - if not uuid_action: - uuid_action_opt = vim.option.OptionValue() - uuid_action_opt.key = "uuid.action" - uuid_action_opt.value = "create" - self.configspec.extraConfig.append(uuid_action_opt) - - self.change_detected = True - - # add customize existing VM after VM re-configure - if 'existing_vm' in self.params['customization'] and self.params['customization']['existing_vm']: - if self.current_vm_obj.config.template: - self.module.fail_json(msg="VM is template, not support guest OS customization.") - if self.current_vm_obj.runtime.powerState != vim.VirtualMachinePowerState.poweredOff: - self.module.fail_json(msg="VM is not in poweroff state, can not do guest OS customization.") - cus_result = self.customize_exist_vm() - if cus_result['failed']: - return cus_result - - vm_facts = self.gather_facts(self.current_vm_obj) - return {'changed': self.change_applied, 'failed': False, 'instance': vm_facts} - - def customize_exist_vm(self): - task = None - # Find if we need network customizations (find keys in dictionary that requires customizations) - network_changes = False - for nw in self.params['networks']: - for key in nw: - # We don't need customizations for these keys - if key not in ('device_type', 'mac', 'name', 'vlan', 'type', 'start_connected', 'dvswitch_name'): - network_changes = True - break - if len(self.params['customization']) > 1 or network_changes or self.params.get('customization_spec'): - self.customize_vm(vm_obj=self.current_vm_obj) - try: - task = self.current_vm_obj.CustomizeVM_Task(self.customspec) - except vim.fault.CustomizationFault as e: - self.module.fail_json(msg="Failed to customization virtual machine due to CustomizationFault: %s" % to_native(e.msg)) - except vim.fault.RuntimeFault as e: - self.module.fail_json(msg="failed to customization virtual machine due to RuntimeFault: %s" % to_native(e.msg)) - except Exception as e: - self.module.fail_json(msg="failed to customization virtual machine due to fault: %s" % to_native(e.msg)) - self.wait_for_task(task) - if task.info.state == 'error': - return {'changed': self.change_applied, 'failed': True, 'msg': task.info.error.msg, 'op': 'customize_exist'} - - if self.params['wait_for_customization']: - set_vm_power_state(self.content, self.current_vm_obj, 'poweredon', force=False) - is_customization_ok = self.wait_for_customization(vm=self.current_vm_obj, timeout=self.params['wait_for_customization_timeout']) - if not is_customization_ok: - return {'changed': self.change_applied, 'failed': True, - 'msg': 'Wait for customization failed due to timeout', 'op': 'wait_for_customize_exist'} - - return {'changed': self.change_applied, 'failed': False} - - def wait_for_task(self, task, poll_interval=1): - """ - Wait for a VMware task to complete. Terminal states are 'error' and 'success'. - - Inputs: - - task: the task to wait for - - poll_interval: polling interval to check the task, in seconds - - Modifies: - - self.change_applied - """ - # https://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/vim.Task.html - # https://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/vim.TaskInfo.html - # https://github.com/virtdevninja/pyvmomi-community-samples/blob/master/samples/tools/tasks.py - while task.info.state not in ['error', 'success']: - time.sleep(poll_interval) - self.change_applied = self.change_applied or task.info.state == 'success' - - def get_vm_events(self, vm, eventTypeIdList): - byEntity = vim.event.EventFilterSpec.ByEntity(entity=vm, recursion="self") - filterSpec = vim.event.EventFilterSpec(entity=byEntity, eventTypeId=eventTypeIdList) - eventManager = self.content.eventManager - return eventManager.QueryEvent(filterSpec) - - def wait_for_customization(self, vm, timeout=3600, sleep=10): - poll = int(timeout // sleep) - thispoll = 0 - while thispoll <= poll: - eventStarted = self.get_vm_events(vm, ['CustomizationStartedEvent']) - if len(eventStarted): - thispoll = 0 - while thispoll <= poll: - eventsFinishedResult = self.get_vm_events(vm, ['CustomizationSucceeded', 'CustomizationFailed']) - if len(eventsFinishedResult): - if not isinstance(eventsFinishedResult[0], vim.event.CustomizationSucceeded): - self.module.warn("Customization failed with error {%s}:{%s}" - % (eventsFinishedResult[0]._wsdlName, eventsFinishedResult[0].fullFormattedMessage)) - return False - else: - return True - else: - time.sleep(sleep) - thispoll += 1 - if len(eventsFinishedResult) == 0: - self.module.warn('Waiting for customization result event timed out.') - return False - else: - time.sleep(sleep) - thispoll += 1 - if len(eventStarted): - self.module.warn('Waiting for customization result event timed out.') - else: - self.module.warn('Waiting for customization start event timed out.') - return False - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - state=dict(type='str', default='present', - choices=['absent', 'poweredoff', 'poweredon', 'present', 'rebootguest', 'restarted', 'shutdownguest', 'suspended']), - template=dict(type='str', aliases=['template_src']), - is_template=dict(type='bool', default=False), - annotation=dict(type='str', aliases=['notes']), - customvalues=dict(type='list', default=[]), - name=dict(type='str'), - name_match=dict(type='str', choices=['first', 'last'], default='first'), - uuid=dict(type='str'), - use_instance_uuid=dict(type='bool', default=False), - folder=dict(type='str'), - guest_id=dict(type='str'), - disk=dict(type='list', default=[]), - cdrom=dict(type=list_or_dict, default=[]), - hardware=dict(type='dict', default={}), - force=dict(type='bool', default=False), - datacenter=dict(type='str', default='ha-datacenter'), - esxi_hostname=dict(type='str'), - cluster=dict(type='str'), - wait_for_ip_address=dict(type='bool', default=False), - wait_for_ip_address_timeout=dict(type='int', default=300), - state_change_timeout=dict(type='int', default=0), - snapshot_src=dict(type='str'), - linked_clone=dict(type='bool', default=False), - networks=dict(type='list', default=[]), - resource_pool=dict(type='str'), - customization=dict(type='dict', default={}, no_log=True), - customization_spec=dict(type='str', default=None), - wait_for_customization=dict(type='bool', default=False), - wait_for_customization_timeout=dict(type='int', default=3600), - vapp_properties=dict(type='list', default=[]), - datastore=dict(type='str'), - convert=dict(type='str', choices=['thin', 'thick', 'eagerzeroedthick']), - delete_from_inventory=dict(type='bool', default=False), - ) - - module = AnsibleModule(argument_spec=argument_spec, - supports_check_mode=True, - mutually_exclusive=[ - ['cluster', 'esxi_hostname'], - ], - required_one_of=[ - ['name', 'uuid'], - ], - ) - - result = {'failed': False, 'changed': False} - - pyv = PyVmomiHelper(module) - - # Check if the VM exists before continuing - vm = pyv.get_vm() - - # VM already exists - if vm: - if module.params['state'] == 'absent': - # destroy it - if module.check_mode: - result.update( - vm_name=vm.name, - changed=True, - current_powerstate=vm.summary.runtime.powerState.lower(), - desired_operation='remove_vm', - ) - module.exit_json(**result) - if module.params['force']: - # has to be poweredoff first - set_vm_power_state(pyv.content, vm, 'poweredoff', module.params['force']) - result = pyv.remove_vm(vm, module.params['delete_from_inventory']) - elif module.params['state'] == 'present': - if module.check_mode: - result.update( - vm_name=vm.name, - changed=True, - desired_operation='reconfigure_vm', - ) - module.exit_json(**result) - result = pyv.reconfigure_vm() - elif module.params['state'] in ['poweredon', 'poweredoff', 'restarted', 'suspended', 'shutdownguest', 'rebootguest']: - if module.check_mode: - result.update( - vm_name=vm.name, - changed=True, - current_powerstate=vm.summary.runtime.powerState.lower(), - desired_operation='set_vm_power_state', - ) - module.exit_json(**result) - # set powerstate - tmp_result = set_vm_power_state(pyv.content, vm, module.params['state'], module.params['force'], module.params['state_change_timeout']) - if tmp_result['changed']: - result["changed"] = True - if module.params['state'] in ['poweredon', 'restarted', 'rebootguest'] and module.params['wait_for_ip_address']: - wait_result = wait_for_vm_ip(pyv.content, vm, module.params['wait_for_ip_address_timeout']) - if not wait_result: - module.fail_json(msg='Waiting for IP address timed out') - tmp_result['instance'] = wait_result - if not tmp_result["failed"]: - result["failed"] = False - result['instance'] = tmp_result['instance'] - if tmp_result["failed"]: - result["failed"] = True - result["msg"] = tmp_result["msg"] - else: - # This should not happen - raise AssertionError() - # VM doesn't exist - else: - if module.params['state'] in ['poweredon', 'poweredoff', 'present', 'restarted', 'suspended']: - if module.check_mode: - result.update( - changed=True, - desired_operation='deploy_vm', - ) - module.exit_json(**result) - result = pyv.deploy_vm() - if result['failed']: - module.fail_json(msg='Failed to create a virtual machine : %s' % result['msg']) - - if result['failed']: - module.fail_json(**result) - else: - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_boot_info.py b/lib/ansible/modules/cloud/vmware/vmware_guest_boot_info.py deleted file mode 100644 index 4f3b8e9670..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_boot_info.py +++ /dev/null @@ -1,214 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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 = ''' ---- -module: vmware_guest_boot_info -short_description: Gather info about boot options for the given virtual machine -description: - - Gather information about boot options for the given virtual machine. -version_added: '2.9' -author: - - Abhijeet Kasurde (@Akasurde) -notes: - - Tested on vSphere 6.5 -requirements: - - "python >= 2.6" - - PyVmomi -options: - name: - description: - - Name of the VM to work with. - - This is required if C(uuid) or C(moid) parameter is not supplied. - type: str - uuid: - description: - - UUID of the instance to manage if known, this is VMware's BIOS UUID by default. - - This is required if C(name) or C(moid) parameter is not supplied. - type: str - moid: - description: - - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. - - This is required if C(name) or C(uuid) is not supplied. - type: str - use_instance_uuid: - description: - - Whether to use the VMware instance UUID rather than the BIOS UUID. - default: no - type: bool - name_match: - description: - - If multiple virtual machines matching the name, use the first or last found. - default: 'first' - choices: ['first', 'last'] - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather info about virtual machine's boot order and related parameters - vmware_guest_boot_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - name: "{{ vm_name }}" - register: vm_boot_order_info - -- name: Gather information about virtual machine's boot order using MoID - vmware_guest_boot_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - moid: "vm-42" - register: vm_moid_boot_order_info -''' - -RETURN = r""" -vm_boot_info: - description: metadata about boot order of virtual machine - returned: always - type: dict - sample: { - "current_boot_order": [ - "floppy", - "disk", - "ethernet", - "cdrom" - ], - "current_boot_delay": 2000, - "current_boot_retry_delay": 22300, - "current_boot_retry_enabled": true, - "current_enter_bios_setup": true, - "current_boot_firmware": "bios", - "current_secure_boot_enabled": false, - } -""" - - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec, find_vm_by_id - -try: - from pyVmomi import vim, VmomiSupport -except ImportError: - pass - - -class VmBootInfoManager(PyVmomi): - def __init__(self, module): - super(VmBootInfoManager, self).__init__(module) - self.name = self.params['name'] - self.uuid = self.params['uuid'] - self.moid = self.params['moid'] - self.use_instance_uuid = self.params['use_instance_uuid'] - self.vm = None - - def _get_vm(self): - vms = [] - - if self.uuid: - if self.use_instance_uuid: - vm_obj = find_vm_by_id(self.content, vm_id=self.uuid, vm_id_type="use_instance_uuid") - else: - vm_obj = find_vm_by_id(self.content, vm_id=self.uuid, vm_id_type="uuid") - if vm_obj is None: - self.module.fail_json(msg="Failed to find the virtual machine with UUID : %s" % self.uuid) - vms = [vm_obj] - - elif self.name: - objects = self.get_managed_objects_properties(vim_type=vim.VirtualMachine, properties=['name']) - for temp_vm_object in objects: - if temp_vm_object.obj.name == self.name: - vms.append(temp_vm_object.obj) - - elif self.moid: - vm_obj = VmomiSupport.templateOf('VirtualMachine')(self.module.params['moid'], self.si._stub) - if vm_obj: - vms.append(vm_obj) - - if vms: - if self.params.get('name_match') == 'first': - self.vm = vms[0] - elif self.params.get('name_match') == 'last': - self.vm = vms[-1] - else: - self.module.fail_json(msg="Failed to find virtual machine using %s" % (self.name or self.uuid or self.moid)) - - @staticmethod - def humanize_boot_order(boot_order): - results = [] - for device in boot_order: - if isinstance(device, vim.vm.BootOptions.BootableCdromDevice): - results.append('cdrom') - elif isinstance(device, vim.vm.BootOptions.BootableDiskDevice): - results.append('disk') - elif isinstance(device, vim.vm.BootOptions.BootableEthernetDevice): - results.append('ethernet') - elif isinstance(device, vim.vm.BootOptions.BootableFloppyDevice): - results.append('floppy') - return results - - def ensure(self): - self._get_vm() - - results = dict() - if self.vm and self.vm.config: - results = dict( - current_boot_order=self.humanize_boot_order(self.vm.config.bootOptions.bootOrder), - current_boot_delay=self.vm.config.bootOptions.bootDelay, - current_enter_bios_setup=self.vm.config.bootOptions.enterBIOSSetup, - current_boot_retry_enabled=self.vm.config.bootOptions.bootRetryEnabled, - current_boot_retry_delay=self.vm.config.bootOptions.bootRetryDelay, - current_boot_firmware=self.vm.config.firmware, - current_secure_boot_enabled=self.vm.config.bootOptions.efiSecureBootEnabled - ) - - self.module.exit_json(changed=False, vm_boot_info=results) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - name=dict(type='str'), - uuid=dict(type='str'), - moid=dict(type='str'), - use_instance_uuid=dict(type='bool', default=False), - name_match=dict( - choices=['first', 'last'], - default='first' - ), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['name', 'uuid', 'moid'] - ], - mutually_exclusive=[ - ['name', 'uuid', 'moid'] - ], - supports_check_mode=True, - ) - - pyv = VmBootInfoManager(module) - pyv.ensure() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_boot_manager.py b/lib/ansible/modules/cloud/vmware/vmware_guest_boot_manager.py deleted file mode 100644 index 3bfe689668..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_boot_manager.py +++ /dev/null @@ -1,417 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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 = ''' ---- -module: vmware_guest_boot_manager -short_description: Manage boot options for the given virtual machine -description: - - This module can be used to manage boot options for the given virtual machine. -version_added: 2.7 -author: - - Abhijeet Kasurde (@Akasurde) <akasurde@redhat.com> -notes: - - Tested on vSphere 6.5 -requirements: - - "python >= 2.6" - - PyVmomi -options: - name: - description: - - Name of the VM to work with. - - This is required if C(uuid) or C(moid) parameter is not supplied. - type: str - uuid: - description: - - UUID of the instance to manage if known, this is VMware's BIOS UUID by default. - - This is required if C(name) or C(moid) parameter is not supplied. - type: str - moid: - description: - - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. - - This is required if C(name) or C(uuid) is not supplied. - version_added: '2.9' - type: str - use_instance_uuid: - description: - - Whether to use the VMware instance UUID rather than the BIOS UUID. - default: no - type: bool - version_added: '2.8' - boot_order: - description: - - List of the boot devices. - default: [] - type: list - name_match: - description: - - If multiple virtual machines matching the name, use the first or last found. - default: 'first' - choices: ['first', 'last'] - type: str - boot_delay: - description: - - Delay in milliseconds before starting the boot sequence. - default: 0 - type: int - enter_bios_setup: - description: - - If set to C(True), the virtual machine automatically enters BIOS setup the next time it boots. - - The virtual machine resets this flag, so that the machine boots proceeds normally. - type: 'bool' - default: False - boot_retry_enabled: - description: - - If set to C(True), the virtual machine that fails to boot, will try to boot again after C(boot_retry_delay) is expired. - - If set to C(False), the virtual machine waits indefinitely for user intervention. - type: 'bool' - default: False - boot_retry_delay: - description: - - Specify the time in milliseconds between virtual machine boot failure and subsequent attempt to boot again. - - If set, will automatically set C(boot_retry_enabled) to C(True) as this parameter is required. - default: 0 - type: int - boot_firmware: - description: - - Choose which firmware should be used to boot the virtual machine. - choices: ["bios", "efi"] - type: str - secure_boot_enabled: - description: - - Choose if EFI secure boot should be enabled. EFI secure boot can only be enabled with boot_firmware = efi - type: 'bool' - default: False - version_added: '2.8' -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Change virtual machine's boot order and related parameters - vmware_guest_boot_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: testvm - boot_delay: 2000 - enter_bios_setup: True - boot_retry_enabled: True - boot_retry_delay: 22300 - boot_firmware: bios - secure_boot_enabled: False - boot_order: - - floppy - - cdrom - - ethernet - - disk - delegate_to: localhost - register: vm_boot_order - -- name: Change virtual machine's boot order using Virtual Machine MoID - vmware_guest_boot_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - moid: vm-42 - boot_delay: 2000 - enter_bios_setup: True - boot_retry_enabled: True - boot_retry_delay: 22300 - boot_firmware: bios - secure_boot_enabled: False - boot_order: - - floppy - - cdrom - - ethernet - - disk - delegate_to: localhost - register: vm_boot_order -''' - -RETURN = r""" -vm_boot_status: - description: metadata about boot order of virtual machine - returned: always - type: dict - sample: { - "current_boot_order": [ - "floppy", - "disk", - "ethernet", - "cdrom" - ], - "current_boot_delay": 2000, - "current_boot_retry_delay": 22300, - "current_boot_retry_enabled": true, - "current_enter_bios_setup": true, - "current_boot_firmware": "bios", - "current_secure_boot_enabled": false, - "previous_boot_delay": 10, - "previous_boot_retry_delay": 10000, - "previous_boot_retry_enabled": true, - "previous_enter_bios_setup": false, - "previous_boot_firmware": "efi", - "previous_secure_boot_enabled": true, - "previous_boot_order": [ - "ethernet", - "cdrom", - "floppy", - "disk" - ], - } -""" - - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils._text import to_native -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec, find_vm_by_id, wait_for_task, TaskError - -try: - from pyVmomi import vim, VmomiSupport -except ImportError: - pass - - -class VmBootManager(PyVmomi): - def __init__(self, module): - super(VmBootManager, self).__init__(module) - self.name = self.params['name'] - self.uuid = self.params['uuid'] - self.moid = self.params['moid'] - self.use_instance_uuid = self.params['use_instance_uuid'] - self.vm = None - - def _get_vm(self): - vms = [] - - if self.uuid: - if self.use_instance_uuid: - vm_obj = find_vm_by_id(self.content, vm_id=self.uuid, vm_id_type="instance_uuid") - else: - vm_obj = find_vm_by_id(self.content, vm_id=self.uuid, vm_id_type="uuid") - if vm_obj is None: - self.module.fail_json(msg="Failed to find the virtual machine with UUID : %s" % self.uuid) - vms = [vm_obj] - - elif self.name: - objects = self.get_managed_objects_properties(vim_type=vim.VirtualMachine, properties=['name']) - for temp_vm_object in objects: - if temp_vm_object.obj.name == self.name: - vms.append(temp_vm_object.obj) - - elif self.moid: - vm_obj = VmomiSupport.templateOf('VirtualMachine')(self.module.params['moid'], self.si._stub) - if vm_obj: - vms.append(vm_obj) - - if vms: - if self.params.get('name_match') == 'first': - self.vm = vms[0] - elif self.params.get('name_match') == 'last': - self.vm = vms[-1] - else: - self.module.fail_json(msg="Failed to find virtual machine using %s" % (self.name or self.uuid)) - - @staticmethod - def humanize_boot_order(boot_order): - results = [] - for device in boot_order: - if isinstance(device, vim.vm.BootOptions.BootableCdromDevice): - results.append('cdrom') - elif isinstance(device, vim.vm.BootOptions.BootableDiskDevice): - results.append('disk') - elif isinstance(device, vim.vm.BootOptions.BootableEthernetDevice): - results.append('ethernet') - elif isinstance(device, vim.vm.BootOptions.BootableFloppyDevice): - results.append('floppy') - return results - - def ensure(self): - self._get_vm() - - valid_device_strings = ['cdrom', 'disk', 'ethernet', 'floppy'] - - boot_order_list = [] - for device_order in self.params.get('boot_order'): - if device_order not in valid_device_strings: - self.module.fail_json(msg="Invalid device found [%s], please specify device from ['%s']" % (device_order, - "', '".join(valid_device_strings))) - if device_order == 'cdrom': - first_cdrom = [device for device in self.vm.config.hardware.device if isinstance(device, vim.vm.device.VirtualCdrom)] - if first_cdrom: - boot_order_list.append(vim.vm.BootOptions.BootableCdromDevice()) - elif device_order == 'disk': - first_hdd = [device for device in self.vm.config.hardware.device if isinstance(device, vim.vm.device.VirtualDisk)] - if first_hdd: - boot_order_list.append(vim.vm.BootOptions.BootableDiskDevice(deviceKey=first_hdd[0].key)) - elif device_order == 'ethernet': - first_ether = [device for device in self.vm.config.hardware.device if isinstance(device, vim.vm.device.VirtualEthernetCard)] - if first_ether: - boot_order_list.append(vim.vm.BootOptions.BootableEthernetDevice(deviceKey=first_ether[0].key)) - elif device_order == 'floppy': - first_floppy = [device for device in self.vm.config.hardware.device if isinstance(device, vim.vm.device.VirtualFloppy)] - if first_floppy: - boot_order_list.append(vim.vm.BootOptions.BootableFloppyDevice()) - - change_needed = False - kwargs = dict() - if len(boot_order_list) != len(self.vm.config.bootOptions.bootOrder): - kwargs.update({'bootOrder': boot_order_list}) - change_needed = True - else: - for i in range(0, len(boot_order_list)): - boot_device_type = type(boot_order_list[i]) - vm_boot_device_type = type(self.vm.config.bootOptions.bootOrder[i]) - if boot_device_type != vm_boot_device_type: - kwargs.update({'bootOrder': boot_order_list}) - change_needed = True - - if self.vm.config.bootOptions.bootDelay != self.params.get('boot_delay'): - kwargs.update({'bootDelay': self.params.get('boot_delay')}) - change_needed = True - - if self.vm.config.bootOptions.enterBIOSSetup != self.params.get('enter_bios_setup'): - kwargs.update({'enterBIOSSetup': self.params.get('enter_bios_setup')}) - change_needed = True - - if self.vm.config.bootOptions.bootRetryEnabled != self.params.get('boot_retry_enabled'): - kwargs.update({'bootRetryEnabled': self.params.get('boot_retry_enabled')}) - change_needed = True - - if self.vm.config.bootOptions.bootRetryDelay != self.params.get('boot_retry_delay'): - if not self.vm.config.bootOptions.bootRetryEnabled: - kwargs.update({'bootRetryEnabled': True}) - kwargs.update({'bootRetryDelay': self.params.get('boot_retry_delay')}) - change_needed = True - - boot_firmware_required = False - if self.vm.config.firmware != self.params.get('boot_firmware'): - change_needed = True - boot_firmware_required = True - - if self.vm.config.bootOptions.efiSecureBootEnabled != self.params.get('secure_boot_enabled'): - if self.params.get('secure_boot_enabled') and self.params.get('boot_firmware') == "bios": - self.module.fail_json(msg="EFI secure boot cannot be enabled when boot_firmware = bios, but both are specified") - - # If the user is not specifying boot_firmware, make sure they aren't trying to enable it on a - # system with boot_firmware already set to 'bios' - if self.params.get('secure_boot_enabled') and \ - self.params.get('boot_firmware') is None and \ - self.vm.config.firmware == 'bios': - self.module.fail_json(msg="EFI secure boot cannot be enabled when boot_firmware = bios. VM's boot_firmware currently set to bios") - - kwargs.update({'efiSecureBootEnabled': self.params.get('secure_boot_enabled')}) - change_needed = True - - changed = False - results = dict( - previous_boot_order=self.humanize_boot_order(self.vm.config.bootOptions.bootOrder), - previous_boot_delay=self.vm.config.bootOptions.bootDelay, - previous_enter_bios_setup=self.vm.config.bootOptions.enterBIOSSetup, - previous_boot_retry_enabled=self.vm.config.bootOptions.bootRetryEnabled, - previous_boot_retry_delay=self.vm.config.bootOptions.bootRetryDelay, - previous_boot_firmware=self.vm.config.firmware, - previous_secure_boot_enabled=self.vm.config.bootOptions.efiSecureBootEnabled, - current_boot_order=[], - ) - - if change_needed: - vm_conf = vim.vm.ConfigSpec() - vm_conf.bootOptions = vim.vm.BootOptions(**kwargs) - if boot_firmware_required: - vm_conf.firmware = self.params.get('boot_firmware') - task = self.vm.ReconfigVM_Task(vm_conf) - - try: - changed, result = wait_for_task(task) - except TaskError as e: - self.module.fail_json(msg="Failed to perform reconfigure virtual" - " machine %s for boot order due to: %s" % (self.name or self.uuid, - to_native(e))) - - results.update( - { - 'current_boot_order': self.humanize_boot_order(self.vm.config.bootOptions.bootOrder), - 'current_boot_delay': self.vm.config.bootOptions.bootDelay, - 'current_enter_bios_setup': self.vm.config.bootOptions.enterBIOSSetup, - 'current_boot_retry_enabled': self.vm.config.bootOptions.bootRetryEnabled, - 'current_boot_retry_delay': self.vm.config.bootOptions.bootRetryDelay, - 'current_boot_firmware': self.vm.config.firmware, - 'current_secure_boot_enabled': self.vm.config.bootOptions.efiSecureBootEnabled, - } - ) - - self.module.exit_json(changed=changed, vm_boot_status=results) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - name=dict(type='str'), - uuid=dict(type='str'), - moid=dict(type='str'), - use_instance_uuid=dict(type='bool', default=False), - boot_order=dict( - type='list', - default=[], - ), - name_match=dict( - choices=['first', 'last'], - default='first' - ), - boot_delay=dict( - type='int', - default=0, - ), - enter_bios_setup=dict( - type='bool', - default=False, - ), - boot_retry_enabled=dict( - type='bool', - default=False, - ), - boot_retry_delay=dict( - type='int', - default=0, - ), - secure_boot_enabled=dict( - type='bool', - default=False, - ), - boot_firmware=dict( - type='str', - choices=['efi', 'bios'], - ) - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['name', 'uuid', 'moid'] - ], - mutually_exclusive=[ - ['name', 'uuid', 'moid'] - ], - ) - - pyv = VmBootManager(module) - pyv.ensure() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_controller.py b/lib/ansible/modules/cloud/vmware/vmware_guest_controller.py deleted file mode 100644 index 1019fe37dc..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_controller.py +++ /dev/null @@ -1,553 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2019, Ansible Project -# Copyright: (c) 2019, VMware, Inc. All Rights Reserved. -# 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 = ''' ---- -module: vmware_guest_controller -short_description: Manage disk or USB controllers related to virtual machine in given vCenter infrastructure -description: - - This module can be used to add, remove disk controllers or USB controllers belonging to given virtual machine. - - All parameters and VMware object names are case sensitive. -version_added: '2.10' -author: - - Diane Wang (@Tomorrow9) <dianew@vmware.com> -notes: - - Tested on vSphere 6.0, 6.5 and 6.7 -requirements: - - "python >= 2.7" - - PyVmomi -options: - name: - description: - - Name of the virtual machine. - - This is a required parameter, if parameter C(uuid) or C(moid) is not supplied. - type: str - uuid: - description: - - UUID of the instance to gather facts if known, this is VMware's unique identifier. - - This is a required parameter, if parameter C(name) or C(moid) is not supplied. - type: str - moid: - description: - - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. - - This is required if C(name) or C(uuid) is not supplied. - type: str - folder: - description: - - Destination folder, absolute or relative path to find an existing guest. - - This is a required parameter, only if multiple VMs are found with same name. - - The folder should include the datacenter. ESX's datacenter is ha-datacenter - - 'Examples:' - - ' folder: /ha-datacenter/vm' - - ' folder: ha-datacenter/vm' - - ' folder: /datacenter1/vm' - - ' folder: datacenter1/vm' - - ' folder: /datacenter1/vm/folder1' - - ' folder: datacenter1/vm/folder1' - - ' folder: /folder1/datacenter1/vm' - - ' folder: folder1/datacenter1/vm' - - ' folder: /folder1/datacenter1/vm/folder2' - type: str - datacenter: - description: - - The datacenter name to which virtual machine belongs to. - default: ha-datacenter - type: str - use_instance_uuid: - description: - - Whether to use the VMware instance UUID rather than the BIOS UUID. - default: no - type: bool - controllers: - description: - - A list of disk or USB controllers to add or remove. - - Total 4 disk controllers with the same type are allowed per VM. - - Total 2 USB controllers are allowed per VM, 1 USB 2.0 and 1 USB 3.0 or 3.1. - - For specific guest OS, supported controller types please refer to VMware Compatibility Guide. - suboptions: - controller_number: - description: - - Disk controller bus number. When C(state) is set to C(absent), this parameter is required. - - When C(type) set to C(usb2) or C(usb3), this parameter is not required. - type: int - choices: - - 0 - - 1 - - 2 - - 3 - type: - description: - - Type of disk or USB controller. - - From vSphere 6.5 and virtual machine with hardware version 13, C(nvme) controller starts to be supported. - required: true - type: str - choices: - - buslogic - - lsilogic - - lsilogicsas - - paravirtual - - sata - - nvme - - usb2 - - usb3 - state: - description: - - Add new controller or remove specified existing controller. - - If C(state) is set to C(absent), the specified controller will be removed from virtual machine when there is no disk or device attaching to it. - - If specified controller is removed or not exist, no action will be taken only warning message. - - If C(state) is set to C(present), new controller with specified type will be added. - - If the number of controller with specified controller type reaches it's maximum, no action will be taken only warning message. - required: true - type: str - choices: - - present - - absent - type: list - gather_disk_controller_facts: - description: - - Whether to collect existing disk and USB controllers facts only. - - When this parameter is set to C(True), C(controllers) parameter will be ignored. - type: bool - sleep_time: - description: - - 'The sleep time in seconds after VM reconfigure task completes, used when not get the updated VM controller - facts after VM reconfiguration.' - - This parameter is not required. Maximum value is 600. - default: 10 - type: int -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Add disk and USB 3.0 controllers for virtual machine located by name - vmware_guest_controller: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - validate_certs: no - name: test_VM - controllers: - - state: present - type: sata - - state: present - type: nvme - - state: present - type: usb3 - delegate_to: localhost - register: disk_controller_facts - -- name: Remove disk controllers and USB 2.0 from virtual machine located by moid - vmware_guest_controller: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - validate_certs: no - moid: vm-33 - controllers: - - state: absent - controller_number: 1 - type: sata - - state: absent - controller_number: 0 - type: nvme - - state: absent - type: usb2 - delegate_to: localhost - register: disk_controller_facts -''' - -RETURN = """ -disk_controller_status: - description: metadata about the virtual machine's existing disk controllers or after adding or removing operation - returned: always - type: dict - sample: { - "nvme": { - "0": { - "controller_busnumber": 0, - "controller_controllerkey": 100, - "controller_devicekey": 31000, - "controller_disks_devicekey": [], - "controller_label": "NVME controller 0", - "controller_summary": "NVME controller 0", - "controller_unitnumber": 30 - } - }, - "sata": { - "0": { - "controller_busnumber": 0, - "controller_controllerkey": 100, - "controller_devicekey": 15000, - "controller_disks_devicekey": [ - 16000, - 16001 - ], - "controller_label": "SATA controller 0", - "controller_summary": "AHCI", - "controller_unitnumber": 24 - } - }, - "scsi": { - "0": { - "controller_busnumber": 0, - "controller_controllerkey": 100, - "controller_devicekey": 1000, - "controller_disks_devicekey": [ - 2000 - ], - "controller_label": "SCSI controller 0", - "controller_summary": "LSI Logic SAS", - "controller_unitnumber": 3 - }, - "1": { - "controller_busnumber": 1, - "controller_controllerkey": 100, - "controller_devicekey": 1001, - "controller_disks_devicekey": [], - "controller_label": "SCSI controller 1", - "controller_summary": "VMware paravirtual SCSI", - "controller_unitnumber": 4 - } - }, - "usb2": { - "0": { - "controller_busnumber": 0, - "controller_controllerkey": 100, - "controller_devicekey": 7000, - "controller_disks_devicekey": [], - "controller_label": "USB Controller", - "controller_summary": "Auto connect Disabled", - "controller_unitnumber": 22 - } - } - } -""" - -try: - from pyVmomi import vim -except ImportError: - pass - -from random import randint -import time -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils._text import to_native -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec, wait_for_task - - -class PyVmomiHelper(PyVmomi): - def __init__(self, module): - super(PyVmomiHelper, self).__init__(module) - self.sleep_time = 10 - self.scsi_device_type = dict(lsilogic=vim.vm.device.VirtualLsiLogicController, - paravirtual=vim.vm.device.ParaVirtualSCSIController, - buslogic=vim.vm.device.VirtualBusLogicController, - lsilogicsas=vim.vm.device.VirtualLsiLogicSASController) - self.sata_device_type = vim.vm.device.VirtualAHCIController - self.nvme_device_type = vim.vm.device.VirtualNVMEController - self.usb_device_type = dict(usb2=vim.vm.device.VirtualUSBController, - usb3=vim.vm.device.VirtualUSBXHCIController) - self.controller_types = dict(self.scsi_device_type, sata=self.sata_device_type, nvme=self.nvme_device_type) - self.controller_types.update(self.usb_device_type) - self.config_spec = vim.vm.ConfigSpec() - self.config_spec.deviceChange = [] - self.change_detected = False - self.disk_ctl_bus_num_list = dict(sata=list(range(0, 4)), - nvme=list(range(0, 4)), - scsi=list(range(0, 4))) - - def get_unused_ctl_bus_number(self): - """ - Get gid of occupied bus numbers of each type of disk controller, update the available bus number list - """ - for device in self.current_vm_obj.config.hardware.device: - if isinstance(device, self.sata_device_type): - if len(self.disk_ctl_bus_num_list['sata']) != 0: - self.disk_ctl_bus_num_list['sata'].remove(device.busNumber) - if isinstance(device, self.nvme_device_type): - if len(self.disk_ctl_bus_num_list['nvme']) != 0: - self.disk_ctl_bus_num_list['nvme'].remove(device.busNumber) - if isinstance(device, tuple(self.scsi_device_type.values())): - if len(self.disk_ctl_bus_num_list['scsi']) != 0: - self.disk_ctl_bus_num_list['scsi'].remove(device.busNumber) - - def check_ctl_disk_exist(self, ctl_type=None, bus_number=None): - """ - Check if controller of specified type exists and if there is disk attaching to it - Return: Specified controller device, True or False of attaching disks - """ - ctl_specified = None - disks_attached_exist = False - if ctl_type is None: - return ctl_specified, disks_attached_exist - - for device in self.current_vm_obj.config.hardware.device: - if isinstance(device, self.controller_types.get(ctl_type)): - if bus_number is not None and device.busNumber != bus_number: - continue - ctl_specified = device - if len(device.device) != 0: - disks_attached_exist = True - break - - return ctl_specified, disks_attached_exist - - def create_controller(self, ctl_type, bus_number=0): - """ - Create new disk or USB controller with specified type - Args: - ctl_type: controller type - bus_number: disk controller bus number - - Return: Virtual device spec for virtual controller - """ - disk_ctl = vim.vm.device.VirtualDeviceSpec() - disk_ctl.operation = vim.vm.device.VirtualDeviceSpec.Operation.add - if ctl_type == 'sata': - disk_ctl.device = self.sata_device_type() - disk_ctl.device.key = -randint(15000, 19999) - elif ctl_type == 'nvme': - disk_ctl.device = self.nvme_device_type() - disk_ctl.device.key = -randint(31000, 39999) - elif ctl_type in self.scsi_device_type.keys(): - disk_ctl.device = self.scsi_device_type.get(ctl_type)() - disk_ctl.device.key = -randint(1000, 6999) - disk_ctl.device.hotAddRemove = True - disk_ctl.device.sharedBus = 'noSharing' - disk_ctl.device.scsiCtlrUnitNumber = 7 - elif ctl_type in self.usb_device_type.keys(): - disk_ctl.device = self.usb_device_type.get(ctl_type)() - if ctl_type == 'usb2': - disk_ctl.device.key = 7000 - elif ctl_type == 'usb3': - disk_ctl.device.key = 14000 - - disk_ctl.device.deviceInfo = vim.Description() - disk_ctl.device.busNumber = bus_number - - return disk_ctl - - def gather_disk_controller_facts(self): - """ - Gather existing controller facts - - Return: A dictionary of each type controller facts - """ - disk_ctl_facts = dict( - scsi=dict(), - sata=dict(), - nvme=dict(), - usb2=dict(), - usb3=dict() - ) - for device in self.current_vm_obj.config.hardware.device: - ctl_facts_dict = dict() - if isinstance(device, tuple(self.controller_types.values())): - ctl_facts_dict[device.busNumber] = dict( - controller_summary=device.deviceInfo.summary, - controller_label=device.deviceInfo.label, - controller_busnumber=device.busNumber, - controller_controllerkey=device.controllerKey, - controller_devicekey=device.key, - controller_unitnumber=device.unitNumber, - controller_disks_devicekey=device.device, - ) - if isinstance(device, tuple(self.scsi_device_type.values())): - disk_ctl_facts['scsi'].update(ctl_facts_dict) - if isinstance(device, self.nvme_device_type): - disk_ctl_facts['nvme'].update(ctl_facts_dict) - if isinstance(device, self.sata_device_type): - disk_ctl_facts['sata'].update(ctl_facts_dict) - if isinstance(device, self.usb_device_type.get('usb2')): - disk_ctl_facts['usb2'].update(ctl_facts_dict) - if isinstance(device, self.usb_device_type.get('usb3')): - disk_ctl_facts['usb3'].update(ctl_facts_dict) - - return disk_ctl_facts - - def sanitize_disk_controller_config(self): - """ - Check correctness of controller configuration provided by user - - Return: A list of dictionary with checked controller configured - """ - if not self.params.get('controllers'): - self.module.exit_json(changed=False, msg="No controller provided for virtual" - " machine '%s' for management." % self.current_vm_obj.name) - if 10 != self.params.get('sleep_time') <= 300: - self.sleep_time = self.params.get('sleep_time') - exec_get_unused_ctl_bus_number = False - controller_config = self.params.get('controllers') - for ctl_config in controller_config: - if ctl_config: - if ctl_config['type'] not in self.usb_device_type.keys(): - if ctl_config['state'] == 'absent' and ctl_config.get('controller_number') is None: - self.module.fail_json(msg="Disk controller number is required when removing it.") - if ctl_config['state'] == 'present' and not exec_get_unused_ctl_bus_number: - self.get_unused_ctl_bus_number() - exec_get_unused_ctl_bus_number = True - # starts from hardware version 13 nvme controller supported - if ctl_config['state'] == 'present' and ctl_config['type'] == 'nvme': - vm_hwv = int(self.current_vm_obj.config.version.split('-')[1]) - if vm_hwv < 13: - self.module.fail_json(msg="Can not create new NVMe disk controller due to VM hardware version" - " is '%s', not >= 13." % vm_hwv) - if exec_get_unused_ctl_bus_number: - for ctl_config in controller_config: - if ctl_config and ctl_config['state'] == 'present' and ctl_config['type'] not in self.usb_device_type.keys(): - if ctl_config['type'] in self.scsi_device_type.keys(): - if len(self.disk_ctl_bus_num_list['scsi']) != 0: - ctl_config['controller_number'] = self.disk_ctl_bus_num_list['scsi'].pop(0) - else: - ctl_config['controller_number'] = None - elif ctl_config['type'] == 'sata' or ctl_config['type'] == 'nvme': - if len(self.disk_ctl_bus_num_list.get(ctl_config['type'])) != 0: - ctl_config['controller_number'] = self.disk_ctl_bus_num_list.get(ctl_config['type']).pop(0) - else: - ctl_config['controller_number'] = None - - return controller_config - - def configure_disk_controllers(self): - """ - Do disk controller management, add or remove - - Return: Operation result - """ - if self.params['gather_disk_controller_facts']: - results = {'changed': False, 'failed': False, 'disk_controller_data': self.gather_disk_controller_facts()} - return results - - controller_config = self.sanitize_disk_controller_config() - for disk_ctl_config in controller_config: - if disk_ctl_config and disk_ctl_config['state'] == 'present': - # create new USB controller, bus number is 0 - if disk_ctl_config['type'] in self.usb_device_type.keys(): - usb_exists, has_disks_attached = self.check_ctl_disk_exist(disk_ctl_config['type']) - if usb_exists: - self.module.warn("'%s' USB controller already exists, can not add more." % disk_ctl_config['type']) - else: - disk_controller_new = self.create_controller(disk_ctl_config['type']) - self.config_spec.deviceChange.append(disk_controller_new) - self.change_detected = True - # create other disk controller - else: - if disk_ctl_config.get('controller_number') is not None: - disk_controller_new = self.create_controller(disk_ctl_config['type'], disk_ctl_config.get('controller_number')) - self.config_spec.deviceChange.append(disk_controller_new) - self.change_detected = True - else: - if disk_ctl_config['type'] in self.scsi_device_type.keys(): - self.module.warn("Already 4 SCSI controllers, can not add new '%s' controller." % disk_ctl_config['type']) - else: - self.module.warn("Already 4 '%s' controllers, can not add new one." % disk_ctl_config['type']) - elif disk_ctl_config and disk_ctl_config['state'] == 'absent': - existing_ctl, has_disks_attached = self.check_ctl_disk_exist(disk_ctl_config['type'], disk_ctl_config.get('controller_number')) - if existing_ctl is not None: - if not has_disks_attached: - ctl_spec = vim.vm.device.VirtualDeviceSpec() - ctl_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.remove - ctl_spec.device = existing_ctl - self.config_spec.deviceChange.append(ctl_spec) - self.change_detected = True - else: - self.module.warn("Can not remove specified controller, type '%s', bus number '%s'," - " there are disks attaching to it." % (disk_ctl_config['type'], disk_ctl_config.get('controller_number'))) - else: - self.module.warn("Not find specified controller to remove, type '%s', bus number '%s'." - % (disk_ctl_config['type'], disk_ctl_config.get('controller_number'))) - - try: - task = self.current_vm_obj.ReconfigVM_Task(spec=self.config_spec) - wait_for_task(task) - except vim.fault.InvalidDeviceSpec as e: - self.module.fail_json(msg="Failed to configure controller on given virtual machine due to invalid" - " device spec : %s" % to_native(e.msg), - details="Please check ESXi server logs for more details.") - except vim.fault.RestrictedVersion as e: - self.module.fail_json(msg="Failed to reconfigure virtual machine due to" - " product versioning restrictions: %s" % to_native(e.msg)) - if task.info.state == 'error': - results = {'changed': self.change_detected, 'failed': True, 'msg': task.info.error.msg} - else: - if self.change_detected: - time.sleep(self.sleep_time) - results = {'changed': self.change_detected, 'failed': False, 'disk_controller_data': self.gather_disk_controller_facts()} - - return results - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - name=dict(type='str'), - uuid=dict(type='str'), - moid=dict(type='str'), - folder=dict(type='str'), - datacenter=dict(type='str', default='ha-datacenter'), - controllers=dict( - type='list', - elements='dict', - required=False, - options=dict( - state=dict(type='str', choices=['present', 'absent'], required=True), - controller_number=dict(type='int', choices=[0, 1, 2, 3], required=False), - type=dict( - type='str', - choices=['sata', 'nvme', 'lsilogic', 'buslogic', 'lsilogicsas', 'paravirtual', 'usb2', 'usb3'], - required=True, - ), - ), - ), - use_instance_uuid=dict(type='bool', default=False), - gather_disk_controller_facts=dict(type='bool', default=False), - sleep_time=dict(type='int', default=10), - ) - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['name', 'uuid', 'moid'] - ] - ) - - if module.params['folder']: - # FindByInventoryPath() does not require an absolute path - # so we should leave the input folder path unmodified - module.params['folder'] = module.params['folder'].rstrip('/') - - pyv = PyVmomiHelper(module) - # Check if the VM exists before continuing - vm = pyv.get_vm() - - if not vm: - # We unable to find the virtual machine user specified - # Bail out - vm_id = (module.params.get('name') or module.params.get('uuid') or module.params.get('moid')) - module.fail_json(msg="Unable to manage disk or USB controllers for non-existing virtual machine '%s'." % vm_id) - - # VM exists - result = pyv.configure_disk_controllers() - if result['failed']: - module.fail_json(**result) - else: - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_cross_vc_clone.py b/lib/ansible/modules/cloud/vmware/vmware_guest_cross_vc_clone.py deleted file mode 100644 index 7f6f9afb0b..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_cross_vc_clone.py +++ /dev/null @@ -1,429 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2020, Anusha Hegde <anushah@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 = ''' -module: vmware_guest_cross_vc_clone - -short_description: Cross-vCenter VM/template clone - -version_added: '2.10' - -description: - - 'This module can be used for Cross-vCenter vm/template clone' - -options: - name: - description: - - Name of the virtual machine or template. - - This is a required parameter, if parameter C(uuid) or C(moid) is not supplied. - type: str - uuid: - description: - - UUID of the vm/template instance to clone from, this is VMware's unique identifier. - - This is a required parameter, if parameter C(name) or C(moid) is not supplied. - type: str - moid: - description: - - Managed Object ID of the vm/template instance to manage if known, this is a unique identifier only within a single vCenter instance. - - This is required if C(name) or C(uuid) is not supplied. - type: str - use_instance_uuid: - description: - - Whether to use the VMware instance UUID rather than the BIOS UUID. - default: no - type: bool - destination_vm_name: - description: - - The name of the cloned VM. - type: str - required: True - destination_vcenter: - description: - - The hostname or IP address of the destination VCenter. - type: str - required: True - destination_vcenter_username: - description: - - The username of the destination VCenter. - type: str - required: True - destination_vcenter_password: - description: - - The password of the destination VCenter. - type: str - required: True - destination_vcenter_port: - description: - - The port to establish connection in the destination VCenter. - type: int - default: 443 - destination_vcenter_validate_certs: - description: - - Parameter to indicate if certification validation needs to be done on destination VCenter. - type: bool - default: False - destination_host: - description: - - The name of the destination host. - type: str - required: True - destination_datastore: - description: - - The name of the destination datastore or the datastore cluster. - - If datastore cluster name is specified, we will find the Storage DRS recommended datastore in that cluster. - type: str - required: True - destination_vm_folder: - description: - - Destination folder, absolute path to deploy the cloned vm. - - This parameter is case sensitive. - - 'Examples:' - - ' folder: vm' - - ' folder: ha-datacenter/vm' - - ' folder: /datacenter1/vm' - type: str - required: True - destination_resource_pool: - description: - - Destination resource pool. - - If not provided, the destination host's parent's resource pool will be used. - type: str - state: - description: - - The state of Virtual Machine deployed. - - 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.documentation - -author: - - Anusha Hegde (@anusha94) -''' - -EXAMPLES = ''' -# Clone template -- name: clone a template across VC - vmware_guest_cross_vc_clone: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - name: "test_vm1" - destination_vm_name: "cloned_vm_from_template" - destination_vcenter: '{{ destination_vcenter_hostname }}' - destination_vcenter_username: '{{ destination_vcenter_username }}' - destination_vcenter_password: '{{ destination_vcenter_password }}' - destination_vcenter_port: '{{ destination_vcenter_port }}' - destination_vcenter_validate_certs: '{{ destination_vcenter_validate_certs }}' - destination_host: '{{ destination_esxi }}' - destination_datastore: '{{ destination_datastore }}' - destination_vm_folder: '{{ destination_vm_folder }}' - state: present - register: cross_vc_clone_from_template - -- name: clone a VM across VC - vmware_guest_cross_vc_clone: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: "{{ vcenter_password }}" - validate_certs: no - name: "test_vm1" - destination_vm_name: "cloned_vm_from_vm" - destination_vcenter: '{{ destination_vcenter_hostname }}' - destination_vcenter_username: '{{ destination_vcenter_username }}' - destination_vcenter_password: '{{ destination_vcenter_password }}' - destination_host: '{{ destination_esxi }}' - destination_datastore: '{{ destination_datastore }}' - destination_vm_folder: '{{ destination_vm_folder }}' - state: poweredon - register: cross_vc_clone_from_vm - -- name: check_mode support - vmware_guest_cross_vc_clone: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: "{{ vcenter_password }}" - validate_certs: no - name: "test_vm1" - destination_vm_name: "cloned_vm_from_vm" - destination_vcenter: '{{ destination_vcenter_hostname }}' - destination_vcenter_username: '{{ destination_vcenter_username }}' - destination_vcenter_password: '{{ destination_vcenter_password }}' - destination_host: '{{ destination_esxi }}' - destination_datastore: '{{ destination_datastore }}' - destination_vm_folder: '{{ destination_vm_folder }}' - check_mode: yes -''' - -RETURN = r''' -vm_info: - description: metadata about the virtual machine - returned: always - type: dict - sample: { - "vm_name": "", - "vcenter": "", - "host": "", - "datastore": "", - "vm_folder": "", - "power_on": "" - } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import (PyVmomi, find_hostsystem_by_name, - find_datastore_by_name, - find_folder_by_name, find_vm_by_name, - connect_to_api, vmware_argument_spec, - gather_vm_facts, find_obj, find_resource_pool_by_name, - wait_for_task, TaskError) -from ansible.module_utils._text import to_native -try: - from pyVmomi import vim -except ImportError: - pass - - -class CrossVCCloneManager(PyVmomi): - def __init__(self, module): - super(CrossVCCloneManager, self).__init__(module) - self.config_spec = vim.vm.ConfigSpec() - self.clone_spec = vim.vm.CloneSpec() - self.relocate_spec = vim.vm.RelocateSpec() - self.service_locator = vim.ServiceLocator() - self.destination_vcenter = self.params['destination_vcenter'] - self.destination_vcenter_username = self.params['destination_vcenter_username'] - self.destination_vcenter_password = self.params['destination_vcenter_password'] - self.destination_vcenter_port = self.params.get('port', 443) - self.destination_vcenter_validate_certs = self.params.get('destination_vcenter_validate_certs', None) - - def get_new_vm_info(self, vm): - # to check if vm has been cloned in the destination vc - # query for the vm in destination vc - # get the host and datastore info - # get the power status of the newly cloned vm - info = {} - vm_obj = find_vm_by_name(content=self.destination_content, vm_name=vm) - if vm_obj is None: - self.module.fail_json(msg="Newly cloned VM is not found in the destination VCenter") - else: - vm_facts = gather_vm_facts(self.destination_content, vm_obj) - info['vm_name'] = vm - info['vcenter'] = self.destination_vcenter - info['host'] = vm_facts['hw_esxi_host'] - info['datastore'] = vm_facts['hw_datastores'] - info['vm_folder'] = vm_facts['hw_folder'] - info['power_on'] = vm_facts['hw_power_status'] - return info - - def clone(self): - # clone the vm/template on destination VC - vm_folder = find_folder_by_name(content=self.destination_content, folder_name=self.params['destination_vm_folder']) - if not vm_folder: - self.module.fail_json(msg="Destination folder does not exist. Please refer to the documentation to correctly specify the folder.") - vm_name = self.params['destination_vm_name'] - task = self.vm_obj.Clone(folder=vm_folder, name=vm_name, spec=self.clone_spec) - wait_for_task(task) - if task.info.state == 'error': - result = {'changed': False, 'failed': True, 'msg': task.info.error.msg} - else: - vm_info = self.get_new_vm_info(vm_name) - result = {'changed': True, 'failed': False, 'vm_info': vm_info} - return result - - def sanitize_params(self): - ''' - this method is used to verify user provided parameters - ''' - self.vm_obj = self.get_vm() - if self.vm_obj is None: - vm_id = self.vm_uuid or self.vm_name or self.moid - self.module.fail_json(msg="Failed to find the VM/template with %s" % vm_id) - - # connect to destination VC - self.destination_content = connect_to_api( - self.module, - hostname=self.destination_vcenter, - username=self.destination_vcenter_username, - password=self.destination_vcenter_password, - port=self.destination_vcenter_port, - validate_certs=self.destination_vcenter_validate_certs) - - # Check if vm name already exists in the destination VC - vm = find_vm_by_name(content=self.destination_content, vm_name=self.params['destination_vm_name']) - if vm: - self.module.exit_json(changed=False, msg="A VM with the given name already exists") - - datastore_name = self.params['destination_datastore'] - datastore_cluster = find_obj(self.destination_content, [vim.StoragePod], datastore_name) - if datastore_cluster: - # If user specified datastore cluster so get recommended datastore - datastore_name = self.get_recommended_datastore(datastore_cluster_obj=datastore_cluster) - # Check if get_recommended_datastore or user specified datastore exists or not - self.destination_datastore = find_datastore_by_name(content=self.destination_content, datastore_name=datastore_name) - if self.destination_datastore is None: - self.module.fail_json(msg="Destination datastore not found.") - - self.destination_host = find_hostsystem_by_name(content=self.destination_content, hostname=self.params['destination_host']) - if self.destination_host is None: - self.module.fail_json(msg="Destination host not found.") - - if self.params['destination_resource_pool']: - self.destination_resource_pool = find_resource_pool_by_name( - content=self.destination_content, - resource_pool_name=self.params['destination_resource_pool']) - else: - self.destination_resource_pool = self.destination_host.parent.resourcePool - - def populate_specs(self): - # populate service locator - self.service_locator.instanceUuid = self.destination_content.about.instanceUuid - self.service_locator.url = "https://" + self.destination_vcenter + ":" + str(self.params['port']) + "/sdk" - creds = vim.ServiceLocatorNamePassword() - creds.username = self.destination_vcenter_username - creds.password = self.destination_vcenter_password - self.service_locator.credential = creds - - # populate relocate spec - self.relocate_spec.datastore = self.destination_datastore - self.relocate_spec.pool = self.destination_resource_pool - self.relocate_spec.service = self.service_locator - self.relocate_spec.host = self.destination_host - - # populate clone spec - self.clone_spec.config = self.config_spec - self.clone_spec.powerOn = True if self.params['state'].lower() == 'poweredon' else False - self.clone_spec.location = self.relocate_spec - - def get_recommended_datastore(self, datastore_cluster_obj=None): - """ - Function to return Storage DRS recommended datastore from datastore cluster - Args: - datastore_cluster_obj: datastore cluster managed object - Returns: Name of recommended datastore from the given datastore cluster - """ - if datastore_cluster_obj is None: - return None - # Check if Datastore Cluster provided by user is SDRS ready - sdrs_status = datastore_cluster_obj.podStorageDrsEntry.storageDrsConfig.podConfig.enabled - if sdrs_status: - # We can get storage recommendation only if SDRS is enabled on given datastorage cluster - pod_sel_spec = vim.storageDrs.PodSelectionSpec() - pod_sel_spec.storagePod = datastore_cluster_obj - storage_spec = vim.storageDrs.StoragePlacementSpec() - storage_spec.podSelectionSpec = pod_sel_spec - storage_spec.type = 'create' - - try: - rec = self.content.storageResourceManager.RecommendDatastores(storageSpec=storage_spec) - rec_action = rec.recommendations[0].action[0] - return rec_action.destination.name - except Exception: - # There is some error so we fall back to general workflow - pass - datastore = None - datastore_freespace = 0 - for ds in datastore_cluster_obj.childEntity: - if isinstance(ds, vim.Datastore) and ds.summary.freeSpace > datastore_freespace: - # If datastore field is provided, filter destination datastores - if not self.is_datastore_valid(datastore_obj=ds): - continue - - datastore = ds - datastore_freespace = ds.summary.freeSpace - if datastore: - return datastore.name - return None - - -def main(): - """ - Main method - """ - argument_spec = vmware_argument_spec() - argument_spec.update( - name=dict(type='str'), - uuid=dict(type='str'), - moid=dict(type='str'), - use_instance_uuid=dict(type='bool', default=False), - destination_vm_name=dict(type='str', required=True), - destination_datastore=dict(type='str', required=True), - destination_host=dict(type='str', required=True), - destination_vcenter=dict(type='str', required=True), - destination_vcenter_username=dict(type='str', required=True), - destination_vcenter_password=dict(type='str', required=True, no_log=True), - destination_vcenter_port=dict(type='int', default=443), - destination_vcenter_validate_certs=dict(type='bool', default=False), - destination_vm_folder=dict(type='str', required=True), - destination_resource_pool=dict(type='str', default=None), - state=dict(type='str', default='present', - choices=['present', 'poweredon']) - ) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - required_one_of=[ - ['uuid', 'name', 'moid'], - ], - mutually_exclusive=[ - ['uuid', 'name', 'moid'], - ], - ) - result = {'failed': False, 'changed': False} - if module.check_mode: - if module.params['state'] in ['present']: - result.update( - vm_name=module.params['destination_vm_name'], - vcenter=module.params['destination_vcenter'], - host=module.params['destination_host'], - datastore=module.params['destination_datastore'], - vm_folder=module.params['destination_vm_folder'], - state=module.params['state'], - changed=True, - desired_operation='Create VM with PowerOff State' - ) - if module.params['state'] == 'poweredon': - result.update( - vm_name=module.params['destination_vm_name'], - vcenter=module.params['destination_vcenter'], - host=module.params['destination_host'], - datastore=module.params['destination_datastore'], - vm_folder=module.params['destination_vm_folder'], - state=module.params['state'], - changed=True, - desired_operation='Create VM with PowerON State' - ) - module.exit_json(**result) - - clone_manager = CrossVCCloneManager(module) - clone_manager.sanitize_params() - clone_manager.populate_specs() - result = clone_manager.clone() - - if result['failed']: - module.fail_json(**result) - else: - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_custom_attribute_defs.py b/lib/ansible/modules/cloud/vmware/vmware_guest_custom_attribute_defs.py deleted file mode 100644 index ae66304c94..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_custom_attribute_defs.py +++ /dev/null @@ -1,152 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Ansible Project -# -# 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 = ''' ---- -module: vmware_guest_custom_attribute_defs -short_description: Manage custom attributes definitions for virtual machine from VMware -description: - - This module can be used to add and remove custom attributes definitions for the given virtual machine from VMware. -version_added: 2.7 -author: - - Jimmy Conner (@cigamit) - - Abhijeet Kasurde (@Akasurde) -notes: - - Tested on vSphere 6.5 -requirements: - - "python >= 2.6" - - PyVmomi -options: - attribute_key: - description: - - Name of the custom attribute definition. - - This is required parameter, if C(state) is set to C(present) or C(absent). - required: False - type: str - state: - description: - - Manage definition of custom attributes. - - If set to C(present) and definition not present, then custom attribute definition is created. - - If set to C(present) and definition is present, then no action taken. - - If set to C(absent) and definition is present, then custom attribute definition is removed. - - If set to C(absent) and definition is absent, then no action taken. - default: 'present' - choices: ['present', 'absent'] - required: True - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Add VMware Attribute Definition - vmware_guest_custom_attribute_defs: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - state: present - attribute_key: custom_attr_def_1 - delegate_to: localhost - register: defs - -- name: Remove VMware Attribute Definition - vmware_guest_custom_attribute_defs: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - state: absent - attribute_key: custom_attr_def_1 - delegate_to: localhost - register: defs -''' - -RETURN = """ -custom_attribute_defs: - description: list of all current attribute definitions - returned: always - type: list - sample: ["sample_5", "sample_4"] -""" - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec - -try: - from pyVmomi import vim -except ImportError: - pass - - -class VmAttributeDefManager(PyVmomi): - def __init__(self, module): - super(VmAttributeDefManager, self).__init__(module) - - def remove_custom_def(self, field): - changed = False - f = dict() - for x in self.custom_field_mgr: - if x.name == field and x.managedObjectType == vim.VirtualMachine: - changed = True - if not self.module.check_mode: - self.content.customFieldsManager.RemoveCustomFieldDef(key=x.key) - break - f[x.name] = (x.key, x.managedObjectType) - return {'changed': changed, 'failed': False, 'custom_attribute_defs': list(f.keys())} - - def add_custom_def(self, field): - changed = False - found = False - f = dict() - for x in self.custom_field_mgr: - if x.name == field: - found = True - f[x.name] = (x.key, x.managedObjectType) - - if not found: - changed = True - if not self.module.check_mode: - new_field = self.content.customFieldsManager.AddFieldDefinition(name=field, moType=vim.VirtualMachine) - f[new_field.name] = (new_field.key, new_field.type) - return {'changed': changed, 'failed': False, 'custom_attribute_defs': list(f.keys())} - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - attribute_key=dict(type='str'), - state=dict(type='str', default='present', choices=['absent', 'present']), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - required_if=[ - ['state', 'present', ['attribute_key']], - ['state', 'absent', ['attribute_key']], - ] - ) - - pyv = VmAttributeDefManager(module) - results = dict(changed=False, custom_attribute_defs=list()) - if module.params['state'] == "present": - results = pyv.add_custom_def(module.params['attribute_key']) - elif module.params['state'] == "absent": - results = pyv.remove_custom_def(module.params['attribute_key']) - - module.exit_json(**results) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_custom_attributes.py b/lib/ansible/modules/cloud/vmware/vmware_guest_custom_attributes.py deleted file mode 100644 index e55a3ad754..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_custom_attributes.py +++ /dev/null @@ -1,259 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright, (c) 2018, Ansible Project -# Copyright, (c) 2018, Abhijeet Kasurde <akasurde@redhat.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 = ''' ---- -module: vmware_guest_custom_attributes -short_description: Manage custom attributes from VMware for the given virtual machine -description: - - This module can be used to add, remove and update custom attributes for the given virtual machine. -version_added: 2.7 -author: - - Jimmy Conner (@cigamit) - - Abhijeet Kasurde (@Akasurde) -notes: - - Tested on vSphere 6.5 -requirements: - - "python >= 2.6" - - PyVmomi -options: - name: - description: - - Name of the virtual machine to work with. - - This is required parameter, if C(uuid) or C(moid) is not supplied. - type: str - state: - description: - - The action to take. - - If set to C(present), then custom attribute is added or updated. - - If set to C(absent), then custom attribute is removed. - default: 'present' - choices: ['present', 'absent'] - type: str - uuid: - description: - - UUID of the virtual machine to manage if known. This is VMware's unique identifier. - - This is required parameter, if C(name) or C(moid) is not supplied. - type: str - moid: - description: - - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. - - This is required if C(name) or C(uuid) is not supplied. - version_added: '2.9' - type: str - use_instance_uuid: - description: - - Whether to use the VMware instance UUID rather than the BIOS UUID. - default: no - type: bool - version_added: '2.8' - folder: - description: - - Absolute path to find an existing guest. - - This is required parameter, if C(name) is supplied and multiple virtual machines with same name are found. - type: str - datacenter: - description: - - Datacenter name where the virtual machine is located in. - required: True - type: str - attributes: - description: - - A list of name and value of custom attributes that needs to be manage. - - Value of custom attribute is not required and will be ignored, if C(state) is set to C(absent). - default: [] - type: list -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Add virtual machine custom attributes - vmware_guest_custom_attributes: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - uuid: 421e4592-c069-924d-ce20-7e7533fab926 - state: present - attributes: - - name: MyAttribute - value: MyValue - delegate_to: localhost - register: attributes - -- name: Add multiple virtual machine custom attributes - vmware_guest_custom_attributes: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - uuid: 421e4592-c069-924d-ce20-7e7533fab926 - state: present - attributes: - - name: MyAttribute - value: MyValue - - name: MyAttribute2 - value: MyValue2 - delegate_to: localhost - register: attributes - -- name: Remove virtual machine Attribute - vmware_guest_custom_attributes: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - uuid: 421e4592-c069-924d-ce20-7e7533fab926 - state: absent - attributes: - - name: MyAttribute - delegate_to: localhost - register: attributes - -- name: Remove virtual machine Attribute using Virtual Machine MoID - vmware_guest_custom_attributes: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - moid: vm-42 - state: absent - attributes: - - name: MyAttribute - delegate_to: localhost - register: attributes -''' - -RETURN = """ -custom_attributes: - description: metadata about the virtual machine attributes - returned: always - type: dict - sample: { - "mycustom": "my_custom_value", - "mycustom_2": "my_custom_value_2", - "sample_1": "sample_1_value", - "sample_2": "sample_2_value", - "sample_3": "sample_3_value" - } -""" - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec - - -class VmAttributeManager(PyVmomi): - def __init__(self, module): - super(VmAttributeManager, self).__init__(module) - - def set_custom_field(self, vm, user_fields): - result_fields = dict() - change_list = list() - changed = False - - for field in user_fields: - field_key = self.check_exists(field['name']) - found = False - field_value = field.get('value', '') - - for k, v in [(x.name, v.value) for x in self.custom_field_mgr for v in vm.customValue if x.key == v.key]: - if k == field['name']: - found = True - if v != field_value: - if not self.module.check_mode: - self.content.customFieldsManager.SetField(entity=vm, key=field_key.key, value=field_value) - result_fields[k] = field_value - change_list.append(True) - if not found and field_value != "": - if not field_key and not self.module.check_mode: - field_key = self.content.customFieldsManager.AddFieldDefinition(name=field['name'], moType=vim.VirtualMachine) - change_list.append(True) - if not self.module.check_mode: - self.content.customFieldsManager.SetField(entity=vm, key=field_key.key, value=field_value) - result_fields[field['name']] = field_value - - if any(change_list): - changed = True - - return {'changed': changed, 'failed': False, 'custom_attributes': result_fields} - - def check_exists(self, field): - for x in self.custom_field_mgr: - if x.name == field: - return x - return False - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - datacenter=dict(type='str'), - name=dict(type='str'), - folder=dict(type='str'), - uuid=dict(type='str'), - moid=dict(type='str'), - use_instance_uuid=dict(type='bool', default=False), - state=dict(type='str', default='present', - choices=['absent', 'present']), - attributes=dict( - type='list', - default=[], - options=dict( - name=dict(type='str', required=True), - value=dict(type='str'), - ) - ), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - required_one_of=[ - ['name', 'uuid', 'moid'] - ], - ) - - if module.params.get('folder'): - # FindByInventoryPath() does not require an absolute path - # so we should leave the input folder path unmodified - module.params['folder'] = module.params['folder'].rstrip('/') - - pyv = VmAttributeManager(module) - results = {'changed': False, 'failed': False, 'instance': dict()} - - # Check if the virtual machine exists before continuing - vm = pyv.get_vm() - - if vm: - # virtual machine already exists - if module.params['state'] == "present": - results = pyv.set_custom_field(vm, module.params['attributes']) - elif module.params['state'] == "absent": - results = pyv.set_custom_field(vm, module.params['attributes']) - module.exit_json(**results) - else: - # virtual machine does not exists - vm_id = (module.params.get('name') or module.params.get('uuid') or module.params.get('moid')) - module.fail_json(msg="Unable to manage custom attributes for non-existing" - " virtual machine %s" % vm_id) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_customization_info.py b/lib/ansible/modules/cloud/vmware/vmware_guest_customization_info.py deleted file mode 100644 index a8e0e26618..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_customization_info.py +++ /dev/null @@ -1,193 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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 = ''' ---- -module: vmware_guest_customization_info -short_description: Gather info about VM customization specifications -description: - - This module can be used to gather information about customization specifications. - - All parameters and VMware object names are case sensitive. -version_added: '2.9' -author: - - Abhijeet Kasurde (@Akasurde) -notes: - - Tested on vSphere 6.0 and 6.5 -requirements: - - "python >= 2.6" - - PyVmomi -options: - spec_name: - description: - - Name of customization specification to find. - required: False - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Gather info about all customization specification - vmware_guest_customization_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - delegate_to: localhost - register: all_custom_spec_info - -- name: Gather info about customization specification with the given name - vmware_guest_customization_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - spec_name: custom_linux_spec - delegate_to: localhost - register: custom_spec_info -''' - -RETURN = """ -custom_spec_info: - description: metadata about the customization specification - returned: always - type: dict - sample: { - "assignip-eee0d684-44b7-457c-8c55-2585590b0d99": { - "change_version": "1523438001", - "description": "sample description", - "dns_server_list": [], - "dns_suffix_list": [], - "domain": "None", - "hostname": "sample1", - "hw_clock_utc": null, - "last_updated_time": "2018-04-11T09:13:21+00:00", - "name": "sample", - "nic_setting_map": [ - { - "dns_domain": null, - "gateway": [], - "ip_address": "192.168.10.10", - "net_bios": null, - "nic_dns_server_list": [], - "primary_wins": null, - "secondry_wins": null, - "subnet_mask": "255.255.255.0" - } - ], - "time_zone": null, - "type": "Linux" - }, - } -""" - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils._text import to_text -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec - - -class VmwareCustomSpecManger(PyVmomi): - def __init__(self, module): - super(VmwareCustomSpecManger, self).__init__(module) - self.cc_mgr = self.content.customizationSpecManager - if self.cc_mgr is None: - self.module.fail_json(msg="Failed to get customization spec manager.") - - def gather_custom_spec_info(self): - """ - Gather information about customization specifications - """ - - spec_name = self.params.get('spec_name', None) - specs_list = [] - if spec_name: - if self.cc_mgr.DoesCustomizationSpecExist(name=spec_name): - specs_list.append(spec_name) - else: - self.module.fail_json(msg="Unable to find customization specification named '%s'" % spec_name) - else: - available_specs = self.cc_mgr.info - for spec_info in available_specs: - specs_list.append(spec_info.name) - - spec_info = dict() - for spec in specs_list: - current_spec = self.cc_mgr.GetCustomizationSpec(name=spec) - adapter_mapping_list = [] - for nic in current_spec.spec.nicSettingMap: - temp_data = dict( - mac_address=nic.macAddress, - ip_address=nic.adapter.ip.ipAddress, - subnet_mask=nic.adapter.subnetMask, - gateway=[gw for gw in nic.adapter.gateway], - nic_dns_server_list=[ndsl for ndsl in nic.adapter.dnsServerList], - dns_domain=nic.adapter.dnsDomain, - primary_wins=nic.adapter.primaryWINS, - secondry_wins=nic.adapter.secondaryWINS, - net_bios=nic.adapter.netBIOS, - ) - adapter_mapping_list.append(temp_data) - - current_hostname = None - if isinstance(current_spec.spec.identity.hostName, vim.vm.customization.PrefixNameGenerator): - current_hostname = current_spec.spec.identity.hostName.base - elif isinstance(current_spec.spec.identity.hostName, vim.vm.customization.FixedName): - current_hostname = current_spec.spec.identity.hostName.name - - spec_info[spec] = dict( - # Spec - name=current_spec.info.name, - description=current_spec.info.description, - type=current_spec.info.type, - last_updated_time=current_spec.info.lastUpdateTime, - change_version=current_spec.info.changeVersion, - # Identity - hostname=current_hostname, - domain=current_spec.spec.identity.domain, - time_zone=current_spec.spec.identity.timeZone, - hw_clock_utc=current_spec.spec.identity.hwClockUTC, - # global IP Settings - dns_suffix_list=[i for i in current_spec.spec.globalIPSettings.dnsSuffixList], - dns_server_list=[i for i in current_spec.spec.globalIPSettings.dnsServerList], - # NIC setting map - nic_setting_map=adapter_mapping_list, - ) - return spec_info - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - spec_name=dict(type='str'), - ) - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True - ) - - pyv = VmwareCustomSpecManger(module) - try: - module.exit_json(custom_spec_info=pyv.gather_custom_spec_info()) - except Exception as exc: - module.fail_json(msg="Failed to gather information with exception : %s" % to_text(exc)) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_disk.py b/lib/ansible/modules/cloud/vmware/vmware_guest_disk.py deleted file mode 100644 index 41889d3835..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_disk.py +++ /dev/null @@ -1,886 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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 = ''' ---- -module: vmware_guest_disk -short_description: Manage disks related to virtual machine in given vCenter infrastructure -description: - - This module can be used to add, remove and update disks belonging to given virtual machine. - - All parameters and VMware object names are case sensitive. - - This module is destructive in nature, please read documentation carefully before proceeding. - - Be careful while removing disk specified as this may lead to data loss. -version_added: 2.8 -author: - - Abhijeet Kasurde (@Akasurde) <akasurde@redhat.com> -notes: - - Tested on vSphere 6.0 and 6.5 -requirements: - - "python >= 2.6" - - PyVmomi -options: - name: - description: - - Name of the virtual machine. - - This is a required parameter, if parameter C(uuid) or C(moid) is not supplied. - type: str - uuid: - description: - - UUID of the instance to gather facts if known, this is VMware's unique identifier. - - This is a required parameter, if parameter C(name) or C(moid) is not supplied. - type: str - moid: - description: - - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. - - This is required if C(name) or C(uuid) is not supplied. - version_added: '2.9' - type: str - folder: - description: - - Destination folder, absolute or relative path to find an existing guest. - - This is a required parameter, only if multiple VMs are found with same name. - - The folder should include the datacenter. ESX's datacenter is ha-datacenter - - 'Examples:' - - ' folder: /ha-datacenter/vm' - - ' folder: ha-datacenter/vm' - - ' folder: /datacenter1/vm' - - ' folder: datacenter1/vm' - - ' folder: /datacenter1/vm/folder1' - - ' folder: datacenter1/vm/folder1' - - ' folder: /folder1/datacenter1/vm' - - ' folder: folder1/datacenter1/vm' - - ' folder: /folder1/datacenter1/vm/folder2' - type: str - datacenter: - description: - - The datacenter name to which virtual machine belongs to. - required: True - type: str - use_instance_uuid: - description: - - Whether to use the VMware instance UUID rather than the BIOS UUID. - default: no - type: bool - version_added: '2.8' - disk: - description: - - A list of disks to add. - - The virtual disk related information is provided using this list. - - All values and parameters are case sensitive. - - 'Valid attributes are:' - - ' - C(size[_tb,_gb,_mb,_kb]) (integer): Disk storage size in specified unit.' - - ' If C(size) specified then unit must be specified. There is no space allowed in between size number and unit.' - - ' Only first occurrence in disk element will be considered, even if there are multiple size* parameters available.' - - ' - C(type) (string): Valid values are:' - - ' - C(thin) thin disk' - - ' - C(eagerzeroedthick) eagerzeroedthick disk' - - ' - C(thick) thick disk' - - ' Default: C(thick) thick disk, no eagerzero.' - - ' - C(disk_mode) (string): Type of disk mode. Valid values are:' - - ' - C(persistent) Changes are immediately and permanently written to the virtual disk. This is default.' - - ' - C(independent_persistent) Same as persistent, but not affected by snapshots.' - - ' - C(independent_nonpersistent) Changes to virtual disk are made to a redo log and discarded at power off, but not affected by snapshots.' - - ' - C(datastore) (string): Name of datastore or datastore cluster to be used for the disk.' - - ' - C(autoselect_datastore) (bool): Select the less used datastore. Specify only if C(datastore) is not specified.' - - ' - C(scsi_controller) (integer): SCSI controller number. Valid value range from 0 to 3.' - - ' Only 4 SCSI controllers are allowed per VM.' - - ' Care should be taken while specifying C(scsi_controller) is 0 and C(unit_number) as 0 as this disk may contain OS.' - - ' - C(unit_number) (integer): Disk Unit Number. Valid value range from 0 to 15. Only 15 disks are allowed per SCSI Controller.' - - ' - C(scsi_type) (string): Type of SCSI controller. This value is required only for the first occurrence of SCSI Controller.' - - ' This value is ignored, if SCSI Controller is already present or C(state) is C(absent).' - - ' Valid values are C(buslogic), C(lsilogic), C(lsilogicsas) and C(paravirtual).' - - ' C(paravirtual) is default value for this parameter.' - - ' - C(destroy) (bool): If C(state) is C(absent), make sure the disk file is deleted from the datastore (default C(yes)).' - - ' Added in version 2.10.' - - ' - C(filename) (string): Existing disk image to be used. Filename must already exist on the datastore.' - - ' Specify filename string in C([datastore_name] path/to/file.vmdk) format. Added in version 2.10.' - - ' - C(state) (string): State of disk. This is either "absent" or "present".' - - ' If C(state) is set to C(absent), disk will be removed permanently from virtual machine configuration and from VMware storage.' - - ' If C(state) is set to C(present), disk will be added if not present at given SCSI Controller and Unit Number.' - - ' If C(state) is set to C(present) and disk exists with different size, disk size is increased.' - - ' Reducing disk size is not allowed.' - suboptions: - iolimit: - description: - - Section specifies the shares and limit for storage I/O resource. - suboptions: - limit: - description: - - Section specifies values for limit where the utilization of a virtual machine will not exceed, even if there are available resources. - shares: - description: - - Specifies different types of shares user can add for the given disk. - suboptions: - level: - description: - - Specifies different level for the shares section. - - Valid values are low, normal, high, custom. - level_value: - description: - - Custom value when C(level) is set as C(custom). - type: int - type: list - elements: dict - shares: - description: - - section for iolimit section tells about what are all different types of shares user can add for disk. - suboptions: - level: - description: - - tells about different level for the shares section, valid values are low,normal,high,custom. - type: str - level_value: - description: - - custom value when level is set as custom. - type: int - type: list - elements: dict - default: [] - type: list -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Add disks to virtual machine using UUID - vmware_guest_disk: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - validate_certs: no - uuid: 421e4592-c069-924d-ce20-7e7533fab926 - disk: - - size_mb: 10 - type: thin - datastore: datacluster0 - state: present - scsi_controller: 1 - unit_number: 1 - scsi_type: 'paravirtual' - disk_mode: 'persistent' - - size_gb: 10 - type: eagerzeroedthick - state: present - autoselect_datastore: True - scsi_controller: 2 - scsi_type: 'buslogic' - unit_number: 12 - disk_mode: 'independent_persistent' - - size: 10Gb - type: eagerzeroedthick - state: present - autoselect_datastore: True - scsi_controller: 2 - scsi_type: 'buslogic' - unit_number: 1 - disk_mode: 'independent_nonpersistent' - - filename: "[datastore1] path/to/existing/disk.vmdk" - delegate_to: localhost - register: disk_facts - -- name: Add disks with specified shares to the virtual machine - vmware_guest_disk: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - validate_certs: no - disk: - - size_gb: 1 - type: thin - datastore: datacluster0 - state: present - scsi_controller: 1 - unit_number: 1 - disk_mode: 'independent_persistent' - shares: - level: custom - level_value: 1300 - delegate_to: localhost - register: test_custom_shares - -- name: create new disk with custom IO limits and shares in IO Limits - vmware_guest_disk: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - validate_certs: no - disk: - - size_gb: 1 - type: thin - datastore: datacluster0 - state: present - scsi_controller: 1 - unit_number: 1 - disk_mode: 'independent_persistent' - iolimit: - limit: 1506 - shares: - level: custom - level_value: 1305 - delegate_to: localhost - register: test_custom_IoLimit_shares - -- name: Remove disks from virtual machine using name - vmware_guest_disk: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - validate_certs: no - name: VM_225 - disk: - - state: absent - scsi_controller: 1 - unit_number: 1 - delegate_to: localhost - register: disk_facts - -- name: Remove disk from virtual machine using moid - vmware_guest_disk: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - validate_certs: no - moid: vm-42 - disk: - - state: absent - scsi_controller: 1 - unit_number: 1 - delegate_to: localhost - register: disk_facts - -- name: Remove disk from virtual machine but keep the VMDK file on the datastore - vmware_guest_disk: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - validate_certs: no - name: VM_225 - disk: - - state: absent - scsi_controller: 1 - unit_number: 2 - destroy: no - delegate_to: localhost - register: disk_facts -''' - -RETURN = """ -disk_status: - description: metadata about the virtual machine's disks after managing them - returned: always - type: dict - sample: { - "0": { - "backing_datastore": "datastore2", - "backing_disk_mode": "persistent", - "backing_eagerlyscrub": false, - "backing_filename": "[datastore2] VM_225/VM_225.vmdk", - "backing_thinprovisioned": false, - "backing_writethrough": false, - "capacity_in_bytes": 10485760, - "capacity_in_kb": 10240, - "controller_key": 1000, - "key": 2000, - "label": "Hard disk 1", - "summary": "10,240 KB", - "unit_number": 0 - }, - } -""" - -import re -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils._text import to_native -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec, wait_for_task, find_obj, get_all_objs - - -class PyVmomiHelper(PyVmomi): - def __init__(self, module): - super(PyVmomiHelper, self).__init__(module) - self.desired_disks = self.params['disk'] # Match with vmware_guest parameter - self.vm = None - self.scsi_device_type = dict(lsilogic=vim.vm.device.VirtualLsiLogicController, - paravirtual=vim.vm.device.ParaVirtualSCSIController, - buslogic=vim.vm.device.VirtualBusLogicController, - lsilogicsas=vim.vm.device.VirtualLsiLogicSASController) - self.config_spec = vim.vm.ConfigSpec() - self.config_spec.deviceChange = [] - - def create_scsi_controller(self, scsi_type, scsi_bus_number): - """ - Create SCSI Controller with given SCSI Type and SCSI Bus Number - Args: - scsi_type: Type of SCSI - scsi_bus_number: SCSI Bus number to be assigned - - Returns: Virtual device spec for SCSI Controller - - """ - scsi_ctl = vim.vm.device.VirtualDeviceSpec() - scsi_ctl.operation = vim.vm.device.VirtualDeviceSpec.Operation.add - scsi_ctl.device = self.scsi_device_type[scsi_type]() - scsi_ctl.device.unitNumber = 3 - scsi_ctl.device.busNumber = scsi_bus_number - scsi_ctl.device.hotAddRemove = True - scsi_ctl.device.sharedBus = 'noSharing' - scsi_ctl.device.scsiCtlrUnitNumber = 7 - - return scsi_ctl - - @staticmethod - def create_scsi_disk(scsi_ctl_key, disk_index, disk_mode, disk_filename): - """ - Create Virtual Device Spec for virtual disk - Args: - scsi_ctl_key: Unique SCSI Controller Key - disk_index: Disk unit number at which disk needs to be attached - disk_mode: Disk mode - disk_filename: Path to the disk file on the datastore - - Returns: Virtual Device Spec for virtual disk - - """ - disk_spec = vim.vm.device.VirtualDeviceSpec() - disk_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.add - disk_spec.device = vim.vm.device.VirtualDisk() - disk_spec.device.backing = vim.vm.device.VirtualDisk.FlatVer2BackingInfo() - disk_spec.device.backing.diskMode = disk_mode - disk_spec.device.controllerKey = scsi_ctl_key - disk_spec.device.unitNumber = disk_index - - if disk_filename is not None: - disk_spec.device.backing.fileName = disk_filename - else: - disk_spec.fileOperation = vim.vm.device.VirtualDeviceSpec.FileOperation.create - - return disk_spec - - def reconfigure_vm(self, config_spec, device_type): - """ - Reconfigure virtual machine after modifying device spec - Args: - config_spec: Config Spec - device_type: Type of device being modified - - Returns: Boolean status 'changed' and actual task result - - """ - changed, results = (False, '') - try: - # Perform actual VM reconfiguration - task = self.vm.ReconfigVM_Task(spec=config_spec) - changed, results = wait_for_task(task) - except vim.fault.InvalidDeviceSpec as invalid_device_spec: - self.module.fail_json(msg="Failed to manage %s on given virtual machine due to invalid" - " device spec : %s" % (device_type, to_native(invalid_device_spec.msg)), - details="Please check ESXi server logs for more details.") - except vim.fault.RestrictedVersion as e: - self.module.fail_json(msg="Failed to reconfigure virtual machine due to" - " product versioning restrictions: %s" % to_native(e.msg)) - - return changed, results - - def get_ioandshares_diskconfig(self, disk_spec, disk): - io_disk_spec = vim.StorageResourceManager.IOAllocationInfo() - if 'iolimit' in disk: - io_disk_spec.limit = disk['iolimit']['limit'] - if 'shares' in disk['iolimit']: - shares_spec = vim.SharesInfo() - shares_spec.level = disk['iolimit']['shares']['level'] - if shares_spec.level == 'custom': - shares_spec.shares = disk['iolimit']['shares']['level_value'] - io_disk_spec.shares = shares_spec - disk_spec.device.storageIOAllocation = io_disk_spec - if 'shares' in disk: - shares_spec = vim.SharesInfo() - shares_spec.level = disk['shares']['level'] - if shares_spec.level == 'custom': - shares_spec.shares = disk['shares']['level_value'] - io_disk_spec.shares = shares_spec - disk_spec.device.storageIOAllocation = io_disk_spec - return disk_spec - - def ensure_disks(self, vm_obj=None): - """ - Manage internal state of virtual machine disks - Args: - vm_obj: Managed object of virtual machine - - """ - # Set vm object - self.vm = vm_obj - # Sanitize user input - disk_data = self.sanitize_disk_inputs() - # Create stateful information about SCSI devices - current_scsi_info = dict() - results = dict(changed=False, disk_data=None, disk_changes=dict()) - - # Deal with SCSI Controller - for device in vm_obj.config.hardware.device: - if isinstance(device, tuple(self.scsi_device_type.values())): - # Found SCSI device - if device.busNumber not in current_scsi_info: - device_bus_number = 1000 + device.busNumber - current_scsi_info[device_bus_number] = dict(disks=dict()) - - scsi_changed = False - for disk in disk_data: - scsi_controller = disk['scsi_controller'] + 1000 - if scsi_controller not in current_scsi_info and disk['state'] == 'present': - scsi_ctl = self.create_scsi_controller(disk['scsi_type'], disk['scsi_controller']) - current_scsi_info[scsi_controller] = dict(disks=dict()) - self.config_spec.deviceChange.append(scsi_ctl) - scsi_changed = True - if scsi_changed: - self.reconfigure_vm(self.config_spec, 'SCSI Controller') - self.config_spec = vim.vm.ConfigSpec() - self.config_spec.deviceChange = [] - - # Deal with Disks - for device in vm_obj.config.hardware.device: - if isinstance(device, vim.vm.device.VirtualDisk): - # Found Virtual Disk device - if device.controllerKey not in current_scsi_info: - current_scsi_info[device.controllerKey] = dict(disks=dict()) - current_scsi_info[device.controllerKey]['disks'][device.unitNumber] = device - - vm_name = self.vm.name - disk_change_list = [] - for disk in disk_data: - disk_change = False - scsi_controller = disk['scsi_controller'] + 1000 # VMware auto assign 1000 + SCSI Controller - if disk['disk_unit_number'] not in current_scsi_info[scsi_controller]['disks'] and disk['state'] == 'present': - # Add new disk - disk_spec = self.create_scsi_disk(scsi_controller, disk['disk_unit_number'], disk['disk_mode'], disk['filename']) - if disk['filename'] is None: - disk_spec.device.capacityInKB = disk['size'] - if disk['disk_type'] == 'thin': - disk_spec.device.backing.thinProvisioned = True - elif disk['disk_type'] == 'eagerzeroedthick': - disk_spec.device.backing.eagerlyScrub = True - # get Storage DRS recommended datastore from the datastore cluster - if disk['datastore_cluster'] is not None: - datastore_name = self.get_recommended_datastore(datastore_cluster_obj=disk['datastore_cluster'], disk_spec_obj=disk_spec) - disk['datastore'] = find_obj(self.content, [vim.Datastore], datastore_name) - if disk['filename'] is None: - disk_spec.device.backing.fileName = "[%s] %s/%s_%s_%s.vmdk" % ( - disk['datastore'].name, - vm_name, vm_name, - str(scsi_controller), - str(disk['disk_unit_number'])) - else: - disk_spec.device.backing.fileName = disk['filename'] - disk_spec.device.backing.datastore = disk['datastore'] - disk_spec = self.get_ioandshares_diskconfig(disk_spec, disk) - self.config_spec.deviceChange.append(disk_spec) - disk_change = True - current_scsi_info[scsi_controller]['disks'][disk['disk_unit_number']] = disk_spec.device - results['disk_changes'][disk['disk_index']] = "Disk created." - elif disk['disk_unit_number'] in current_scsi_info[scsi_controller]['disks']: - if disk['state'] == 'present': - disk_spec = vim.vm.device.VirtualDeviceSpec() - # set the operation to edit so that it knows to keep other settings - disk_spec.device = current_scsi_info[scsi_controller]['disks'][disk['disk_unit_number']] - # Edit and no resizing allowed - if disk['size'] < disk_spec.device.capacityInKB: - self.module.fail_json(msg="Given disk size at disk index [%s] is smaller than found (%d < %d)." - "Reducing disks is not allowed." % (disk['disk_index'], - disk['size'], - disk_spec.device.capacityInKB)) - if disk['size'] != disk_spec.device.capacityInKB: - disk_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.edit - disk_spec = self.get_ioandshares_diskconfig(disk_spec, disk) - disk_spec.device.capacityInKB = disk['size'] - self.config_spec.deviceChange.append(disk_spec) - disk_change = True - results['disk_changes'][disk['disk_index']] = "Disk size increased." - else: - results['disk_changes'][disk['disk_index']] = "Disk already exists." - - elif disk['state'] == 'absent': - # Disk already exists, deleting - disk_spec = vim.vm.device.VirtualDeviceSpec() - disk_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.remove - if disk['destroy'] is True: - disk_spec.fileOperation = vim.vm.device.VirtualDeviceSpec.FileOperation.destroy - disk_spec.device = current_scsi_info[scsi_controller]['disks'][disk['disk_unit_number']] - self.config_spec.deviceChange.append(disk_spec) - disk_change = True - results['disk_changes'][disk['disk_index']] = "Disk deleted." - - if disk_change: - # Adding multiple disks in a single attempt raises weird errors - # So adding single disk at a time. - self.reconfigure_vm(self.config_spec, 'disks') - self.config_spec = vim.vm.ConfigSpec() - self.config_spec.deviceChange = [] - disk_change_list.append(disk_change) - - if any(disk_change_list): - results['changed'] = True - results['disk_data'] = self.gather_disk_facts(vm_obj=self.vm) - self.module.exit_json(**results) - - def sanitize_disk_inputs(self): - """ - Check correctness of disk input provided by user - Returns: A list of dictionary containing disk information - - """ - disks_data = list() - if not self.desired_disks: - self.module.exit_json(changed=False, msg="No disks provided for virtual" - " machine '%s' for management." % self.vm.name) - - for disk_index, disk in enumerate(self.desired_disks): - # Initialize default value for disk - current_disk = dict(disk_index=disk_index, - state='present', - destroy=True, - filename=None, - datastore_cluster=None, - datastore=None, - autoselect_datastore=True, - disk_unit_number=0, - scsi_controller=0, - disk_mode='persistent') - # Check state - if 'state' in disk: - if disk['state'] not in ['absent', 'present']: - self.module.fail_json(msg="Invalid state provided '%s' for disk index [%s]." - " State can be either - 'absent', 'present'" % (disk['state'], - disk_index)) - else: - current_disk['state'] = disk['state'] - - if current_disk['state'] == 'absent': - current_disk['destroy'] = disk['destroy'] - elif current_disk['state'] == 'present': - # Select datastore or datastore cluster - if 'datastore' in disk: - if 'autoselect_datastore' in disk: - self.module.fail_json(msg="Please specify either 'datastore' " - "or 'autoselect_datastore' for disk index [%s]" % disk_index) - - # Check if given value is datastore or datastore cluster - datastore_name = disk['datastore'] - datastore_cluster = find_obj(self.content, [vim.StoragePod], datastore_name) - datastore = find_obj(self.content, [vim.Datastore], datastore_name) - - if datastore is None and datastore_cluster is None: - self.module.fail_json(msg="Failed to find datastore or datastore cluster named '%s' " - "in given configuration." % disk['datastore']) - if datastore_cluster: - # If user specified datastore cluster, keep track of that for determining datastore later - current_disk['datastore_cluster'] = datastore_cluster - elif datastore: - current_disk['datastore'] = datastore - current_disk['autoselect_datastore'] = False - elif 'autoselect_datastore' in disk: - # Find datastore which fits requirement - datastores = get_all_objs(self.content, [vim.Datastore]) - if not datastores: - self.module.fail_json(msg="Failed to gather information about" - " available datastores in given datacenter.") - datastore = None - datastore_freespace = 0 - for ds in datastores: - if ds.summary.freeSpace > datastore_freespace: - # If datastore field is provided, filter destination datastores - datastore = ds - datastore_freespace = ds.summary.freeSpace - current_disk['datastore'] = datastore - - if 'datastore' not in disk and 'autoselect_datastore' not in disk and 'filename' not in disk: - self.module.fail_json(msg="Either 'datastore' or 'autoselect_datastore' is" - " required parameter while creating disk for " - "disk index [%s]." % disk_index) - - if 'filename' in disk: - current_disk['filename'] = disk['filename'] - - if [x for x in disk.keys() if x.startswith('size_') or x == 'size']: - # size, size_tb, size_gb, size_mb, size_kb - disk_size_parse_failed = False - if 'size' in disk: - size_regex = re.compile(r'(\d+(?:\.\d+)?)([tgmkTGMK][bB])') - disk_size_m = size_regex.match(disk['size']) - if disk_size_m: - expected = disk_size_m.group(1) - unit = disk_size_m.group(2) - else: - disk_size_parse_failed = True - try: - if re.match(r'\d+\.\d+', expected): - # We found float value in string, let's typecast it - expected = float(expected) - else: - # We found int value in string, let's typecast it - expected = int(expected) - except (TypeError, ValueError, NameError): - disk_size_parse_failed = True - else: - # Even multiple size_ parameter provided by user, - # consider first value only - param = [x for x in disk.keys() if x.startswith('size_')][0] - unit = param.split('_')[-1] - disk_size = disk[param] - if isinstance(disk_size, (float, int)): - disk_size = str(disk_size) - - try: - if re.match(r'\d+\.\d+', disk_size): - # We found float value in string, let's typecast it - expected = float(disk_size) - else: - # We found int value in string, let's typecast it - expected = int(disk_size) - except (TypeError, ValueError, NameError): - disk_size_parse_failed = True - - if disk_size_parse_failed: - # Common failure - self.module.fail_json(msg="Failed to parse disk size for disk index [%s]," - " please review value provided" - " using documentation." % disk_index) - - disk_units = dict(tb=3, gb=2, mb=1, kb=0) - unit = unit.lower() - if unit in disk_units: - current_disk['size'] = expected * (1024 ** disk_units[unit]) - else: - self.module.fail_json(msg="%s is not a supported unit for disk size for disk index [%s]." - " Supported units are ['%s']." % (unit, - disk_index, - "', '".join(disk_units.keys()))) - - elif current_disk['filename'] is None: - # No size found but disk, fail - self.module.fail_json(msg="No size, size_kb, size_mb, size_gb or size_tb" - " attribute found into disk index [%s] configuration." % disk_index) - # Check SCSI controller key - if 'scsi_controller' in disk: - try: - temp_disk_controller = int(disk['scsi_controller']) - except ValueError: - self.module.fail_json(msg="Invalid SCSI controller ID '%s' specified" - " at index [%s]" % (disk['scsi_controller'], disk_index)) - if temp_disk_controller not in range(0, 4): - # Only 4 SCSI controllers are allowed per VM - self.module.fail_json(msg="Invalid SCSI controller ID specified [%s]," - " please specify value between 0 to 3 only." % temp_disk_controller) - current_disk['scsi_controller'] = temp_disk_controller - else: - self.module.fail_json(msg="Please specify 'scsi_controller' under disk parameter" - " at index [%s], which is required while creating disk." % disk_index) - # Check for disk unit number - if 'unit_number' in disk: - try: - temp_disk_unit_number = int(disk['unit_number']) - except ValueError: - self.module.fail_json(msg="Invalid Disk unit number ID '%s'" - " specified at index [%s]" % (disk['unit_number'], disk_index)) - if temp_disk_unit_number not in range(0, 16): - self.module.fail_json(msg="Invalid Disk unit number ID specified for disk [%s] at index [%s]," - " please specify value between 0 to 15" - " only (excluding 7)." % (temp_disk_unit_number, disk_index)) - - if temp_disk_unit_number == 7: - self.module.fail_json(msg="Invalid Disk unit number ID specified for disk at index [%s]," - " please specify value other than 7 as it is reserved" - "for SCSI Controller" % disk_index) - current_disk['disk_unit_number'] = temp_disk_unit_number - - else: - self.module.fail_json(msg="Please specify 'unit_number' under disk parameter" - " at index [%s], which is required while creating disk." % disk_index) - - # Type of Disk - disk_type = disk.get('type', 'thick').lower() - if disk_type not in ['thin', 'thick', 'eagerzeroedthick']: - self.module.fail_json(msg="Invalid 'disk_type' specified for disk index [%s]. Please specify" - " 'disk_type' value from ['thin', 'thick', 'eagerzeroedthick']." % disk_index) - current_disk['disk_type'] = disk_type - - # Mode of Disk - temp_disk_mode = disk.get('disk_mode', 'persistent').lower() - if temp_disk_mode not in ['persistent', 'independent_persistent', 'independent_nonpersistent']: - self.module.fail_json(msg="Invalid 'disk_mode' specified for disk index [%s]. Please specify" - " 'disk_mode' value from ['persistent', 'independent_persistent', 'independent_nonpersistent']." % disk_index) - current_disk['disk_mode'] = temp_disk_mode - - # SCSI Controller Type - scsi_contrl_type = disk.get('scsi_type', 'paravirtual').lower() - if scsi_contrl_type not in self.scsi_device_type.keys(): - self.module.fail_json(msg="Invalid 'scsi_type' specified for disk index [%s]. Please specify" - " 'scsi_type' value from ['%s']" % (disk_index, - "', '".join(self.scsi_device_type.keys()))) - current_disk['scsi_type'] = scsi_contrl_type - if 'shares' in disk: - current_disk['shares'] = disk['shares'] - if 'iolimit' in disk: - current_disk['iolimit'] = disk['iolimit'] - disks_data.append(current_disk) - return disks_data - - def get_recommended_datastore(self, datastore_cluster_obj, disk_spec_obj): - """ - Return Storage DRS recommended datastore from datastore cluster - Args: - datastore_cluster_obj: datastore cluster managed object - - Returns: Name of recommended datastore from the given datastore cluster, - Returns None if no datastore recommendation found. - - """ - # Check if Datastore Cluster provided by user is SDRS ready - sdrs_status = datastore_cluster_obj.podStorageDrsEntry.storageDrsConfig.podConfig.enabled - if sdrs_status: - # We can get storage recommendation only if SDRS is enabled on given datastorage cluster - disk_loc = vim.storageDrs.PodSelectionSpec.DiskLocator() - pod_config = vim.storageDrs.PodSelectionSpec.VmPodConfig() - pod_config.storagePod = datastore_cluster_obj - pod_config.disk = [disk_loc] - pod_sel_spec = vim.storageDrs.PodSelectionSpec() - pod_sel_spec.initialVmConfig = [pod_config] - storage_spec = vim.storageDrs.StoragePlacementSpec() - storage_spec.configSpec = vim.vm.ConfigSpec() - storage_spec.configSpec.deviceChange.append(disk_spec_obj) - storage_spec.resourcePool = self.vm.resourcePool - storage_spec.podSelectionSpec = pod_sel_spec - storage_spec.vm = self.vm - storage_spec.type = 'reconfigure' - - try: - rec = self.content.storageResourceManager.RecommendDatastores(storageSpec=storage_spec) - rec_action = rec.recommendations[0].action[0] - return rec_action.destination.name - except Exception: - # There is some error so we fall back to general workflow - pass - datastore = None - datastore_freespace = 0 - for ds in datastore_cluster_obj.childEntity: - if ds.summary.freeSpace > datastore_freespace: - # If datastore field is provided, filter destination datastores - datastore = ds - datastore_freespace = ds.summary.freeSpace - if datastore: - return datastore.name - return None - - @staticmethod - def gather_disk_facts(vm_obj): - """ - Gather facts about VM's disks - Args: - vm_obj: Managed object of virtual machine - - Returns: A list of dict containing disks information - - """ - disks_facts = dict() - if vm_obj is None: - return disks_facts - - disk_index = 0 - for disk in vm_obj.config.hardware.device: - if isinstance(disk, vim.vm.device.VirtualDisk): - if disk.storageIOAllocation is None: - disk.storageIOAllocation = vim.StorageResourceManager.IOAllocationInfo() - disk.storageIOAllocation.shares = vim.SharesInfo() - if disk.shares is None: - disk.shares = vim.SharesInfo() - disks_facts[disk_index] = dict( - key=disk.key, - label=disk.deviceInfo.label, - summary=disk.deviceInfo.summary, - backing_filename=disk.backing.fileName, - backing_datastore=disk.backing.datastore.name, - backing_disk_mode=disk.backing.diskMode, - backing_writethrough=disk.backing.writeThrough, - backing_thinprovisioned=disk.backing.thinProvisioned, - backing_eagerlyscrub=bool(disk.backing.eagerlyScrub), - controller_key=disk.controllerKey, - unit_number=disk.unitNumber, - iolimit_limit=disk.storageIOAllocation.limit, - iolimit_shares_level=disk.storageIOAllocation.shares.level, - iolimit_shares_limit=disk.storageIOAllocation.shares.shares, - shares_level=disk.shares.level, - shares_limit=disk.shares.shares, - capacity_in_kb=disk.capacityInKB, - capacity_in_bytes=disk.capacityInBytes, - ) - disk_index += 1 - return disks_facts - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - name=dict(type='str'), - uuid=dict(type='str'), - moid=dict(type='str'), - folder=dict(type='str'), - datacenter=dict(type='str', required=True), - disk=dict(type='list', default=[]), - use_instance_uuid=dict(type='bool', default=False), - ) - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['name', 'uuid', 'moid'] - ] - ) - - if module.params['folder']: - # FindByInventoryPath() does not require an absolute path - # so we should leave the input folder path unmodified - module.params['folder'] = module.params['folder'].rstrip('/') - - pyv = PyVmomiHelper(module) - # Check if the VM exists before continuing - vm = pyv.get_vm() - - if not vm: - # We unable to find the virtual machine user specified - # Bail out - vm_id = (module.params.get('name') or module.params.get('uuid') or module.params.get('moid')) - module.fail_json(msg="Unable to manage disks for non-existing" - " virtual machine '%s'." % vm_id) - - # VM exists - try: - pyv.ensure_disks(vm_obj=vm) - except Exception as exc: - module.fail_json(msg="Failed to manage disks for virtual machine" - " '%s' with exception : %s" % (vm.name, - to_native(exc))) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_disk_info.py b/lib/ansible/modules/cloud/vmware/vmware_guest_disk_info.py deleted file mode 100644 index da495a2d87..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_disk_info.py +++ /dev/null @@ -1,332 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2019, NAER William Leemans (@bushvin) <willie@elaba.net> -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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 = ''' ---- -module: vmware_guest_disk_info -short_description: Gather info about disks of given virtual machine -description: - - This module can be used to gather information about disks belonging to given virtual machine. - - All parameters and VMware object names are case sensitive. -version_added: '2.9' -author: - - Abhijeet Kasurde (@Akasurde) <akasurde@redhat.com> -notes: - - Tested on vSphere 6.0 and 6.5. - - Disk UUID information is added in version 2.8. - - Additional information about guest disk backings added in version 2.8. -requirements: - - "python >= 2.6" - - PyVmomi -options: - name: - description: - - Name of the virtual machine. - - This is required parameter, if parameter C(uuid) or C(moid) is not supplied. - type: str - uuid: - description: - - UUID of the instance to gather information if known, this is VMware's unique identifier. - - This is required parameter, if parameter C(name) or C(moid) is not supplied. - type: str - moid: - description: - - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. - - This is required if C(name) or C(uuid) is not supplied. - type: str - use_instance_uuid: - description: - - Whether to use the VMware instance UUID rather than the BIOS UUID. - default: no - type: bool - folder: - description: - - Destination folder, absolute or relative path to find an existing guest. - - This is required parameter, only if multiple VMs are found with same name. - - The folder should include the datacenter. ESX's datacenter is ha-datacenter - - 'Examples:' - - ' folder: /ha-datacenter/vm' - - ' folder: ha-datacenter/vm' - - ' folder: /datacenter1/vm' - - ' folder: datacenter1/vm' - - ' folder: /datacenter1/vm/folder1' - - ' folder: datacenter1/vm/folder1' - - ' folder: /folder1/datacenter1/vm' - - ' folder: folder1/datacenter1/vm' - - ' folder: /folder1/datacenter1/vm/folder2' - type: str - datacenter: - description: - - The datacenter name to which virtual machine belongs to. - required: True - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Gather disk info from virtual machine using UUID - vmware_guest_disk_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: ha-datacenter - validate_certs: no - uuid: 421e4592-c069-924d-ce20-7e7533fab926 - delegate_to: localhost - register: disk_info - -- name: Gather disk info from virtual machine using name - vmware_guest_disk_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: ha-datacenter - validate_certs: no - name: VM_225 - delegate_to: localhost - register: disk_info - -- name: Gather disk info from virtual machine using moid - vmware_guest_disk_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: ha-datacenter - validate_certs: no - moid: vm-42 - delegate_to: localhost - register: disk_info -''' - -RETURN = """ -guest_disk_info: - description: metadata about the virtual machine's disks - returned: always - type: dict - sample: { - "0": { - "backing_datastore": "datastore2", - "backing_disk_mode": "persistent", - "backing_diskmode": "persistent", - "backing_eagerlyscrub": false, - "backing_filename": "[datastore2] VM_225/VM_225.vmdk", - "backing_thinprovisioned": false, - "backing_type": "FlatVer2", - "backing_writethrough": false, - "backing_uuid": "200C3A00-f82a-97af-02ff-62a595f0020a", - "capacity_in_bytes": 10485760, - "capacity_in_kb": 10240, - "controller_bus_number": 0, - "controller_key": 1000, - "controller_type": "paravirtual", - "key": 2000, - "label": "Hard disk 1", - "summary": "10,240 KB", - "unit_number": 0 - }, - "1": { - "backing_datastore": "datastore3", - "backing_devicename": "vml.012345678901234567890123456789012345678901234567890123", - "backing_disk_mode": "independent_persistent", - "backing_diskmode": "independent_persistent", - "backing_filename": "[datastore3] VM_226/VM_226.vmdk", - "backing_lunuuid": "012345678901234567890123456789012345678901234567890123", - "backing_type": "RawDiskMappingVer1", - "backing_uuid": null, - "capacity_in_bytes": 15728640, - "capacity_in_kb": 15360, - "controller_bus_number": 0, - "controller_key": 1000, - "controller_type": "paravirtual", - "key": 2001, - "label": "Hard disk 3", - "summary": "15,360 KB", - "unit_number": 1 - }, - } -""" - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils._text import to_text -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec - - -class PyVmomiHelper(PyVmomi): - def __init__(self, module): - super(PyVmomiHelper, self).__init__(module) - - def gather_disk_info(self, vm_obj): - """ - Gather information about VM's disks - Args: - vm_obj: Managed object of virtual machine - - Returns: A list of dict containing disks information - - """ - controller_info = dict() - disks_info = dict() - if vm_obj is None: - return disks_info - - controller_types = { - vim.vm.device.VirtualLsiLogicController: 'lsilogic', - vim.vm.device.ParaVirtualSCSIController: 'paravirtual', - vim.vm.device.VirtualBusLogicController: 'buslogic', - vim.vm.device.VirtualLsiLogicSASController: 'lsilogicsas', - vim.vm.device.VirtualIDEController: 'ide' - } - - controller_index = 0 - for controller in vm_obj.config.hardware.device: - if isinstance(controller, tuple(controller_types.keys())): - controller_info[controller_index] = dict( - key=controller.key, - controller_type=controller_types[type(controller)], - bus_number=controller.busNumber, - devices=controller.device - ) - controller_index += 1 - - disk_index = 0 - for disk in vm_obj.config.hardware.device: - if isinstance(disk, vim.vm.device.VirtualDisk): - disks_info[disk_index] = dict( - key=disk.key, - label=disk.deviceInfo.label, - summary=disk.deviceInfo.summary, - backing_filename=disk.backing.fileName, - backing_datastore=disk.backing.datastore.name, - controller_key=disk.controllerKey, - unit_number=disk.unitNumber, - capacity_in_kb=disk.capacityInKB, - capacity_in_bytes=disk.capacityInBytes, - ) - if isinstance(disk.backing, vim.vm.device.VirtualDisk.FlatVer1BackingInfo): - disks_info[disk_index]['backing_type'] = 'FlatVer1' - disks_info[disk_index]['backing_writethrough'] = disk.backing.writeThrough - - elif isinstance(disk.backing, vim.vm.device.VirtualDisk.FlatVer2BackingInfo): - disks_info[disk_index]['backing_type'] = 'FlatVer2' - disks_info[disk_index]['backing_writethrough'] = bool(disk.backing.writeThrough) - disks_info[disk_index]['backing_thinprovisioned'] = bool(disk.backing.thinProvisioned) - disks_info[disk_index]['backing_eagerlyscrub'] = bool(disk.backing.eagerlyScrub) - disks_info[disk_index]['backing_uuid'] = disk.backing.uuid - - elif isinstance(disk.backing, vim.vm.device.VirtualDisk.LocalPMemBackingInfo): - disks_info[disk_index]['backing_type'] = 'LocalPMem' - disks_info[disk_index]['backing_volumeuuid'] = disk.backing.volumeUUID - disks_info[disk_index]['backing_uuid'] = disk.backing.uuid - - elif isinstance(disk.backing, vim.vm.device.VirtualDisk.PartitionedRawDiskVer2BackingInfo): - disks_info[disk_index]['backing_type'] = 'PartitionedRawDiskVer2' - disks_info[disk_index]['backing_descriptorfilename'] = disk.backing.descriptorFileName - disks_info[disk_index]['backing_uuid'] = disk.backing.uuid - - elif isinstance(disk.backing, vim.vm.device.VirtualDisk.RawDiskMappingVer1BackingInfo): - disks_info[disk_index]['backing_type'] = 'RawDiskMappingVer1' - disks_info[disk_index]['backing_devicename'] = disk.backing.deviceName - disks_info[disk_index]['backing_diskmode'] = disk.backing.diskMode - disks_info[disk_index]['backing_disk_mode'] = disk.backing.diskMode - disks_info[disk_index]['backing_lunuuid'] = disk.backing.lunUuid - disks_info[disk_index]['backing_uuid'] = disk.backing.uuid - - elif isinstance(disk.backing, vim.vm.device.VirtualDisk.RawDiskVer2BackingInfo): - disks_info[disk_index]['backing_type'] = 'RawDiskVer2' - disks_info[disk_index]['backing_descriptorfilename'] = disk.backing.descriptorFileName - disks_info[disk_index]['backing_uuid'] = disk.backing.uuid - - elif isinstance(disk.backing, vim.vm.device.VirtualDisk.SeSparseBackingInfo): - disks_info[disk_index]['backing_type'] = 'SeSparse' - disks_info[disk_index]['backing_diskmode'] = disk.backing.diskMode - disks_info[disk_index]['backing_disk_mode'] = disk.backing.diskMode - disks_info[disk_index]['backing_writethrough'] = bool(disk.backing.writeThrough) - disks_info[disk_index]['backing_uuid'] = disk.backing.uuid - - elif isinstance(disk.backing, vim.vm.device.VirtualDisk.SparseVer1BackingInfo): - disks_info[disk_index]['backing_type'] = 'SparseVer1' - disks_info[disk_index]['backing_diskmode'] = disk.backing.diskMode - disks_info[disk_index]['backing_disk_mode'] = disk.backing.diskMode - disks_info[disk_index]['backing_spaceusedinkb'] = disk.backing.spaceUsedInKB - disks_info[disk_index]['backing_split'] = bool(disk.backing.split) - disks_info[disk_index]['backing_writethrough'] = bool(disk.backing.writeThrough) - - elif isinstance(disk.backing, vim.vm.device.VirtualDisk.SparseVer2BackingInfo): - disks_info[disk_index]['backing_type'] = 'SparseVer2' - disks_info[disk_index]['backing_diskmode'] = disk.backing.diskMode - disks_info[disk_index]['backing_disk_mode'] = disk.backing.diskMode - disks_info[disk_index]['backing_spaceusedinkb'] = disk.backing.spaceUsedInKB - disks_info[disk_index]['backing_split'] = bool(disk.backing.split) - disks_info[disk_index]['backing_writethrough'] = bool(disk.backing.writeThrough) - disks_info[disk_index]['backing_uuid'] = disk.backing.uuid - - for controller_index in range(len(controller_info)): - if controller_info[controller_index]['key'] == disks_info[disk_index]['controller_key']: - disks_info[disk_index]['controller_bus_number'] = controller_info[controller_index]['bus_number'] - disks_info[disk_index]['controller_type'] = controller_info[controller_index]['controller_type'] - - disk_index += 1 - return disks_info - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - name=dict(type='str'), - uuid=dict(type='str'), - moid=dict(type='str'), - use_instance_uuid=dict(type='bool', default=False), - folder=dict(type='str'), - datacenter=dict(type='str', required=True), - ) - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['name', 'uuid', 'moid'] - ], - supports_check_mode=True, - ) - - if module.params['folder']: - # FindByInventoryPath() does not require an absolute path - # so we should leave the input folder path unmodified - module.params['folder'] = module.params['folder'].rstrip('/') - - pyv = PyVmomiHelper(module) - # Check if the VM exists before continuing - vm = pyv.get_vm() - - if vm: - # VM exists - try: - module.exit_json(guest_disk_info=pyv.gather_disk_info(vm)) - except Exception as exc: - module.fail_json(msg="Failed to gather information with exception : %s" % to_text(exc)) - else: - # We unable to find the virtual machine user specified - # Bail out - vm_id = (module.params.get('uuid') or module.params.get('moid') or module.params.get('name')) - module.fail_json(msg="Unable to gather disk information for non-existing VM %s" % vm_id) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_file_operation.py b/lib/ansible/modules/cloud/vmware/vmware_guest_file_operation.py deleted file mode 100644 index a4ea0226cb..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_file_operation.py +++ /dev/null @@ -1,460 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2017, Stéphane Travassac <stravassac@gmail.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 = ''' ---- -module: vmware_guest_file_operation -short_description: Files operation in a VMware guest operating system without network -description: - - Module to copy a file to a VM, fetch a file from a VM and create or delete a directory in the guest OS. -version_added: "2.5" -author: - - Stéphane Travassac (@stravassac) -notes: - - Tested on vSphere 6 - - Only the first match against vm_id is used, even if there are multiple matches -requirements: - - "python >= 2.6" - - PyVmomi - - requests -options: - datacenter: - description: - - The datacenter hosting the virtual machine. - - If set, it will help to speed up virtual machine search. - type: str - cluster: - description: - - The cluster hosting the virtual machine. - - If set, it will help to speed up virtual machine search. - type: str - folder: - description: - - Destination folder, absolute path to find an existing guest or create the new guest. - - The folder should include the datacenter. ESX's datacenter is ha-datacenter - - Used only if C(vm_id_type) is C(inventory_path). - - 'Examples:' - - ' folder: /ha-datacenter/vm' - - ' folder: ha-datacenter/vm' - - ' folder: /datacenter1/vm' - - ' folder: datacenter1/vm' - - ' folder: /datacenter1/vm/folder1' - - ' folder: datacenter1/vm/folder1' - - ' folder: /folder1/datacenter1/vm' - - ' folder: folder1/datacenter1/vm' - - ' folder: /folder1/datacenter1/vm/folder2' - - ' folder: vm/folder2' - - ' folder: folder2' - type: str - vm_id: - description: - - Name of the virtual machine to work with. - required: True - type: str - vm_id_type: - description: - - The VMware identification method by which the virtual machine will be identified. - default: vm_name - choices: - - 'uuid' - - 'instance_uuid' - - 'dns_name' - - 'inventory_path' - - 'vm_name' - type: str - vm_username: - description: - - The user to login in to the virtual machine. - required: True - type: str - vm_password: - description: - - The password used to login-in to the virtual machine. - required: True - type: str - directory: - description: - - Create or delete a directory. - - Can be used to create temp directory inside guest using mktemp operation. - - mktemp sets variable C(dir) in the result with the name of the new directory. - - mktemp operation option is added in version 2.8 - - 'Valid attributes are:' - - ' operation (str): Valid values are: create, delete, mktemp' - - ' path (str): directory path (required for create or remove)' - - ' prefix (str): temporary directory prefix (required for mktemp)' - - ' suffix (str): temporary directory suffix (required for mktemp)' - - ' recurse (boolean): Not required, default (false)' - required: False - type: dict - copy: - description: - - Copy file to vm without requiring network. - - 'Valid attributes are:' - - ' src: file source absolute or relative' - - ' dest: file destination, path must be exist' - - ' overwrite: False or True (not required, default False)' - required: False - type: dict - fetch: - description: - - Get file from virtual machine without requiring network. - - 'Valid attributes are:' - - ' src: The file on the remote system to fetch. This I(must) be a file, not a directory' - - ' dest: file destination on localhost, path must be exist' - required: False - type: dict - version_added: 2.5 - -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Create directory inside a vm - vmware_guest_file_operation: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - validate_certs: no - vm_id: "{{ guest_name }}" - vm_username: "{{ guest_username }}" - vm_password: "{{ guest_userpassword }}" - directory: - path: "/test" - operation: create - recurse: no - delegate_to: localhost - -- name: copy file to vm - vmware_guest_file_operation: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - vm_id: "{{ guest_name }}" - vm_username: "{{ guest_username }}" - vm_password: "{{ guest_userpassword }}" - copy: - src: "files/test.zip" - dest: "/root/test.zip" - overwrite: False - delegate_to: localhost - -- name: fetch file from vm - vmware_guest_file_operation: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - vm_id: "{{ guest_name }}" - vm_username: "{{ guest_username }}" - vm_password: "{{ guest_userpassword }}" - fetch: - src: "/root/test.zip" - dest: "files/test.zip" - delegate_to: localhost -''' - -RETURN = r''' -''' - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -import os -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils import urls -from ansible.module_utils._text import to_bytes, to_native -from ansible.module_utils.vmware import (PyVmomi, find_cluster_by_name, find_datacenter_by_name, - find_vm_by_id, vmware_argument_spec) - - -class VmwareGuestFileManager(PyVmomi): - def __init__(self, module): - super(VmwareGuestFileManager, self).__init__(module) - datacenter_name = module.params['datacenter'] - cluster_name = module.params['cluster'] - folder = module.params['folder'] - - datacenter = None - if datacenter_name: - datacenter = find_datacenter_by_name(self.content, datacenter_name) - if not datacenter: - module.fail_json(msg="Unable to find %(datacenter)s datacenter" % module.params) - - cluster = None - if cluster_name: - cluster = find_cluster_by_name(self.content, cluster_name, datacenter) - if not cluster: - module.fail_json(msg="Unable to find %(cluster)s cluster" % module.params) - - if module.params['vm_id_type'] == 'inventory_path': - vm = find_vm_by_id(self.content, vm_id=module.params['vm_id'], vm_id_type="inventory_path", folder=folder) - else: - vm = find_vm_by_id(self.content, - vm_id=module.params['vm_id'], - vm_id_type=module.params['vm_id_type'], - datacenter=datacenter, - cluster=cluster) - - if not vm: - module.fail_json(msg='Unable to find virtual machine.') - - self.vm = vm - try: - result = dict(changed=False) - if module.params['directory']: - result = self.directory() - if module.params['copy']: - result = self.copy() - if module.params['fetch']: - result = self.fetch() - module.exit_json(**result) - except vmodl.RuntimeFault as runtime_fault: - module.fail_json(msg=to_native(runtime_fault.msg)) - except vmodl.MethodFault as method_fault: - module.fail_json(msg=to_native(method_fault.msg)) - except Exception as e: - module.fail_json(msg=to_native(e)) - - def directory(self): - result = dict(changed=True, uuid=self.vm.summary.config.uuid) - vm_username = self.module.params['vm_username'] - vm_password = self.module.params['vm_password'] - - recurse = bool(self.module.params['directory']['recurse']) - operation = self.module.params['directory']['operation'] - path = self.module.params['directory']['path'] - prefix = self.module.params['directory']['prefix'] - suffix = self.module.params['directory']['suffix'] - creds = vim.vm.guest.NamePasswordAuthentication(username=vm_username, password=vm_password) - file_manager = self.content.guestOperationsManager.fileManager - if operation in ("create", "mktemp"): - try: - if operation == "create": - file_manager.MakeDirectoryInGuest(vm=self.vm, - auth=creds, - directoryPath=path, - createParentDirectories=recurse) - else: - newdir = file_manager.CreateTemporaryDirectoryInGuest(vm=self.vm, auth=creds, - prefix=prefix, suffix=suffix) - result['dir'] = newdir - except vim.fault.FileAlreadyExists as file_already_exists: - result['changed'] = False - result['msg'] = "Guest directory %s already exist: %s" % (path, - to_native(file_already_exists.msg)) - except vim.fault.GuestPermissionDenied as permission_denied: - self.module.fail_json(msg="Permission denied for path %s : %s" % (path, - to_native(permission_denied.msg)), - uuid=self.vm.summary.config.uuid) - except vim.fault.InvalidGuestLogin as invalid_guest_login: - self.module.fail_json(msg="Invalid guest login for user %s : %s" % (vm_username, - to_native(invalid_guest_login.msg)), - uuid=self.vm.summary.config.uuid) - # other exceptions - except Exception as e: - self.module.fail_json(msg="Failed to Create directory into VM VMware exception : %s" % to_native(e), - uuid=self.vm.summary.config.uuid) - - if operation == "delete": - try: - file_manager.DeleteDirectoryInGuest(vm=self.vm, auth=creds, directoryPath=path, - recursive=recurse) - except vim.fault.FileNotFound as file_not_found: - result['changed'] = False - result['msg'] = "Guest directory %s not exists %s" % (path, - to_native(file_not_found.msg)) - except vim.fault.FileFault as e: - self.module.fail_json(msg="FileFault : %s" % e.msg, - uuid=self.vm.summary.config.uuid) - except vim.fault.GuestPermissionDenied as permission_denied: - self.module.fail_json(msg="Permission denied for path %s : %s" % (path, - to_native(permission_denied.msg)), - uuid=self.vm.summary.config.uuid) - except vim.fault.InvalidGuestLogin as invalid_guest_login: - self.module.fail_json(msg="Invalid guest login for user %s : %s" % (vm_username, - to_native(invalid_guest_login.msg)), - uuid=self.vm.summary.config.uuid) - # other exceptions - except Exception as e: - self.module.fail_json(msg="Failed to Delete directory into Vm VMware exception : %s" % to_native(e), - uuid=self.vm.summary.config.uuid) - - return result - - def fetch(self): - result = dict(changed=True, uuid=self.vm.summary.config.uuid) - vm_username = self.module.params['vm_username'] - vm_password = self.module.params['vm_password'] - hostname = self.module.params['hostname'] - dest = self.module.params["fetch"]['dest'] - src = self.module.params['fetch']['src'] - creds = vim.vm.guest.NamePasswordAuthentication(username=vm_username, password=vm_password) - file_manager = self.content.guestOperationsManager.fileManager - - try: - fileTransferInfo = file_manager.InitiateFileTransferFromGuest(vm=self.vm, auth=creds, - guestFilePath=src) - url = fileTransferInfo.url - url = url.replace("*", hostname) - resp, info = urls.fetch_url(self.module, url, method="GET") - try: - with open(dest, "wb") as local_file: - local_file.write(resp.read()) - except Exception as e: - self.module.fail_json(msg="local file write exception : %s" % to_native(e), - uuid=self.vm.summary.config.uuid) - except vim.fault.FileNotFound as file_not_found: - self.module.fail_json(msg="Guest file %s does not exist : %s" % (src, to_native(file_not_found.msg)), - uuid=self.vm.summary.config.uuid) - except vim.fault.FileFault as e: - self.module.fail_json(msg="FileFault : %s" % to_native(e.msg), - uuid=self.vm.summary.config.uuid) - except vim.fault.GuestPermissionDenied: - self.module.fail_json(msg="Permission denied to fetch file %s" % src, - uuid=self.vm.summary.config.uuid) - except vim.fault.InvalidGuestLogin: - self.module.fail_json(msg="Invalid guest login for user %s" % vm_username, - uuid=self.vm.summary.config.uuid) - # other exceptions - except Exception as e: - self.module.fail_json(msg="Failed to Fetch file from Vm VMware exception : %s" % to_native(e), - uuid=self.vm.summary.config.uuid) - - return result - - def copy(self): - result = dict(changed=True, uuid=self.vm.summary.config.uuid) - vm_username = self.module.params['vm_username'] - vm_password = self.module.params['vm_password'] - hostname = self.module.params['hostname'] - overwrite = self.module.params["copy"]["overwrite"] - dest = self.module.params["copy"]['dest'] - src = self.module.params['copy']['src'] - b_src = to_bytes(src, errors='surrogate_or_strict') - - if not os.path.exists(b_src): - self.module.fail_json(msg="Source %s not found" % src) - if not os.access(b_src, os.R_OK): - self.module.fail_json(msg="Source %s not readable" % src) - if os.path.isdir(b_src): - self.module.fail_json(msg="copy does not support copy of directory: %s" % src) - - data = None - with open(b_src, "rb") as local_file: - data = local_file.read() - file_size = os.path.getsize(b_src) - - creds = vim.vm.guest.NamePasswordAuthentication(username=vm_username, password=vm_password) - file_attributes = vim.vm.guest.FileManager.FileAttributes() - file_manager = self.content.guestOperationsManager.fileManager - try: - url = file_manager.InitiateFileTransferToGuest(vm=self.vm, auth=creds, guestFilePath=dest, - fileAttributes=file_attributes, overwrite=overwrite, - fileSize=file_size) - url = url.replace("*", hostname) - resp, info = urls.fetch_url(self.module, url, data=data, method="PUT") - - status_code = info["status"] - if status_code != 200: - self.module.fail_json(msg='problem during file transfer, http message:%s' % info, - uuid=self.vm.summary.config.uuid) - except vim.fault.FileAlreadyExists: - result['changed'] = False - result['msg'] = "Guest file %s already exists" % dest - return result - except vim.fault.FileFault as e: - self.module.fail_json(msg="FileFault:%s" % to_native(e.msg), - uuid=self.vm.summary.config.uuid) - except vim.fault.GuestPermissionDenied as permission_denied: - self.module.fail_json(msg="Permission denied to copy file into " - "destination %s : %s" % (dest, to_native(permission_denied.msg)), - uuid=self.vm.summary.config.uuid) - except vim.fault.InvalidGuestLogin as invalid_guest_login: - self.module.fail_json(msg="Invalid guest login for user" - " %s : %s" % (vm_username, to_native(invalid_guest_login.msg))) - # other exceptions - except Exception as e: - self.module.fail_json(msg="Failed to Copy file to Vm VMware exception : %s" % to_native(e), - uuid=self.vm.summary.config.uuid) - return result - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update(dict( - datacenter=dict(type='str'), - cluster=dict(type='str'), - folder=dict(type='str'), - vm_id=dict(type='str', required=True), - vm_id_type=dict( - default='vm_name', - type='str', - choices=['inventory_path', 'uuid', 'instance_uuid', 'dns_name', 'vm_name']), - vm_username=dict(type='str', required=True), - vm_password=dict(type='str', no_log=True, required=True), - directory=dict( - type='dict', - default=None, - options=dict( - operation=dict(required=True, type='str', choices=['create', 'delete', 'mktemp']), - path=dict(required=False, type='str'), - prefix=dict(required=False, type='str'), - suffix=dict(required=False, type='str'), - recurse=dict(required=False, type='bool', default=False) - ) - ), - copy=dict( - type='dict', - default=None, - options=dict(src=dict(required=True, type='str'), - dest=dict(required=True, type='str'), - overwrite=dict(required=False, type='bool', default=False) - ) - ), - fetch=dict( - type='dict', - default=None, - options=dict( - src=dict(required=True, type='str'), - dest=dict(required=True, type='str'), - ) - ) - ) - ) - - module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, - required_if=[['vm_id_type', 'inventory_path', ['folder']]], - mutually_exclusive=[['directory', 'copy', 'fetch']], - required_one_of=[['directory', 'copy', 'fetch']], - ) - - if module.params['directory']: - if module.params['directory']['operation'] in ('create', 'delete') and not module.params['directory']['path']: - module.fail_json(msg='directory.path is required when operation is "create" or "delete"') - if module.params['directory']['operation'] == 'mktemp' and not (module.params['directory']['prefix'] and module.params['directory']['suffix']): - module.fail_json(msg='directory.prefix and directory.suffix are required when operation is "mktemp"') - - if module.params['vm_id_type'] == 'inventory_path' and not module.params['folder']: - module.fail_json(msg='Folder is required parameter when vm_id_type is inventory_path') - - vmware_guest_file_manager = VmwareGuestFileManager(module) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_find.py b/lib/ansible/modules/cloud/vmware/vmware_guest_find.py deleted file mode 100644 index 36fbb3ceeb..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_find.py +++ /dev/null @@ -1,154 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright: (c) 2017, Ansible Project -# 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 = ''' ---- -module: vmware_guest_find -short_description: Find the folder path(s) for a virtual machine by name or UUID -description: - - Find the folder path(s) for a virtual machine by name or UUID -version_added: 2.4 -author: - - Abhijeet Kasurde (@Akasurde) <akasurde@redhat.com> -notes: - - Tested on vSphere 6.5 -requirements: - - "python >= 2.6" - - PyVmomi -options: - name: - description: - - Name of the VM to work with. - - This is required if C(uuid) parameter is not supplied. - type: str - uuid: - description: - - UUID of the instance to manage if known, this is VMware's BIOS UUID by default. - - This is required if C(name) parameter is not supplied. - type: str - use_instance_uuid: - description: - - Whether to use the VMware instance UUID rather than the BIOS UUID. - default: no - type: bool - version_added: '2.8' -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Find Guest's Folder using name - vmware_guest_find: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - name: testvm - delegate_to: localhost - register: vm_folder - -- name: Find Guest's Folder using UUID - vmware_guest_find: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - uuid: 38c4c89c-b3d7-4ae6-ae4e-43c5118eae49 - delegate_to: localhost - register: vm_folder -''' - -RETURN = r""" -folders: - description: List of folders for user specified virtual machine - returned: on success - type: list - sample: [ - '/DC0/vm', - ] -""" - - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils._text import to_native -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec, find_vm_by_id - -try: - from pyVmomi import vim -except ImportError: - pass - - -class PyVmomiHelper(PyVmomi): - def __init__(self, module): - super(PyVmomiHelper, self).__init__(module) - self.name = self.params['name'] - self.uuid = self.params['uuid'] - self.use_instance_uuid = self.params['use_instance_uuid'] - - def getvm_folder_paths(self): - results = [] - vms = [] - - if self.uuid: - if self.use_instance_uuid: - vm_obj = find_vm_by_id(self.content, vm_id=self.uuid, vm_id_type="instance_uuid") - else: - vm_obj = find_vm_by_id(self.content, vm_id=self.uuid, vm_id_type="uuid") - if vm_obj is None: - self.module.fail_json(msg="Failed to find the virtual machine with UUID : %s" % self.uuid) - vms = [vm_obj] - - elif self.name: - objects = self.get_managed_objects_properties(vim_type=vim.VirtualMachine, properties=['name']) - for temp_vm_object in objects: - if temp_vm_object.obj.name == self.name: - vms.append(temp_vm_object.obj) - - for vm in vms: - folder_path = self.get_vm_path(self.content, vm) - results.append(folder_path) - - return results - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - name=dict(type='str'), - uuid=dict(type='str'), - use_instance_uuid=dict(type='bool', default=False), - ) - - module = AnsibleModule(argument_spec=argument_spec, - required_one_of=[['name', 'uuid']], - mutually_exclusive=[['name', 'uuid']], - ) - - pyv = PyVmomiHelper(module) - # Check if the VM exists before continuing - folders = pyv.getvm_folder_paths() - - # VM already exists - if folders: - try: - module.exit_json(folders=folders) - except Exception as exc: - module.fail_json(msg="Folder enumeration failed with exception %s" % to_native(exc)) - else: - module.fail_json(msg="Unable to find folders for virtual machine %s" % (module.params.get('name') or - module.params.get('uuid'))) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_info.py b/lib/ansible/modules/cloud/vmware/vmware_guest_info.py deleted file mode 100644 index 4f9b02eff8..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_info.py +++ /dev/null @@ -1,316 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# This module is also sponsored by E.T.A.I. (www.etai.fr) -# Copyright (C) 2018 James E. King III (@jeking3) <jking@apache.org> -# 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 = ''' ---- -module: vmware_guest_info -short_description: Gather info about a single VM -description: - - Gather information about a single VM on a VMware ESX cluster. - - This module was called C(vmware_guest_facts) before Ansible 2.9. The usage did not change. -version_added: 2.3 -author: - - Loic Blot (@nerzhul) <loic.blot@unix-experience.fr> -notes: - - Tested on vSphere 5.5, 6.7 -requirements: - - "python >= 2.6" - - PyVmomi -options: - name: - description: - - Name of the VM to work with - - This is required if C(uuid) or C(moid) is not supplied. - type: str - name_match: - description: - - If multiple VMs matching the name, use the first or last found - default: 'first' - choices: ['first', 'last'] - type: str - uuid: - description: - - UUID of the instance to manage if known, this is VMware's unique identifier. - - This is required if C(name) or C(moid) is not supplied. - type: str - use_instance_uuid: - description: - - Whether to use the VMware instance UUID rather than the BIOS UUID. - default: no - type: bool - version_added: '2.8' - moid: - description: - - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. - - This is required if C(name) or C(uuid) is not supplied. - version_added: '2.9' - type: str - folder: - description: - - Destination folder, absolute or relative path to find an existing guest. - - This is required if name is supplied. - - The folder should include the datacenter. ESX's datacenter is ha-datacenter - - 'Examples:' - - ' folder: /ha-datacenter/vm' - - ' folder: ha-datacenter/vm' - - ' folder: /datacenter1/vm' - - ' folder: datacenter1/vm' - - ' folder: /datacenter1/vm/folder1' - - ' folder: datacenter1/vm/folder1' - - ' folder: /folder1/datacenter1/vm' - - ' folder: folder1/datacenter1/vm' - - ' folder: /folder1/datacenter1/vm/folder2' - type: str - datacenter: - description: - - Destination datacenter for the deploy operation - required: True - type: str - tags: - description: - - Whether to show tags or not. - - If set C(True), shows tag information. - - If set C(False), hides tags information. - - vSphere Automation SDK and vCloud Suite SDK is required. - default: 'no' - type: bool - version_added: '2.8' - schema: - description: - - Specify the output schema desired. - - The 'summary' output schema is the legacy output from the module - - The 'vsphere' output schema is the vSphere API class definition - which requires pyvmomi>6.7.1 - choices: ['summary', 'vsphere'] - default: 'summary' - type: str - version_added: '2.8' - properties: - description: - - Specify the properties to retrieve. - - If not specified, all properties are retrieved (deeply). - - Results are returned in a structure identical to the vsphere API. - - 'Example:' - - ' properties: [' - - ' "config.hardware.memoryMB",' - - ' "config.hardware.numCPU",' - - ' "guest.disk",' - - ' "overallStatus"' - - ' ]' - - Only valid when C(schema) is C(vsphere). - type: list - required: False - version_added: '2.8' -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Gather info from standalone ESXi server having datacenter as 'ha-datacenter' - vmware_guest_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: ha-datacenter - validate_certs: no - uuid: 421e4592-c069-924d-ce20-7e7533fab926 - delegate_to: localhost - register: info - -- name: Gather some info from a guest using the vSphere API output schema - vmware_guest_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ datacenter_name }}" - name: "{{ vm_name }}" - schema: "vsphere" - properties: ["config.hardware.memoryMB", "guest.disk", "overallStatus"] - delegate_to: localhost - register: info - -- name: Gather some information about a guest using MoID - vmware_guest_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ datacenter_name }}" - moid: vm-42 - schema: "vsphere" - properties: ["config.hardware.memoryMB", "guest.disk", "overallStatus"] - delegate_to: localhost - register: vm_moid_info - -- name: Gather Managed object ID (moid) from a guest using the vSphere API output schema for REST Calls - vmware_guest_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ datacenter_name }}" - name: "{{ vm_name }}" - schema: "vsphere" - properties: - - _moId - delegate_to: localhost - register: moid_info -''' - -RETURN = """ -instance: - description: metadata about the virtual machine - returned: always - type: dict - sample: { - "annotation": "", - "current_snapshot": null, - "customvalues": {}, - "guest_consolidation_needed": false, - "guest_question": null, - "guest_tools_status": "guestToolsNotRunning", - "guest_tools_version": "10247", - "hw_cores_per_socket": 1, - "hw_datastores": [ - "ds_226_3" - ], - "hw_esxi_host": "10.76.33.226", - "hw_eth0": { - "addresstype": "assigned", - "ipaddresses": null, - "label": "Network adapter 1", - "macaddress": "00:50:56:87:a5:9a", - "macaddress_dash": "00-50-56-87-a5-9a", - "portgroup_key": null, - "portgroup_portkey": null, - "summary": "VM Network" - }, - "hw_files": [ - "[ds_226_3] ubuntu_t/ubuntu_t.vmx", - "[ds_226_3] ubuntu_t/ubuntu_t.nvram", - "[ds_226_3] ubuntu_t/ubuntu_t.vmsd", - "[ds_226_3] ubuntu_t/vmware.log", - "[ds_226_3] u0001/u0001.vmdk" - ], - "hw_folder": "/DC0/vm/Discovered virtual machine", - "hw_guest_full_name": null, - "hw_guest_ha_state": null, - "hw_guest_id": null, - "hw_interfaces": [ - "eth0" - ], - "hw_is_template": false, - "hw_memtotal_mb": 1024, - "hw_name": "ubuntu_t", - "hw_power_status": "poweredOff", - "hw_processor_count": 1, - "hw_product_uuid": "4207072c-edd8-3bd5-64dc-903fd3a0db04", - "hw_version": "vmx-13", - "instance_uuid": "5007769d-add3-1e12-f1fe-225ae2a07caf", - "ipv4": null, - "ipv6": null, - "module_hw": true, - "snapshots": [], - "tags": [ - "backup" - ], - "vnc": {}, - "moid": "vm-42", - "vimref": "vim.VirtualMachine:vm-42" - } -""" - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils._text import to_text -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec -from ansible.module_utils.vmware_rest_client import VmwareRestClient -try: - from com.vmware.vapi.std_client import DynamicID - HAS_VSPHERE = True -except ImportError: - HAS_VSPHERE = False - - -class VmwareTag(VmwareRestClient): - def __init__(self, module): - super(VmwareTag, self).__init__(module) - self.tag_service = self.api_client.tagging.Tag - self.tag_association_svc = self.api_client.tagging.TagAssociation - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - name=dict(type='str'), - name_match=dict(type='str', choices=['first', 'last'], default='first'), - uuid=dict(type='str'), - use_instance_uuid=dict(type='bool', default=False), - moid=dict(type='str'), - folder=dict(type='str'), - datacenter=dict(type='str', required=True), - tags=dict(type='bool', default=False), - schema=dict(type='str', choices=['summary', 'vsphere'], default='summary'), - properties=dict(type='list') - ) - module = AnsibleModule(argument_spec=argument_spec, - required_one_of=[['name', 'uuid', 'moid']], - supports_check_mode=True) - if module._name == 'vmware_guest_facts': - module.deprecate("The 'vmware_guest_facts' module has been renamed to 'vmware_guest_info'", version='2.13') - - if module.params.get('folder'): - # FindByInventoryPath() does not require an absolute path - # so we should leave the input folder path unmodified - module.params['folder'] = module.params['folder'].rstrip('/') - - if module.params['schema'] != 'vsphere' and module.params.get('properties'): - module.fail_json(msg="The option 'properties' is only valid when the schema is 'vsphere'") - - pyv = PyVmomi(module) - # Check if the VM exists before continuing - vm = pyv.get_vm() - - # VM already exists - if vm: - try: - if module.params['schema'] == 'summary': - instance = pyv.gather_facts(vm) - else: - instance = pyv.to_json(vm, module.params['properties']) - if module.params.get('tags'): - if not HAS_VSPHERE: - module.fail_json(msg="Unable to find 'vCloud Suite SDK' Python library which is required." - " Please refer this URL for installation steps" - " - https://code.vmware.com/web/sdk/60/vcloudsuite-python") - - vm_rest_client = VmwareTag(module) - instance.update( - tags=vm_rest_client.get_vm_tags(vm_rest_client.tag_service, - vm_rest_client.tag_association_svc, - vm_mid=vm._moId) - ) - module.exit_json(instance=instance) - except Exception as exc: - module.fail_json(msg="Information gathering failed with exception %s" % to_text(exc)) - else: - vm_id = (module.params.get('uuid') or module.params.get('name') or module.params.get('moid')) - module.fail_json(msg="Unable to gather information for non-existing VM %s" % vm_id) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_move.py b/lib/ansible/modules/cloud/vmware/vmware_guest_move.py deleted file mode 100644 index 13a05a01e9..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_move.py +++ /dev/null @@ -1,260 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Jose Angel Munoz <josea.munoz () gmail.com> -# Copyright: (c) 2018, Ansible Project -# 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_guest_move -short_description: Moves virtual machines in vCenter -description: - - This module can be used to move virtual machines between folders. -version_added: '2.7' -author: - - Jose Angel Munoz (@imjoseangel) -notes: - - Tested on vSphere 5.5 and vSphere 6.5 -requirements: - - python >= 2.6 - - PyVmomi -options: - name: - description: - - Name of the existing virtual machine to move. - - This is required if C(uuid) or C(moid) is not supplied. - type: str - uuid: - description: - - UUID of the virtual machine to manage if known, this is VMware's unique identifier. - - This is required if C(name) or C(moid) is not supplied. - type: str - moid: - description: - - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. - - This is required if C(name) or C(uuid) is not supplied. - version_added: '2.9' - type: str - use_instance_uuid: - description: - - Whether to use the VMware instance UUID rather than the BIOS UUID. - default: no - type: bool - version_added: '2.8' - name_match: - description: - - If multiple virtual machines matching the name, use the first or last found. - default: 'first' - choices: [ first, last ] - type: str - dest_folder: - description: - - Absolute path to move an existing guest - - The dest_folder should include the datacenter. ESX's datacenter is ha-datacenter. - - This parameter is case sensitive. - - 'Examples:' - - ' dest_folder: /ha-datacenter/vm' - - ' dest_folder: ha-datacenter/vm' - - ' dest_folder: /datacenter1/vm' - - ' dest_folder: datacenter1/vm' - - ' dest_folder: /datacenter1/vm/folder1' - - ' dest_folder: datacenter1/vm/folder1' - - ' dest_folder: /folder1/datacenter1/vm' - - ' dest_folder: folder1/datacenter1/vm' - - ' dest_folder: /folder1/datacenter1/vm/folder2' - required: True - type: str - datacenter: - description: - - Destination datacenter for the move operation - required: True - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Move Virtual Machine - vmware_guest_move: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: datacenter - validate_certs: no - name: testvm-1 - dest_folder: "/{{ datacenter }}/vm" - delegate_to: localhost - -- name: Move Virtual Machine using MoID - vmware_guest_move: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: datacenter - validate_certs: no - moid: vm-42 - dest_folder: "/{{ datacenter }}/vm" - delegate_to: localhost - -- name: Get VM UUID - vmware_guest_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ datacenter }}" - folder: "/{{datacenter}}/vm" - name: "{{ vm_name }}" - delegate_to: localhost - register: vm_facts - -- name: Get UUID from previous task and pass it to this task - vmware_guest_move: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ datacenter }}" - uuid: "{{ vm_facts.instance.hw_product_uuid }}" - dest_folder: "/DataCenter/vm/path/to/new/folder/where/we/want" - delegate_to: localhost - register: facts -''' - -RETURN = """ -instance: - description: metadata about the virtual machine - returned: always - type: dict - sample: { - "annotation": null, - "current_snapshot": null, - "customvalues": {}, - "guest_consolidation_needed": false, - "guest_question": null, - "guest_tools_status": null, - "guest_tools_version": "0", - "hw_cores_per_socket": 1, - "hw_datastores": [ - "LocalDS_0" - ], - "hw_esxi_host": "DC0_H0", - "hw_eth0": { - "addresstype": "generated", - "ipaddresses": null, - "label": "ethernet-0", - "macaddress": "00:0c:29:6b:34:2c", - "macaddress_dash": "00-0c-29-6b-34-2c", - "summary": "DVSwitch: 43cdd1db-1ef7-4016-9bbe-d96395616199" - }, - "hw_files": [ - "[LocalDS_0] DC0_H0_VM0/DC0_H0_VM0.vmx" - ], - "hw_folder": "/F0/DC0/vm/F0", - "hw_guest_full_name": null, - "hw_guest_ha_state": null, - "hw_guest_id": "otherGuest", - "hw_interfaces": [ - "eth0" - ], - "hw_is_template": false, - "hw_memtotal_mb": 32, - "hw_name": "DC0_H0_VM0", - "hw_power_status": "poweredOn", - "hw_processor_count": 1, - "hw_product_uuid": "581c2808-64fb-45ee-871f-6a745525cb29", - "instance_uuid": "8bcb0b6e-3a7d-4513-bf6a-051d15344352", - "ipv4": null, - "ipv6": null, - "module_hw": true, - "snapshots": [] - } -""" - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils._text import to_native -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec, wait_for_task - - -class PyVmomiHelper(PyVmomi): - def __init__(self, module): - super(PyVmomiHelper, self).__init__(module) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - name=dict(type='str'), - name_match=dict( - type='str', choices=['first', 'last'], default='first'), - uuid=dict(type='str'), - moid=dict(type='str'), - use_instance_uuid=dict(type='bool', default=False), - dest_folder=dict(type='str', required=True), - datacenter=dict(type='str', required=True), - ) - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['name', 'uuid', 'moid'] - ], - mutually_exclusive=[ - ['name', 'uuid', 'moid'] - ], - supports_check_mode=True - ) - - # FindByInventoryPath() does not require an absolute path - # so we should leave the input folder path unmodified - module.params['dest_folder'] = module.params['dest_folder'].rstrip('/') - pyv = PyVmomiHelper(module) - search_index = pyv.content.searchIndex - - # Check if the VM exists before continuing - vm = pyv.get_vm() - - # VM exists - if vm: - try: - vm_path = pyv.get_vm_path(pyv.content, vm).lstrip('/') - if module.params['name']: - vm_name = module.params['name'] - else: - vm_name = vm.name - - vm_full = vm_path + '/' + vm_name - folder = search_index.FindByInventoryPath(module.params['dest_folder']) - if folder is None: - module.fail_json(msg="Folder name and/or path does not exist") - vm_to_move = search_index.FindByInventoryPath(vm_full) - if module.check_mode: - module.exit_json(changed=True, instance=pyv.gather_facts(vm)) - if vm_path != module.params['dest_folder'].lstrip('/'): - move_task = folder.MoveInto([vm_to_move]) - changed, err = wait_for_task(move_task) - if changed: - module.exit_json( - changed=True, instance=pyv.gather_facts(vm)) - else: - module.exit_json(instance=pyv.gather_facts(vm)) - except Exception as exc: - module.fail_json(msg="Failed to move VM with exception %s" % - to_native(exc)) - else: - if module.check_mode: - module.exit_json(changed=False) - vm_id = (module.params.get('uuid') or module.params.get('name') or module.params.get('moid')) - module.fail_json(msg="Unable to find VM %s to move to %s" % (vm_id, module.params.get('dest_folder'))) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_network.py b/lib/ansible/modules/cloud/vmware/vmware_guest_network.py deleted file mode 100644 index cd1cc0e140..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_network.py +++ /dev/null @@ -1,594 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2019, Ansible Project -# Copyright: (c) 2019, Diane Wang <dianew@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 = ''' ---- -module: vmware_guest_network -short_description: Manage network adapters of specified virtual machine in given vCenter infrastructure -description: - - This module is used to add, reconfigure, remove network adapter of given virtual machine. - - All parameters and VMware object names are case sensitive. -version_added: '2.9' -author: - - Diane Wang (@Tomorrow9) <dianew@vmware.com> -notes: - - Tested on vSphere 6.0, 6.5 and 6.7 -requirements: - - "python >= 2.6" - - PyVmomi -options: - name: - description: - - Name of the virtual machine. - - This is a required parameter, if parameter C(uuid) or C(moid) is not supplied. - type: str - uuid: - description: - - UUID of the instance to gather info if known, this is VMware's unique identifier. - - This is a required parameter, if parameter C(name) or C(moid) is not supplied. - type: str - use_instance_uuid: - description: - - Whether to use the VMware instance UUID rather than the BIOS UUID. - default: False - type: bool - version_added: '2.10' - moid: - description: - - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. - - This is required if C(name) or C(uuid) is not supplied. - type: str - folder: - description: - - Destination folder, absolute or relative path to find an existing guest. - - This is a required parameter, only if multiple VMs are found with same name. - - The folder should include the datacenter. ESXi server's datacenter is ha-datacenter. - - 'Examples:' - - ' folder: /ha-datacenter/vm' - - ' folder: ha-datacenter/vm' - - ' folder: /datacenter1/vm' - - ' folder: datacenter1/vm' - - ' folder: /datacenter1/vm/folder1' - - ' folder: datacenter1/vm/folder1' - - ' folder: /folder1/datacenter1/vm' - - ' folder: folder1/datacenter1/vm' - - ' folder: /folder1/datacenter1/vm/folder2' - type: str - cluster: - description: - - The name of cluster where the virtual machine will run. - - This is a required parameter, if C(esxi_hostname) is not set. - - C(esxi_hostname) and C(cluster) are mutually exclusive parameters. - type: str - esxi_hostname: - description: - - The ESXi hostname where the virtual machine will run. - - This is a required parameter, if C(cluster) is not set. - - C(esxi_hostname) and C(cluster) are mutually exclusive parameters. - type: str - datacenter: - default: ha-datacenter - description: - - The datacenter name to which virtual machine belongs to. - type: str - gather_network_info: - description: - - If set to C(True), return settings of all network adapters, other parameters are ignored. - - If set to C(False), will add, reconfigure or remove network adapters according to the parameters in C(networks). - type: bool - default: False - aliases: [ gather_network_facts ] - networks: - type: list - description: - - A list of network adapters. - - C(mac) or C(label) or C(device_type) is required to reconfigure or remove an existing network adapter. - - 'If there are multiple network adapters with the same C(device_type), you should set C(label) or C(mac) to match - one of them, or will apply changes on all network adapters with the C(device_type) specified.' - - 'C(mac), C(label), C(device_type) is the order of precedence from greatest to least if all set.' - - 'Valid attributes are:' - - ' - C(mac) (string): MAC address of the existing network adapter to be reconfigured or removed.' - - ' - C(label) (string): Label of the existing network adapter to be reconfigured or removed, e.g., "Network adapter 1".' - - ' - C(device_type) (string): Valid virtual network device types are: - C(e1000), C(e1000e), C(pcnet32), C(vmxnet2), C(vmxnet3) (default), C(sriov). - Used to add new network adapter, reconfigure or remove the existing network adapter with this type. - If C(mac) and C(label) not specified or not find network adapter by C(mac) or C(label) will use this parameter.' - - ' - C(name) (string): Name of the portgroup or distributed virtual portgroup for this interface. - When specifying distributed virtual portgroup make sure given C(esxi_hostname) or C(cluster) is associated with it.' - - ' - C(vlan) (integer): VLAN number for this interface.' - - ' - C(dvswitch_name) (string): Name of the distributed vSwitch. - This value is required if multiple distributed portgroups exists with the same name.' - - ' - C(state) (string): State of the network adapter.' - - ' If set to C(present), then will do reconfiguration for the specified network adapter.' - - ' If set to C(new), then will add the specified network adapter.' - - ' If set to C(absent), then will remove this network adapter.' - - ' - C(manual_mac) (string): Manual specified MAC address of the network adapter when creating, or reconfiguring. - If not specified when creating new network adapter, mac address will be generated automatically. - When reconfigure MAC address, VM should be in powered off state.' - - ' - C(connected) (bool): Indicates that virtual network adapter connects to the associated virtual machine.' - - ' - C(start_connected) (bool): Indicates that virtual network adapter starts with associated virtual machine powers on.' - - ' - C(directpath_io) (bool): If set, Universal Pass-Through (UPT or DirectPath I/O) will be enabled on the network adapter. - UPT is only compatible for Vmxnet3 adapter.' -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Change network adapter settings of virtual machine - vmware_guest_network: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - validate_certs: no - name: test-vm - gather_network_info: false - networks: - - name: "VM Network" - state: new - manual_mac: "00:50:56:11:22:33" - - state: present - device_type: e1000e - manual_mac: "00:50:56:44:55:66" - - state: present - label: "Network adapter 3" - connected: false - - state: absent - mac: "00:50:56:44:55:77" - delegate_to: localhost - register: network_info - -- name: Change network adapter settings of virtual machine using MoID - vmware_guest_network: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - validate_certs: no - moid: vm-42 - gather_network_info: false - networks: - - state: absent - mac: "00:50:56:44:55:77" - delegate_to: localhost - -- name: Change network adapter settings of virtual machine using instance UUID - vmware_guest_network: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - validate_certs: no - uuid: 5003b4f5-c705-2f37-ccf6-dfc0b40afeb7 - use_instance_uuid: True - gather_network_info: false - networks: - - state: absent - mac: "00:50:56:44:55:77" - delegate_to: localhost - -- name: Enable DirectPath I/O on a Vmxnet3 adapter - vmware_guest_network: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - validate_certs: no - name: test-vm - gather_network_info: false - networks: - - state: present - mac: "aa:50:56:58:59:61" - directpath_io: True - delegate_to: localhost -''' - -RETURN = """ -network_data: - description: metadata about the virtual machine's network adapter after managing them - returned: always - type: dict - sample: { - "0": { - "label": "Network Adapter 1", - "name": "VM Network", - "device_type": "E1000E", - "directpath_io": "N/A", - "mac_addr": "00:50:56:89:dc:05", - "unit_number": 7, - "wake_onlan": false, - "allow_guest_ctl": true, - "connected": true, - "start_connected": true, - }, - "1": { - "label": "Network Adapter 2", - "name": "VM Network", - "device_type": "VMXNET3", - "directpath_io": true, - "mac_addr": "00:50:56:8d:93:8c", - "unit_number": 8, - "start_connected": true, - "wake_on_lan": true, - "connected": true, - } - } -""" - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.common.network import is_mac -from ansible.module_utils._text import to_native, to_text -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec, wait_for_task, get_all_objs, get_parent_datacenter - - -class PyVmomiHelper(PyVmomi): - def __init__(self, module): - super(PyVmomiHelper, self).__init__(module) - self.change_detected = False - self.config_spec = vim.vm.ConfigSpec() - self.config_spec.deviceChange = [] - self.nic_device_type = dict( - pcnet32=vim.vm.device.VirtualPCNet32, - vmxnet2=vim.vm.device.VirtualVmxnet2, - vmxnet3=vim.vm.device.VirtualVmxnet3, - e1000=vim.vm.device.VirtualE1000, - e1000e=vim.vm.device.VirtualE1000e, - sriov=vim.vm.device.VirtualSriovEthernetCard, - ) - - def get_device_type(self, device_type=None): - """ Get network adapter device type """ - if device_type and device_type in list(self.nic_device_type.keys()): - return self.nic_device_type[device_type]() - else: - self.module.fail_json(msg='Invalid network device_type %s' % device_type) - - def get_network_device(self, vm=None, mac=None, device_type=None, device_label=None): - """ - Get network adapter - """ - nic_devices = [] - nic_device = None - if vm is None: - if device_type: - return nic_devices - else: - return nic_device - - for device in vm.config.hardware.device: - if mac: - if isinstance(device, vim.vm.device.VirtualEthernetCard): - if device.macAddress == mac: - nic_device = device - break - elif device_type: - if isinstance(device, self.nic_device_type[device_type]): - nic_devices.append(device) - elif device_label: - if isinstance(device, vim.vm.device.VirtualEthernetCard): - if device.deviceInfo.label == device_label: - nic_device = device - break - if device_type: - return nic_devices - else: - return nic_device - - def get_network_device_by_mac(self, vm=None, mac=None): - """ Get network adapter with the specified mac address""" - return self.get_network_device(vm=vm, mac=mac) - - def get_network_devices_by_type(self, vm=None, device_type=None): - """ Get network adapter list with the name type """ - return self.get_network_device(vm=vm, device_type=device_type) - - def get_network_device_by_label(self, vm=None, device_label=None): - """ Get network adapter with the specified label """ - return self.get_network_device(vm=vm, device_label=device_label) - - def create_network_adapter(self, device_info): - nic = vim.vm.device.VirtualDeviceSpec() - nic.device = self.get_device_type(device_type=device_info.get('device_type', 'vmxnet3')) - nic.device.deviceInfo = vim.Description() - network_object = self.find_network_by_name(network_name=device_info['name'])[0] - if network_object: - if hasattr(network_object, 'portKeys'): - # DistributedVirtualPortGroup - nic.device.backing = vim.vm.device.VirtualEthernetCard.DistributedVirtualPortBackingInfo() - nic.device.backing.port = vim.dvs.PortConnection() - nic.device.backing.port.switchUuid = network_object.config.distributedVirtualSwitch.uuid - nic.device.backing.port.portgroupKey = network_object.key - elif isinstance(network_object, vim.OpaqueNetwork): - # NSX-T Logical Switch - nic.device.backing = vim.vm.device.VirtualEthernetCard.OpaqueNetworkBackingInfo() - network_id = network_object.summary.opaqueNetworkId - nic.device.backing.opaqueNetworkType = 'nsx.LogicalSwitch' - nic.device.backing.opaqueNetworkId = network_id - nic.device.deviceInfo.summary = 'nsx.LogicalSwitch: %s' % network_id - else: - # Standard vSwitch - nic.device.deviceInfo.summary = device_info['name'] - nic.device.backing = vim.vm.device.VirtualEthernetCard.NetworkBackingInfo() - nic.device.backing.deviceName = device_info['name'] - nic.device.backing.network = network_object - nic.device.connectable = vim.vm.device.VirtualDevice.ConnectInfo() - nic.device.connectable.startConnected = device_info.get('start_connected', True) - nic.device.connectable.allowGuestControl = True - nic.device.connectable.connected = device_info.get('connected', True) - if 'manual_mac' in device_info: - nic.device.addressType = 'manual' - nic.device.macAddress = device_info['manual_mac'] - else: - nic.device.addressType = 'generated' - if 'directpath_io' in device_info: - if isinstance(nic.device, vim.vm.device.VirtualVmxnet3): - nic.device.uptCompatibilityEnabled = device_info['directpath_io'] - else: - self.module.fail_json(msg='UPT is only compatible for Vmxnet3 adapter.' - + ' Clients can set this property enabled or disabled if ethernet virtual device is Vmxnet3.') - - return nic - - def get_network_info(self, vm_obj): - network_info = dict() - if vm_obj is None: - return network_info - - nic_index = 0 - for nic in vm_obj.config.hardware.device: - nic_type = None - directpath_io = 'N/A' - if isinstance(nic, vim.vm.device.VirtualPCNet32): - nic_type = 'PCNet32' - elif isinstance(nic, vim.vm.device.VirtualVmxnet2): - nic_type = 'VMXNET2' - elif isinstance(nic, vim.vm.device.VirtualVmxnet3): - nic_type = 'VMXNET3' - directpath_io = nic.uptCompatibilityEnabled - elif isinstance(nic, vim.vm.device.VirtualE1000): - nic_type = 'E1000' - elif isinstance(nic, vim.vm.device.VirtualE1000e): - nic_type = 'E1000E' - elif isinstance(nic, vim.vm.device.VirtualSriovEthernetCard): - nic_type = 'SriovEthernetCard' - if nic_type is not None: - network_info[nic_index] = dict( - device_type=nic_type, - label=nic.deviceInfo.label, - name=nic.deviceInfo.summary, - mac_addr=nic.macAddress, - unit_number=nic.unitNumber, - wake_onlan=nic.wakeOnLanEnabled, - allow_guest_ctl=nic.connectable.allowGuestControl, - connected=nic.connectable.connected, - start_connected=nic.connectable.startConnected, - directpath_io=directpath_io - ) - nic_index += 1 - - return network_info - - def sanitize_network_params(self): - network_list = [] - valid_state = ['new', 'present', 'absent'] - if len(self.params['networks']) != 0: - for network in self.params['networks']: - if 'state' not in network or network['state'].lower() not in valid_state: - self.module.fail_json(msg="Network adapter state not specified or invalid: '%s', valid values: " - "%s" % (network.get('state', ''), valid_state)) - # add new network adapter but no name specified - if network['state'].lower() == 'new' and 'name' not in network and 'vlan' not in network: - self.module.fail_json(msg="Please specify at least network name or VLAN name for adding new network adapter.") - if network['state'].lower() == 'new' and 'mac' in network: - self.module.fail_json(msg="networks.mac is used for vNIC reconfigure, but networks.state is set to 'new'.") - if network['state'].lower() == 'present' and 'mac' not in network and 'label' not in network and 'device_type' not in network: - self.module.fail_json(msg="Should specify 'mac', 'label' or 'device_type' parameter to reconfigure network adapter") - if 'connected' in network: - if not isinstance(network['connected'], bool): - self.module.fail_json(msg="networks.connected parameter should be boolean.") - if network['state'].lower() == 'new' and not network['connected']: - network['start_connected'] = False - if 'start_connected' in network: - if not isinstance(network['start_connected'], bool): - self.module.fail_json(msg="networks.start_connected parameter should be boolean.") - if network['state'].lower() == 'new' and not network['start_connected']: - network['connected'] = False - # specified network does not exist - if 'name' in network and not self.network_exists_by_name(network['name']): - self.module.fail_json(msg="Network '%(name)s' does not exist." % network) - elif 'vlan' in network: - objects = get_all_objs(self.content, [vim.dvs.DistributedVirtualPortgroup]) - dvps = [x for x in objects if to_text(get_parent_datacenter(x).name) == to_text(self.params['datacenter'])] - for dvp in dvps: - if hasattr(dvp.config.defaultPortConfig, 'vlan') and \ - isinstance(dvp.config.defaultPortConfig.vlan.vlanId, int) and \ - str(dvp.config.defaultPortConfig.vlan.vlanId) == str(network['vlan']): - network['name'] = dvp.config.name - break - if 'dvswitch_name' in network and \ - dvp.config.distributedVirtualSwitch.name == network['dvswitch_name'] and \ - dvp.config.name == network['vlan']: - network['name'] = dvp.config.name - break - if dvp.config.name == network['vlan']: - network['name'] = dvp.config.name - break - else: - self.module.fail_json(msg="VLAN '%(vlan)s' does not exist." % network) - - if 'device_type' in network and network['device_type'] not in list(self.nic_device_type.keys()): - self.module.fail_json(msg="Device type specified '%s' is invalid. " - "Valid types %s " % (network['device_type'], list(self.nic_device_type.keys()))) - - if ('mac' in network and not is_mac(network['mac'])) or \ - ('manual_mac' in network and not is_mac(network['manual_mac'])): - self.module.fail_json(msg="Device MAC address '%s' or manual set MAC address %s is invalid. " - "Please provide correct MAC address." % (network['mac'], network['manual_mac'])) - - network_list.append(network) - - return network_list - - def get_network_config_spec(self, vm_obj, network_list): - # create network adapter config spec for adding, editing, removing - for network in network_list: - # add new network adapter - if network['state'].lower() == 'new': - nic_spec = self.create_network_adapter(network) - nic_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.add - self.change_detected = True - self.config_spec.deviceChange.append(nic_spec) - # reconfigure network adapter or remove network adapter - else: - nic_devices = [] - if 'mac' in network: - nic = self.get_network_device_by_mac(vm_obj, mac=network['mac']) - if nic is not None: - nic_devices.append(nic) - if 'label' in network and len(nic_devices) == 0: - nic = self.get_network_device_by_label(vm_obj, device_label=network['label']) - if nic is not None: - nic_devices.append(nic) - if 'device_type' in network and len(nic_devices) == 0: - nic_devices = self.get_network_devices_by_type(vm_obj, device_type=network['device_type']) - if len(nic_devices) != 0: - for nic_device in nic_devices: - nic_spec = vim.vm.device.VirtualDeviceSpec() - if network['state'].lower() == 'present': - nic_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.edit - nic_spec.device = nic_device - if 'start_connected' in network and nic_device.connectable.startConnected != network['start_connected']: - nic_device.connectable.startConnected = network['start_connected'] - self.change_detected = True - if 'connected' in network and nic_device.connectable.connected != network['connected']: - nic_device.connectable.connected = network['connected'] - self.change_detected = True - if 'name' in network: - network_object = self.find_network_by_name(network_name=network['name'])[0] - if network_object and hasattr(network_object, 'portKeys') and hasattr(nic_spec.device.backing, 'port'): - if network_object.config.distributedVirtualSwitch.uuid != nic_spec.device.backing.port.switchUuid: - # DistributedVirtualPortGroup - nic_spec.device.backing = vim.vm.device.VirtualEthernetCard.DistributedVirtualPortBackingInfo() - nic_spec.device.backing.port = vim.dvs.PortConnection() - nic_spec.device.backing.port.switchUuid = network_object.config.distributedVirtualSwitch.uuid - nic_spec.device.backing.port.portgroupKey = network_object.key - self.change_detected = True - elif network_object and isinstance(network_object, vim.OpaqueNetwork) and hasattr(nic_spec.device.backing, 'opaqueNetworkId'): - if nic_spec.device.backing.opaqueNetworkId != network_object.summary.opaqueNetworkId: - # NSX-T Logical Switch - nic_spec.device.backing = vim.vm.device.VirtualEthernetCard.OpaqueNetworkBackingInfo() - network_id = network_object.summary.opaqueNetworkId - nic_spec.device.backing.opaqueNetworkType = 'nsx.LogicalSwitch' - nic_spec.device.backing.opaqueNetworkId = network_id - nic_spec.device.deviceInfo.summary = 'nsx.LogicalSwitch: %s' % network_id - self.change_detected = True - elif nic_device.deviceInfo.summary != network['name']: - # Standard vSwitch - nic_spec.device.backing = vim.vm.device.VirtualEthernetCard.NetworkBackingInfo() - nic_spec.device.backing.deviceName = network['name'] - nic_spec.device.backing.network = network_object - self.change_detected = True - if 'manual_mac' in network and nic_device.macAddress != network['manual_mac']: - if vm_obj.runtime.powerState != vim.VirtualMachinePowerState.poweredOff: - self.module.fail_json(msg='Expected power state is poweredOff to reconfigure MAC address') - nic_device.addressType = 'manual' - nic_device.macAddress = network['manual_mac'] - self.change_detected = True - if 'directpath_io' in network: - if isinstance(nic_device, vim.vm.device.VirtualVmxnet3): - if nic_device.uptCompatibilityEnabled != network['directpath_io']: - nic_device.uptCompatibilityEnabled = network['directpath_io'] - self.change_detected = True - else: - self.module.fail_json(msg='UPT is only compatible for Vmxnet3 adapter.' - + ' Clients can set this property enabled or disabled if ethernet virtual device is Vmxnet3.') - if self.change_detected: - self.config_spec.deviceChange.append(nic_spec) - elif network['state'].lower() == 'absent': - nic_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.remove - nic_spec.device = nic_device - self.change_detected = True - self.config_spec.deviceChange.append(nic_spec) - else: - self.module.fail_json(msg='Unable to find the specified network adapter: %s' % network) - - def reconfigure_vm_network(self, vm_obj): - network_list = self.sanitize_network_params() - # gather network adapter info only - if (self.params['gather_network_info'] is not None and self.params['gather_network_info']) or len(network_list) == 0: - results = {'changed': False, 'failed': False, 'network_data': self.get_network_info(vm_obj)} - # do reconfigure then gather info - else: - self.get_network_config_spec(vm_obj, network_list) - try: - task = vm_obj.ReconfigVM_Task(spec=self.config_spec) - wait_for_task(task) - except vim.fault.InvalidDeviceSpec as e: - self.module.fail_json(msg="Failed to configure network adapter on given virtual machine due to invalid" - " device spec : %s" % to_native(e.msg), - details="Please check ESXi server logs for more details.") - except vim.fault.RestrictedVersion as e: - self.module.fail_json(msg="Failed to reconfigure virtual machine due to" - " product versioning restrictions: %s" % to_native(e.msg)) - if task.info.state == 'error': - results = {'changed': self.change_detected, 'failed': True, 'msg': task.info.error.msg} - else: - network_info = self.get_network_info(vm_obj) - results = {'changed': self.change_detected, 'failed': False, 'network_data': network_info} - - return results - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - name=dict(type='str'), - uuid=dict(type='str'), - use_instance_uuid=dict(type='bool', default=False), - moid=dict(type='str'), - folder=dict(type='str'), - datacenter=dict(type='str', default='ha-datacenter'), - esxi_hostname=dict(type='str'), - cluster=dict(type='str'), - gather_network_info=dict(type='bool', default=False, aliases=['gather_network_facts']), - networks=dict(type='list', default=[]) - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['name', 'uuid', 'moid'] - ] - ) - - pyv = PyVmomiHelper(module) - vm = pyv.get_vm() - if not vm: - vm_id = (module.params.get('uuid') or module.params.get('name') or module.params.get('moid')) - module.fail_json(msg='Unable to find the specified virtual machine using %s' % vm_id) - - result = pyv.reconfigure_vm_network(vm) - if result['failed']: - module.fail_json(**result) - else: - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_powerstate.py b/lib/ansible/modules/cloud/vmware/vmware_guest_powerstate.py deleted file mode 100644 index f46c8c1f75..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_powerstate.py +++ /dev/null @@ -1,284 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright: (c) 2017, Abhijeet Kasurde <akasurde@redhat.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_guest_powerstate -short_description: Manages power states of virtual machines in vCenter -description: -- Power on / Power off / Restart a virtual machine. -version_added: '2.5' -author: -- Abhijeet Kasurde (@Akasurde) <akasurde@redhat.com> -requirements: -- python >= 2.6 -- PyVmomi -options: - state: - description: - - Set the state of the virtual machine. - choices: [ powered-off, powered-on, reboot-guest, restarted, shutdown-guest, suspended, present] - default: present - type: str - name: - description: - - Name of the virtual machine to work with. - - Virtual machine names in vCenter are not necessarily unique, which may be problematic, see C(name_match). - type: str - name_match: - description: - - If multiple virtual machines matching the name, use the first or last found. - default: first - choices: [ first, last ] - type: str - uuid: - description: - - UUID of the instance to manage if known, this is VMware's unique identifier. - - This is required if C(name) or C(moid) is not supplied. - type: str - moid: - description: - - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. - - This is required if C(name) or C(uuid) is not supplied. - version_added: '2.9' - type: str - use_instance_uuid: - description: - - Whether to use the VMware instance UUID rather than the BIOS UUID. - default: no - type: bool - version_added: '2.8' - folder: - description: - - Destination folder, absolute or relative path to find an existing guest. - - The folder should include the datacenter. ESX's datacenter is ha-datacenter - - 'Examples:' - - ' folder: /ha-datacenter/vm' - - ' folder: ha-datacenter/vm' - - ' folder: /datacenter1/vm' - - ' folder: datacenter1/vm' - - ' folder: /datacenter1/vm/folder1' - - ' folder: datacenter1/vm/folder1' - - ' folder: /folder1/datacenter1/vm' - - ' folder: folder1/datacenter1/vm' - - ' folder: /folder1/datacenter1/vm/folder2' - type: str - scheduled_at: - description: - - Date and time in string format at which specified task needs to be performed. - - "The required format for date and time - 'dd/mm/yyyy hh:mm'." - - Scheduling task requires vCenter server. A standalone ESXi server does not support this option. - type: str - schedule_task_name: - description: - - Name of schedule task. - - Valid only if C(scheduled_at) is specified. - type: str - required: False - version_added: '2.9' - schedule_task_description: - description: - - Description of schedule task. - - Valid only if C(scheduled_at) is specified. - type: str - required: False - version_added: '2.9' - schedule_task_enabled: - description: - - Flag to indicate whether the scheduled task is enabled or disabled. - type: bool - required: False - default: True - version_added: '2.9' - force: - description: - - Ignore warnings and complete the actions. - - This parameter is useful while forcing virtual machine state. - default: False - type: bool - version_added: 2.5 - state_change_timeout: - description: - - If the C(state) is set to C(shutdown-guest), by default the module will return immediately after sending the shutdown signal. - - If this argument is set to a positive integer, the module will instead wait for the VM to reach the poweredoff state. - - The value sets a timeout in seconds for the module to wait for the state change. - default: 0 - version_added: '2.6' - type: int -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Set the state of a virtual machine to poweroff - vmware_guest_powerstate: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - folder: "/{{ datacenter_name }}/vm/my_folder" - name: "{{ guest_name }}" - state: powered-off - delegate_to: localhost - register: deploy - -- name: Set the state of a virtual machine to poweron using MoID - vmware_guest_powerstate: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - folder: "/{{ datacenter_name }}/vm/my_folder" - moid: vm-42 - state: powered-on - delegate_to: localhost - register: deploy - -- name: Set the state of a virtual machine to poweroff at given scheduled time - vmware_guest_powerstate: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - folder: "/{{ datacenter_name }}/vm/my_folder" - name: "{{ guest_name }}" - state: powered-off - scheduled_at: "09/01/2018 10:18" - schedule_task_name: "task_00001" - schedule_task_description: "Sample task to poweroff VM" - schedule_task_enabled: True - delegate_to: localhost - register: deploy_at_schedule_datetime - -- name: Wait for the virtual machine to shutdown - vmware_guest_powerstate: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "{{ guest_name }}" - state: shutdown-guest - state_change_timeout: 200 - delegate_to: localhost - register: deploy -''' - -RETURN = r''' # ''' - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from random import randint -from datetime import datetime -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, set_vm_power_state, vmware_argument_spec -from ansible.module_utils._text import to_native - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - state=dict(type='str', default='present', - choices=['present', 'powered-off', 'powered-on', 'reboot-guest', 'restarted', 'shutdown-guest', 'suspended']), - name=dict(type='str'), - name_match=dict(type='str', choices=['first', 'last'], default='first'), - uuid=dict(type='str'), - moid=dict(type='str'), - use_instance_uuid=dict(type='bool', default=False), - folder=dict(type='str'), - force=dict(type='bool', default=False), - scheduled_at=dict(type='str'), - schedule_task_name=dict(), - schedule_task_description=dict(), - schedule_task_enabled=dict(type='bool', default=True), - state_change_timeout=dict(type='int', default=0), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=False, - mutually_exclusive=[ - ['name', 'uuid', 'moid'], - ], - ) - - result = dict(changed=False,) - - pyv = PyVmomi(module) - - # Check if the VM exists before continuing - vm = pyv.get_vm() - - if vm: - # VM already exists, so set power state - scheduled_at = module.params.get('scheduled_at', None) - if scheduled_at: - if not pyv.is_vcenter(): - module.fail_json(msg="Scheduling task requires vCenter, hostname %s " - "is an ESXi server." % module.params.get('hostname')) - powerstate = { - 'present': vim.VirtualMachine.PowerOn, - 'powered-off': vim.VirtualMachine.PowerOff, - 'powered-on': vim.VirtualMachine.PowerOn, - 'reboot-guest': vim.VirtualMachine.RebootGuest, - 'restarted': vim.VirtualMachine.Reset, - 'shutdown-guest': vim.VirtualMachine.ShutdownGuest, - 'suspended': vim.VirtualMachine.Suspend, - } - dt = '' - try: - dt = datetime.strptime(scheduled_at, '%d/%m/%Y %H:%M') - except ValueError as e: - module.fail_json(msg="Failed to convert given date and time string to Python datetime object," - "please specify string in 'dd/mm/yyyy hh:mm' format: %s" % to_native(e)) - schedule_task_spec = vim.scheduler.ScheduledTaskSpec() - schedule_task_name = module.params['schedule_task_name'] or 'task_%s' % str(randint(10000, 99999)) - schedule_task_desc = module.params['schedule_task_description'] - if schedule_task_desc is None: - schedule_task_desc = 'Schedule task for vm %s for ' \ - 'operation %s at %s' % (vm.name, module.params['state'], scheduled_at) - schedule_task_spec.name = schedule_task_name - schedule_task_spec.description = schedule_task_desc - schedule_task_spec.scheduler = vim.scheduler.OnceTaskScheduler() - schedule_task_spec.scheduler.runAt = dt - schedule_task_spec.action = vim.action.MethodAction() - schedule_task_spec.action.name = powerstate[module.params['state']] - schedule_task_spec.enabled = module.params['schedule_task_enabled'] - - try: - pyv.content.scheduledTaskManager.CreateScheduledTask(vm, schedule_task_spec) - # As this is async task, we create scheduled task and mark state to changed. - module.exit_json(changed=True) - except vim.fault.InvalidName as e: - module.fail_json(msg="Failed to create scheduled task %s for %s : %s" % (module.params.get('state'), - vm.name, - to_native(e.msg))) - except vim.fault.DuplicateName as e: - module.exit_json(changed=False, details=to_native(e.msg)) - except vmodl.fault.InvalidArgument as e: - module.fail_json(msg="Failed to create scheduled task %s as specifications " - "given are invalid: %s" % (module.params.get('state'), - to_native(e.msg))) - else: - result = set_vm_power_state(pyv.content, vm, module.params['state'], module.params['force'], module.params['state_change_timeout']) - else: - id = module.params.get('uuid') or module.params.get('moid') or module.params.get('name') - module.fail_json(msg="Unable to set power state for non-existing virtual machine : '%s'" % id) - - if result.get('failed') is True: - module.fail_json(**result) - - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_register_operation.py b/lib/ansible/modules/cloud/vmware/vmware_guest_register_operation.py deleted file mode 100644 index 12cbf29b18..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_register_operation.py +++ /dev/null @@ -1,276 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2019, sky-joker -# 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 = ''' -module: vmware_guest_register_operation -short_description: VM inventory registration operation -author: - - sky-joker (@sky-joker) -version_added: '2.10' -description: - - This module can register or unregister VMs to the inventory. -requirements: - - python >= 2.7 - - PyVmomi -options: - datacenter: - description: - - Destination datacenter for the register/unregister operation. - - This parameter is case sensitive. - type: str - cluster: - description: - - Specify a cluster name to register VM. - type: str - folder: - description: - - Description folder, absolute path of the target folder. - - The folder should include the datacenter. ESX's datacenter is ha-datacenter. - - This parameter is case sensitive. - - 'Examples:' - - ' folder: /ha-datacenter/vm' - - ' folder: ha-datacenter/vm' - - ' folder: /datacenter1/vm' - - ' folder: datacenter1/vm' - - ' folder: /datacenter1/vm/folder1' - - ' folder: datacenter1/vm/folder1' - type: str - name: - description: - - Specify VM name to be registered in the inventory. - required: True - type: str - uuid: - description: - - UUID of the virtual machine to manage if known, this is VMware's unique identifier. - - If virtual machine does not exists, then this parameter is ignored. - type: str - esxi_hostname: - description: - - The ESXi hostname where the virtual machine will run. - - This parameter is case sensitive. - type: str - template: - description: - - Whether to register VM as a template. - default: False - type: bool - path: - description: - - Specify the path of vmx file. - - 'Examples:' - - ' [datastore1] vm/vm.vmx' - - ' [datastore1] vm/vm.vmtx' - type: str - resource_pool: - description: - - Specify a resource pool name to register VM. - - This parameter is case sensitive. - - Resource pool should be child of the selected host parent. - type: str - state: - description: - - Specify the state the virtual machine should be in. - - if set to C(present), register VM in inventory. - - if set to C(absent), unregister VM from inventory. - default: present - choices: [ present, absent ] - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Register VM to inventory - vmware_guest_register_operation: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ datacenter }}" - folder: "/vm" - esxi_hostname: "{{ esxi_hostname }}" - name: "{{ vm_name }}" - template: no - path: "[datastore1] vm/vm.vmx" - state: present - -- name: Register VM in resource pool - vmware_guest_register_operation: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ datacenter }}" - folder: "/vm" - resource_pool: "{{ resource_pool }}" - name: "{{ vm_name }}" - template: no - path: "[datastore1] vm/vm.vmx" - state: present - -- name: Register VM in Cluster - vmware_guest_register_operation: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ datacenter }}" - folder: "/vm" - cluster: "{{ cluster_name }}" - name: "{{ vm_name }}" - template: no - path: "[datastore1] vm/vm.vmx" - state: present - -- name: UnRegister VM from inventory - vmware_guest_register_operation: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ datacenter }}" - folder: "/vm" - name: "{{ vm_name }}" - state: absent -''' - -RETURN = r''' -''' - -try: - from pyVmomi import vim, vmodl - HAS_PYVMOMI = True -except ImportError: - HAS_PYVMOMI = False - -from ansible.module_utils._text import to_native -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec, find_resource_pool_by_name, \ - wait_for_task, compile_folder_path_for_object, find_cluster_by_name -from ansible.module_utils.basic import AnsibleModule - - -class VMwareGuestRegisterOperation(PyVmomi): - def __init__(self, module): - super(VMwareGuestRegisterOperation, self).__init__(module) - self.datacenter = module.params["datacenter"] - self.cluster = module.params["cluster"] - self.folder = module.params["folder"] - self.name = module.params["name"] - self.esxi_hostname = module.params["esxi_hostname"] - self.path = module.params["path"] - self.template = module.params["template"] - self.resource_pool = module.params["resource_pool"] - self.state = module.params["state"] - - def execute(self): - result = dict(changed=False) - - datacenter = self.find_datacenter_by_name(self.datacenter) - if not datacenter: - self.module.fail_json(msg="Cannot find the specified Datacenter: %s" % self.datacenter) - - dcpath = compile_folder_path_for_object(datacenter) - if not dcpath.endswith("/"): - dcpath += "/" - - if(self.folder in [None, "", "/"]): - self.module.fail_json(msg="Please specify folder path other than blank or '/'") - elif(self.folder.startswith("/vm")): - fullpath = "%s%s%s" % (dcpath, self.datacenter, self.folder) - else: - fullpath = "%s%s" % (dcpath, self.folder) - - folder_obj = self.content.searchIndex.FindByInventoryPath(inventoryPath="%s" % fullpath) - if not folder_obj: - details = { - 'datacenter': datacenter.name, - 'datacenter_path': dcpath, - 'folder': self.folder, - 'full_search_path': fullpath, - } - self.module.fail_json(msg="No folder %s matched in the search path : %s" % (self.folder, fullpath), - details=details) - - if self.state == "present": - if self.get_vm(): - self.module.exit_json(**result) - - if self.esxi_hostname: - host_obj = self.find_hostsystem_by_name(self.esxi_hostname) - if not host_obj: - self.module.fail_json(msg="Cannot find the specified ESXi host: %s" % self.esxi_hostname) - else: - host_obj = None - - if self.cluster: - cluster_obj = find_cluster_by_name(self.content, self.cluster, datacenter) - if not cluster_obj: - self.module.fail_json(msg="Cannot find the specified cluster name: %s" % self.cluster) - - resource_pool_obj = cluster_obj.resourcePool - elif self.resource_pool: - resource_pool_obj = find_resource_pool_by_name(self.content, self.resource_pool) - if not resource_pool_obj: - self.module.fail_json(msg="Cannot find the specified resource pool: %s" % self.resource_pool) - else: - resource_pool_obj = host_obj.parent.resourcePool - - task = folder_obj.RegisterVM_Task(path=self.path, name=self.name, asTemplate=self.template, - pool=resource_pool_obj, host=host_obj) - - changed = False - try: - changed, info = wait_for_task(task) - except Exception as task_e: - self.module.fail_json(msg=to_native(task_e)) - - result.update(changed=changed) - self.module.exit_json(**result) - - if self.state == "absent": - vm_obj = self.get_vm() - if vm_obj: - try: - vm_obj.UnregisterVM() - result.update(changed=True) - except Exception as exc: - self.module.fail_json(msg=to_native(exc)) - - self.module.exit_json(**result) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update(datacenter=dict(type="str"), - cluster=dict(type="str"), - folder=dict(type="str"), - name=dict(type="str", required=True), - uuid=dict(type="str"), - esxi_hostname=dict(type="str"), - path=dict(type="str"), - template=dict(type="bool", default=False), - resource_pool=dict(type="str"), - state=dict(type="str", default="present", choices=["present", "absent"])) - - module = AnsibleModule(argument_spec=argument_spec, - supports_check_mode=True) - - vmware_guest_register_operation = VMwareGuestRegisterOperation(module) - vmware_guest_register_operation.execute() - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_screenshot.py b/lib/ansible/modules/cloud/vmware/vmware_guest_screenshot.py deleted file mode 100644 index 5ae273ea8e..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_screenshot.py +++ /dev/null @@ -1,287 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2019, Ansible Project -# Copyright: (c) 2019, Diane Wang <dianew@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 = ''' ---- -module: vmware_guest_screenshot -short_description: Create a screenshot of the Virtual Machine console. -description: - - This module is used to take screenshot of the given virtual machine when virtual machine is powered on. - - All parameters and VMware object names are case sensitive. -version_added: '2.9' -author: - - Diane Wang (@Tomorrow9) <dianew@vmware.com> -notes: - - Tested on vSphere 6.5 and 6.7 -requirements: - - "python >= 2.6" - - PyVmomi -options: - name: - description: - - Name of the virtual machine. - - This is a required parameter, if parameter C(uuid) or C(moid) is not supplied. - type: str - uuid: - description: - - UUID of the instance to gather facts if known, this is VMware's unique identifier. - - This is a required parameter, if parameter C(name) or C(moid) is not supplied. - type: str - moid: - description: - - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. - - This is required if C(name) or C(uuid) is not supplied. - version_added: '2.9' - type: str - folder: - description: - - Destination folder, absolute or relative path to find an existing guest. - - This is a required parameter, only if multiple VMs are found with same name. - - The folder should include the datacenter. ESXi server's datacenter is ha-datacenter. - - 'Examples:' - - ' folder: /ha-datacenter/vm' - - ' folder: ha-datacenter/vm' - - ' folder: /datacenter1/vm' - - ' folder: datacenter1/vm' - - ' folder: /datacenter1/vm/folder1' - - ' folder: datacenter1/vm/folder1' - - ' folder: /folder1/datacenter1/vm' - - ' folder: folder1/datacenter1/vm' - - ' folder: /folder1/datacenter1/vm/folder2' - type: str - cluster: - description: - - The name of cluster where the virtual machine is running. - - This is a required parameter, if C(esxi_hostname) is not set. - - C(esxi_hostname) and C(cluster) are mutually exclusive parameters. - type: str - esxi_hostname: - description: - - The ESXi hostname where the virtual machine is running. - - This is a required parameter, if C(cluster) is not set. - - C(esxi_hostname) and C(cluster) are mutually exclusive parameters. - type: str - datacenter: - description: - - The datacenter name to which virtual machine belongs to. - type: str - local_path: - description: - - 'If C(local_path) is not set, the created screenshot file will be kept in the directory of the virtual machine - on ESXi host. If C(local_path) is set to a valid path on local machine, then the screenshot file will be - downloaded from ESXi host to the local directory.' - - 'If not download screenshot file to local machine, you can open it through the returned file URL in screenshot - facts manually.' - type: path -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: take a screenshot of the virtual machine console - vmware_guest_screenshot: - validate_certs: no - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - folder: "{{ folder_name }}" - name: "{{ vm_name }}" - local_path: "/tmp/" - delegate_to: localhost - register: take_screenshot - -- name: Take a screenshot of the virtual machine console using MoID - vmware_guest_screenshot: - validate_certs: no - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - folder: "{{ folder_name }}" - moid: vm-42 - local_path: "/tmp/" - delegate_to: localhost - register: take_screenshot -''' - -RETURN = """ -screenshot_info: - description: display the facts of captured virtual machine screenshot file - returned: always - type: dict - sample: { - "virtual_machine": "test_vm", - "screenshot_file": "[datastore0] test_vm/test_vm-1.png", - "task_start_time": "2019-05-25T10:35:04.215016Z", - "task_complete_time": "2019-05-25T10:35:04.412622Z", - "result": "success", - "screenshot_file_url": "https://test_vcenter/folder/test_vm/test_vm-1.png?dcPath=test-dc&dsName=datastore0", - "download_local_path": "/tmp/", - "download_file_size": 2367, - } -""" - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.six.moves.urllib.parse import urlencode, quote -from ansible.module_utils._text import to_native -from ansible.module_utils.urls import open_url -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec, wait_for_task, get_parent_datacenter -import os - - -class PyVmomiHelper(PyVmomi): - def __init__(self, module): - super(PyVmomiHelper, self).__init__(module) - self.change_detected = False - - def generate_http_access_url(self, file_path): - # e.g., file_path is like this format: [datastore0] test_vm/test_vm-1.png - # from file_path generate URL - url_path = None - if not file_path: - return url_path - - path = "/folder/%s" % quote(file_path.split()[1]) - params = dict(dsName=file_path.split()[0].strip('[]')) - if not self.is_vcenter(): - datacenter = 'ha-datacenter' - else: - datacenter = get_parent_datacenter(self.current_vm_obj).name.replace('&', '%26') - params['dcPath'] = datacenter - url_path = "https://%s%s?%s" % (self.params['hostname'], path, urlencode(params)) - - return url_path - - def download_screenshot_file(self, file_url, local_file_path, file_name): - response = None - download_size = 0 - # file is downloaded as local_file_name when specified, or use original file name - if local_file_path.endswith('.png'): - local_file_name = local_file_path.split('/')[-1] - local_file_path = local_file_path.rsplit('/', 1)[0] - else: - local_file_name = file_name - if not os.path.exists(local_file_path): - try: - os.makedirs(local_file_path) - except OSError as err: - self.module.fail_json(msg="Exception caught when create folder %s on local machine, with error %s" - % (local_file_path, to_native(err))) - local_file = os.path.join(local_file_path, local_file_name) - with open(local_file, 'wb') as handle: - try: - response = open_url(file_url, url_username=self.params.get('username'), - url_password=self.params.get('password'), validate_certs=False) - except Exception as err: - self.module.fail_json(msg="Download screenshot file from URL %s, failed due to %s" % (file_url, to_native(err))) - if not response or response.getcode() >= 400: - self.module.fail_json(msg="Download screenshot file from URL %s, failed with response %s, response code %s" - % (file_url, response, response.getcode())) - bytes_read = response.read(2 ** 20) - while bytes_read: - handle.write(bytes_read) - handle.flush() - os.fsync(handle.fileno()) - download_size += len(bytes_read) - bytes_read = response.read(2 ** 20) - - return download_size - - def get_screenshot_facts(self, task_info, file_url, file_size): - screenshot_facts = dict() - if task_info is not None: - screenshot_facts = dict( - virtual_machine=task_info.entityName, - screenshot_file=task_info.result, - task_start_time=task_info.startTime, - task_complete_time=task_info.completeTime, - result=task_info.state, - screenshot_file_url=file_url, - download_local_path=self.params.get('local_path'), - download_file_size=file_size, - ) - - return screenshot_facts - - def take_vm_screenshot(self): - if self.current_vm_obj.runtime.powerState != vim.VirtualMachinePowerState.poweredOn: - self.module.fail_json(msg="VM is %s, valid power state is poweredOn." % self.current_vm_obj.runtime.powerState) - try: - task = self.current_vm_obj.CreateScreenshot_Task() - wait_for_task(task) - except vim.fault.FileFault as e: - self.module.fail_json(msg="Failed to create screenshot due to errors when creating or accessing one or more" - " files needed for this operation, %s" % to_native(e.msg)) - except vim.fault.InvalidState as e: - self.module.fail_json(msg="Failed to create screenshot due to VM is not ready to respond to such requests," - " %s" % to_native(e.msg)) - except vmodl.RuntimeFault as e: - self.module.fail_json(msg="Failed to create screenshot due to runtime fault, %s," % to_native(e.msg)) - except vim.fault.TaskInProgress as e: - self.module.fail_json(msg="Failed to create screenshot due to VM is busy, %s" % to_native(e.msg)) - - if task.info.state == 'error': - return {'changed': self.change_detected, 'failed': True, 'msg': task.info.error.msg} - else: - download_file_size = None - self.change_detected = True - file_url = self.generate_http_access_url(task.info.result) - if self.params.get('local_path'): - if file_url: - download_file_size = self.download_screenshot_file(file_url=file_url, - local_file_path=self.params['local_path'], - file_name=task.info.result.split('/')[-1]) - screenshot_facts = self.get_screenshot_facts(task.info, file_url, download_file_size) - return {'changed': self.change_detected, 'failed': False, 'screenshot_info': screenshot_facts} - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - name=dict(type='str'), - uuid=dict(type='str'), - moid=dict(type='str'), - folder=dict(type='str'), - datacenter=dict(type='str'), - esxi_hostname=dict(type='str'), - cluster=dict(type='str'), - local_path=dict(type='path'), - ) - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['name', 'uuid', 'moid'] - ] - ) - pyv = PyVmomiHelper(module) - vm = pyv.get_vm() - if not vm: - vm_id = (module.params.get('uuid') or module.params.get('name') or module.params.get('moid')) - module.fail_json(msg='Unable to find the specified virtual machine : %s' % vm_id) - - result = pyv.take_vm_screenshot() - if result['failed']: - module.fail_json(**result) - else: - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_sendkey.py b/lib/ansible/modules/cloud/vmware/vmware_guest_sendkey.py deleted file mode 100644 index 6a52239be9..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_sendkey.py +++ /dev/null @@ -1,388 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Diane Wang <dianew@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 = ''' ---- -module: vmware_guest_sendkey -short_description: Send USB HID codes to the Virtual Machine's keyboard. -description: - - This module is used to send keystrokes to given virtual machine. - - All parameters and VMware object names are case sensitive. -version_added: '2.9' -author: - - Diane Wang (@Tomorrow9) <dianew@vmware.com> -notes: - - Tested on vSphere 6.5 and 6.7 -requirements: - - "python >= 2.6" - - PyVmomi -options: - name: - description: - - Name of the virtual machine. - - This is a required parameter, if parameter C(uuid) or C(moid) is not supplied. - type: str - uuid: - description: - - UUID of the instance to gather facts if known, this is VMware's unique identifier. - - This is a required parameter, if parameter C(name) or C(moid) is not supplied. - type: str - moid: - description: - - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. - - This is required if C(name) or C(uuid) is not supplied. - type: str - folder: - description: - - Destination folder, absolute or relative path to find an existing guest. - - This is a required parameter, only if multiple VMs are found with same name. - - The folder should include the datacenter. ESXi server's datacenter is ha-datacenter. - - 'Examples:' - - ' folder: /ha-datacenter/vm' - - ' folder: ha-datacenter/vm' - - ' folder: /datacenter1/vm' - - ' folder: datacenter1/vm' - - ' folder: /datacenter1/vm/folder1' - - ' folder: datacenter1/vm/folder1' - - ' folder: /folder1/datacenter1/vm' - - ' folder: folder1/datacenter1/vm' - - ' folder: /folder1/datacenter1/vm/folder2' - type: str - cluster: - description: - - The name of cluster where the virtual machine is running. - - This is a required parameter, if C(esxi_hostname) is not set. - - C(esxi_hostname) and C(cluster) are mutually exclusive parameters. - type: str - esxi_hostname: - description: - - The ESXi hostname where the virtual machine is running. - - This is a required parameter, if C(cluster) is not set. - - C(esxi_hostname) and C(cluster) are mutually exclusive parameters. - type: str - datacenter: - description: - - The datacenter name to which virtual machine belongs to. - type: str - string_send: - description: - - The string will be sent to the virtual machine. - - This string can contain valid special character, alphabet and digit on the keyboard. - type: str - keys_send: - description: - - The list of the keys will be sent to the virtual machine. - - 'Valid values are C(ENTER), C(ESC), C(BACKSPACE), C(TAB), C(SPACE), C(CAPSLOCK), C(DELETE), C(CTRL_ALT_DEL), - C(CTRL_C) and C(F1) to C(F12), C(RIGHTARROW), C(LEFTARROW), C(DOWNARROW), C(UPARROW).' - - If both C(keys_send) and C(string_send) are specified, keys in C(keys_send) list will be sent in front of the C(string_send). - type: list -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Send list of keys to virtual machine - vmware_guest_sendkey: - validate_certs: no - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - folder: "{{ folder_name }}" - name: "{{ vm_name }}" - keys_send: - - TAB - - TAB - - ENTER - delegate_to: localhost - register: keys_num_sent - -- name: Send list of keys to virtual machine using MoID - vmware_guest_sendkey: - validate_certs: no - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - folder: "{{ folder_name }}" - moid: vm-42 - keys_send: - - CTRL_ALT_DEL - delegate_to: localhost - register: ctrl_alt_del_sent - -- name: Send a string to virtual machine - vmware_guest_sendkey: - validate_certs: no - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - folder: "{{ folder_name }}" - name: "{{ vm_name }}" - string_send: "user_logon" - delegate_to: localhost - register: keys_num_sent -''' - -RETURN = """ -sendkey_info: - description: display the keys and the number of keys sent to the virtual machine - returned: always - type: dict - sample: { - "virtual_machine": "test_vm", - "keys_send": [ - "SPACE", - "DOWNARROW", - "DOWNARROW", - "ENTER" - ], - "string_send": null, - "keys_send_number": 4, - "returned_keys_send_number": 4, - } -""" - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils._text import to_native -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec - - -class PyVmomiHelper(PyVmomi): - def __init__(self, module): - super(PyVmomiHelper, self).__init__(module) - self.change_detected = False - self.usb_scan_code_spec = vim.UsbScanCodeSpec() - self.num_keys_send = 0 - # HID usage tables https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf - # define valid characters and keys value, hex_code, key value and key modifier - self.keys_hid_code = [ - (('a', 'A'), '0x04', [('a', []), ('A', ['LEFTSHIFT'])]), - (('b', 'B'), '0x05', [('b', []), ('B', ['LEFTSHIFT'])]), - (('c', 'C'), '0x06', [('c', []), ('C', ['LEFTSHIFT'])]), - (('d', 'D'), '0x07', [('d', []), ('D', ['LEFTSHIFT'])]), - (('e', 'E'), '0x08', [('e', []), ('E', ['LEFTSHIFT'])]), - (('f', 'F'), '0x09', [('f', []), ('F', ['LEFTSHIFT'])]), - (('g', 'G'), '0x0a', [('g', []), ('G', ['LEFTSHIFT'])]), - (('h', 'H'), '0x0b', [('h', []), ('H', ['LEFTSHIFT'])]), - (('i', 'I'), '0x0c', [('i', []), ('I', ['LEFTSHIFT'])]), - (('j', 'J'), '0x0d', [('j', []), ('J', ['LEFTSHIFT'])]), - (('k', 'K'), '0x0e', [('k', []), ('K', ['LEFTSHIFT'])]), - (('l', 'L'), '0x0f', [('l', []), ('L', ['LEFTSHIFT'])]), - (('m', 'M'), '0x10', [('m', []), ('M', ['LEFTSHIFT'])]), - (('n', 'N'), '0x11', [('n', []), ('N', ['LEFTSHIFT'])]), - (('o', 'O'), '0x12', [('o', []), ('O', ['LEFTSHIFT'])]), - (('p', 'P'), '0x13', [('p', []), ('P', ['LEFTSHIFT'])]), - (('q', 'Q'), '0x14', [('q', []), ('Q', ['LEFTSHIFT'])]), - (('r', 'R'), '0x15', [('r', []), ('R', ['LEFTSHIFT'])]), - (('s', 'S'), '0x16', [('s', []), ('S', ['LEFTSHIFT'])]), - (('t', 'T'), '0x17', [('t', []), ('T', ['LEFTSHIFT'])]), - (('u', 'U'), '0x18', [('u', []), ('U', ['LEFTSHIFT'])]), - (('v', 'V'), '0x19', [('v', []), ('V', ['LEFTSHIFT'])]), - (('w', 'W'), '0x1a', [('w', []), ('W', ['LEFTSHIFT'])]), - (('x', 'X'), '0x1b', [('x', []), ('X', ['LEFTSHIFT'])]), - (('y', 'Y'), '0x1c', [('y', []), ('Y', ['LEFTSHIFT'])]), - (('z', 'Z'), '0x1d', [('z', []), ('Z', ['LEFTSHIFT'])]), - (('1', '!'), '0x1e', [('1', []), ('!', ['LEFTSHIFT'])]), - (('2', '@'), '0x1f', [('2', []), ('@', ['LEFTSHIFT'])]), - (('3', '#'), '0x20', [('3', []), ('#', ['LEFTSHIFT'])]), - (('4', '$'), '0x21', [('4', []), ('$', ['LEFTSHIFT'])]), - (('5', '%'), '0x22', [('5', []), ('%', ['LEFTSHIFT'])]), - (('6', '^'), '0x23', [('6', []), ('^', ['LEFTSHIFT'])]), - (('7', '&'), '0x24', [('7', []), ('&', ['LEFTSHIFT'])]), - (('8', '*'), '0x25', [('8', []), ('*', ['LEFTSHIFT'])]), - (('9', '('), '0x26', [('9', []), ('(', ['LEFTSHIFT'])]), - (('0', ')'), '0x27', [('0', []), (')', ['LEFTSHIFT'])]), - (('-', '_'), '0x2d', [('-', []), ('_', ['LEFTSHIFT'])]), - (('=', '+'), '0x2e', [('=', []), ('+', ['LEFTSHIFT'])]), - (('[', '{'), '0x2f', [('[', []), ('{', ['LEFTSHIFT'])]), - ((']', '}'), '0x30', [(']', []), ('}', ['LEFTSHIFT'])]), - (('\\', '|'), '0x31', [('\\', []), ('|', ['LEFTSHIFT'])]), - ((';', ':'), '0x33', [(';', []), (':', ['LEFTSHIFT'])]), - (('\'', '"'), '0x34', [('\'', []), ('"', ['LEFTSHIFT'])]), - (('`', '~'), '0x35', [('`', []), ('~', ['LEFTSHIFT'])]), - ((',', '<'), '0x36', [(',', []), ('<', ['LEFTSHIFT'])]), - (('.', '>'), '0x37', [('.', []), ('>', ['LEFTSHIFT'])]), - (('/', '?'), '0x38', [('/', []), ('?', ['LEFTSHIFT'])]), - ('ENTER', '0x28', [('', [])]), - ('ESC', '0x29', [('', [])]), - ('BACKSPACE', '0x2a', [('', [])]), - ('TAB', '0x2b', [('', [])]), - ('SPACE', '0x2c', [(' ', [])]), - ('CAPSLOCK', '0x39', [('', [])]), - ('F1', '0x3a', [('', [])]), - ('F2', '0x3b', [('', [])]), - ('F3', '0x3c', [('', [])]), - ('F4', '0x3d', [('', [])]), - ('F5', '0x3e', [('', [])]), - ('F6', '0x3f', [('', [])]), - ('F7', '0x40', [('', [])]), - ('F8', '0x41', [('', [])]), - ('F9', '0x42', [('', [])]), - ('F10', '0x43', [('', [])]), - ('F11', '0x44', [('', [])]), - ('F12', '0x45', [('', [])]), - ('DELETE', '0x4c', [('', [])]), - ('CTRL_ALT_DEL', '0x4c', [('', ['CTRL', 'ALT'])]), - ('CTRL_C', '0x06', [('', ['CTRL'])]), - ('RIGHTARROW', '0x4f', [('', [])]), - ('LEFTARROW', '0x50', [('', [])]), - ('DOWNARROW', '0x51', [('', [])]), - ('UPARROW', '0x52', [('', [])]), - ] - - @staticmethod - def hid_to_hex(hid_code): - return int(hid_code, 16) << 16 | 0o0007 - - def get_hid_from_key(self, key): - if key == ' ': - return '0x2c', [] - for keys_name, key_code, keys_value in self.keys_hid_code: - if isinstance(keys_name, tuple): - for keys in keys_value: - if key == keys[0]: - return key_code, keys[1] - else: - if key == keys_name: - return key_code, keys_value[0][1] - - def get_key_event(self, hid_code, modifiers): - key_event = vim.UsbScanCodeSpecKeyEvent() - key_modifier = vim.UsbScanCodeSpecModifierType() - key_modifier.leftAlt = False - key_modifier.leftControl = False - key_modifier.leftGui = False - key_modifier.leftShift = False - key_modifier.rightAlt = False - key_modifier.rightControl = False - key_modifier.rightGui = False - key_modifier.rightShift = False - # rightShift, rightControl, rightAlt, leftGui, rightGui are not used - if "LEFTSHIFT" in modifiers: - key_modifier.leftShift = True - if "CTRL" in modifiers: - key_modifier.leftControl = True - if "ALT" in modifiers: - key_modifier.leftAlt = True - key_event.modifiers = key_modifier - key_event.usbHidCode = self.hid_to_hex(hid_code) - - return key_event - - def get_sendkey_facts(self, vm_obj, returned_value=0): - sendkey_facts = dict() - if vm_obj is not None: - sendkey_facts = dict( - virtual_machine=vm_obj.name, - keys_send=self.params['keys_send'], - string_send=self.params['string_send'], - keys_send_number=self.num_keys_send, - returned_keys_send_number=returned_value, - ) - - return sendkey_facts - - def send_key_to_vm(self, vm_obj): - key_event = None - num_keys_returned = 0 - if self.params['keys_send']: - for specified_key in self.params['keys_send']: - key_found = False - for keys in self.keys_hid_code: - if (isinstance(keys[0], tuple) and specified_key in keys[0]) or \ - (not isinstance(keys[0], tuple) and specified_key == keys[0]): - hid_code, modifiers = self.get_hid_from_key(specified_key) - key_event = self.get_key_event(hid_code, modifiers) - self.usb_scan_code_spec.keyEvents.append(key_event) - self.num_keys_send += 1 - key_found = True - break - if not key_found: - self.module.fail_json(msg="keys_send parameter: '%s' in %s not supported." - % (specified_key, self.params['keys_send'])) - - if self.params['string_send']: - for char in self.params['string_send']: - key_found = False - for keys in self.keys_hid_code: - if (isinstance(keys[0], tuple) and char in keys[0]) or char == ' ': - hid_code, modifiers = self.get_hid_from_key(char) - key_event = self.get_key_event(hid_code, modifiers) - self.usb_scan_code_spec.keyEvents.append(key_event) - self.num_keys_send += 1 - key_found = True - break - if not key_found: - self.module.fail_json(msg="string_send parameter: '%s' contains char: '%s' not supported." - % (self.params['string_send'], char)) - - if self.usb_scan_code_spec.keyEvents: - try: - num_keys_returned = vm_obj.PutUsbScanCodes(self.usb_scan_code_spec) - self.change_detected = True - except vmodl.RuntimeFault as e: - self.module.fail_json(msg="Failed to send key %s to virtual machine due to %s" % (key_event, to_native(e.msg))) - - sendkey_facts = self.get_sendkey_facts(vm_obj, num_keys_returned) - if num_keys_returned != self.num_keys_send: - results = {'changed': self.change_detected, 'failed': True, 'sendkey_info': sendkey_facts} - else: - results = {'changed': self.change_detected, 'failed': False, 'sendkey_info': sendkey_facts} - - return results - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - name=dict(type='str'), - uuid=dict(type='str'), - moid=dict(type='str'), - folder=dict(type='str'), - datacenter=dict(type='str'), - esxi_hostname=dict(type='str'), - cluster=dict(type='str'), - keys_send=dict(type='list', default=[]), - string_send=dict(type='str') - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['name', 'uuid', 'moid'] - ] - ) - - pyv = PyVmomiHelper(module) - vm = pyv.get_vm() - if not vm: - vm_id = (module.params.get('uuid') or module.params.get('name') or module.params.get('moid')) - module.fail_json(msg='Unable to find the specified virtual machine : %s ' % vm_id) - - result = pyv.send_key_to_vm(vm) - if result['failed']: - module.fail_json(**result) - else: - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_serial_port.py b/lib/ansible/modules/cloud/vmware/vmware_guest_serial_port.py deleted file mode 100644 index 13525621a5..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_serial_port.py +++ /dev/null @@ -1,468 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2019, Anusha Hegde <anushah@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 = ''' ---- -module: vmware_guest_serial_port - -short_description: Manage serial ports on an existing VM - -version_added: "2.10" - -description: - - "This module can be used to manage serial ports on an existing VM" - -options: - name: - description: - - Name of the virtual machine. - - This is a required parameter, if parameter C(uuid) or C(moid) is not supplied. - type: str - uuid: - description: - - UUID of the instance to manage the serial ports, this is VMware's unique identifier. - - This is a required parameter, if parameter C(name) or C(moid) is not supplied. - type: str - moid: - description: - - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. - - This is required if C(name) or C(uuid) is not supplied. - type: str - use_instance_uuid: - description: - - Whether to use the VMware instance UUID rather than the BIOS UUID. - default: no - type: bool - backings: - type: list - description: - - A list of backings for serial ports. - - 'C(backing_type) (str): is required to add or reconfigure or remove an existing serial port.' - - 'Valid attributes are:' - - ' - C(backing_type) (str): Backing type is required for the serial ports to be added or reconfigured or removed.' - - ' - C(state) (str): is required to identify whether we are adding, modifying or removing the serial port. - - choices: - - C(present): modify an existing serial port. C(backing_type) is required to determine the port. - The first matching C(backing_type) and either of C(service_uri) or C(pipe_name) or C(device_name) or C(file_path) will be modified. - If there is only one device with a backing type, the secondary details are not needed. - We will match the last such device with the given backing type. - - C(absent): remove an existing serial port. C(backing_type) is required to determine the port. - The first matching C(backing_type) and either of C(service_uri) or C(pipe_name) or C(device_name) or C(file_path) will be removed. - If there is only one device with a backing type, the secondary details are not needed. - We will match the last such device with the given backing type.' - - ' - C(yield_on_poll) (bool): Enables CPU yield behavior. Default value is true.' - - ' - C(direction) (str): Required when I(backing_type=network). - The direction of the connection. - - choices: - - client - - server' - - ' - C(service_uri) (str): Required when I(backing_type=network). - Identifies the local host or a system on the network, depending on the value of I(direction). - If you use the virtual machine as a server, the URI identifies the host on which the virtual machine runs. - In this case, the host name part of the URI should be empty, or it should specify the address of the local host. - If you use the virtual machine as a client, the URI identifies the remote system on the network.' - - ' - C(endpoint) (str): Required when I(backing_type=pipe). - When you use serial port pipe backing to connect a virtual machine to another process, you must define the endpoints.' - - ' - C(no_rx_loss) (bool): Required when I(backing_type=pipe). - Enables optimized data transfer over the pipe. - - choices: - - client - - server' - - ' - C(pipe_name) (str): Required when I(backing_type=pipe).' - - ' - C(device_name) (str): Required when I(backing_type=device).' - - ' - C(file_path) (str): Required when I(backing_type=file). - File path for the host file used in this backing. Fully qualified path is required, like <datastore_name>/<file_name>' - -extends_documentation_fragment: - - vmware.documentation - -author: - - Anusha Hegde (@anusha94) -''' - -EXAMPLES = ''' -# Create serial ports -- name: Create multiple serial ports with Backing type - network, pipe, device and file - vmware_guest_serial_port: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - name: "test_vm1" - backings: - - type: 'network' - direction: 'client' - service_uri: 'tcp://6000' - yield_on_poll: True - - type: 'pipe' - pipe_name: 'serial_pipe' - endpoint: 'client' - - type: 'device' - device_name: '/dev/char/serial/uart0' - - type: 'file' - file_path: '[datastore1]/file1' - yield_on_poll: True - register: create_multiple_ports - -# Modify existing serial port -- name: Modify Network backing type - vmware_guest_serial_port: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - name: '{{ name }}' - backings: - - type: 'network' - state: 'present' - direction: 'server' - service_uri: 'tcp://6000' - delegate_to: localhost - -# Remove serial port -- name: Remove pipe backing type - vmware_guest_serial_port: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - name: '{{ name }}' - backings: - - type: 'pipe' - state: 'absent' - delegate_to: localhost - -''' - -RETURN = r''' -serial_port_data: - description: metadata about the virtual machine's serial ports after managing them - returned: always - type: dict - sample: [ - { - "backing_type": "network", - "direction": "client", - "service_uri": "tcp://6000" - }, - { - "backing_type": "pipe", - "direction": "server", - "pipe_name": "serial pipe" - }, - ] -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec, wait_for_task -from ansible.module_utils._text import to_native -try: - from pyVmomi import vim -except ImportError: - pass - - -class PyVmomiHelper(PyVmomi): - """ This class is a helper to create easily VMware Spec for PyVmomiHelper """ - - def __init__(self, module): - super(PyVmomiHelper, self).__init__(module) - self.change_applied = False # a change was applied meaning at least one task succeeded - self.config_spec = vim.vm.ConfigSpec() - self.config_spec.deviceChange = [] - self.serial_ports = [] - - def check_vm_state(self, vm_obj): - """ - To add serial port, the VM must be in powered off state - - Input: - - vm: Virtual Machine - - Output: - - True if vm is in poweredOff state - - module fails otherwise - """ - if vm_obj.runtime.powerState == vim.VirtualMachinePowerState.poweredOff: - return True - else: - self.module.fail_json(msg="A serial device cannot be added to a VM in the current state(" + vm_obj.runtime.powerState + ")." - + "Please use the vmware_guest_powerstate module to power off the VM") - - def get_serial_port_config_spec(self, vm_obj): - """ - Variables changed: - - self.config_spec - - self.change_applied - """ - # create serial config spec for adding, editing, removing - for backing in self.params.get('backings'): - backing_keys = backing.keys() - serial_port = get_serial_port(vm_obj, backing) - if serial_port is None and 'state' not in backing_keys: - # if serial port is None and state is not mentioned - # create a new serial port - serial_port_spec = self.create_serial_port(backing) - serial_port_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.add - self.serial_ports.append(serial_port_spec) - self.change_applied = True - else: - if serial_port is not None and 'state' in backing_keys: - serial_spec = vim.vm.device.VirtualDeviceSpec() - serial_spec.device = serial_port - if backing['state'].lower() == 'present': - # modify existing serial port - serial_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.edit - serial_spec.device.backing = self.get_backing_info(serial_port, backing, backing['type']) - self.change_applied = True - self.config_spec.deviceChange.append(serial_spec) - elif backing['state'].lower() == 'absent': - # remove serial port - serial_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.remove - self.change_applied = True - self.config_spec.deviceChange.append(serial_spec) - else: - self.module.fail_json(msg='Unable to find the specified serial port: %s' % backing) - - def reconfigure_vm_serial_port(self, vm_obj): - """ - Reconfigure vm with new or modified serial port config spec - """ - self.get_serial_port_config_spec(vm_obj) - try: - # configure create tasks first - if self.serial_ports: - for serial_port in self.serial_ports: - # each type of serial port is of config_spec.device = vim.vm.device.VirtualSerialPort() object type - # because serial ports differ in the backing types and config_spec.device has to be unique, - # we are creating a new spec for every create port configuration - spec = vim.vm.ConfigSpec() - spec.deviceChange.append(serial_port) - task = vm_obj.ReconfigVM_Task(spec=spec) - wait_for_task(task) - task = vm_obj.ReconfigVM_Task(spec=self.config_spec) - wait_for_task(task) - except vim.fault.InvalidDatastorePath as e: - self.module.fail_json(msg="Failed to configure serial port on given virtual machine due to invalid path: %s" % to_native(e.msg)) - except vim.fault.RestrictedVersion as e: - self.module.fail_json(msg="Failed to reconfigure virtual machine due to product versioning restrictions: %s" % to_native(e.msg)) - if task.info.state == 'error': - results = {'changed': self.change_applied, 'failed': True, 'msg': task.info.error.msg} - else: - serial_port_info = get_serial_port_info(vm_obj) - results = {'changed': self.change_applied, 'failed': False, 'serial_port_info': serial_port_info} - - return results - - def set_network_backing(self, serial_port, backing_info): - """ - Set the networking backing params - """ - required_params = ['service_uri', 'direction'] - if set(required_params).issubset(backing_info.keys()): - backing = serial_port.URIBackingInfo() - backing.serviceURI = backing_info['service_uri'] - backing.direction = backing_info['direction'] - else: - self.module.fail_json(msg="Failed to create a new serial port of network backing type due to insufficient parameters." - + "The required parameters are service_uri and direction") - return backing - - def set_pipe_backing(self, serial_port, backing_info): - """ - Set the pipe backing params - """ - required_params = ['pipe_name', 'endpoint'] - if set(required_params).issubset(backing_info.keys()): - backing = serial_port.PipeBackingInfo() - backing.pipeName = backing_info['pipe_name'] - backing.endpoint = backing_info['endpoint'] - else: - self.module.fail_json(msg="Failed to create a new serial port of pipe backing type due to insufficient parameters." - + "The required parameters are pipe_name and endpoint") - - # since no_rx_loss is an optional argument, so check if the key is present - if 'no_rx_loss' in backing_info.keys() and backing_info['no_rx_loss']: - backing.noRxLoss = backing_info['no_rx_loss'] - return backing - - def set_device_backing(self, serial_port, backing_info): - """ - Set the device backing params - """ - required_params = ['device_name'] - if set(required_params).issubset(backing_info.keys()): - backing = serial_port.DeviceBackingInfo() - backing.deviceName = backing_info['device_name'] - else: - self.module.fail_json(msg="Failed to create a new serial port of device backing type due to insufficient parameters." - + "The required parameters are device_name") - return backing - - def set_file_backing(self, serial_port, backing_info): - """ - Set the file backing params - """ - required_params = ['file_path'] - if set(required_params).issubset(backing_info.keys()): - backing = serial_port.FileBackingInfo() - backing.fileName = backing_info['file_path'] - else: - self.module.fail_json(msg="Failed to create a new serial port of file backing type due to insufficient parameters." - + "The required parameters are file_path") - return backing - - def get_backing_info(self, serial_port, backing, backing_type): - """ - Returns the call to the appropriate backing function based on the backing type - """ - switcher = { - "network": self.set_network_backing, - "pipe": self.set_pipe_backing, - "device": self.set_device_backing, - "file": self.set_file_backing - } - backing_func = switcher.get(backing_type, "Invalid Backing Info") - return backing_func(serial_port, backing) - - def create_serial_port(self, backing): - """ - Create a new serial port - """ - serial_spec = vim.vm.device.VirtualDeviceSpec() - serial_port = vim.vm.device.VirtualSerialPort() - serial_port.yieldOnPoll = backing['yield_on_poll'] if 'yield_on_poll' in backing.keys() else True - serial_port.backing = self.get_backing_info(serial_port, backing, backing['type']) - serial_spec.device = serial_port - return serial_spec - - -def get_serial_port(vm_obj, backing): - """ - Return the serial port of specified backing type - """ - serial_port = None - backing_type_mapping = { - 'network': vim.vm.device.VirtualSerialPort.URIBackingInfo, - 'pipe': vim.vm.device.VirtualSerialPort.PipeBackingInfo, - 'device': vim.vm.device.VirtualSerialPort.DeviceBackingInfo, - 'file': vim.vm.device.VirtualSerialPort.FileBackingInfo - } - valid_params = backing.keys() - for device in vm_obj.config.hardware.device: - if isinstance(device, vim.vm.device.VirtualSerialPort): - if isinstance(device.backing, backing_type_mapping[backing['type']]): - if 'service_uri' in valid_params: - # network backing type - if device.backing.serviceURI == backing['service_uri']: - serial_port = device - break - elif 'pipe_name' in valid_params: - # named pipe backing type - if device.backing.pipeName == backing['pipe_name']: - serial_port = device - break - elif 'device_name' in valid_params: - # physical serial device backing type - if device.backing.deviceName == backing['device_name']: - serial_port = device - break - elif 'file_path' in valid_params: - # file backing type - if device.backing.fileName == backing['file_path']: - serial_port = device - break - # if there is a backing of only one type, user need not provide secondary details like service_uri, pipe_name, device_name or file_path - # we will match the serial port with backing type only - # in this case, the last matching serial port will be returned - serial_port = device - return serial_port - - -def get_serial_port_info(vm_obj): - """ - Get the serial port info - """ - serial_port_info = [] - if vm_obj is None: - return serial_port_info - for port in vm_obj.config.hardware.device: - backing = dict() - if isinstance(port, vim.vm.device.VirtualSerialPort): - if isinstance(port.backing, vim.vm.device.VirtualSerialPort.URIBackingInfo): - backing['backing_type'] = 'network' - backing['direction'] = port.backing.direction - backing['service_uri'] = port.backing.serviceURI - elif isinstance(port.backing, vim.vm.device.VirtualSerialPort.PipeBackingInfo): - backing['backing_type'] = 'pipe' - backing['pipe_name'] = port.backing.pipeName - backing['endpoint'] = port.backing.endpoint - backing['no_rx_loss'] = port.backing.noRxLoss - elif isinstance(port.backing, vim.vm.device.VirtualSerialPort.DeviceBackingInfo): - backing['backing_type'] = 'device' - backing['device_name'] = port.backing.deviceName - elif isinstance(port.backing, vim.vm.device.VirtualSerialPort.FileBackingInfo): - backing['backing_type'] = 'file' - backing['file_path'] = port.backing.fileName - else: - continue - serial_port_info.append(backing) - return serial_port_info - - -def main(): - """ - Main method - """ - argument_spec = vmware_argument_spec() - argument_spec.update( - name=dict(type='str'), - uuid=dict(type='str'), - moid=dict(type='str'), - use_instance_uuid=dict(type='bool', default=False), - backings=dict(type='list', default=[]) - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['name', 'uuid', 'moid'] - ], - mutually_exclusive=[ - ['name', 'uuid', 'moid'] - ], - ) - result = {'failed': False, 'changed': False} - - pyv = PyVmomiHelper(module) - # Check if the VM exists before continuing - vm_obj = pyv.get_vm() - - if vm_obj: - proceed = pyv.check_vm_state(vm_obj) - if proceed: - result = pyv.reconfigure_vm_serial_port(vm_obj) - - else: - # We are unable to find the virtual machine user specified - # Bail out - vm_id = (module.params.get('name') or module.params.get('uuid') or module.params.get('vm_id')) - module.fail_json(msg="Unable to manage serial ports for non-existing" - " virtual machine '%s'." % vm_id) - - if result['failed']: - module.fail_json(**result) - else: - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_snapshot.py b/lib/ansible/modules/cloud/vmware/vmware_guest_snapshot.py deleted file mode 100644 index 119eace575..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_snapshot.py +++ /dev/null @@ -1,475 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2018, Ansible Project -# This module is also sponsored by E.T.A.I. (www.etai.fr) -# 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 = ''' ---- -module: vmware_guest_snapshot -short_description: Manages virtual machines snapshots in vCenter -description: - - This module can be used to create, delete and update snapshot(s) of the given virtual machine. - - All parameters and VMware object names are case sensitive. -version_added: 2.3 -author: - - Loic Blot (@nerzhul) <loic.blot@unix-experience.fr> -notes: - - Tested on vSphere 5.5, 6.0 and 6.5 -requirements: - - "python >= 2.6" - - PyVmomi -options: - state: - description: - - Manage snapshot(s) attached to a specific virtual machine. - - If set to C(present) and snapshot absent, then will create a new snapshot with the given name. - - If set to C(present) and snapshot present, then no changes are made. - - If set to C(absent) and snapshot present, then snapshot with the given name is removed. - - If set to C(absent) and snapshot absent, then no changes are made. - - If set to C(revert) and snapshot present, then virtual machine state is reverted to the given snapshot. - - If set to C(revert) and snapshot absent, then no changes are made. - - If set to C(remove_all) and snapshot(s) present, then all snapshot(s) will be removed. - - If set to C(remove_all) and snapshot(s) absent, then no changes are made. - required: True - choices: ['present', 'absent', 'revert', 'remove_all'] - default: 'present' - type: str - name: - description: - - Name of the virtual machine to work with. - - This is required parameter, if C(uuid) or C(moid) is not supplied. - type: str - name_match: - description: - - If multiple VMs matching the name, use the first or last found. - default: 'first' - choices: ['first', 'last'] - type: str - uuid: - description: - - UUID of the instance to manage if known, this is VMware's BIOS UUID by default. - - This is required if C(name) or C(moid) parameter is not supplied. - type: str - moid: - description: - - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. - - This is required if C(name) or C(uuid) is not supplied. - version_added: '2.9' - type: str - use_instance_uuid: - description: - - Whether to use the VMware instance UUID rather than the BIOS UUID. - default: no - type: bool - version_added: '2.8' - folder: - description: - - Destination folder, absolute or relative path to find an existing guest. - - This is required parameter, if C(name) is supplied. - - The folder should include the datacenter. ESX's datacenter is ha-datacenter. - - 'Examples:' - - ' folder: /ha-datacenter/vm' - - ' folder: ha-datacenter/vm' - - ' folder: /datacenter1/vm' - - ' folder: datacenter1/vm' - - ' folder: /datacenter1/vm/folder1' - - ' folder: datacenter1/vm/folder1' - - ' folder: /folder1/datacenter1/vm' - - ' folder: folder1/datacenter1/vm' - - ' folder: /folder1/datacenter1/vm/folder2' - type: str - datacenter: - description: - - Destination datacenter for the deploy operation. - required: True - type: str - snapshot_name: - description: - - Sets the snapshot name to manage. - - This param is required only if state is not C(remove_all) - type: str - description: - description: - - Define an arbitrary description to attach to snapshot. - default: '' - type: str - quiesce: - description: - - If set to C(true) and virtual machine is powered on, it will quiesce the file system in virtual machine. - - Note that VMware Tools are required for this flag. - - If virtual machine is powered off or VMware Tools are not available, then this flag is set to C(false). - - If virtual machine does not provide capability to take quiesce snapshot, then this flag is set to C(false). - required: False - version_added: "2.4" - type: bool - default: False - memory_dump: - description: - - If set to C(true), memory dump of virtual machine is also included in snapshot. - - Note that memory snapshots take time and resources, this will take longer time to create. - - If virtual machine does not provide capability to take memory snapshot, then this flag is set to C(false). - required: False - version_added: "2.4" - type: bool - default: False - remove_children: - description: - - If set to C(true) and state is set to C(absent), then entire snapshot subtree is set for removal. - required: False - version_added: "2.4" - type: bool - default: False - new_snapshot_name: - description: - - Value to rename the existing snapshot to. - version_added: "2.5" - type: str - new_description: - description: - - Value to change the description of an existing snapshot to. - version_added: "2.5" - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' - - name: Create a snapshot - vmware_guest_snapshot: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - folder: "/{{ datacenter_name }}/vm/" - name: "{{ guest_name }}" - state: present - snapshot_name: snap1 - description: snap1_description - delegate_to: localhost - - - name: Remove a snapshot - vmware_guest_snapshot: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - folder: "/{{ datacenter_name }}/vm/" - name: "{{ guest_name }}" - state: absent - snapshot_name: snap1 - delegate_to: localhost - - - name: Revert to a snapshot - vmware_guest_snapshot: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - folder: "/{{ datacenter_name }}/vm/" - name: "{{ guest_name }}" - state: revert - snapshot_name: snap1 - delegate_to: localhost - - - name: Remove all snapshots of a VM - vmware_guest_snapshot: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - folder: "/{{ datacenter_name }}/vm/" - name: "{{ guest_name }}" - state: remove_all - delegate_to: localhost - - - name: Remove all snapshots of a VM using MoID - vmware_guest_snapshot: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - folder: "/{{ datacenter_name }}/vm/" - moid: vm-42 - state: remove_all - delegate_to: localhost - - - name: Take snapshot of a VM using quiesce and memory flag on - vmware_guest_snapshot: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - folder: "/{{ datacenter_name }}/vm/" - name: "{{ guest_name }}" - state: present - snapshot_name: dummy_vm_snap_0001 - quiesce: yes - memory_dump: yes - delegate_to: localhost - - - name: Remove a snapshot and snapshot subtree - vmware_guest_snapshot: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - folder: "/{{ datacenter_name }}/vm/" - name: "{{ guest_name }}" - state: absent - remove_children: yes - snapshot_name: snap1 - delegate_to: localhost - - - name: Rename a snapshot - vmware_guest_snapshot: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - folder: "/{{ datacenter_name }}/vm/" - name: "{{ guest_name }}" - state: present - snapshot_name: current_snap_name - new_snapshot_name: im_renamed - new_description: "{{ new_snapshot_description }}" - delegate_to: localhost -''' - -RETURN = """ -snapshot_results: - description: metadata about the virtual machine snapshots - returned: always - type: dict - sample: { - "current_snapshot": { - "creation_time": "2019-04-09T14:40:26.617427+00:00", - "description": "Snapshot 4 example", - "id": 4, - "name": "snapshot4", - "state": "poweredOff" - }, - "snapshots": [ - { - "creation_time": "2019-04-09T14:38:24.667543+00:00", - "description": "Snapshot 3 example", - "id": 3, - "name": "snapshot3", - "state": "poweredOff" - }, - { - "creation_time": "2019-04-09T14:40:26.617427+00:00", - "description": "Snapshot 4 example", - "id": 4, - "name": "snapshot4", - "state": "poweredOff" - } - ] - } -""" - -import time -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils._text import to_native -from ansible.module_utils.vmware import PyVmomi, list_snapshots, vmware_argument_spec - - -class PyVmomiHelper(PyVmomi): - def __init__(self, module): - super(PyVmomiHelper, self).__init__(module) - - @staticmethod - def wait_for_task(task): - # https://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/vim.Task.html - # https://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/vim.TaskInfo.html - # https://github.com/virtdevninja/pyvmomi-community-samples/blob/master/samples/tools/tasks.py - while task.info.state not in ['success', 'error']: - time.sleep(1) - - def get_snapshots_by_name_recursively(self, snapshots, snapname): - snap_obj = [] - for snapshot in snapshots: - if snapshot.name == snapname: - snap_obj.append(snapshot) - else: - snap_obj = snap_obj + self.get_snapshots_by_name_recursively(snapshot.childSnapshotList, snapname) - return snap_obj - - def snapshot_vm(self, vm): - memory_dump = False - quiesce = False - # Check if there is a latest snapshot already present as specified by user - if vm.snapshot is not None: - snap_obj = self.get_snapshots_by_name_recursively(vm.snapshot.rootSnapshotList, - self.module.params["snapshot_name"]) - if snap_obj: - # Snapshot already exists, do not anything. - self.module.exit_json(changed=False, - msg="Snapshot named [%(snapshot_name)s] already exists and is current." % self.module.params) - # Check if Virtual Machine provides capabilities for Quiesce and Memory Snapshots - if vm.capability.quiescedSnapshotsSupported: - quiesce = self.module.params['quiesce'] - if vm.capability.memorySnapshotsSupported: - memory_dump = self.module.params['memory_dump'] - - task = None - try: - task = vm.CreateSnapshot(self.module.params["snapshot_name"], - self.module.params["description"], - memory_dump, - quiesce) - except vim.fault.RestrictedVersion as exc: - self.module.fail_json(msg="Failed to take snapshot due to VMware Licence" - " restriction : %s" % to_native(exc.msg)) - except Exception as exc: - self.module.fail_json(msg="Failed to create snapshot of virtual machine" - " %s due to %s" % (self.module.params['name'], to_native(exc))) - return task - - def rename_snapshot(self, vm): - if vm.snapshot is None: - vm_id = self.module.params.get('uuid') or self.module.params.get('name') or self.params.get('moid') - self.module.fail_json(msg="virtual machine - %s doesn't have any snapshots" % vm_id) - - snap_obj = self.get_snapshots_by_name_recursively(vm.snapshot.rootSnapshotList, - self.module.params["snapshot_name"]) - task = None - if len(snap_obj) == 1: - snap_obj = snap_obj[0].snapshot - if self.module.params["new_snapshot_name"] and self.module.params["new_description"]: - task = snap_obj.RenameSnapshot(name=self.module.params["new_snapshot_name"], - description=self.module.params["new_description"]) - elif self.module.params["new_snapshot_name"]: - task = snap_obj.RenameSnapshot(name=self.module.params["new_snapshot_name"]) - else: - task = snap_obj.RenameSnapshot(description=self.module.params["new_description"]) - else: - vm_id = self.module.params.get('uuid') or self.module.params.get('name') or self.params.get('moid') - self.module.exit_json( - msg="Couldn't find any snapshots with specified name: %s on VM: %s" % - (self.module.params["snapshot_name"], vm_id)) - return task - - def remove_or_revert_snapshot(self, vm): - if vm.snapshot is None: - vm_name = (self.module.params.get('uuid') or self.module.params.get('name')) - if self.module.params.get('state') == 'revert': - self.module.fail_json(msg="virtual machine - %s does not" - " have any snapshots to revert to." % vm_name) - self.module.exit_json(msg="virtual machine - %s doesn't have any" - " snapshots to remove." % vm_name) - - snap_obj = self.get_snapshots_by_name_recursively(vm.snapshot.rootSnapshotList, - self.module.params["snapshot_name"]) - task = None - if len(snap_obj) == 1: - snap_obj = snap_obj[0].snapshot - if self.module.params["state"] == "absent": - # Remove subtree depending upon the user input - remove_children = self.module.params.get('remove_children', False) - task = snap_obj.RemoveSnapshot_Task(remove_children) - elif self.module.params["state"] == "revert": - task = snap_obj.RevertToSnapshot_Task() - else: - vm_id = self.module.params.get('uuid') or self.module.params.get('name') or self.params.get('moid') - self.module.exit_json(msg="Couldn't find any snapshots with" - " specified name: %s on VM: %s" % (self.module.params["snapshot_name"], vm_id)) - - return task - - def apply_snapshot_op(self, vm): - result = {} - if self.module.params["state"] == "present": - if self.module.params["new_snapshot_name"] or self.module.params["new_description"]: - self.rename_snapshot(vm) - result = {'changed': True, 'failed': False, 'renamed': True} - task = None - else: - task = self.snapshot_vm(vm) - elif self.module.params["state"] in ["absent", "revert"]: - task = self.remove_or_revert_snapshot(vm) - elif self.module.params["state"] == "remove_all": - task = vm.RemoveAllSnapshots() - else: - # This should not happen - raise AssertionError() - - if task: - self.wait_for_task(task) - if task.info.state == 'error': - result = {'changed': False, 'failed': True, 'msg': task.info.error.msg} - else: - result = {'changed': True, 'failed': False, 'snapshot_results': list_snapshots(vm)} - - return result - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - state=dict(default='present', choices=['present', 'absent', 'revert', 'remove_all']), - name=dict(type='str'), - name_match=dict(type='str', choices=['first', 'last'], default='first'), - uuid=dict(type='str'), - moid=dict(type='str'), - use_instance_uuid=dict(type='bool', default=False), - folder=dict(type='str'), - datacenter=dict(required=True, type='str'), - snapshot_name=dict(type='str'), - description=dict(type='str', default=''), - quiesce=dict(type='bool', default=False), - memory_dump=dict(type='bool', default=False), - remove_children=dict(type='bool', default=False), - new_snapshot_name=dict(type='str'), - new_description=dict(type='str'), - ) - module = AnsibleModule( - argument_spec=argument_spec, - required_together=[ - ['name', 'folder'] - ], - required_one_of=[ - ['name', 'uuid', 'moid'] - ], - ) - - if module.params['folder']: - # FindByInventoryPath() does not require an absolute path - # so we should leave the input folder path unmodified - module.params['folder'] = module.params['folder'].rstrip('/') - - pyv = PyVmomiHelper(module) - # Check if the VM exists before continuing - vm = pyv.get_vm() - - if not vm: - vm_id = (module.params.get('uuid') or module.params.get('name') or module.params.get('moid')) - module.fail_json(msg="Unable to manage snapshots for non-existing VM %s" % vm_id) - - if not module.params['snapshot_name'] and module.params['state'] != 'remove_all': - module.fail_json(msg="snapshot_name param is required when state is '%(state)s'" % module.params) - - result = pyv.apply_snapshot_op(vm) - - if 'failed' not in result: - result['failed'] = False - - if result['failed']: - module.fail_json(**result) - else: - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_snapshot_info.py b/lib/ansible/modules/cloud/vmware/vmware_guest_snapshot_info.py deleted file mode 100644 index 02e57fc211..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_snapshot_info.py +++ /dev/null @@ -1,193 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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 = ''' ---- -module: vmware_guest_snapshot_info -short_description: Gather info about virtual machine's snapshots in vCenter -description: - - This module can be used to gather information about virtual machine's snapshots. - - This module was called C(vmware_guest_snapshot_facts) before Ansible 2.9. The usage did not change. -version_added: 2.6 -author: - - Abhijeet Kasurde (@Akasurde) -notes: - - Tested on vSphere 6.0 and 6.5 -requirements: - - "python >= 2.6" - - PyVmomi -options: - name: - description: - - Name of the VM to work with. - - This is required if C(uuid) or C(moid) is not supplied. - type: str - uuid: - description: - - UUID of the instance to manage if known, this is VMware's BIOS UUID by default. - - This is required if C(name) or C(moid) parameter is not supplied. - - The C(folder) is ignored, if C(uuid) is provided. - type: str - moid: - description: - - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. - - This is required if C(name) or C(uuid) is not supplied. - version_added: '2.9' - type: str - use_instance_uuid: - description: - - Whether to use the VMware instance UUID rather than the BIOS UUID. - default: no - type: bool - version_added: '2.8' - folder: - description: - - Destination folder, absolute or relative path to find an existing guest. - - This is required only, if multiple virtual machines with same name are found on given vCenter. - - The folder should include the datacenter. ESX's datacenter is ha-datacenter - - 'Examples:' - - ' folder: /ha-datacenter/vm' - - ' folder: ha-datacenter/vm' - - ' folder: /datacenter1/vm' - - ' folder: datacenter1/vm' - - ' folder: /datacenter1/vm/folder1' - - ' folder: datacenter1/vm/folder1' - - ' folder: /folder1/datacenter1/vm' - - ' folder: folder1/datacenter1/vm' - - ' folder: /folder1/datacenter1/vm/folder2' - type: str - datacenter: - description: - - Name of the datacenter. - required: True - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Gather snapshot information about the virtual machine in the given vCenter - vmware_guest_snapshot_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - name: "{{ guest_name }}" - delegate_to: localhost - register: snapshot_info - -- name: Gather snapshot information about the virtual machine using MoID - vmware_guest_snapshot_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - moid: vm-42 - delegate_to: localhost - register: snapshot_info -''' - -RETURN = """ -guest_snapshots: - description: metadata about the snapshot information - returned: always - type: dict - sample: { - "current_snapshot": { - "creation_time": "2018-02-10T14:48:31.999459+00:00", - "description": "", - "id": 28, - "name": "snap_0003", - "state": "poweredOff" - }, - "snapshots": [ - { - "creation_time": "2018-02-10T14:48:31.999459+00:00", - "description": "", - "id": 28, - "name": "snap_0003", - "state": "poweredOff" - } - ] - } -""" - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, list_snapshots, vmware_argument_spec - - -class PyVmomiHelper(PyVmomi): - def __init__(self, module): - super(PyVmomiHelper, self).__init__(module) - - @staticmethod - def gather_guest_snapshot_info(vm_obj=None): - """ - Return snapshot related information about given virtual machine - Args: - vm_obj: Virtual Machine Managed object - - Returns: Dictionary containing snapshot information - - """ - if vm_obj is None: - return {} - return list_snapshots(vm=vm_obj) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - name=dict(type='str'), - uuid=dict(type='str'), - moid=dict(type='str'), - use_instance_uuid=dict(type='bool', default=False), - folder=dict(type='str'), - datacenter=dict(required=True, type='str'), - ) - module = AnsibleModule( - argument_spec=argument_spec, - required_together=[ - ['name', 'folder'] - ], - required_one_of=[ - ['name', 'uuid', 'moid'] - ], - supports_check_mode=True, - ) - if module._name == 'vmware_guest_snapshot_facts': - module.deprecate("The 'vmware_guest_snapshot_facts' module has been renamed to 'vmware_guest_snapshot_info'", version='2.13') - - if module.params['folder']: - # FindByInventoryPath() does not require an absolute path - # so we should leave the input folder path unmodified - module.params['folder'] = module.params['folder'].rstrip('/') - - pyv = PyVmomiHelper(module) - # Check if the VM exists before continuing - vm = pyv.get_vm() - - if not vm: - # If UUID is set, get_vm select UUID, show error message accordingly. - vm_id = (module.params.get('uuid') or module.params.get('name') or module.params.get('moid')) - module.fail_json(msg="Unable to gather information about snapshots for" - " non-existing VM ['%s']" % vm_id) - - results = dict(changed=False, guest_snapshots=pyv.gather_guest_snapshot_info(vm_obj=vm)) - module.exit_json(**results) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_tools_info.py b/lib/ansible/modules/cloud/vmware/vmware_guest_tools_info.py deleted file mode 100644 index b0ca6ec847..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_tools_info.py +++ /dev/null @@ -1,206 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2019, Ansible Project -# Copyright: (c) 2019, VMware, Inc. All Rights Reserved. -# 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 = ''' ---- -module: vmware_guest_tools_info -short_description: Gather info about VMware tools installed in VM -description: - - Gather information about the VMware tools installed in virtual machine. -version_added: '2.10' -author: - - Diane Wang (@Tomorrow9) <dianew@vmware.com> -notes: - - Tested on vSphere 6.0, 6.5, 6.7 -requirements: - - "python >= 2.7" - - PyVmomi -options: - name: - description: - - Name of the VM to get VMware tools info. - - This is required if C(uuid) or C(moid) is not supplied. - type: str - name_match: - description: - - If multiple VMs matching the name, use the first or last found. - default: 'first' - choices: ['first', 'last'] - type: str - uuid: - description: - - UUID of the instance to manage if known, this is VMware's unique identifier. - - This is required if C(name) or C(moid) is not supplied. - type: str - use_instance_uuid: - description: - - Whether to use the VMware instance UUID rather than the BIOS UUID. - default: no - type: bool - moid: - description: - - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. - - This is required if C(name) or C(uuid) is not supplied. - type: str - folder: - description: - - Destination folder, absolute or relative path to find an existing guest. - - This is required if name is supplied. - - The folder should include the datacenter. ESXi server's datacenter is ha-datacenter. - - 'Examples:' - - ' folder: /ha-datacenter/vm' - - ' folder: ha-datacenter/vm' - - ' folder: /datacenter1/vm' - - ' folder: datacenter1/vm' - - ' folder: /datacenter1/vm/folder1' - - ' folder: datacenter1/vm/folder1' - - ' folder: /folder1/datacenter1/vm' - - ' folder: folder1/datacenter1/vm' - - ' folder: /folder1/datacenter1/vm/folder2' - type: str - datacenter: - description: - - The datacenter name to which virtual machine belongs to. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Gather VMware tools info installed in VM specified by uuid - vmware_guest_tools_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - uuid: 421e4592-c069-924d-ce20-7e7533fab926 - delegate_to: localhost - register: vmtools_info - -- name: Gather VMware tools info installed in VM specified by name - vmware_guest_tools_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - name: "{{ vm_name }}" - delegate_to: localhost - register: vmtools_info -''' - -RETURN = """ -vmtools_info: - description: metadata about the VMware tools installed in virtual machine - returned: always - type: dict - sample: { - "vm_uuid": null, - "vm_moid": null, - "vm_use_instance_uuid": false, - "vm_guest_fullname": "Microsoft Windows 10 (64-bit)", - "vm_guest_hostname": "test", - "vm_guest_id": "windows9_64Guest", - "vm_hw_version": "vmx-14", - "vm_ipaddress": "10.10.10.10", - "vm_name": "test_vm", - "vm_tools_install_status": "toolsOk", - "vm_tools_install_type": "guestToolsTypeMSI", - "vm_tools_last_install_count": 0, - "vm_tools_running_status": "guestToolsRunning", - "vm_tools_upgrade_policy": "manual", - "vm_tools_version": 10341, - "vm_tools_version_status": "guestToolsCurrent" - } -""" - - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec - - -class PyVmomiHelper(PyVmomi): - def __init__(self, module): - super(PyVmomiHelper, self).__init__(module) - self.name = self.params['name'] - self.uuid = self.params['uuid'] - self.moid = self.params['moid'] - self.use_instance_uuid = self.params['use_instance_uuid'] - - def gather_vmtools_info(self): - vmtools_info = dict( - vm_name=self.name, - vm_uuid=self.uuid, - vm_moid=self.moid, - vm_use_instance_uuid=self.use_instance_uuid, - vm_hw_version=self.current_vm_obj.config.version, - vm_guest_id=self.current_vm_obj.summary.guest.guestId, - vm_guest_fullname=self.current_vm_obj.summary.guest.guestFullName, - vm_guest_hostname=self.current_vm_obj.summary.guest.hostName, - vm_ipaddress=self.current_vm_obj.summary.guest.ipAddress, - vm_tools_running_status=self.current_vm_obj.summary.guest.toolsRunningStatus, - vm_tools_install_status=self.current_vm_obj.summary.guest.toolsStatus, - vm_tools_version_status=self.current_vm_obj.summary.guest.toolsVersionStatus, - vm_tools_install_type=self.current_vm_obj.config.tools.toolsInstallType, - vm_tools_version=self.current_vm_obj.config.tools.toolsVersion, - vm_tools_upgrade_policy=self.current_vm_obj.config.tools.toolsUpgradePolicy, - vm_tools_last_install_count=self.current_vm_obj.config.tools.lastInstallInfo.counter, - ) - - return {'changed': False, 'failed': False, 'vmtools_info': vmtools_info} - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - name=dict(type='str'), - uuid=dict(type='str'), - moid=dict(type='str'), - use_instance_uuid=dict(type='bool', default=False), - name_match=dict( - choices=['first', 'last'], - default='first', - type='str' - ), - folder=dict(type='str'), - datacenter=dict(type='str'), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['name', 'uuid', 'moid'] - ], - mutually_exclusive=[ - ['name', 'uuid', 'moid'] - ], - supports_check_mode=True, - ) - - pyv = PyVmomiHelper(module) - vm = pyv.get_vm() - if not vm: - vm_id = (module.params.get('uuid') or module.params.get('name') or module.params.get('moid')) - module.fail_json(msg='Unable to find the specified virtual machine using: %s' % vm_id) - results = pyv.gather_vmtools_info() - module.exit_json(**results) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_tools_upgrade.py b/lib/ansible/modules/cloud/vmware/vmware_guest_tools_upgrade.py deleted file mode 100644 index ae58c564cf..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_tools_upgrade.py +++ /dev/null @@ -1,205 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright: (c) 2018, Mike Klebolt <michael.klebolt@centurylink.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 = ''' ---- -module: vmware_guest_tools_upgrade -short_description: Module to upgrade VMTools -version_added: 2.8 -description: - - This module upgrades the VMware Tools on Windows and Linux guests. -requirements: - - "python >= 2.6" - - PyVmomi -notes: - - In order to upgrade VMTools, please power on virtual machine before hand - either 'manually' or using module M(vmware_guest_powerstate). -options: - name: - description: - - Name of the virtual machine to work with. - - This is required if C(uuid) or C(moid) is not supplied. - type: str - name_match: - description: - - If multiple virtual machines matching the name, use the first or last found. - default: 'first' - choices: ['first', 'last'] - type: str - uuid: - description: - - UUID of the instance to manage if known, this is VMware's unique identifier. - - This is required if C(name) or C(moid) is not supplied. - type: str - moid: - description: - - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. - - This is required if C(name) or C(uuid) is not supplied. - version_added: '2.9' - type: str - folder: - description: - - Destination folder, absolute or relative path to find an existing guest. - - This is required, if C(name) is supplied. - - The folder should include the datacenter. ESX's datacenter is ha-datacenter - - 'Examples:' - - ' folder: /ha-datacenter/vm' - - ' folder: ha-datacenter/vm' - - ' folder: /datacenter1/vm' - - ' folder: datacenter1/vm' - - ' folder: /datacenter1/vm/folder1' - - ' folder: datacenter1/vm/folder1' - - ' folder: /folder1/datacenter1/vm' - - ' folder: folder1/datacenter1/vm' - - ' folder: /folder1/datacenter1/vm/folder2' - type: str - datacenter: - description: - - Destination datacenter where the virtual machine exists. - required: True - type: str -extends_documentation_fragment: vmware.documentation -author: - - Mike Klebolt (@MikeKlebolt) <michael.klebolt@centurylink.com> -''' - -EXAMPLES = ''' -- name: Upgrade VMware Tools using uuid - vmware_guest_tools_upgrade: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - uuid: 421e4592-c069-924d-ce20-7e7533fab926 - delegate_to: localhost - -- name: Upgrade VMware Tools using MoID - vmware_guest_tools_upgrade: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - moid: vm-42 - delegate_to: localhost -''' - -RETURN = ''' # ''' - - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec, wait_for_task -from ansible.module_utils._text import to_native - - -class PyVmomiHelper(PyVmomi): - def __init__(self, module): - super(PyVmomiHelper, self).__init__(module) - - def upgrade_tools(self, vm): - result = {'failed': False, 'changed': False, 'msg': ''} - # Exit if VMware tools is already up to date - if vm.guest.toolsStatus == "toolsOk": - result.update( - changed=False, - msg="VMware tools is already up to date", - ) - return result - - # Fail if VM is not powered on - elif vm.summary.runtime.powerState != "poweredOn": - result.update( - failed=True, - msg="VM must be powered on to upgrade tools", - ) - return result - - # Fail if VMware tools is either not running or not installed - elif vm.guest.toolsStatus in ["toolsNotRunning", "toolsNotInstalled"]: - result.update( - failed=True, - msg="VMware tools is either not running or not installed", - ) - return result - - # If vmware tools is out of date, check major OS family - # Upgrade tools on Linux and Windows guests - elif vm.guest.toolsStatus == "toolsOld": - try: - if vm.guest.guestFamily in ["linuxGuest", "windowsGuest"]: - task = vm.UpgradeTools() - changed, err_msg = wait_for_task(task) - result.update(changed=changed, msg=to_native(err_msg)) - else: - result.update(msg='Guest Operating System is other than Linux and Windows.') - return result - except Exception as exc: - result.update( - failed=True, - msg='Error while upgrading VMware tools %s' % to_native(exc), - ) - return result - else: - result.update( - failed=True, - msg="VMware tools could not be upgraded", - ) - return result - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - name=dict(type='str'), - name_match=dict(type='str', choices=['first', 'last'], default='first'), - uuid=dict(type='str'), - moid=dict(type='str'), - folder=dict(type='str'), - datacenter=dict(type='str', required=True), - ) - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['name', 'uuid', 'moid'] - ] - ) - - if module.params['folder']: - # FindByInventoryPath() does not require an absolute path - # so we should leave the input folder path unmodified - module.params['folder'] = module.params['folder'].rstrip('/') - - pyv = PyVmomiHelper(module) - # Check if the VM exists before continuing - vm = pyv.get_vm() - - # VM already exists - if vm: - try: - result = pyv.upgrade_tools(vm) - if result['changed']: - module.exit_json(changed=result['changed']) - elif result['failed']: - module.fail_json(msg=result['msg']) - else: - module.exit_json(msg=result['msg'], changed=result['changed']) - except Exception as exc: - module.fail_json(msg='Unknown error: %s' % to_native(exc)) - else: - vm_id = module.params.get('uuid') or module.params.get('name') or module.params.get('moid') - module.fail_json(msg='Unable to find VM %s' % vm_id) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_tools_wait.py b/lib/ansible/modules/cloud/vmware/vmware_guest_tools_wait.py deleted file mode 100644 index 12f602cc89..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_tools_wait.py +++ /dev/null @@ -1,216 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2017, Philippe Dellaert <philippe@dellaert.org> -# 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 = ''' ---- -module: vmware_guest_tools_wait -short_description: Wait for VMware tools to become available -description: - - This module can be used to wait for VMware tools to become available on the given VM and return facts. -version_added: '2.4' -author: - - Philippe Dellaert (@pdellaert) <philippe@dellaert.org> -notes: - - Tested on vSphere 6.5 -requirements: - - python >= 2.6 - - PyVmomi -options: - name: - description: - - Name of the VM for which to wait until the tools become available. - - This is required if C(uuid) or C(moid) is not supplied. - type: str - name_match: - description: - - If multiple VMs match the name, use the first or last found. - default: 'first' - choices: ['first', 'last'] - type: str - folder: - description: - - Destination folder, absolute or relative path to find an existing guest. - - This is required only, if multiple VMs with same C(name) is found. - - The folder should include the datacenter. ESX's datacenter is C(ha-datacenter). - - 'Examples:' - - ' folder: /ha-datacenter/vm' - - ' folder: ha-datacenter/vm' - - ' folder: /datacenter1/vm' - - ' folder: datacenter1/vm' - - ' folder: /datacenter1/vm/folder1' - - ' folder: datacenter1/vm/folder1' - - ' folder: /folder1/datacenter1/vm' - - ' folder: folder1/datacenter1/vm' - - ' folder: /folder1/datacenter1/vm/folder2' - type: str - uuid: - description: - - UUID of the VM for which to wait until the tools become available, if known. This is VMware's unique identifier. - - This is required, if C(name) or C(moid) is not supplied. - type: str - moid: - description: - - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. - - This is required if C(name) or C(uuid) is not supplied. - version_added: '2.9' - type: str - use_instance_uuid: - description: - - Whether to use the VMware instance UUID rather than the BIOS UUID. - default: no - type: bool - version_added: '2.8' - timeout: - description: - - Max duration of the waiting period (seconds). - default: 500 - type: int - version_added: '2.10' -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Wait for VMware tools to become available by UUID - vmware_guest_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ datacenter }}" - folder: "/{{datacenter}}/vm" - name: "{{ vm_name }}" - delegate_to: localhost - register: vm_facts - -- name: Get UUID from previous task and pass it to this task - vmware_guest_tools_wait: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - uuid: "{{ vm_facts.instance.hw_product_uuid }}" - delegate_to: localhost - register: facts - - -- name: Wait for VMware tools to become available by MoID - vmware_guest_tools_wait: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - moid: vm-42 - delegate_to: localhost - register: facts - -- name: Wait for VMware tools to become available by name - vmware_guest_tools_wait: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - name: test-vm - folder: "/{{datacenter}}/vm" - delegate_to: localhost - register: facts -''' - -RETURN = """ -instance: - description: metadata about the virtual machine - returned: always - type: dict - sample: None -""" - -import datetime -import time - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils._text import to_native -from ansible.module_utils.vmware import PyVmomi, gather_vm_facts, vmware_argument_spec - - -class PyVmomiHelper(PyVmomi): - def __init__(self, module): - super(PyVmomiHelper, self).__init__(module) - - def gather_facts(self, vm): - return gather_vm_facts(self.content, vm) - - def wait_for_tools(self, vm, timeout): - tools_running = False - vm_facts = {} - start_at = datetime.datetime.now() - - while start_at + timeout > datetime.datetime.now(): - newvm = self.get_vm() - vm_facts = self.gather_facts(newvm) - if vm_facts['guest_tools_status'] == 'guestToolsRunning': - return {'changed': True, 'failed': False, 'instance': vm_facts} - time.sleep(5) - - if not tools_running: - return {'failed': True, 'msg': 'VMware tools either not present or not running after {0} seconds'.format(timeout.total_seconds())} - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - name=dict(type='str'), - name_match=dict(type='str', default='first', choices=['first', 'last']), - folder=dict(type='str'), - uuid=dict(type='str'), - moid=dict(type='str'), - use_instance_uuid=dict(type='bool', default=False), - timeout=dict(type='int', default=500), - ) - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['name', 'uuid', 'moid'] - ] - ) - - if module.params['folder']: - # FindByInventoryPath() does not require an absolute path - # so we should leave the input folder path unmodified - module.params['folder'] = module.params['folder'].rstrip('/') - - pyv = PyVmomiHelper(module) - # Check if the VM exists before continuing - vm = pyv.get_vm() - - if not vm: - vm_id = module.params.get('name') or module.params.get('uuid') or module.params.get('moid') - module.fail_json(msg="Unable to wait for VMware tools for non-existing VM '%s'." % vm_id) - - timeout = datetime.timedelta(seconds=module.params['timeout']) - - result = dict(changed=False) - try: - result = pyv.wait_for_tools(vm, timeout) - except Exception as e: - module.fail_json(msg="Waiting for VMware tools failed with" - " exception: {0:s}".format(to_native(e))) - - if result['failed']: - module.fail_json(**result) - else: - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_video.py b/lib/ansible/modules/cloud/vmware/vmware_guest_video.py deleted file mode 100644 index 2bdaf051f9..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_video.py +++ /dev/null @@ -1,366 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Diane Wang <dianew@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 = ''' ---- -module: vmware_guest_video -short_description: Modify video card configurations of specified virtual machine in given vCenter infrastructure -description: - - This module is used to reconfigure video card settings of given virtual machine. - - All parameters and VMware object names are case sensitive. -version_added: '2.8' -author: - - Diane Wang (@Tomorrow9) <dianew@vmware.com> -notes: - - Tested on vSphere 6.0, 6.5 and 6.7 -requirements: - - "python >= 2.6" - - PyVmomi -options: - name: - description: - - Name of the virtual machine. - - This is a required parameter, if parameter C(uuid) or C(moid) is not supplied. - type: str - uuid: - description: - - UUID of the instance to gather facts if known, this is VMware's unique identifier. - - This is a required parameter, if parameter C(name) or C(moid) is not supplied. - type: str - moid: - description: - - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. - - This is required if C(name) or C(uuid) is not supplied. - version_added: '2.9' - type: str - folder: - description: - - Destination folder, absolute or relative path to find an existing guest. - - This is a required parameter, only if multiple VMs are found with same name. - - The folder should include the datacenter. ESXi server's datacenter is ha-datacenter. - - 'Examples:' - - ' folder: /ha-datacenter/vm' - - ' folder: ha-datacenter/vm' - - ' folder: /datacenter1/vm' - - ' folder: datacenter1/vm' - - ' folder: /datacenter1/vm/folder1' - - ' folder: datacenter1/vm/folder1' - - ' folder: /folder1/datacenter1/vm' - - ' folder: folder1/datacenter1/vm' - - ' folder: /folder1/datacenter1/vm/folder2' - type: str - datacenter: - default: ha-datacenter - description: - - The datacenter name to which virtual machine belongs to. - - This parameter is case sensitive. - type: str - gather_video_facts: - description: - - If set to True, return settings of the video card, other attributes are ignored. - - If set to False, will do reconfiguration and return video card settings. - type: bool - default: 'no' - use_auto_detect: - description: - - 'If set to True, applies common video settings to the guest operating system, attributes C(display_number) and C(video_memory_mb) are ignored.' - - 'If set to False, the number of display and the total video memory will be reconfigured using C(display_number) and C(video_memory_mb).' - type: bool - display_number: - description: - - The number of display. Valid value from 1 to 10. The maximum display number is 4 on vCenter 6.0, 6.5 web UI. - type: int - video_memory_mb: - description: - - 'Valid total MB of video memory range of virtual machine is from 1.172 MB to 256 MB on ESXi 6.7U1, - from 1.172 MB to 128 MB on ESXi 6.7 and previous versions.' - - For specific guest OS, supported minimum and maximum video memory are different, please be careful on setting this. - type: float - enable_3D: - description: - - Enable 3D for guest operating systems on which VMware supports 3D. - type: bool - renderer_3D: - description: - - 'If set to C(automatic), selects the appropriate option (software or hardware) for this virtual machine automatically.' - - 'If set to C(software), uses normal CPU processing for 3D calculations.' - - 'If set to C(hardware), requires graphics hardware (GPU) for faster 3D calculations.' - choices: [ automatic, software, hardware ] - type: str - memory_3D_mb: - description: - - The value of 3D Memory must be power of 2 and valid value is from 32 MB to 2048 MB. - type: int -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Change video card settings of virtual machine - vmware_guest_video: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - validate_certs: no - name: test-vm - gather_video_facts: false - use_auto_detect: false - display_number: 2 - video_memory_mb: 8.0 - enable_3D: true - renderer_3D: automatic - memory_3D_mb: 512 - delegate_to: localhost - register: video_facts - -- name: Change video card settings of virtual machine using MoID - vmware_guest_video: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter_name }}" - validate_certs: no - moid: vm-42 - gather_video_facts: false - use_auto_detect: false - display_number: 2 - video_memory_mb: 8.0 - enable_3D: true - renderer_3D: automatic - memory_3D_mb: 512 - delegate_to: localhost - register: video_facts -''' - -RETURN = """ -video_status: - description: metadata about the virtual machine's video card after managing them - returned: always - type: dict - sample: { - "auto_detect": false, - "display_number": 2, - "enable_3D_support": true, - "memory_3D": 524288, - "renderer_3D": "automatic", - "video_memory": 8192 - } -""" - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils._text import to_native -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec, wait_for_task - - -class PyVmomiHelper(PyVmomi): - def __init__(self, module): - super(PyVmomiHelper, self).__init__(module) - self.change_detected = False - self.config_spec = vim.vm.ConfigSpec() - self.config_spec.deviceChange = [] - self.video_card_facts = None - - @staticmethod - def is_power_of_2(num): - return num != 0 and ((num & (num - 1)) == 0) - - def gather_video_card_facts(self, vm_obj): - """ - Gather facts about VM's video card settings - Args: - vm_obj: Managed object of virtual machine - Returns: Video Card device and a list of dict video card configuration - """ - video_facts = dict() - video_card = None - for device in vm_obj.config.hardware.device: - if isinstance(device, vim.vm.device.VirtualVideoCard): - video_card = device - video_facts = dict( - auto_detect=device.useAutoDetect, - display_number=device.numDisplays, - video_memory=device.videoRamSizeInKB, - enable_3D_support=device.enable3DSupport, - renderer_3D=device.use3dRenderer, - memory_3D=device.graphicsMemorySizeInKB, - ) - break - return video_card, video_facts - - def get_video_card_spec(self, vm_obj): - """ - Get device changes of virtual machine - Args: - vm_obj: Managed object of virtual machine - Returns: virtual device spec - """ - video_card, video_card_facts = self.gather_video_card_facts(vm_obj) - self.video_card_facts = video_card_facts - if video_card is None: - self.module.fail_json(msg='Not get video card device of specified virtual machine.') - video_spec = vim.vm.device.VirtualDeviceSpec() - video_spec.operation = vim.vm.device.VirtualDeviceSpec.Operation.edit - video_spec.device = video_card - auto_detect = False - enabled_3d = False - - if self.params['gather_video_facts']: - return None - if self.params['use_auto_detect'] is not None: - if video_card_facts['auto_detect'] and self.params['use_auto_detect']: - auto_detect = True - elif not video_card_facts['auto_detect'] and self.params['use_auto_detect']: - video_spec.device.useAutoDetect = True - self.change_detected = True - auto_detect = True - elif video_card_facts['auto_detect'] and not self.params['use_auto_detect']: - video_spec.device.useAutoDetect = False - self.change_detected = True - else: - if video_card_facts['auto_detect']: - auto_detect = True - # useAutoDetect set to False then display number and video memory config can be changed - if not auto_detect: - if self.params['display_number'] is not None: - if self.params['display_number'] < 1: - self.module.fail_json(msg="display_number attribute valid value: 1-10.") - if self.params['display_number'] != video_card_facts['display_number']: - video_spec.device.numDisplays = self.params['display_number'] - self.change_detected = True - - if self.params['video_memory_mb'] is not None: - if self.params['video_memory_mb'] < 1.172: - self.module.fail_json(msg="video_memory_mb attribute valid value: ESXi 6.7U1(1.172-256 MB)," - "ESXi 6.7/6.5/6.0(1.172-128 MB).") - if int(self.params['video_memory_mb'] * 1024) != video_card_facts['video_memory']: - video_spec.device.videoRamSizeInKB = int(self.params['video_memory_mb'] * 1024) - self.change_detected = True - else: - if self.params['display_number'] is not None or self.params['video_memory_mb'] is not None: - self.module.fail_json(msg="display_number and video_memory_mb can not be changed if use_auto_detect is true.") - # useAutoDetect value not control 3D config - if self.params['enable_3D'] is not None: - if self.params['enable_3D'] != video_card_facts['enable_3D_support']: - video_spec.device.enable3DSupport = self.params['enable_3D'] - self.change_detected = True - if self.params['enable_3D']: - enabled_3d = True - else: - if video_card_facts['enable_3D_support']: - enabled_3d = True - else: - if video_card_facts['enable_3D_support']: - enabled_3d = True - # 3D is enabled then 3D memory and renderer method can be set - if enabled_3d: - if self.params['renderer_3D'] is not None: - renderer = self.params['renderer_3D'].lower() - if renderer not in ['automatic', 'software', 'hardware']: - self.module.fail_json(msg="renderer_3D attribute valid value: automatic, software, hardware.") - if renderer != video_card_facts['renderer_3D']: - video_spec.device.use3dRenderer = renderer - self.change_detected = True - if self.params['memory_3D_mb'] is not None: - memory_3d = self.params['memory_3D_mb'] - if not self.is_power_of_2(memory_3d): - self.module.fail_json(msg="memory_3D_mb attribute should be an integer value and power of 2(32-2048).") - else: - if memory_3d < 32 or memory_3d > 2048: - self.module.fail_json(msg="memory_3D_mb attribute should be an integer value and power of 2(32-2048).") - if memory_3d * 1024 != video_card_facts['memory_3D']: - video_spec.device.graphicsMemorySizeInKB = memory_3d * 1024 - self.change_detected = True - else: - if self.params['renderer_3D'] is not None or self.params['memory_3D_mb'] is not None: - self.module.fail_json(msg='3D renderer or 3D memory can not be configured if 3D is not enabled.') - if not self.change_detected: - return None - return video_spec - - def reconfigure_vm_video(self, vm_obj): - """ - Reconfigure video card settings of virtual machine - Args: - vm_obj: Managed object of virtual machine - Returns: Reconfigure results - """ - video_card_spec = self.get_video_card_spec(vm_obj) - if video_card_spec is None: - return {'changed': False, 'failed': False, 'instance': self.video_card_facts} - self.config_spec.deviceChange.append(video_card_spec) - try: - task = vm_obj.ReconfigVM_Task(spec=self.config_spec) - wait_for_task(task) - except vim.fault.InvalidDeviceSpec as invalid_device_spec: - self.module.fail_json(msg="Failed to configure video card on given virtual machine due to invalid" - " device spec : %s" % (to_native(invalid_device_spec.msg)), - details="Please check ESXi server logs for more details.") - except vim.fault.RestrictedVersion as e: - self.module.fail_json(msg="Failed to reconfigure virtual machine due to" - " product versioning restrictions: %s" % to_native(e.msg)) - if task.info.state == 'error': - return {'changed': self.change_detected, 'failed': True, 'msg': task.info.error.msg} - video_card_facts = self.gather_video_card_facts(vm_obj)[1] - return {'changed': self.change_detected, 'failed': False, 'instance': video_card_facts} - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - name=dict(type='str'), - uuid=dict(type='str'), - moid=dict(type='str'), - folder=dict(type='str'), - datacenter=dict(type='str', default='ha-datacenter'), - gather_video_facts=dict(type='bool', default=False), - use_auto_detect=dict(type='bool'), - display_number=dict(type='int'), - video_memory_mb=dict(type='float'), - enable_3D=dict(type='bool'), - renderer_3D=dict(type='str', choices=['automatic', 'software', 'hardware']), - memory_3D_mb=dict(type='int'), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['name', 'uuid', 'moid'] - ] - ) - - pyv = PyVmomiHelper(module) - vm = pyv.get_vm() - if not vm: - vm_id = module.params.get('uuid') or module.params.get('name') or module.params.get('moid') - module.fail_json(msg='Unable to find the specified virtual machine : %s' % vm_id) - - vm_facts = pyv.gather_facts(vm) - vm_power_state = vm_facts['hw_power_status'].lower() - if vm_power_state != 'poweredoff': - module.fail_json(msg='VM state should be poweredoff to reconfigure video card settings.') - result = pyv.reconfigure_vm_video(vm_obj=vm) - if result['failed']: - module.fail_json(**result) - else: - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_guest_vnc.py b/lib/ansible/modules/cloud/vmware/vmware_guest_vnc.py deleted file mode 100644 index 6e70059312..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_guest_vnc.py +++ /dev/null @@ -1,268 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (c) 2018, Armin Ranjbar Daemi <armin@webair.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 = ''' ---- -module: vmware_guest_vnc -short_description: Manages VNC remote display on virtual machines in vCenter -description: - - This module can be used to enable and disable VNC remote display on virtual machine. -version_added: 2.8 -author: - - Armin Ranjbar Daemi (@rmin) -requirements: - - python >= 2.6 - - PyVmomi -options: - datacenter: - description: - - Destination datacenter for the deploy operation. - - This parameter is case sensitive. - default: ha-datacenter - type: str - state: - description: - - Set the state of VNC on virtual machine. - choices: [present, absent] - default: present - required: false - type: str - name: - description: - - Name of the virtual machine to work with. - - Virtual machine names in vCenter are not necessarily unique, which may be problematic, see C(name_match). - required: false - type: str - name_match: - description: - - If multiple virtual machines matching the name, use the first or last found. - default: first - choices: [first, last] - required: false - type: str - uuid: - description: - - UUID of the instance to manage if known, this is VMware's unique identifier. - - This is required, if C(name) or C(moid) is not supplied. - required: false - type: str - moid: - description: - - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. - - This is required if C(name) or C(uuid) is not supplied. - version_added: '2.9' - type: str - folder: - description: - - Destination folder, absolute or relative path to find an existing guest. - - The folder should include the datacenter. ESX's datacenter is ha-datacenter - required: false - type: str - vnc_ip: - description: - - Sets an IP for VNC on virtual machine. - - This is required only when I(state) is set to present and will be ignored if I(state) is absent. - default: 0.0.0.0 - required: false - type: str - vnc_port: - description: - - The port that VNC listens on. Usually a number between 5900 and 7000 depending on your config. - - This is required only when I(state) is set to present and will be ignored if I(state) is absent. - default: 0 - required: false - type: int - vnc_password: - description: - - Sets a password for VNC on virtual machine. - - This is required only when I(state) is set to present and will be ignored if I(state) is absent. - default: "" - required: false - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Enable VNC remote display on the VM - vmware_guest_vnc: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - folder: /mydatacenter/vm - name: testvm1 - vnc_port: 5990 - vnc_password: vNc5ecr3t - datacenter: "{{ datacenter_name }}" - state: present - delegate_to: localhost - register: vnc_result - -- name: Disable VNC remote display on the VM - vmware_guest_vnc: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ datacenter_name }}" - uuid: 32074771-7d6b-699a-66a8-2d9cf8236fff - state: absent - delegate_to: localhost - register: vnc_result - -- name: Disable VNC remote display on the VM using MoID - vmware_guest_vnc: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ datacenter_name }}" - moid: vm-42 - state: absent - delegate_to: localhost - register: vnc_result -''' - -RETURN = ''' -changed: - description: If anything changed on VM's extraConfig. - returned: always - type: bool -failed: - description: If changes failed. - returned: always - type: bool -instance: - description: Dictionary describing the VM, including VNC info. - returned: On success in both I(state) - type: dict -''' - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec, get_vnc_extraconfig, wait_for_task, gather_vm_facts, TaskError -from ansible.module_utils._text import to_native - - -def set_vnc_extraconfig(content, vm, enabled, ip, port, password): - result = dict( - changed=False, - failed=False, - ) - # set new values - key_prefix = "remotedisplay.vnc." - new_values = dict() - for key in ['enabled', 'ip', 'port', 'password']: - new_values[key_prefix + key] = "" - if enabled: - new_values[key_prefix + "enabled"] = "true" - new_values[key_prefix + "password"] = str(password).strip() - new_values[key_prefix + "ip"] = str(ip).strip() - new_values[key_prefix + "port"] = str(port).strip() - - # get current vnc config - current_values = get_vnc_extraconfig(vm) - # check if any value is changed - reconfig_vm = False - for key, val in new_values.items(): - key = key.replace(key_prefix, "") - current_value = current_values.get(key, "") - # enabled is not case-sensitive - if key == "enabled": - current_value = current_value.lower() - val = val.lower() - if current_value != val: - reconfig_vm = True - if not reconfig_vm: - return result - # reconfigure vm - spec = vim.vm.ConfigSpec() - spec.extraConfig = [] - for key, val in new_values.items(): - opt = vim.option.OptionValue() - opt.key = key - opt.value = val - spec.extraConfig.append(opt) - task = vm.ReconfigVM_Task(spec) - try: - wait_for_task(task) - except TaskError as task_err: - result['failed'] = True - result['msg'] = to_native(task_err) - - if task.info.state == 'error': - result['failed'] = True - result['msg'] = task.info.error.msg - else: - result['changed'] = True - result['instance'] = gather_vm_facts(content, vm) - return result - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - state=dict(type='str', default='present', choices=['present', 'absent']), - name=dict(type='str'), - name_match=dict(type='str', choices=['first', 'last'], default='first'), - uuid=dict(type='str'), - moid=dict(type='str'), - folder=dict(type='str'), - vnc_ip=dict(type='str', default='0.0.0.0'), - vnc_port=dict(type='int', default=0), - vnc_password=dict(type='str', default='', no_log=True), - datacenter=dict(type='str', default='ha-datacenter') - ) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - required_one_of=[ - ['name', 'uuid', 'moid'] - ], - mutually_exclusive=[ - ['name', 'uuid', 'moid'] - ] - ) - - result = dict(changed=False, failed=False) - - pyv = PyVmomi(module) - vm = pyv.get_vm() - if vm: - result = set_vnc_extraconfig( - pyv.content, - vm, - (module.params['state'] == "present"), - module.params['vnc_ip'], - module.params['vnc_port'], - module.params['vnc_password'] - ) - else: - vm_id = module.params.get('uuid') or module.params.get('name') or module.params.get('moid') - module.fail_json(msg="Unable to set VNC config for non-existing virtual machine : '%s'" % vm_id) - - if result.get('failed') is True: - module.fail_json(**result) - - module.exit_json(**result) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host.py b/lib/ansible/modules/cloud/vmware/vmware_host.py deleted file mode 100644 index 531582e138..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host.py +++ /dev/null @@ -1,841 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2015, Joseph Callen <jcallen () csc.com> -# Copyright: (c) 2017, Ansible Project -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# 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_host -short_description: Add, remove, or move an ESXi host to, from, or within vCenter -description: -- This module can be used to add, reconnect, or remove an ESXi host to or from vCenter. -- This module can also be used to move an ESXi host to a cluster or folder, or vice versa, within the same datacenter. -version_added: '2.0' -author: -- Joseph Callen (@jcpowermac) -- Russell Teague (@mtnbikenc) -- Maxime de Roucy (@tchernomax) -- Christian Kotte (@ckotte) -notes: -- Tested on vSphere 5.5, 6.0, 6.5 and 6.7 -requirements: -- python >= 2.6 -- PyVmomi -- ssl -- socket -- hashlib -options: - datacenter_name: - description: - - Name of the datacenter to add the host. - - Aliases added in version 2.6. - required: yes - aliases: ['datacenter'] - type: str - cluster_name: - description: - - Name of the cluster to add the host. - - If C(folder) is not set, then this parameter is required. - - Aliases added in version 2.6. - aliases: ['cluster'] - type: str - folder: - description: - - Name of the folder under which host to add. - - If C(cluster_name) is not set, then this parameter is required. - - "For example, if there is a datacenter 'dc1' under folder called 'Site1' then, this value will be '/Site1/dc1/host'." - - "Here 'host' is an invisible folder under VMware Web Client." - - "Another example, if there is a nested folder structure like '/myhosts/india/pune' under - datacenter 'dc2', then C(folder) value will be '/dc2/host/myhosts/india/pune'." - - "Other Examples: '/Site2/dc2/Asia-Cluster/host' or '/dc3/Asia-Cluster/host'" - version_added: "2.6" - aliases: ['folder_name'] - type: str - add_connected: - description: - - If set to C(True), then the host should be connected as soon as it is added. - - This parameter is ignored if state is set to a value other than C(present). - default: True - type: bool - version_added: "2.6" - esxi_hostname: - description: - - ESXi hostname to manage. - required: yes - type: str - esxi_username: - description: - - ESXi username. - - Required for adding a host. - - Optional for reconnect. If both C(esxi_username) and C(esxi_password) are used - - Unused for removing. - - No longer a required parameter from version 2.5. - type: str - esxi_password: - description: - - ESXi password. - - Required for adding a host. - - Optional for reconnect. - - Unused for removing. - - No longer a required parameter from version 2.5. - type: str - state: - description: - - If set to C(present), add the host if host is absent. - - If set to C(present), update the location of the host if host already exists. - - If set to C(absent), remove the host if host is present. - - If set to C(absent), do nothing if host already does not exists. - - If set to C(add_or_reconnect), add the host if it's absent else reconnect it and update the location. - - If set to C(reconnect), then reconnect the host if it's present and update the location. - default: present - choices: ['present', 'absent', 'add_or_reconnect', 'reconnect'] - type: str - esxi_ssl_thumbprint: - description: - - "Specifying the hostsystem certificate's thumbprint." - - "Use following command to get hostsystem certificate's thumbprint - " - - "# openssl x509 -in /etc/vmware/ssl/rui.crt -fingerprint -sha1 -noout" - - Only used if C(fetch_thumbprint) isn't set to C(true). - version_added: 2.5 - default: '' - type: str - aliases: ['ssl_thumbprint'] - fetch_ssl_thumbprint: - description: - - Fetch the thumbprint of the host's SSL certificate. - - This basically disables the host certificate verification (check if it was signed by a recognized CA). - - Disable this option if you want to allow only hosts with valid certificates to be added to vCenter. - - If this option is set to C(false) and the certificate can't be verified, an add or reconnect will fail. - - Unused when C(esxi_ssl_thumbprint) is set. - - Optional for reconnect, but only used if C(esxi_username) and C(esxi_password) are used. - - Unused for removing. - type: bool - version_added: 2.8 - default: True - force_connection: - description: - - Force the connection if the host is already being managed by another vCenter server. - type: bool - version_added: 2.8 - default: True - reconnect_disconnected: - description: - - Reconnect disconnected hosts. - - This is only used if C(state) is set to C(present) and if the host already exists. - type: bool - version_added: 2.8 - default: True -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Add ESXi Host to vCenter - vmware_host: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: datacenter_name - cluster: cluster_name - esxi_hostname: '{{ esxi_hostname }}' - esxi_username: '{{ esxi_username }}' - esxi_password: '{{ esxi_password }}' - state: present - delegate_to: localhost - -- name: Add ESXi Host to vCenter under a specific folder - vmware_host: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: datacenter_name - folder: '/Site2/Asia-Cluster/host' - esxi_hostname: '{{ esxi_hostname }}' - esxi_username: '{{ esxi_username }}' - esxi_password: '{{ esxi_password }}' - state: present - add_connected: True - delegate_to: localhost - -- name: Reconnect ESXi Host (with username/password set) - vmware_host: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: datacenter_name - cluster: cluster_name - esxi_hostname: '{{ esxi_hostname }}' - esxi_username: '{{ esxi_username }}' - esxi_password: '{{ esxi_password }}' - state: reconnect - delegate_to: localhost - -- name: Reconnect ESXi Host (with default username/password) - vmware_host: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: datacenter_name - cluster: cluster_name - esxi_hostname: '{{ esxi_hostname }}' - state: reconnect - delegate_to: localhost - -- name: Add ESXi Host with SSL Thumbprint to vCenter - vmware_host: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: datacenter_name - cluster: cluster_name - esxi_hostname: '{{ esxi_hostname }}' - esxi_username: '{{ esxi_username }}' - esxi_password: '{{ esxi_password }}' - esxi_ssl_thumbprint: "3C:A5:60:6F:7A:B7:C4:6C:48:28:3D:2F:A5:EC:A3:58:13:88:F6:DD" - state: present - delegate_to: localhost -''' - -RETURN = r''' -result: - description: metadata about the new host system added - returned: on successful addition - type: str - sample: "Host already connected to vCenter 'vcenter01' in cluster 'cluster01'" -''' - -try: - from pyVmomi import vim, vmodl - import ssl - import socket - import hashlib -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils._text import to_native -from ansible.module_utils.vmware import ( - PyVmomi, TaskError, vmware_argument_spec, - wait_for_task, find_host_by_cluster_datacenter, find_hostsystem_by_name -) - - -class VMwareHost(PyVmomi): - """Class to manage vCenter connection""" - def __init__(self, module): - super(VMwareHost, self).__init__(module) - self.vcenter = module.params['hostname'] - self.datacenter_name = module.params['datacenter_name'] - self.cluster_name = module.params['cluster_name'] - self.folder_name = module.params['folder'] - 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.esxi_ssl_thumbprint = module.params.get('esxi_ssl_thumbprint', '') - self.force_connection = module.params.get('force_connection') - self.fetch_ssl_thumbprint = module.params.get('fetch_ssl_thumbprint') - self.reconnect_disconnected = module.params.get('reconnect_disconnected') - self.host_update = self.host = self.cluster = self.folder = self.host_parent_compute_resource = None - - def process_state(self): - """Check the current state""" - host_states = { - 'absent': { - 'present': self.state_remove_host, - 'update': self.state_remove_host, - 'absent': self.state_exit_unchanged, - }, - 'present': { - 'present': self.state_exit_unchanged, - 'update': self.state_update_host, - 'absent': self.state_add_host, - }, - 'add_or_reconnect': { - 'present': self.state_reconnect_host, - 'update': self.state_update_host, - 'absent': self.state_add_host, - }, - 'reconnect': { - 'present': self.state_reconnect_host, - 'update': self.state_update_host, - } - } - - try: - host_states[self.state][self.check_host_state()]() - except vmodl.RuntimeFault as runtime_fault: - self.module.fail_json(msg=to_native(runtime_fault.msg)) - except vmodl.MethodFault as method_fault: - self.module.fail_json(msg=to_native(method_fault.msg)) - except Exception as e: - self.module.fail_json(msg=to_native(e)) - - def check_host_state(self): - """Check current state""" - # Check if the host is already connected to vCenter - self.host_update = find_hostsystem_by_name(self.content, self.esxi_hostname) - if self.host_update: - # The host name is unique in vCenter; A host with the same name cannot exist in another datacenter - # However, the module will fail later if the target folder/cluster is in another datacenter as the host - # Check if the host is connected under the target cluster - if self.cluster_name: - self.host, self.cluster = self.search_cluster(self.datacenter_name, self.cluster_name, self.esxi_hostname) - if self.host: - state = 'present' - else: - state = 'update' - # Check if the host is connected under the target folder - elif self.folder_name: - self.folder = self.search_folder(self.folder_name) - for child in self.folder.childEntity: - if not child or not isinstance(child, vim.ComputeResource): - continue - try: - if isinstance(child.host[0], vim.HostSystem) and child.name == self.esxi_hostname: - self.host_parent_compute_resource = child - self.host = child.host[0] - break - except IndexError: - continue - if self.host: - state = 'present' - else: - state = 'update' - else: - state = 'absent' - return state - - def search_folder(self, folder_name): - """ - Search folder in vCenter - Returns: folder object - """ - search_index = self.content.searchIndex - folder_obj = search_index.FindByInventoryPath(folder_name) - if not (folder_obj and isinstance(folder_obj, vim.Folder)): - self.module.fail_json(msg="Folder '%s' not found" % folder_name) - return folder_obj - - def search_cluster(self, datacenter_name, cluster_name, esxi_hostname): - """ - Search cluster in vCenter - Returns: host and cluster object - """ - return find_host_by_cluster_datacenter( - self.module, self.content, datacenter_name, cluster_name, esxi_hostname - ) - - def state_exit_unchanged(self): - """Exit with status message""" - if not self.host_update: - result = "Host already disconnected" - elif self.reconnect_disconnected and self.host_update.runtime.connectionState == 'disconnected': - self.state_reconnect_host() - else: - if self.folder_name: - result = "Host already connected to vCenter '%s' in folder '%s'" % (self.vcenter, self.folder_name) - elif self.cluster_name: - result = "Host already connected to vCenter '%s' in cluster '%s'" % (self.vcenter, self.cluster_name) - self.module.exit_json(changed=False, result=str(result)) - - def state_add_host(self): - """Add ESXi host to a cluster of folder in vCenter""" - changed = True - result = None - - if self.module.check_mode: - result = "Host would be connected to vCenter '%s'" % self.vcenter - else: - host_connect_spec = self.get_host_connect_spec() - as_connected = self.params.get('add_connected') - esxi_license = None - resource_pool = None - task = None - if self.folder_name: - self.folder = self.search_folder(self.folder_name) - try: - task = self.folder.AddStandaloneHost( - spec=host_connect_spec, compResSpec=resource_pool, - addConnected=as_connected, license=esxi_license - ) - except vim.fault.InvalidLogin as invalid_login: - self.module.fail_json( - msg="Cannot authenticate with the host : %s" % to_native(invalid_login) - ) - except vim.fault.HostConnectFault as connect_fault: - self.module.fail_json( - msg="An error occurred during connect : %s" % to_native(connect_fault) - ) - except vim.fault.DuplicateName as duplicate_name: - self.module.fail_json( - msg="The folder already contains a host with the same name : %s" % - to_native(duplicate_name) - ) - except vmodl.fault.InvalidArgument as invalid_argument: - self.module.fail_json( - msg="An argument was specified incorrectly : %s" % to_native(invalid_argument) - ) - except vim.fault.AlreadyBeingManaged as already_managed: - self.module.fail_json( - msg="The host is already being managed by another vCenter server : %s" % - to_native(already_managed) - ) - except vmodl.fault.NotEnoughLicenses as not_enough_licenses: - self.module.fail_json( - msg="There are not enough licenses to add this host : %s" % to_native(not_enough_licenses) - ) - except vim.fault.NoHost as no_host: - self.module.fail_json( - msg="Unable to contact the host : %s" % to_native(no_host) - ) - except vmodl.fault.NotSupported as not_supported: - self.module.fail_json( - msg="The folder is not a host folder : %s" % to_native(not_supported) - ) - except vim.fault.NotSupportedHost as host_not_supported: - self.module.fail_json( - msg="The host is running a software version that is not supported : %s" % - to_native(host_not_supported) - ) - except vim.fault.AgentInstallFailed as agent_install: - self.module.fail_json( - msg="Error during vCenter agent installation : %s" % to_native(agent_install) - ) - except vim.fault.AlreadyConnected as already_connected: - self.module.fail_json( - msg="The host is already connected to the vCenter server : %s" % to_native(already_connected) - ) - except vim.fault.SSLVerifyFault as ssl_fault: - self.module.fail_json( - msg="The host certificate could not be authenticated : %s" % to_native(ssl_fault) - ) - elif self.cluster_name: - self.host, self.cluster = self.search_cluster( - self.datacenter_name, - self.cluster_name, - self.esxi_hostname - ) - try: - task = self.cluster.AddHost_Task( - spec=host_connect_spec, asConnected=as_connected, - resourcePool=resource_pool, license=esxi_license - ) - except vim.fault.InvalidLogin as invalid_login: - self.module.fail_json( - msg="Cannot authenticate with the host : %s" % to_native(invalid_login) - ) - except vim.fault.HostConnectFault as connect_fault: - self.module.fail_json( - msg="An error occurred during connect : %s" % to_native(connect_fault) - ) - except vim.fault.DuplicateName as duplicate_name: - self.module.fail_json( - msg="The cluster already contains a host with the same name : %s" % - to_native(duplicate_name) - ) - except vim.fault.AlreadyBeingManaged as already_managed: - self.module.fail_json( - msg="The host is already being managed by another vCenter server : %s" % - to_native(already_managed) - ) - except vmodl.fault.NotEnoughLicenses as not_enough_licenses: - self.module.fail_json( - msg="There are not enough licenses to add this host : %s" % to_native(not_enough_licenses) - ) - except vim.fault.NoHost as no_host: - self.module.fail_json( - msg="Unable to contact the host : %s" % to_native(no_host) - ) - except vim.fault.NotSupportedHost as host_not_supported: - self.module.fail_json( - msg="The host is running a software version that is not supported; " - "It may still be possible to add the host as a stand-alone host : %s" % - to_native(host_not_supported) - ) - except vim.fault.TooManyHosts as too_many_hosts: - self.module.fail_json( - msg="No additional hosts can be added to the cluster : %s" % to_native(too_many_hosts) - ) - except vim.fault.AgentInstallFailed as agent_install: - self.module.fail_json( - msg="Error during vCenter agent installation : %s" % to_native(agent_install) - ) - except vim.fault.AlreadyConnected as already_connected: - self.module.fail_json( - msg="The host is already connected to the vCenter server : %s" % to_native(already_connected) - ) - except vim.fault.SSLVerifyFault as ssl_fault: - self.module.fail_json( - msg="The host certificate could not be authenticated : %s" % to_native(ssl_fault) - ) - try: - changed, result = wait_for_task(task) - result = "Host connected to vCenter '%s'" % self.vcenter - except TaskError as task_error: - self.module.fail_json( - msg="Failed to add host to vCenter '%s' : %s" % (self.vcenter, to_native(task_error)) - ) - - self.module.exit_json(changed=changed, result=result) - - def get_host_connect_spec(self): - """ - Function to return Host connection specification - Returns: host connection specification - """ - # Get the thumbprint of the SSL certificate - if self.fetch_ssl_thumbprint and self.esxi_ssl_thumbprint == '': - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.settimeout(1) - if self.module.params['proxy_host']: - sock.connect(( - self.module.params['proxy_host'], - self.module.params['proxy_port'])) - command = "CONNECT %s:443 HTTP/1.0\r\n\r\n" % (self.esxi_hostname) - sock.send(command.encode()) - buf = sock.recv(8192).decode() - if buf.split()[1] != '200': - self.module.fail_json(msg="Failed to connect to the proxy") - ctx = ssl.create_default_context() - ctx.check_hostname = False - ctx.verify_mode = ssl.CERT_NONE - der_cert_bin = ctx.wrap_socket(sock, server_hostname=self.esxi_hostname).getpeercert(True) - sock.close() - else: - wrapped_socket = ssl.wrap_socket(sock) - try: - wrapped_socket.connect((self.esxi_hostname, 443)) - except socket.error as socket_error: - self.module.fail_json(msg="Cannot connect to host : %s" % socket_error) - else: - der_cert_bin = wrapped_socket.getpeercert(True) - wrapped_socket.close() - - thumb_sha1 = self.format_number(hashlib.sha1(der_cert_bin).hexdigest()) - sslThumbprint = thumb_sha1 - else: - sslThumbprint = self.esxi_ssl_thumbprint - - host_connect_spec = vim.host.ConnectSpec() - host_connect_spec.sslThumbprint = sslThumbprint - 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 = self.force_connection - return host_connect_spec - - @staticmethod - def format_number(number): - """Format number""" - string = str(number) - return ':'.join(a + b for a, b in zip(string[::2], string[1::2])) - - def state_reconnect_host(self): - """Reconnect host to vCenter""" - changed = True - result = None - - if self.module.check_mode: - result = "Host would be reconnected to vCenter '%s'" % self.vcenter - else: - self.reconnect_host(self.host) - result = "Host reconnected to vCenter '%s'" % self.vcenter - self.module.exit_json(changed=changed, result=str(result)) - - def reconnect_host(self, host_object): - """Reconnect host to vCenter""" - reconnecthost_args = {} - reconnecthost_args['reconnectSpec'] = vim.HostSystem.ReconnectSpec() - reconnecthost_args['reconnectSpec'].syncState = True - - if self.esxi_username and self.esxi_password: - # Build the connection spec as well and fetch thumbprint if enabled - # Useful if you reinstalled a host and it uses a new self-signed certificate - reconnecthost_args['cnxSpec'] = self.get_host_connect_spec() - try: - task = host_object.ReconnectHost_Task(**reconnecthost_args) - except vim.fault.InvalidLogin as invalid_login: - self.module.fail_json( - msg="Cannot authenticate with the host : %s" % to_native(invalid_login) - ) - except vim.fault.InvalidState as invalid_state: - self.module.fail_json( - msg="The host is not disconnected : %s" % to_native(invalid_state) - ) - except vim.fault.InvalidName as invalid_name: - self.module.fail_json( - msg="The host name is invalid : %s" % to_native(invalid_name) - ) - except vim.fault.HostConnectFault as connect_fault: - self.module.fail_json( - msg="An error occurred during reconnect : %s" % to_native(connect_fault) - ) - except vmodl.fault.NotSupported as not_supported: - self.module.fail_json( - msg="No host can be added to this group : %s" % to_native(not_supported) - ) - except vim.fault.AlreadyBeingManaged as already_managed: - self.module.fail_json( - msg="The host is already being managed by another vCenter server : %s" % to_native(already_managed) - ) - except vmodl.fault.NotEnoughLicenses as not_enough_licenses: - self.module.fail_json( - msg="There are not enough licenses to add this host : %s" % to_native(not_enough_licenses) - ) - except vim.fault.NoHost as no_host: - self.module.fail_json( - msg="Unable to contact the host : %s" % to_native(no_host) - ) - except vim.fault.NotSupportedHost as host_not_supported: - self.module.fail_json( - msg="The host is running a software version that is not supported : %s" % - to_native(host_not_supported) - ) - except vim.fault.SSLVerifyFault as ssl_fault: - self.module.fail_json( - msg="The host certificate could not be authenticated : %s" % to_native(ssl_fault) - ) - try: - changed, result = wait_for_task(task) - except TaskError as task_error: - self.module.fail_json( - msg="Failed to reconnect host to vCenter '%s' due to %s" % - (self.vcenter, to_native(task_error)) - ) - - def state_remove_host(self): - """Remove host from vCenter""" - changed = True - result = None - if self.module.check_mode: - result = "Host would be removed from vCenter '%s'" % self.vcenter - else: - # Check parent type - parent_type = self.get_parent_type(self.host_update) - if parent_type == 'cluster': - self.put_host_in_maintenance_mode(self.host_update) - try: - if self.folder_name: - task = self.host_parent_compute_resource.Destroy_Task() - elif self.cluster_name: - task = self.host.Destroy_Task() - except vim.fault.VimFault as vim_fault: - self.module.fail_json(msg=vim_fault) - try: - changed, result = wait_for_task(task) - result = "Host removed from vCenter '%s'" % self.vcenter - except TaskError as task_error: - self.module.fail_json( - msg="Failed to remove the host from vCenter '%s' : %s" % (self.vcenter, to_native(task_error)) - ) - self.module.exit_json(changed=changed, result=str(result)) - - def put_host_in_maintenance_mode(self, host_object): - """Put host in maintenance mode, if not already""" - if not host_object.runtime.inMaintenanceMode: - try: - try: - maintenance_mode_task = host_object.EnterMaintenanceMode_Task(300, True, None) - except vim.fault.InvalidState as invalid_state: - self.module.fail_json( - msg="The host is already in maintenance mode : %s" % to_native(invalid_state) - ) - except vim.fault.Timedout as timed_out: - self.module.fail_json( - msg="The maintenance mode operation timed out : %s" % to_native(timed_out) - ) - except vim.fault.Timedout as timed_out: - self.module.fail_json( - msg="The maintenance mode operation was canceled : %s" % to_native(timed_out) - ) - wait_for_task(maintenance_mode_task) - except TaskError as task_err: - self.module.fail_json( - msg="Failed to put the host in maintenance mode : %s" % to_native(task_err) - ) - - def get_parent_type(self, host_object): - """ - Get the type of the parent object - Returns: string with 'folder' or 'cluster' - """ - object_type = None - # check 'vim.ClusterComputeResource' first because it's also an - # instance of 'vim.ComputeResource' - if isinstance(host_object.parent, vim.ClusterComputeResource): - object_type = 'cluster' - elif isinstance(host_object.parent, vim.ComputeResource): - object_type = 'folder' - return object_type - - def state_update_host(self): - """Move host to a cluster or a folder, or vice versa""" - changed = True - result = None - reconnect = False - - # Check if the host is disconnected if reconnect disconnected hosts is true - if self.reconnect_disconnected and self.host_update.runtime.connectionState == 'disconnected': - reconnect = True - - # Check parent type - parent_type = self.get_parent_type(self.host_update) - - if self.folder_name: - if self.module.check_mode: - if reconnect or self.state == 'add_or_reconnect' or self.state == 'reconnect': - result = "Host would be reconnected and moved to folder '%s'" % self.folder_name - else: - result = "Host would be moved to folder '%s'" % self.folder_name - else: - # Reconnect the host if disconnected or if specified by state - if reconnect or self.state == 'add_or_reconnect' or self.state == 'reconnect': - self.reconnect_host(self.host_update) - try: - try: - if parent_type == 'folder': - # Move ESXi host from folder to folder - task = self.folder.MoveIntoFolder_Task([self.host_update.parent]) - elif parent_type == 'cluster': - self.put_host_in_maintenance_mode(self.host_update) - # Move ESXi host from cluster to folder - task = self.folder.MoveIntoFolder_Task([self.host_update]) - except vim.fault.DuplicateName as duplicate_name: - self.module.fail_json( - msg="The folder already contains an object with the specified name : %s" % - to_native(duplicate_name) - ) - except vim.fault.InvalidFolder as invalid_folder: - self.module.fail_json( - msg="The parent of this folder is in the list of objects : %s" % - to_native(invalid_folder) - ) - except vim.fault.InvalidState as invalid_state: - self.module.fail_json( - msg="Failed to move host, this can be due to either of following :" - " 1. The host is not part of the same datacenter, 2. The host is not in maintenance mode : %s" % - to_native(invalid_state) - ) - except vmodl.fault.NotSupported as not_supported: - self.module.fail_json( - msg="The target folder is not a host folder : %s" % - to_native(not_supported) - ) - except vim.fault.DisallowedOperationOnFailoverHost as failover_host: - self.module.fail_json( - msg="The host is configured as a failover host : %s" % - to_native(failover_host) - ) - except vim.fault.VmAlreadyExistsInDatacenter as already_exists: - self.module.fail_json( - msg="The host's virtual machines are already registered to a host in " - "the destination datacenter : %s" % to_native(already_exists) - ) - changed, result = wait_for_task(task) - except TaskError as task_error_exception: - task_error = task_error_exception.args[0] - self.module.fail_json( - msg="Failed to move host %s to folder %s due to %s" % - (self.esxi_hostname, self.folder_name, to_native(task_error)) - ) - if reconnect or self.state == 'add_or_reconnect' or self.state == 'reconnect': - result = "Host reconnected and moved to folder '%s'" % self.folder_name - else: - result = "Host moved to folder '%s'" % self.folder_name - elif self.cluster_name: - if self.module.check_mode: - result = "Host would be moved to cluster '%s'" % self.cluster_name - else: - if parent_type == 'cluster': - # Put host in maintenance mode if moved from another cluster - self.put_host_in_maintenance_mode(self.host_update) - resource_pool = None - try: - try: - task = self.cluster.MoveHostInto_Task( - host=self.host_update, resourcePool=resource_pool - ) - except vim.fault.TooManyHosts as too_many_hosts: - self.module.fail_json( - msg="No additional hosts can be added to the cluster : %s" % to_native(too_many_hosts) - ) - except vim.fault.InvalidState as invalid_state: - self.module.fail_json( - msg="The host is already part of a cluster and is not in maintenance mode : %s" % - to_native(invalid_state) - ) - except vmodl.fault.InvalidArgument as invalid_argument: - self.module.fail_json( - msg="Failed to move host, this can be due to either of following :" - " 1. The host is is not a part of the same datacenter as the cluster," - " 2. The source and destination clusters are the same : %s" % - to_native(invalid_argument) - ) - changed, result = wait_for_task(task) - except TaskError as task_error_exception: - task_error = task_error_exception.args[0] - self.module.fail_json( - msg="Failed to move host to cluster '%s' due to : %s" % - (self.cluster_name, to_native(task_error)) - ) - if reconnect or self.state == 'add_or_reconnect' or self.state == 'reconnect': - result = "Host reconnected and moved to cluster '%s'" % self.cluster_name - else: - result = "Host moved to cluster '%s'" % self.cluster_name - - self.module.exit_json(changed=changed, msg=str(result)) - - -def main(): - """Main""" - argument_spec = vmware_argument_spec() - argument_spec.update( - datacenter_name=dict(type='str', required=True, aliases=['datacenter']), - cluster_name=dict(type='str', aliases=['cluster']), - esxi_hostname=dict(type='str', required=True), - esxi_username=dict(type='str'), - esxi_password=dict(type='str', no_log=True), - esxi_ssl_thumbprint=dict(type='str', default='', aliases=['ssl_thumbprint']), - fetch_ssl_thumbprint=dict(type='bool', default=True), - state=dict(default='present', - choices=['present', 'absent', 'add_or_reconnect', 'reconnect'], - type='str'), - folder=dict(type='str', aliases=['folder_name']), - add_connected=dict(type='bool', default=True), - force_connection=dict(type='bool', default=True), - reconnect_disconnected=dict(type='bool', default=True), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - required_if=[ - ['state', 'present', ['esxi_username', 'esxi_password']], - ['state', 'add_or_reconnect', ['esxi_username', 'esxi_password']] - ], - required_one_of=[ - ['cluster_name', 'folder'], - ], - mutually_exclusive=[ - ['cluster_name', 'folder'], - ] - ) - - vmware_host = VMwareHost(module) - vmware_host.process_state() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_acceptance.py b/lib/ansible/modules/cloud/vmware/vmware_host_acceptance.py deleted file mode 100644 index a8233d8e28..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_acceptance.py +++ /dev/null @@ -1,195 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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_host_acceptance -short_description: Manage the host acceptance level of an ESXi host -description: -- This module can be used to manage the host acceptance level of an ESXi host. -- The host acceptance level controls the acceptance level of each VIB on a ESXi host. -version_added: '2.5' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of the cluster. - - Acceptance level of all ESXi host system in the given cluster will be managed. - - If C(esxi_hostname) is not given, this parameter is required. - type: str - esxi_hostname: - description: - - ESXi hostname. - - Acceptance level of this ESXi host system will be managed. - - If C(cluster_name) is not given, this parameter is required. - type: str - state: - description: - - Set or list acceptance level of the given ESXi host. - - 'If set to C(list), then will return current acceptance level of given host system/s.' - - If set to C(present), then will set given acceptance level. - choices: [ list, present ] - required: False - default: 'list' - type: str - acceptance_level: - description: - - Name of acceptance level. - - If set to C(partner), then accept only partner and VMware signed and certified VIBs. - - If set to C(vmware_certified), then accept only VIBs that are signed and certified by VMware. - - If set to C(vmware_accepted), then accept VIBs that have been accepted by VMware. - - If set to C(community), then accept all VIBs, even those that are not signed. - choices: [ community, partner, vmware_accepted, vmware_certified ] - required: False - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Set acceptance level to community for all ESXi Host in given Cluster - vmware_host_acceptance: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: cluster_name - acceptance_level: 'community' - state: present - delegate_to: localhost - register: cluster_acceptance_level - -- name: Set acceptance level to vmware_accepted for the given ESXi Host - vmware_host_acceptance: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - acceptance_level: 'vmware_accepted' - state: present - delegate_to: localhost - register: host_acceptance_level - -- name: Get acceptance level from the given ESXi Host - vmware_host_acceptance: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - state: list - delegate_to: localhost - register: host_acceptance_level -''' - -RETURN = r''' -facts: - description: - - dict with hostname as key and dict with acceptance level facts, error as value - returned: facts - type: dict - sample: { "facts": { "localhost.localdomain": { "error": "NA", "level": "vmware_certified" }}} -''' - -try: - from pyVmomi import vim -except ImportError: - pass -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi -from ansible.module_utils._text import to_native - - -class VMwareAccpetanceManager(PyVmomi): - def __init__(self, module): - super(VMwareAccpetanceManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - self.desired_state = self.params.get('state') - self.hosts_facts = {} - self.acceptance_level = self.params.get('acceptance_level') - - def gather_acceptance_facts(self): - for host in self.hosts: - self.hosts_facts[host.name] = dict(level='', error='NA') - host_image_config_mgr = host.configManager.imageConfigManager - if host_image_config_mgr: - try: - self.hosts_facts[host.name]['level'] = host_image_config_mgr.HostImageConfigGetAcceptance() - except vim.fault.HostConfigFault as e: - self.hosts_facts[host.name]['error'] = to_native(e.msg) - - def set_acceptance_level(self): - change = [] - for host in self.hosts: - host_changed = False - if self.hosts_facts[host.name]['level'] != self.acceptance_level: - host_image_config_mgr = host.configManager.imageConfigManager - if host_image_config_mgr: - try: - if self.module.check_mode: - self.hosts_facts[host.name]['level'] = self.acceptance_level - else: - host_image_config_mgr.UpdateHostImageAcceptanceLevel(newAcceptanceLevel=self.acceptance_level) - self.hosts_facts[host.name]['level'] = host_image_config_mgr.HostImageConfigGetAcceptance() - host_changed = True - except vim.fault.HostConfigFault as e: - self.hosts_facts[host.name]['error'] = to_native(e.msg) - - change.append(host_changed) - self.module.exit_json(changed=any(change), facts=self.hosts_facts) - - def check_acceptance_state(self): - self.gather_acceptance_facts() - if self.desired_state == 'list': - self.module.exit_json(changed=False, facts=self.hosts_facts) - self.set_acceptance_level() - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - acceptance_level=dict(type='str', - choices=['community', 'partner', 'vmware_accepted', 'vmware_certified'] - ), - state=dict(type='str', - choices=['list', 'present'], - default='list'), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - required_if=[ - ['state', 'present', ['acceptance_level']], - ], - supports_check_mode=True - ) - - vmware_host_accept_config = VMwareAccpetanceManager(module) - vmware_host_accept_config.check_acceptance_state() - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_active_directory.py b/lib/ansible/modules/cloud/vmware/vmware_host_active_directory.py deleted file mode 100644 index 3690eef398..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_active_directory.py +++ /dev/null @@ -1,369 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# -# 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_host_active_directory -short_description: Joins an ESXi host system to an Active Directory domain or leaves it -description: -- This module can be used to join or leave an ESXi host to or from an Active Directory domain. -version_added: 2.8 -author: -- Christian Kotte (@ckotte) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - ad_domain: - description: - - AD Domain to join. - type: str - aliases: [ domain, domain_name ] - ad_user: - description: - - Username for AD domain join. - type: str - ad_password: - description: - - Password for AD domain join. - type: str - ad_state: - description: - - Whether the ESXi host is joined to an AD domain or not. - type: str - choices: [ present, absent ] - default: 'absent' - aliases: [ state ] - esxi_hostname: - description: - - Name of the host system to work with. - - This parameter is required if C(cluster_name) is not specified. - type: str - cluster_name: - description: - - Name of the cluster from which all host systems will be used. - - This parameter is required if C(esxi_hostname) is not specified. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Join an AD domain - vmware_host_active_directory: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - ad_domain: example.local - ad_user: adjoin - ad_password: Password123$ - ad_state: present - validate_certs: no - delegate_to: localhost - -- name: Leave AD domain - vmware_host_active_directory: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - ad_state: absent - validate_certs: no - delegate_to: localhost -''' - -RETURN = r''' -results: - description: metadata about host system's AD domain join state - returned: always - type: dict - sample: { - "esxi01": { - "changed": true, - "domain": "example.local", - "membership_state": "ok", - "msg": "Host joined to AD domain", - "ad_state": "present", - "ad_state_current": "present", - "ad_state_previous": "absent", - }, - } -''' - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, TaskError, vmware_argument_spec, wait_for_task -from ansible.module_utils._text import to_native - - -class VmwareHostAdAuthentication(PyVmomi): - """Manage Active Directory Authentication for an ESXi host system""" - - def __init__(self, module): - super(VmwareHostAdAuthentication, self).__init__(module) - cluster_name = self.params.get('cluster_name') - esxi_host_name = self.params.get('esxi_hostname') - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - if not self.hosts: - self.module.fail_json(msg="Failed to find host system.") - - def ensure(self): - """Manage Active Directory Authentication for an ESXi host system""" - results = dict(changed=False, result=dict()) - desired_state = self.params.get('ad_state') - domain = self.params.get('ad_domain') - ad_user = self.params.get('ad_user') - ad_password = self.params.get('ad_password') - host_change_list = [] - for host in self.hosts: - changed = False - results['result'][host.name] = dict(msg='') - - active_directory_info = self.get_ad_info(host) - - results['result'][host.name]['ad_state'] = desired_state - results['result'][host.name]['ad_domain'] = domain - if desired_state == 'present': - # Don't do anything if already enabled and joined - if active_directory_info.enabled: - # Joined and no problems with the domain membership - if active_directory_info.domainMembershipStatus == 'ok': - results['result'][host.name]['changed'] = False - results['result'][host.name]['membership_state'] = active_directory_info.domainMembershipStatus - results['result'][host.name]['joined_domain'] = active_directory_info.joinedDomain - results['result'][host.name]['trusted_domains'] = active_directory_info.trustedDomain - results['result'][host.name]['msg'] = ( - "Host is joined to AD domain and there are no problems with the domain membership" - ) - # Joined, but problems with the domain membership - else: - changed = results['result'][host.name]['changed'] = True - results['result'][host.name]['membership_state'] = active_directory_info.domainMembershipStatus - results['result'][host.name]['joined_domain'] = active_directory_info.joinedDomain - results['result'][host.name]['trusted_domains'] = active_directory_info.trustedDomain - msg = "Host is joined to AD domain, but " - if active_directory_info.domainMembershipStatus == 'clientTrustBroken': - msg += "the client side of the trust relationship is broken" - elif active_directory_info.domainMembershipStatus == 'inconsistentTrust': - msg += "unexpected domain controller responded" - elif active_directory_info.domainMembershipStatus == 'noServers': - msg += "the host thinks it's part of a domain and " \ - "no domain controllers could be reached to confirm" - elif active_directory_info.domainMembershipStatus == 'serverTrustBroken': - msg += "the server side of the trust relationship is broken (or bad machine password)" - elif active_directory_info.domainMembershipStatus == 'otherProblem': - msg += "there are some problems with the domain membership" - elif active_directory_info.domainMembershipStatus == 'unknown': - msg += "the Active Directory integration provider does not support domain trust checks" - results['result'][host.name]['msg'] = msg - # Enable and join AD domain - else: - if self.module.check_mode: - changed = results['result'][host.name]['changed'] = True - results['result'][host.name]['ad_state_previous'] = "absent" - results['result'][host.name]['ad_state_current'] = "present" - results['result'][host.name]['msg'] = "Host would be joined to AD domain" - else: - ad_authentication = self.get_ad_auth_object(host) - try: - try: - task = ad_authentication.JoinDomain( - domainName=domain, userName=ad_user, password=ad_password - ) - wait_for_task(task) - except TaskError as task_err: - self.module.fail_json( - msg="Failed to join domain : %s" % to_native(task_err) - ) - changed = results['result'][host.name]['changed'] = True - results['result'][host.name]['ad_state_previous'] = "absent" - results['result'][host.name]['ad_state_current'] = "present" - results['result'][host.name]['msg'] = "Host joined to AD domain" - active_directory_info = self.get_ad_info(host) - results['result'][host.name]['membership_state'] = active_directory_info.domainMembershipStatus - except vim.fault.InvalidState as invalid_state: - self.module.fail_json( - msg="The host has already joined a domain : %s" % to_native(invalid_state.msg) - ) - except vim.fault.HostConfigFault as host_fault: - self.module.fail_json( - msg="The host configuration prevents the join operation from succeeding : %s" % - to_native(host_fault.msg) - ) - except vim.fault.InvalidLogin as invalid_login: - self.module.fail_json( - msg="Credentials aren't valid : %s" % to_native(invalid_login.msg) - ) - except vim.fault.TaskInProgress as task_in_progress: - self.module.fail_json( - msg="The ActiveDirectoryAuthentication object is busy : %s" % - to_native(task_in_progress.msg) - ) - except vim.fault.BlockedByFirewall as blocked_by_firewall: - self.module.fail_json( - msg="Ports needed by the join operation are blocked by the firewall : %s" % - to_native(blocked_by_firewall.msg) - ) - except vim.fault.DomainNotFound as not_found: - self.module.fail_json( - msg="The domain controller can't be reached : %s" % to_native(not_found.msg) - ) - except vim.fault.NoPermissionOnAD as no_permission: - self.module.fail_json( - msg="The specified user has no right to add hosts to the domain : %s" % - to_native(no_permission.msg) - ) - except vim.fault.InvalidHostName as invalid_host: - self.module.fail_json( - msg="The domain part of the host's FQDN doesn't match the domain being joined : %s" % - to_native(invalid_host.msg) - ) - except vim.fault.ClockSkew as clock_skew: - self.module.fail_json( - msg="The clocks of the host and the domain controller differ by more " - "than the allowed amount of time : %s" % to_native(clock_skew.msg) - ) - except vim.fault.ActiveDirectoryFault as ad_fault: - self.module.fail_json( - msg="An error occurred during AD join : %s" % - to_native(ad_fault.msg) - ) - elif desired_state == 'absent': - # Don't do anything not joined to any AD domain - if not active_directory_info.enabled: - results['result'][host.name]['changed'] = False - results['result'][host.name]['ad_state_current'] = "absent" - results['result'][host.name]['msg'] = "Host isn't joined to an AD domain" - # Disable and leave AD domain - else: - if self.module.check_mode: - changed = results['result'][host.name]['changed'] = True - results['result'][host.name]['ad_state_previous'] = "present" - results['result'][host.name]['ad_state_current'] = "absent" - results['result'][host.name]['msg'] = "Host would leave the AD domain '%s'" % \ - active_directory_info.joinedDomain - else: - ad_authentication = self.get_ad_auth_object(host) - try: - try: - task = ad_authentication.LeaveCurrentDomain(force=True) - wait_for_task(task) - except TaskError as task_err: - self.module.fail_json( - msg="Failed to join domain : %s" % to_native(task_err) - ) - changed = results['result'][host.name]['changed'] = True - results['result'][host.name]['ad_state_previous'] = "present" - results['result'][host.name]['ad_state_current'] = "absent" - results['result'][host.name]['msg'] = "Host left the AD domain '%s'" % \ - active_directory_info.joinedDomain - except vim.fault.InvalidState as invalid_state: - self.module.fail_json( - msg="The host is not in a domain or there are active permissions for " - "Active Directory users : %s" % to_native(invalid_state.msg) - ) - except vim.fault.AuthMinimumAdminPermission as admin_permission: - self.module.fail_json( - msg="This change would leave the system with no Administrator permission " - "on the root node : %s" % to_native(admin_permission.msg) - ) - except vim.fault.TaskInProgress as task_in_progress: - self.module.fail_json( - msg="The ActiveDirectoryAuthentication object is busy : %s" % - to_native(task_in_progress.msg) - ) - except vim.fault.NonADUserRequired as non_ad_user: - self.module.fail_json( - msg="Only non Active Directory users can initiate the leave domain operation : %s" % - to_native(non_ad_user.msg) - ) - except vim.fault.ActiveDirectoryFault as ad_fault: - self.module.fail_json( - msg="An error occurred during AD leave : %s" % - to_native(ad_fault.msg) - ) - - host_change_list.append(changed) - - if any(host_change_list): - results['changed'] = True - self.module.exit_json(**results) - - def get_ad_info(self, host_object): - """Get info about AD membership""" - active_directory_info = None - authentication_store_info = host_object.config.authenticationManagerInfo.authConfig - for authentication_info in authentication_store_info: - if isinstance(authentication_info, vim.host.ActiveDirectoryInfo): - active_directory_info = authentication_info - break - if not active_directory_info: - self.module.fail_json( - msg="Failed to get Active Directory info from authentication manager" - ) - return active_directory_info - - def get_ad_auth_object(self, host_object): - """Get AD authentication managed object""" - ad_authentication = None - authentication_store_info = host_object.configManager.authenticationManager.supportedStore - for store_info in authentication_store_info: - if isinstance(store_info, vim.host.ActiveDirectoryAuthentication): - ad_authentication = store_info - break - if not ad_authentication: - self.module.fail_json( - msg="Failed to get Active Directory authentication managed object from authentication manager" - ) - return ad_authentication - - -def main(): - """Main""" - argument_spec = vmware_argument_spec() - argument_spec.update( - ad_domain=dict(type='str', default='', aliases=['domain', 'domain_name']), - ad_user=dict(type='str', default=''), - ad_password=dict(type='str', default='', no_log=True), - ad_state=dict(default='absent', choices=['present', 'absent'], aliases=['state']), - esxi_hostname=dict(type='str', required=False), - cluster_name=dict(type='str', required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - required_if=[ - ['ad_state', 'present', ['ad_domain', 'ad_user', 'ad_password']], - ], - supports_check_mode=True - ) - - ad_auth = VmwareHostAdAuthentication(module) - ad_auth.ensure() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_auto_start.py b/lib/ansible/modules/cloud/vmware/vmware_host_auto_start.py deleted file mode 100644 index 38486e4c2b..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_auto_start.py +++ /dev/null @@ -1,387 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2019, sky-joker -# 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 = ''' -module: vmware_host_auto_start -short_description: Manage the auto power ON or OFF for vm on ESXi host -author: - - sky-joker (@sky-joker) -version_added: '2.10' -description: - - In this module, can set up automatic startup and shutdown of virtual machines according to host startup or shutdown. -requirements: - - python >= 2.7 - - PyVmomi -options: - esxi_hostname: - description: - - ESXi hostname where the VM to set auto power on or off exists. - type: str - required: True - name: - description: - - VM name to set auto power on or off. - - This is not necessary if change only system default VM settings for autoStart config. - type: str - uuid: - description: - - VM uuid to set auto power on or off, this is VMware's unique identifier. - - This is required if C(name) is not supplied. - - This is not necessary if change only system default VM settings for autoStart config. - type: str - use_instance_uuid: - description: - - Whether to use the VMware instance UUID rather than the BIOS UUID. - type: bool - default: no - moid: - description: - - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. - - This is required if C(name) or C(uuid) is not supplied. - type: str - system_defaults: - description: - - System defaults for auto-start or auto-stop config for virtual machine. - type: dict - suboptions: - enabled: - description: - - Enable automatically start or stop of virtual machines. - type: bool - default: False - start_delay: - description: - - Default auto start delay in seconds. - type: int - default: 120 - stop_action: - description: - - Default stop action executed on the virtual machine when the system stops. - type: str - choices: ['none', 'guestShutdown', 'powerOff', 'suspend'] - default: powerOff - stop_delay: - description: - - Default auto stop delay in seconds. - type: int - default: 120 - wait_for_heartbeat: - description: - - Continue power on processing when VMware Tools started. - - If this parameter is enabled to powers on the next virtual machine without waiting for the delay to pass. - - However, the virtual machine must have VMware Tools installed. - type: bool - default: False - power_info: - description: - - Startup or shutdown settings of virtual machine. - - This setting will override the system defaults. - type: dict - default: - start_action: none - start_delay: -1 - start_order: -1 - stop_action: systemDefault - stop_delay: -1 - wait_for_heartbeat: systemDefault - suboptions: - start_action: - description: - - Whether to start the virtual machine when the host startup. - type: str - choices: ['none', 'powerOn'] - default: none - start_delay: - description: - - Auto start delay in seconds of virtual machine. - type: int - default: -1 - start_order: - description: - - The autostart priority of virtual machine. - - Virtual machines with a lower number are powered on first. - - On host shutdown, the virtual machines are shut down in reverse order, meaning those with a higher number are powered off first. - type: int - default: -1 - stop_action: - description: - - Stop action executed on the virtual machine when the system stops of virtual machine. - choices: ['none', 'systemDefault', 'powerOff', 'suspend'] - type: str - default: systemDefault - stop_delay: - description: - - Auto stop delay in seconds of virtual machine. - type: int - default: -1 - wait_for_heartbeat: - description: - - Continue power on processing when VMware Tools started. - type: str - choices: ['no', 'yes', 'systemDefault'] - default: systemDefault -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' ---- -- name: Update for system defaults config. - vmware_host_auto_start: - hostname: "{{ hostname }}" - username: "{{ username }}" - password: "{{ password }}" - validate_certs: no - esxi_hostname: "{{ esxi_hostname }}" - system_defaults: - enabled: yes - start_delay: 100 - stop_action: guestShutdown - -- name: Update for powerInfo config of virtual machine. - vmware_host_auto_start: - hostname: "{{ hostname }}" - username: "{{ username }}" - password: "{{ password }}" - validate_certs: no - esxi_hostname: "{{ esxi_hostname }}" - name: "{{ vm_name }}" - power_info: - start_action: powerOn - start_delay: 10 - start_order: 1 - stop_action: powerOff - wait_for_heartbeat: yes -''' - -RETURN = ''' -system_defaults_config: - description: Parameter return when system defaults config is changed. - returned: changed - type: dict - sample: >- - { - "enabled": true, - "start_delay": 120, - "stop_action": "powerOff", - "stop_delay": 120, - "wait_for_heartbeat": false - } -power_info_config: - description: Parameter return when virtual machine power info config is changed. - returned: changed - type: dict - sample: >- - { - "start_action": "powerOn", - "start_delay": -1, - "start_order": -1, - "stop_action": "systemDefault", - "stop_delay": -1, - "wait_for_heartbeat": "systemDefault" - } -''' - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -try: - from collections import OrderedDict -except ImportError: - try: - from ordereddict import OrderedDict - except ImportError: - pass - -from ansible.module_utils._text import to_native -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec -from ansible.module_utils.basic import AnsibleModule - - -class VMwareHostAutoStartManager(PyVmomi): - def __init__(self, module): - super(VMwareHostAutoStartManager, self).__init__(module) - self.esxi_hostname = self.params['esxi_hostname'] - self.name = self.params['name'] - self.uuid = self.params['uuid'] - self.moid = self.params['moid'] - self.system_defaults = self.params['system_defaults'] - self.power_info = self.params['power_info'] - - def generate_system_defaults_config(self): - system_defaults_config = vim.host.AutoStartManager.SystemDefaults() - system_defaults_config.enabled = self.system_defaults['enabled'] - system_defaults_config.startDelay = self.system_defaults['start_delay'] - system_defaults_config.stopAction = self.system_defaults['stop_action'] - system_defaults_config.stopDelay = self.system_defaults['stop_delay'] - system_defaults_config.waitForHeartbeat = self.system_defaults['wait_for_heartbeat'] - - return system_defaults_config - - def generate_power_info_config(self): - power_info_config = vim.host.AutoStartManager.AutoPowerInfo() - power_info_config.key = self.vm_obj - power_info_config.startAction = self.power_info['start_action'] - power_info_config.startDelay = self.power_info['start_delay'] - power_info_config.startOrder = self.power_info['start_order'] - power_info_config.stopAction = self.power_info['stop_action'] - power_info_config.stopDelay = self.power_info['stop_delay'] - power_info_config.waitForHeartbeat = self.power_info['wait_for_heartbeat'] - - return power_info_config - - def execute(self): - result = dict(changed=False, diff={'before': {}, 'after': {}}) - - host_obj = self.find_hostsystem_by_name(self.esxi_hostname) - if not host_obj: - self.module.fail_json(msg="Cannot find the specified ESXi host: %s" % self.esxi_hostname) - - self.vm_obj = None - if self.name or self.uuid or self.moid: - self.vm_obj = self.get_vm() - if not self.vm_obj: - self.module.fail_json(msg="Cannot find the specified VM: %s" % (self.name or self.uuid or self.moid)) - elif self.esxi_hostname != self.vm_obj.runtime.host.name: - self.module.fail_json(msg="%s exists on another host: %s" % (self.name or self.uuid or self.moid, self.vm_obj.runtime.host.name)) - - # Check the existing autoStart setting difference. - system_defaults_config_difference = False - existing_system_defaults = self.to_json(host_obj.config.autoStart.defaults) - system_defaults_for_compare = dict( - enabled=existing_system_defaults['enabled'], - start_delay=existing_system_defaults['startDelay'], - stop_action=existing_system_defaults['stopAction'], - stop_delay=existing_system_defaults['stopDelay'], - wait_for_heartbeat=existing_system_defaults['waitForHeartbeat'] - ) - if self.system_defaults: - if 'guestshutdown' == system_defaults_for_compare['stop_action']: - system_defaults_for_compare['stop_action'] = 'guestShutdown' - - if 'poweroff' == system_defaults_for_compare['stop_action']: - system_defaults_for_compare['stop_action'] = 'powerOff' - - if system_defaults_for_compare != self.system_defaults: - result['diff']['before']['system_defaults'] = OrderedDict(sorted(system_defaults_for_compare.items())) - result['diff']['after']['system_defaults'] = OrderedDict(sorted(self.system_defaults.items())) - system_defaults_config_difference = True - - # Check the existing autoStart powerInfo setting difference for VM. - vm_power_info_config_difference = False - existing_vm_power_info = {} - if system_defaults_for_compare['enabled'] and self.vm_obj: - for vm_power_info in host_obj.config.autoStart.powerInfo: - if vm_power_info.key == self.vm_obj: - existing_vm_power_info = self.to_json(vm_power_info) - break - - if existing_vm_power_info: - vm_power_info_for_compare = dict( - start_action=existing_vm_power_info['startAction'], - start_delay=existing_vm_power_info['startDelay'], - start_order=existing_vm_power_info['startOrder'], - stop_action=existing_vm_power_info['stopAction'], - stop_delay=existing_vm_power_info['stopDelay'], - wait_for_heartbeat=existing_vm_power_info['waitForHeartbeat'] - ) - else: - vm_power_info_for_compare = dict( - start_action='none', - start_delay=-1, - start_order=-1, - stop_action='systemDefault', - stop_delay=-1, - wait_for_heartbeat='systemDefault' - ) - - if vm_power_info_for_compare != self.power_info: - result['diff']['before']['power_info'] = OrderedDict(sorted(vm_power_info_for_compare.items())) - result['diff']['after']['power_info'] = OrderedDict(sorted(self.power_info.items())) - vm_power_info_config_difference = True - - auto_start_manager_config = vim.host.AutoStartManager.Config() - auto_start_manager_config.powerInfo = [] - if system_defaults_config_difference or vm_power_info_config_difference: - if system_defaults_config_difference: - auto_start_manager_config.defaults = self.generate_system_defaults_config() - result['system_defaults_config'] = self.system_defaults - - if vm_power_info_config_difference: - auto_start_manager_config.powerInfo = [self.generate_power_info_config()] - result['power_info_config'] = self.power_info - - if self.module.check_mode: - result['changed'] = True - self.module.exit_json(**result) - - try: - host_obj.configManager.autoStartManager.ReconfigureAutostart(spec=auto_start_manager_config) - result['changed'] = True - self.module.exit_json(**result) - except Exception as e: - self.module.fail_json(msg=to_native(e)) - - self.module.exit_json(**result) - else: - self.module.exit_json(**result) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update(esxi_hostname=dict(type='str', required=True), - name=dict(type='str'), - uuid=dict(type='str'), - use_instance_uuid=dict(type='bool', default=False), - moid=dict(type='str'), - system_defaults=dict(type='dict', - options=dict( - enabled=dict(type='bool', default=False), - start_delay=dict(type='int', default=120), - stop_action=dict(type='str', choices=['none', 'guestShutdown', - 'powerOff', 'suspend'], - default='powerOff'), - stop_delay=dict(type='int', default=120), - wait_for_heartbeat=dict(type='bool', default=False)), - ), - power_info=dict(type='dict', - options=dict( - start_action=dict(type='str', choices=['none', 'powerOn'], default='none'), - start_delay=dict(type='int', default=-1), - start_order=dict(type='int', default=-1), - stop_action=dict(type='str', choices=['none', 'systemDefault', 'powerOff', - 'suspend'], default='systemDefault'), - stop_delay=dict(type='int', default=-1), - wait_for_heartbeat=dict(type='str', choices=['no', 'yes', 'systemDefault'], - default='systemDefault')), - default=dict( - start_action='none', - start_delay=-1, - start_order=-1, - stop_action='systemDefault', - stop_delay=-1, - wait_for_heartbeat='systemDefault' - )) - ) - - module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) - - vmware_host_auto_start = VMwareHostAutoStartManager(module) - vmware_host_auto_start.execute() - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_capability_info.py b/lib/ansible/modules/cloud/vmware/vmware_host_capability_info.py deleted file mode 100644 index 1d8059dd6f..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_capability_info.py +++ /dev/null @@ -1,222 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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_host_capability_info -short_description: Gathers info about an ESXi host's capability information -description: -- This module can be used to gather information about an ESXi host's capability information when ESXi hostname or Cluster name is given. -version_added: '2.9' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of the cluster from all host systems to be used for information gathering. - - If C(esxi_hostname) is not given, this parameter is required. - type: str - esxi_hostname: - description: - - ESXi hostname to gather information from. - - If C(cluster_name) is not given, this parameter is required. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather capability info about all ESXi Host in given Cluster - vmware_host_capability_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: cluster_name - delegate_to: localhost - register: all_cluster_hosts_info - -- name: Gather capability info about ESXi Host - vmware_host_capability_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - delegate_to: localhost - register: hosts_info -''' - -RETURN = r''' -hosts_capability_info: - description: metadata about host's capability info - returned: always - type: dict - sample: { - "esxi_hostname_0001": { - "accel3dSupported": false, - "backgroundSnapshotsSupported": false, - "checkpointFtCompatibilityIssues": [], - "checkpointFtSupported": false, - "cloneFromSnapshotSupported": true, - "cpuHwMmuSupported": true, - } - } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class CapabilityInfoManager(PyVmomi): - def __init__(self, module): - super(CapabilityInfoManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - - def gather_host_capability_info(self): - hosts_capability_info = dict() - for host in self.hosts: - hc = host.capability - hosts_capability_info[host.name] = dict( - recursiveResourcePoolsSupported=hc.recursiveResourcePoolsSupported, - cpuMemoryResourceConfigurationSupported=hc.cpuMemoryResourceConfigurationSupported, - rebootSupported=hc.rebootSupported, - shutdownSupported=hc.shutdownSupported, - vmotionSupported=hc.vmotionSupported, - standbySupported=hc.standbySupported, - ipmiSupported=hc.ipmiSupported, - maxSupportedVMs=hc.maxSupportedVMs, - maxRunningVMs=hc.maxRunningVMs, - maxSupportedVcpus=hc.maxSupportedVcpus, - maxRegisteredVMs=hc.maxRegisteredVMs, - datastorePrincipalSupported=hc.datastorePrincipalSupported, - sanSupported=hc.sanSupported, - nfsSupported=hc.nfsSupported, - iscsiSupported=hc.iscsiSupported, - vlanTaggingSupported=hc.vlanTaggingSupported, - nicTeamingSupported=hc.nicTeamingSupported, - highGuestMemSupported=hc.highGuestMemSupported, - maintenanceModeSupported=hc.maintenanceModeSupported, - suspendedRelocateSupported=hc.suspendedRelocateSupported, - restrictedSnapshotRelocateSupported=hc.restrictedSnapshotRelocateSupported, - perVmSwapFiles=hc.perVmSwapFiles, - localSwapDatastoreSupported=hc.localSwapDatastoreSupported, - unsharedSwapVMotionSupported=hc.unsharedSwapVMotionSupported, - backgroundSnapshotsSupported=hc.backgroundSnapshotsSupported, - preAssignedPCIUnitNumbersSupported=hc.preAssignedPCIUnitNumbersSupported, - screenshotSupported=hc.screenshotSupported, - scaledScreenshotSupported=hc.scaledScreenshotSupported, - storageVMotionSupported=hc.storageVMotionSupported, - vmotionWithStorageVMotionSupported=hc.vmotionWithStorageVMotionSupported, - vmotionAcrossNetworkSupported=hc.vmotionAcrossNetworkSupported, - maxNumDisksSVMotion=hc.maxNumDisksSVMotion, - hbrNicSelectionSupported=hc.hbrNicSelectionSupported, - vrNfcNicSelectionSupported=hc.vrNfcNicSelectionSupported, - recordReplaySupported=hc.recordReplaySupported, - ftSupported=hc.ftSupported, - replayUnsupportedReason=hc.replayUnsupportedReason, - checkpointFtSupported=hc.checkpointFtSupported, - smpFtSupported=hc.smpFtSupported, - maxVcpusPerFtVm=hc.maxVcpusPerFtVm, - loginBySSLThumbprintSupported=hc.loginBySSLThumbprintSupported, - cloneFromSnapshotSupported=hc.cloneFromSnapshotSupported, - deltaDiskBackingsSupported=hc.deltaDiskBackingsSupported, - perVMNetworkTrafficShapingSupported=hc.perVMNetworkTrafficShapingSupported, - tpmSupported=hc.tpmSupported, - virtualExecUsageSupported=hc.virtualExecUsageSupported, - storageIORMSupported=hc.storageIORMSupported, - vmDirectPathGen2Supported=hc.vmDirectPathGen2Supported, - vmDirectPathGen2UnsupportedReasonExtended=hc.vmDirectPathGen2UnsupportedReasonExtended, - vStorageCapable=hc.vStorageCapable, - snapshotRelayoutSupported=hc.snapshotRelayoutSupported, - firewallIpRulesSupported=hc.firewallIpRulesSupported, - servicePackageInfoSupported=hc.servicePackageInfoSupported, - maxHostRunningVms=hc.maxHostRunningVms, - maxHostSupportedVcpus=hc.maxHostSupportedVcpus, - vmfsDatastoreMountCapable=hc.vmfsDatastoreMountCapable, - eightPlusHostVmfsSharedAccessSupported=hc.eightPlusHostVmfsSharedAccessSupported, - nestedHVSupported=hc.nestedHVSupported, - vPMCSupported=hc.vPMCSupported, - interVMCommunicationThroughVMCISupported=hc.interVMCommunicationThroughVMCISupported, - scheduledHardwareUpgradeSupported=hc.scheduledHardwareUpgradeSupported, - featureCapabilitiesSupported=hc.featureCapabilitiesSupported, - latencySensitivitySupported=hc.latencySensitivitySupported, - storagePolicySupported=hc.storagePolicySupported, - accel3dSupported=hc.accel3dSupported, - reliableMemoryAware=hc.reliableMemoryAware, - multipleNetworkStackInstanceSupported=hc.multipleNetworkStackInstanceSupported, - messageBusProxySupported=hc.messageBusProxySupported, - vsanSupported=hc.vsanSupported, - vFlashSupported=hc.vFlashSupported, - hostAccessManagerSupported=hc.hostAccessManagerSupported, - provisioningNicSelectionSupported=hc.provisioningNicSelectionSupported, - nfs41Supported=hc.nfs41Supported, - nfs41Krb5iSupported=hc.nfs41Krb5iSupported, - turnDiskLocatorLedSupported=hc.turnDiskLocatorLedSupported, - virtualVolumeDatastoreSupported=hc.virtualVolumeDatastoreSupported, - markAsSsdSupported=hc.markAsSsdSupported, - markAsLocalSupported=hc.markAsLocalSupported, - smartCardAuthenticationSupported=hc.smartCardAuthenticationSupported, - cryptoSupported=hc.cryptoSupported, - oneKVolumeAPIsSupported=hc.oneKVolumeAPIsSupported, - gatewayOnNicSupported=hc.gatewayOnNicSupported, - upitSupported=hc.upitSupported, - cpuHwMmuSupported=hc.cpuHwMmuSupported, - encryptedVMotionSupported=hc.encryptedVMotionSupported, - encryptionChangeOnAddRemoveSupported=hc.encryptionChangeOnAddRemoveSupported, - encryptionHotOperationSupported=hc.encryptionHotOperationSupported, - encryptionWithSnapshotsSupported=hc.encryptionWithSnapshotsSupported, - encryptionFaultToleranceSupported=hc.encryptionFaultToleranceSupported, - encryptionMemorySaveSupported=hc.encryptionMemorySaveSupported, - encryptionRDMSupported=hc.encryptionRDMSupported, - encryptionVFlashSupported=hc.encryptionVFlashSupported, - encryptionCBRCSupported=hc.encryptionCBRCSupported, - encryptionHBRSupported=hc.encryptionHBRSupported, - supportedVmfsMajorVersion=[version for version in hc.supportedVmfsMajorVersion], - vmDirectPathGen2UnsupportedReason=[reason for reason in hc.vmDirectPathGen2UnsupportedReason], - ftCompatibilityIssues=[issue for issue in hc.ftCompatibilityIssues], - checkpointFtCompatibilityIssues=[issue for issue in hc.checkpointFtCompatibilityIssues], - smpFtCompatibilityIssues=[issue for issue in hc.smpFtCompatibilityIssues], - replayCompatibilityIssues=[issue for issue in hc.replayCompatibilityIssues], - ) - return hosts_capability_info - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True, - ) - - host_capability_manager = CapabilityInfoManager(module) - module.exit_json(changed=False, - hosts_capability_info=host_capability_manager.gather_host_capability_info()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_config_info.py b/lib/ansible/modules/cloud/vmware/vmware_host_config_info.py deleted file mode 100644 index 43209f208d..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_config_info.py +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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_host_config_info -short_description: Gathers info about an ESXi host's advance configuration information -description: -- This module can be used to gather information about an ESXi host's advance configuration information when ESXi hostname or Cluster name is given. -version_added: '2.9' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of the cluster from which the ESXi host belong to. - - If C(esxi_hostname) is not given, this parameter is required. - type: str - esxi_hostname: - description: - - ESXi hostname to gather information from. - - If C(cluster_name) is not given, this parameter is required. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather info about all ESXi Host in given Cluster - vmware_host_config_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: cluster_name - delegate_to: localhost - -- name: Gather info about ESXi Host - vmware_host_config_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - delegate_to: localhost -''' - -RETURN = r''' -hosts_info: - description: - - dict with hostname as key and dict with host config information - returned: always - type: dict - sample: { - "10.76.33.226": { - "Annotations.WelcomeMessage": "", - "BufferCache.FlushInterval": 30000, - "BufferCache.HardMaxDirty": 95, - "BufferCache.PerFileHardMaxDirty": 50, - "BufferCache.SoftMaxDirty": 15, - } - } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class VmwareConfigInfoManager(PyVmomi): - def __init__(self, module): - super(VmwareConfigInfoManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - - def gather_host_info(self): - hosts_info = {} - for host in self.hosts: - host_info = {} - for option in host.configManager.advancedOption.QueryOptions(): - host_info[option.key] = option.value - hosts_info[host.name] = host_info - return hosts_info - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True - ) - - vmware_host_config = VmwareConfigInfoManager(module) - module.exit_json(changed=False, hosts_info=vmware_host_config.gather_host_info()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_config_manager.py b/lib/ansible/modules/cloud/vmware/vmware_host_config_manager.py deleted file mode 100644 index 651caa34e4..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_config_manager.py +++ /dev/null @@ -1,198 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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_host_config_manager -short_description: Manage advanced system settings of an ESXi host -description: -- This module can be used to manage advanced system settings of an ESXi host when ESXi hostname or Cluster name is given. -version_added: '2.5' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of the cluster. - - Settings are applied to every ESXi host in given cluster. - - If C(esxi_hostname) is not given, this parameter is required. - type: str - esxi_hostname: - description: - - ESXi hostname. - - Settings are applied to this ESXi host. - - If C(cluster_name) is not given, this parameter is required. - type: str - options: - description: - - A dictionary of advanced system settings. - - Invalid options will cause module to error. - - Note that the list of advanced options (with description and values) can be found by running `vim-cmd hostsvc/advopt/options`. - default: {} - type: dict -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Manage Log level setting for all ESXi hosts in given Cluster - vmware_host_config_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: cluster_name - options: - 'Config.HostAgent.log.level': 'info' - delegate_to: localhost - -- name: Manage Log level setting for an ESXi host - vmware_host_config_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - options: - 'Config.HostAgent.log.level': 'verbose' - delegate_to: localhost - -- name: Manage multiple settings for an ESXi host - vmware_host_config_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - options: - 'Config.HostAgent.log.level': 'verbose' - 'Annotations.WelcomeMessage': 'Hello World' - 'Config.HostAgent.plugins.solo.enableMob': false - delegate_to: localhost -''' - -RETURN = r'''# -''' - -try: - from pyVmomi import vim, vmodl, VmomiSupport -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi, is_boolean, is_integer, is_truthy -from ansible.module_utils._text import to_native -from ansible.module_utils.six import integer_types, string_types - - -class VmwareConfigManager(PyVmomi): - def __init__(self, module): - super(VmwareConfigManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.options = self.params.get('options', dict()) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - - def set_host_configuration_facts(self): - changed_list = [] - message = '' - for host in self.hosts: - option_manager = host.configManager.advancedOption - host_facts = {} - for s_option in option_manager.supportedOption: - host_facts[s_option.key] = dict(option_type=s_option.optionType, value=None) - - for option in option_manager.QueryOptions(): - if option.key in host_facts: - host_facts[option.key].update( - value=option.value, - ) - - change_option_list = [] - for option_key, option_value in self.options.items(): - if option_key in host_facts: - # We handle all supported types here so we can give meaningful errors. - option_type = host_facts[option_key]['option_type'] - if is_boolean(option_value) and isinstance(option_type, vim.option.BoolOption): - option_value = is_truthy(option_value) - elif (isinstance(option_value, integer_types) or is_integer(option_value))\ - and isinstance(option_type, vim.option.IntOption): - option_value = VmomiSupport.vmodlTypes['int'](option_value) - elif (isinstance(option_value, integer_types) or is_integer(option_value, 'long'))\ - and isinstance(option_type, vim.option.LongOption): - option_value = VmomiSupport.vmodlTypes['long'](option_value) - elif isinstance(option_value, float) and isinstance(option_type, vim.option.FloatOption): - pass - elif isinstance(option_value, string_types) and isinstance(option_type, (vim.option.StringOption, vim.option.ChoiceOption)): - pass - else: - self.module.fail_json(msg="Provided value is of type %s." - " Option %s expects: %s" % (type(option_value), option_key, type(option_type))) - - if option_value != host_facts[option_key]['value']: - change_option_list.append(vim.option.OptionValue(key=option_key, value=option_value)) - changed_list.append(option_key) - else: # Don't silently drop unknown options. This prevents typos from falling through the cracks. - self.module.fail_json(msg="Unsupported option %s" % option_key) - if change_option_list: - if self.module.check_mode: - changed_suffix = ' would be changed.' - else: - changed_suffix = ' changed.' - if len(changed_list) > 2: - message = ', '.join(changed_list[:-1]) + ', and ' + str(changed_list[-1]) - elif len(changed_list) == 2: - message = ' and '.join(changed_list) - elif len(changed_list) == 1: - message = changed_list[0] - message += changed_suffix - if self.module.check_mode is False: - try: - option_manager.UpdateOptions(changedValue=change_option_list) - except (vmodl.fault.SystemError, vmodl.fault.InvalidArgument) as e: - self.module.fail_json(msg="Failed to update option/s as one or more OptionValue " - "contains an invalid value: %s" % to_native(e.msg)) - except vim.fault.InvalidName as e: - self.module.fail_json(msg="Failed to update option/s as one or more OptionValue " - "objects refers to a non-existent option : %s" % to_native(e.msg)) - else: - message = 'All settings are already configured.' - - self.module.exit_json(changed=bool(changed_list), msg=message) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - options=dict(type='dict', default=dict(), required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ] - ) - - vmware_host_config = VmwareConfigManager(module) - vmware_host_config.set_host_configuration_facts() - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_datastore.py b/lib/ansible/modules/cloud/vmware/vmware_host_datastore.py deleted file mode 100644 index d5739243b0..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_datastore.py +++ /dev/null @@ -1,351 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Ansible Project -# 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_host_datastore -short_description: Manage a datastore on ESXi host -description: -- This module can be used to mount/umount datastore on ESXi host. -- This module only supports NFS (NFS v3 or NFS v4.1) and VMFS datastores. -- For VMFS datastore, available device must already be connected on ESXi host. -- All parameters and VMware object names are case sensitive. -version_added: '2.5' -author: -- Ludovic Rivallain (@lrivallain) <ludovic.rivallain@gmail.com> -- Christian Kotte (@ckotte) <christian.kotte@gmx.de> -notes: -- Tested on vSphere 6.0, 6.5 and ESXi 6.7 -- NFS v4.1 tested on vSphere 6.5 -- Kerberos authentication with NFS v4.1 isn't implemented -requirements: -- python >= 2.6 -- PyVmomi -options: - datacenter_name: - description: - - Name of the datacenter to add the datastore. - - The datacenter isn't used by the API to create a datastore. - - Will be removed in 2.11. - required: false - type: str - datastore_name: - description: - - Name of the datastore to add/remove. - required: true - type: str - datastore_type: - description: - - Type of the datastore to configure (nfs/nfs41/vmfs). - required: true - choices: [ 'nfs', 'nfs41', 'vmfs' ] - type: str - nfs_server: - description: - - NFS host serving nfs datastore. - - Required if datastore type is set to C(nfs)/C(nfs41) and state is set to C(present), else unused. - - Two or more servers can be defined if datastore type is set to C(nfs41) - type: str - nfs_path: - description: - - Resource path on NFS host. - - Required if datastore type is set to C(nfs)/C(nfs41) and state is set to C(present), else unused. - type: str - nfs_ro: - description: - - ReadOnly or ReadWrite mount. - - Unused if datastore type is not set to C(nfs)/C(nfs41) and state is not set to C(present). - default: False - type: bool - vmfs_device_name: - description: - - Name of the device to be used as VMFS datastore. - - Required for VMFS datastore type and state is set to C(present), else unused. - type: str - vmfs_version: - description: - - VMFS version to use for datastore creation. - - Unused if datastore type is not set to C(vmfs) and state is not set to C(present). - type: int - esxi_hostname: - description: - - ESXi hostname to manage the datastore. - - Required when used with a vcenter - type: str - required: false - state: - description: - - "present: Mount datastore on host if datastore is absent else do nothing." - - "absent: Umount datastore if datastore is present else do nothing." - default: present - choices: [ present, absent ] - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Mount VMFS datastores to ESXi - vmware_host_datastore: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datastore_name: '{{ item.name }}' - datastore_type: '{{ item.type }}' - vmfs_device_name: 'naa.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' - vmfs_version: 6 - esxi_hostname: '{{ inventory_hostname }}' - state: present - delegate_to: localhost - -- name: Mount NFS datastores to ESXi - vmware_host_datastore: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datastore_name: '{{ item.name }}' - datastore_type: '{{ item.type }}' - nfs_server: '{{ item.server }}' - nfs_path: '{{ item.path }}' - nfs_ro: no - esxi_hostname: '{{ inventory_hostname }}' - state: present - delegate_to: localhost - loop: - - { 'name': 'NasDS_vol01', 'server': 'nas01', 'path': '/mnt/vol01', 'type': 'nfs'} - - { 'name': 'NasDS_vol02', 'server': 'nas01', 'path': '/mnt/vol02', 'type': 'nfs'} - -- name: Mount NFS v4.1 datastores to ESXi - vmware_host_datastore: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datastore_name: '{{ item.name }}' - datastore_type: '{{ item.type }}' - nfs_server: '{{ item.server }}' - nfs_path: '{{ item.path }}' - nfs_ro: no - esxi_hostname: '{{ inventory_hostname }}' - state: present - delegate_to: localhost - loop: - - { 'name': 'NasDS_vol03', 'server': 'nas01,nas02', 'path': '/mnt/vol01', 'type': 'nfs41'} - - { 'name': 'NasDS_vol04', 'server': 'nas01,nas02', 'path': '/mnt/vol02', 'type': 'nfs41'} - -- name: Remove/Umount Datastores from a ESXi - vmware_host_datastore: - hostname: '{{ esxi_hostname }}' - username: '{{ esxi_username }}' - password: '{{ esxi_password }}' - datastore_name: NasDS_vol01 - state: absent - delegate_to: localhost -''' - -RETURN = r''' -''' - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi, find_datastore_by_name, find_obj -from ansible.module_utils._text import to_native - - -class VMwareHostDatastore(PyVmomi): - def __init__(self, module): - super(VMwareHostDatastore, self).__init__(module) - - # NOTE: The below parameter is deprecated starting from Ansible v2.11 - self.datacenter_name = module.params['datacenter_name'] - self.datastore_name = module.params['datastore_name'] - self.datastore_type = module.params['datastore_type'] - self.nfs_server = module.params['nfs_server'] - self.nfs_path = module.params['nfs_path'] - self.nfs_ro = module.params['nfs_ro'] - self.vmfs_device_name = module.params['vmfs_device_name'] - self.vmfs_version = module.params['vmfs_version'] - self.esxi_hostname = module.params['esxi_hostname'] - self.state = module.params['state'] - - if self.is_vcenter(): - if not self.esxi_hostname: - self.module.fail_json(msg="esxi_hostname is mandatory with a vcenter") - self.esxi = self.find_hostsystem_by_name(self.esxi_hostname) - if self.esxi is None: - self.module.fail_json(msg="Failed to find ESXi hostname %s" % self.esxi_hostname) - else: - self.esxi = find_obj(self.content, [vim.HostSystem], None) - - def process_state(self): - ds_states = { - 'absent': { - 'present': self.umount_datastore_host, - 'absent': self.state_exit_unchanged, - }, - 'present': { - 'present': self.state_exit_unchanged, - 'absent': self.mount_datastore_host, - } - } - try: - ds_states[self.state][self.check_datastore_host_state()]() - except (vmodl.RuntimeFault, vmodl.MethodFault) as vmodl_fault: - self.module.fail_json(msg=to_native(vmodl_fault.msg)) - except Exception as e: - self.module.fail_json(msg=to_native(e)) - - def state_exit_unchanged(self): - self.module.exit_json(changed=False) - - def check_datastore_host_state(self): - storage_system = self.esxi.configManager.storageSystem - host_file_sys_vol_mount_info = storage_system.fileSystemVolumeInfo.mountInfo - for host_mount_info in host_file_sys_vol_mount_info: - if host_mount_info.volume.name == self.datastore_name: - return 'present' - return 'absent' - - def get_used_disks_names(self): - used_disks = [] - storage_system = self.esxi.configManager.storageSystem - for each_vol_mount_info in storage_system.fileSystemVolumeInfo.mountInfo: - if hasattr(each_vol_mount_info.volume, 'extent'): - for each_partition in each_vol_mount_info.volume.extent: - used_disks.append(each_partition.diskName) - return used_disks - - def umount_datastore_host(self): - ds = find_datastore_by_name(self.content, self.datastore_name) - if not ds: - self.module.fail_json(msg="No datastore found with name %s" % self.datastore_name) - if self.module.check_mode is False: - error_message_umount = "Cannot umount datastore %s from host %s" % (self.datastore_name, self.esxi.name) - try: - self.esxi.configManager.datastoreSystem.RemoveDatastore(ds) - except (vim.fault.NotFound, vim.fault.HostConfigFault, vim.fault.ResourceInUse) as fault: - self.module.fail_json(msg="%s: %s" % (error_message_umount, to_native(fault.msg))) - except Exception as e: - self.module.fail_json(msg="%s: %s" % (error_message_umount, to_native(e))) - self.module.exit_json(changed=True, result="Datastore %s on host %s" % (self.datastore_name, self.esxi.name)) - - def mount_datastore_host(self): - if self.datastore_type == 'nfs' or self.datastore_type == 'nfs41': - self.mount_nfs_datastore_host() - if self.datastore_type == 'vmfs': - self.mount_vmfs_datastore_host() - - def mount_nfs_datastore_host(self): - if self.module.check_mode is False: - mnt_specs = vim.host.NasVolume.Specification() - # NFS v3 - if self.datastore_type == 'nfs': - mnt_specs.type = "NFS" - mnt_specs.remoteHost = self.nfs_server - # NFS v4.1 - if self.datastore_type == 'nfs41': - mnt_specs.type = "NFS41" - # remoteHost needs to be set to a non-empty string, but the value is not used - mnt_specs.remoteHost = "something" - mnt_specs.remoteHostNames = [self.nfs_server] - mnt_specs.remotePath = self.nfs_path - mnt_specs.localPath = self.datastore_name - if self.nfs_ro: - mnt_specs.accessMode = "readOnly" - else: - mnt_specs.accessMode = "readWrite" - error_message_mount = "Cannot mount datastore %s on host %s" % (self.datastore_name, self.esxi.name) - try: - ds = self.esxi.configManager.datastoreSystem.CreateNasDatastore(mnt_specs) - if not ds: - self.module.fail_json(msg=error_message_mount) - except (vim.fault.NotFound, vim.fault.DuplicateName, - vim.fault.AlreadyExists, vim.fault.HostConfigFault, - vmodl.fault.InvalidArgument, vim.fault.NoVirtualNic, - vim.fault.NoGateway) as fault: - self.module.fail_json(msg="%s: %s" % (error_message_mount, to_native(fault.msg))) - except Exception as e: - self.module.fail_json(msg="%s : %s" % (error_message_mount, to_native(e))) - self.module.exit_json(changed=True, result="Datastore %s on host %s" % (self.datastore_name, self.esxi.name)) - - def mount_vmfs_datastore_host(self): - if self.module.check_mode is False: - ds_path = "/vmfs/devices/disks/" + str(self.vmfs_device_name) - host_ds_system = self.esxi.configManager.datastoreSystem - ds_system = vim.host.DatastoreSystem - if self.vmfs_device_name in self.get_used_disks_names(): - error_message_used_disk = "VMFS disk %s already in use" % self.vmfs_device_name - self.module.fail_json(msg="%s" % error_message_used_disk) - error_message_mount = "Cannot mount datastore %s on host %s" % (self.datastore_name, self.esxi.name) - try: - vmfs_ds_options = ds_system.QueryVmfsDatastoreCreateOptions(host_ds_system, - ds_path, - self.vmfs_version) - vmfs_ds_options[0].spec.vmfs.volumeName = self.datastore_name - ds = ds_system.CreateVmfsDatastore(host_ds_system, - vmfs_ds_options[0].spec) - except (vim.fault.NotFound, vim.fault.DuplicateName, - vim.fault.HostConfigFault, vmodl.fault.InvalidArgument) as fault: - self.module.fail_json(msg="%s : %s" % (error_message_mount, to_native(fault.msg))) - except Exception as e: - self.module.fail_json(msg="%s : %s" % (error_message_mount, to_native(e))) - self.module.exit_json(changed=True, result="Datastore %s on host %s" % (self.datastore_name, self.esxi.name)) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - datacenter_name=dict(type='str', required=False, removed_in_version=2.11), - datastore_name=dict(type='str', required=True), - datastore_type=dict(type='str', choices=['nfs', 'nfs41', 'vmfs']), - nfs_server=dict(type='str'), - nfs_path=dict(type='str'), - nfs_ro=dict(type='bool', default=False), - vmfs_device_name=dict(type='str'), - vmfs_version=dict(type='int'), - esxi_hostname=dict(type='str', required=False), - state=dict(type='str', default='present', choices=['absent', 'present']) - ) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - required_together=[ - ['nfs_server', 'nfs_path'] - ], - ) - - # more complex required_if - if module.params['state'] == 'present': - if module.params['datastore_type'] == 'nfs' and not module.params['nfs_server']: - msg = "Missing nfs_server with datastore_type = nfs" - module.fail_json(msg=msg) - - if module.params['datastore_type'] == 'nfs41' and not module.params['nfs_server']: - msg = "Missing nfs_server with datastore_type = nfs41" - module.fail_json(msg=msg) - - if module.params['datastore_type'] == 'vmfs' and not module.params['vmfs_device_name']: - msg = "Missing vmfs_device_name with datastore_type = vmfs" - module.fail_json(msg=msg) - - vmware_host_datastore = VMwareHostDatastore(module) - vmware_host_datastore.process_state() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_dns.py b/lib/ansible/modules/cloud/vmware/vmware_host_dns.py deleted file mode 100644 index eeb578bc4d..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_dns.py +++ /dev/null @@ -1,471 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# -# 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_host_dns -short_description: Manage DNS configuration of an ESXi host system -description: -- This module can be used to configure DNS for the default TCP/IP stack on an ESXi host system. -version_added: '2.10' -author: -- Christian Kotte (@ckotte) -- Mario Lenz (@mariolenz) -notes: -- This module is a replacement for the module C(vmware_dns_config) -- Tested on vSphere 6.7 -requirements: -- python >= 2.6 -- PyVmomi -options: - type: - description: - - Type of DNS assignment. Either C(dhcp) or C(static). - - A VMkernel adapter needs to be set to DHCP if C(type) is set to C(dhcp). - type: str - choices: [ 'dhcp', 'static' ] - required: true - device: - description: - - The VMkernel network adapter to obtain DNS settings from. - - Needs to get its IP through DHCP, a static network configuration combined with a dynamic DNS configuration doesn't work. - - The parameter is only required in case of C(type) is set to C(dhcp). - type: str - host_name: - description: - - The hostname to be used for the ESXi host. - - Cannot be used when configuring a complete cluster. - type: str - domain: - description: - - The domain name to be used for the ESXi host. - type: str - dns_servers: - description: - - A list of DNS servers to be used. - - The order of the DNS servers is important as they are used consecutively in order. - type: list - search_domains: - description: - - A list of domains to be searched through by the resolver. - type: list - verbose: - description: - - Verbose output of the DNS server configuration change. - - Explains if an DNS server was added, removed, or if the DNS server sequence was changed. - type: bool - default: false - esxi_hostname: - description: - - Name of the host system to work with. - - This parameter is required if C(cluster_name) is not specified and you connect to a vCenter. - - Cannot be used when you connect directly to an ESXi host. - type: str - cluster_name: - description: - - Name of the cluster from which all host systems will be used. - - This parameter is required if C(esxi_hostname) is not specified and you connect to a vCenter. - - Cannot be used when you connect directly to an ESXi host. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Configure DNS for an ESXi host - vmware_host_dns: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - type: static - host_name: esx01 - domain: example.local - dns_servers: - - 192.168.1.10 - - 192.168.1.11 - search_domains: - - subdomain.example.local - - example.local - delegate_to: localhost - -- name: Configure DNS for all ESXi hosts of a cluster - vmware_host_dns: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: '{{ cluster_name }}' - type: static - domain: example.local - dns_servers: - - 192.168.1.10 - - 192.168.1.11 - search_domains: - - subdomain.example.local - - example.local - delegate_to: localhost - -- name: Configure DNS via DHCP for an ESXi host - vmware_host_dns: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - type: dhcp - device: vmk0 - delegate_to: localhost -''' - -RETURN = r''' -dns_config_result: - description: metadata about host system's DNS configuration - returned: always - type: dict - sample: { - "esx01.example.local": { - "changed": true, - "dns_servers_changed": ["192.168.1.12", "192.168.1.13"], - "dns_servers": ["192.168.1.10", "192.168.1.11"], - "dns_servers_previous": ["192.168.1.10", "192.168.1.11", "192.168.1.12", "192.168.1.13"], - "domain": "example.local", - "host_name": "esx01", - "msg": "DNS servers and Search domains changed", - "search_domains_changed": ["subdomain.example.local"], - "search_domains": ["subdomain.example.local", "example.local"], - "search_domains_previous": ["example.local"], - }, - } -''' - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec -from ansible.module_utils._text import to_native - - -class VmwareHostDNS(PyVmomi): - """Class to manage DNS configuration of an ESXi host system""" - - def __init__(self, module): - super(VmwareHostDNS, self).__init__(module) - self.cluster_name = self.params.get('cluster_name') - self.esxi_host_name = self.params.get('esxi_hostname') - if self.is_vcenter(): - if not self.cluster_name and not self.esxi_host_name: - self.module.fail_json( - msg="You connected to a vCenter but didn't specify the cluster_name or esxi_hostname you want to configure." - ) - else: - if self.cluster_name: - self.module.warn( - "You connected directly to an ESXi host, cluster_name will be ignored." - ) - if self.esxi_host_name: - self.module.warn( - "You connected directly to an ESXi host, esxi_host_name will be ignored." - ) - self.hosts = self.get_all_host_objs(cluster_name=self.cluster_name, esxi_host_name=self.esxi_host_name) - if not self.hosts: - self.module.fail_json(msg="Failed to find host system(s).") - self.network_type = self.params.get('type') - self.vmkernel_device = self.params.get('device') - self.host_name = self.params.get('host_name') - self.domain = self.params.get('domain') - self.dns_servers = self.params.get('dns_servers') - self.search_domains = self.params.get('search_domains') - - def ensure(self): - """Function to manage DNS configuration of an ESXi host system""" - results = dict(changed=False, dns_config_result=dict()) - verbose = self.module.params.get('verbose', False) - host_change_list = [] - for host in self.hosts: - initial_name = host.name - changed = False - changed_list = [] - host_result = {'changed': '', 'msg': '', 'host_name': host.name} - - host_netstack_config = host.config.network.netStackInstance - for instance in host_netstack_config: - if instance.key == 'defaultTcpipStack': - netstack_spec = vim.host.NetworkConfig.NetStackSpec() - netstack_spec.operation = 'edit' - netstack_spec.netStackInstance = vim.host.NetStackInstance() - netstack_spec.netStackInstance.key = 'defaultTcpipStack' - dns_config = vim.host.DnsConfig() - host_result['dns_config'] = self.network_type - host_result['search_domains'] = self.search_domains - if self.network_type == 'static': - if self.host_name: - if instance.dnsConfig.hostName != self.host_name: - host_result['host_name_previous'] = instance.dnsConfig.hostName - changed = True - changed_list.append("Host name") - dns_config.hostName = self.host_name - else: - dns_config.hostName = instance.dnsConfig.hostName - - if self.search_domains: - if instance.dnsConfig.searchDomain != self.search_domains: - host_result['search_domains_previous'] = instance.dnsConfig.searchDomain - host_result['search_domains_changed'] = ( - self.get_differt_entries(instance.dnsConfig.searchDomain, self.search_domains) - ) - changed = True - changed_list.append("Search domains") - dns_config.searchDomain = self.search_domains - else: - dns_config.searchDomain = instance.dnsConfig.searchDomain - - if instance.dnsConfig.dhcp: - host_result['domain'] = self.domain - host_result['dns_servers'] = self.dns_servers - host_result['search_domains'] = self.search_domains - host_result['dns_config_previous'] = 'DHCP' - changed = True - changed_list.append("DNS configuration") - dns_config.dhcp = False - dns_config.virtualNicDevice = None - dns_config.domainName = self.domain - dns_config.address = self.dns_servers - dns_config.searchDomain = self.search_domains - else: - # Check host name - - # Check domain - host_result['domain'] = self.domain - if self.domain: - if instance.dnsConfig.domainName != self.domain: - host_result['domain_previous'] = instance.dnsConfig.domainName - changed = True - changed_list.append("Domain") - dns_config.domainName = self.domain - else: - dns_config.domainName = instance.dnsConfig.domainName - - # Check DNS server(s) - host_result['dns_servers'] = self.dns_servers - if self.dns_servers: - if instance.dnsConfig.address != self.dns_servers: - host_result['dns_servers_previous'] = instance.dnsConfig.address - host_result['dns_servers_changed'] = ( - self.get_differt_entries(instance.dnsConfig.address, self.dns_servers) - ) - changed = True - # build verbose message - if verbose: - dns_servers_verbose_message = self.build_changed_message( - instance.dnsConfig.address, - self.dns_servers - ) - else: - changed_list.append("DNS servers") - dns_config.address = self.dns_servers - else: - dns_config.address = instance.dnsConfig.address - - elif self.network_type == 'dhcp' and not instance.dnsConfig.dhcp: - host_result['device'] = self.vmkernel_device - host_result['dns_config_previous'] = 'static' - changed = True - changed_list.append("DNS configuration") - dns_config.dhcp = True - dns_config.virtualNicDevice = self.vmkernel_device - netstack_spec.netStackInstance.dnsConfig = dns_config - config = vim.host.NetworkConfig() - config.netStackSpec = [netstack_spec] - - if changed: - if self.module.check_mode: - changed_suffix = ' would be changed' - else: - changed_suffix = ' changed' - if len(changed_list) > 2: - message = ', '.join(changed_list[:-1]) + ', and ' + str(changed_list[-1]) - elif len(changed_list) == 2: - message = ' and '.join(changed_list) - elif len(changed_list) == 1: - message = changed_list[0] - if verbose and dns_servers_verbose_message: - if changed_list: - message = message + changed_suffix + '. ' + dns_servers_verbose_message + '.' - else: - message = dns_servers_verbose_message - else: - message += changed_suffix - host_result['changed'] = True - host_network_system = host.configManager.networkSystem - if not self.module.check_mode: - try: - host_network_system.UpdateNetworkConfig(config, 'modify') - except vim.fault.AlreadyExists: - self.module.fail_json( - msg="Network entity specified in the configuration already exist on host '%s'" % host.name - ) - except vim.fault.NotFound: - self.module.fail_json( - msg="Network entity specified in the configuration doesn't exist on host '%s'" % host.name - ) - except vim.fault.ResourceInUse: - self.module.fail_json(msg="Resource is in use on host '%s'" % host.name) - except vmodl.fault.InvalidArgument: - self.module.fail_json( - msg="An invalid parameter is passed in for one of the networking objects for host '%s'" % - host.name - ) - except vmodl.fault.NotSupported as not_supported: - self.module.fail_json( - msg="Operation isn't supported for the instance on '%s' : %s" % - (host.name, to_native(not_supported.msg)) - ) - except vim.fault.HostConfigFault as config_fault: - self.module.fail_json( - msg="Failed to configure TCP/IP stacks for host '%s' due to : %s" % - (host.name, to_native(config_fault.msg)) - ) - else: - host_result['changed'] = False - message = 'All settings are already configured' - - host_result['msg'] = message - results['dns_config_result'][initial_name] = host_result - - host_change_list.append(changed) - - if any(host_change_list): - results['changed'] = True - self.module.exit_json(**results) - - def build_changed_message(self, dns_servers_configured, dns_servers_new): - """Build changed message""" - check_mode = 'would be ' if self.module.check_mode else '' - # get differences - add = self.get_not_in_list_one(dns_servers_new, dns_servers_configured) - remove = self.get_not_in_list_one(dns_servers_configured, dns_servers_new) - diff_servers = list(dns_servers_configured) - if add and remove: - for server in add: - diff_servers.append(server) - for server in remove: - diff_servers.remove(server) - if dns_servers_new != diff_servers: - message = ( - "DNS server %s %sadded and %s %sremoved and the server sequence %schanged as well" % - (self.array_to_string(add), check_mode, self.array_to_string(remove), check_mode, check_mode) - ) - else: - if dns_servers_new != dns_servers_configured: - message = ( - "DNS server %s %sreplaced with %s" % - (self.array_to_string(remove), check_mode, self.array_to_string(add)) - ) - else: - message = ( - "DNS server %s %sremoved and %s %sadded" % - (self.array_to_string(remove), check_mode, self.array_to_string(add), check_mode) - ) - elif add: - for server in add: - diff_servers.append(server) - if dns_servers_new != diff_servers: - message = ( - "DNS server %s %sadded and the server sequence %schanged as well" % - (self.array_to_string(add), check_mode, check_mode) - ) - else: - message = "DNS server %s %sadded" % (self.array_to_string(add), check_mode) - elif remove: - for server in remove: - diff_servers.remove(server) - if dns_servers_new != diff_servers: - message = ( - "DNS server %s %sremoved and the server sequence %schanged as well" % - (self.array_to_string(remove), check_mode, check_mode) - ) - else: - message = "DNS server %s %sremoved" % (self.array_to_string(remove), check_mode) - else: - message = "DNS server sequence %schanged" % check_mode - - return message - - @staticmethod - def get_not_in_list_one(list1, list2): - """Return entries that ore not in list one""" - return [x for x in list1 if x not in set(list2)] - - @staticmethod - def array_to_string(array): - """Return string from array""" - if len(array) > 2: - string = ( - ', '.join("'{0}'".format(element) for element in array[:-1]) + ', and ' - + "'{0}'".format(str(array[-1])) - ) - elif len(array) == 2: - string = ' and '.join("'{0}'".format(element) for element in array) - elif len(array) == 1: - string = "'{0}'".format(array[0]) - return string - - @staticmethod - def get_differt_entries(list1, list2): - """Return different entries of two lists""" - return [a for a in list1 + list2 if (a not in list1) or (a not in list2)] - - -def main(): - """Main""" - argument_spec = vmware_argument_spec() - argument_spec.update( - type=dict(required=True, type='str', choices=['dhcp', 'static']), - device=dict(type='str'), - host_name=dict(required=False, type='str'), - domain=dict(required=False, type='str'), - dns_servers=dict(required=False, type='list'), - search_domains=dict(required=False, type='list'), - esxi_hostname=dict(required=False, type='str'), - cluster_name=dict(required=False, type='str'), - verbose=dict(type='bool', default=False, required=False) - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_if=[ - ['type', 'dhcp', ['device']], - ], - mutually_exclusive=[ - ['cluster_name', 'host_name'], - ['cluster_name', 'esxi_host_name'], - ['static', 'device'], - ['dhcp', 'host_name'], - ['dhcp', 'domain'], - ['dhcp', 'dns_servers'], - ['dhcp', 'search_domains'], - ], - supports_check_mode=True - ) - - dns = VmwareHostDNS(module) - dns.ensure() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_dns_info.py b/lib/ansible/modules/cloud/vmware/vmware_host_dns_info.py deleted file mode 100644 index ee95b8ec5e..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_dns_info.py +++ /dev/null @@ -1,131 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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_host_dns_info -short_description: Gathers info about an ESXi host's DNS configuration information -description: -- This module can be used to gather information about an ESXi host's DNS configuration information when ESXi hostname or Cluster name is given. -- All parameters and VMware object names are case sensitive. -version_added: '2.9' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of the cluster from which the ESXi host belong to. - - If C(esxi_hostname) is not given, this parameter is required. - type: str - esxi_hostname: - description: - - ESXi hostname to gather information from. - - If C(cluster_name) is not given, this parameter is required. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather DNS info about all ESXi Hosts in given Cluster - vmware_host_dns_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: cluster_name - delegate_to: localhost - -- name: Gather DNS info about ESXi Host - vmware_host_dns_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - delegate_to: localhost -''' - -RETURN = r''' -hosts_dns_info: - description: metadata about DNS config from given cluster / host system - returned: always - type: dict - sample: { - "DC0_C0_H0": { - "dhcp": true, - "domain_name": "localdomain", - "host_name": "localhost", - "ip_address": [ - "8.8.8.8" - ], - "search_domain": [ - "localdomain" - ], - "virtual_nic_device": "vmk0" - } - } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class VmwareDnsInfoManager(PyVmomi): - def __init__(self, module): - super(VmwareDnsInfoManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - - def gather_dns_info(self): - hosts_info = {} - for host in self.hosts: - host_info = {} - dns_config = host.config.network.dnsConfig - host_info['dhcp'] = dns_config.dhcp - host_info['virtual_nic_device'] = dns_config.virtualNicDevice - host_info['host_name'] = dns_config.hostName - host_info['domain_name'] = dns_config.domainName - host_info['ip_address'] = [ip for ip in dns_config.address] - host_info['search_domain'] = [domain for domain in dns_config.searchDomain] - hosts_info[host.name] = host_info - return hosts_info - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True - ) - - vmware_dns_config = VmwareDnsInfoManager(module) - module.exit_json(changed=False, hosts_dns_info=vmware_dns_config.gather_dns_info()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_facts.py b/lib/ansible/modules/cloud/vmware/vmware_host_facts.py deleted file mode 100644 index f5bfbe7fad..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_facts.py +++ /dev/null @@ -1,393 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2017, Wei Gao <gaowei3@qq.com> -# Copyright: (c) 2018, Ansible Project -# -# 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_host_facts -short_description: Gathers facts about remote ESXi hostsystem -description: - - This module can be used to gathers facts like CPU, memory, datastore, network and system etc. about ESXi host system. - - Please specify hostname or IP address of ESXi host system as C(hostname). - - If hostname or IP address of vCenter is provided as C(hostname) and C(esxi_hostname) is not specified, then the - module will throw an error. - - VSAN facts added in 2.7 version. - - SYSTEM fact uuid added in 2.10 version. -version_added: 2.5 -author: - - Wei Gao (@woshihaoren) -requirements: - - python >= 2.6 - - PyVmomi -options: - esxi_hostname: - description: - - ESXi hostname. - - Host facts about the specified ESXi server will be returned. - - By specifying this option, you can select which ESXi hostsystem is returned if connecting to a vCenter. - version_added: 2.8 - type: str - show_tag: - description: - - Tags related to Host are shown if set to C(True). - default: False - type: bool - required: False - version_added: 2.9 - schema: - description: - - Specify the output schema desired. - - The 'summary' output schema is the legacy output from the module - - The 'vsphere' output schema is the vSphere API class definition - which requires pyvmomi>6.7.1 - choices: ['summary', 'vsphere'] - default: 'summary' - type: str - version_added: '2.10' - properties: - description: - - Specify the properties to retrieve. - - If not specified, all properties are retrieved (deeply). - - Results are returned in a structure identical to the vsphere API. - - 'Example:' - - ' properties: [' - - ' "hardware.memorySize",' - - ' "hardware.cpuInfo.numCpuCores",' - - ' "config.product.apiVersion",' - - ' "overallStatus"' - - ' ]' - - Only valid when C(schema) is C(vsphere). - type: list - required: False - version_added: '2.10' -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather vmware host facts - vmware_host_facts: - hostname: "{{ esxi_server }}" - username: "{{ esxi_username }}" - password: "{{ esxi_password }}" - register: host_facts - delegate_to: localhost - -- name: Gather vmware host facts from vCenter - vmware_host_facts: - hostname: "{{ vcenter_server }}" - username: "{{ vcenter_user }}" - password: "{{ vcenter_pass }}" - esxi_hostname: "{{ esxi_hostname }}" - register: host_facts - delegate_to: localhost - -- name: Gather vmware host facts from vCenter with tag information - vmware_host_facts: - hostname: "{{ vcenter_server }}" - username: "{{ vcenter_user }}" - password: "{{ vcenter_pass }}" - esxi_hostname: "{{ esxi_hostname }}" - show_tag: True - register: host_facts_tag - delegate_to: localhost - -- name: Get VSAN Cluster UUID from host facts - vmware_host_facts: - hostname: "{{ esxi_server }}" - username: "{{ esxi_username }}" - password: "{{ esxi_password }}" - register: host_facts -- set_fact: - cluster_uuid: "{{ host_facts['ansible_facts']['vsan_cluster_uuid'] }}" - -- name: Gather some info from a host using the vSphere API output schema - vmware_host_facts: - hostname: "{{ vcenter_server }}" - username: "{{ vcenter_user }}" - password: "{{ vcenter_pass }}" - esxi_hostname: "{{ esxi_hostname }}" - schema: vsphere - properties: - - hardware.memorySize - - hardware.cpuInfo.numCpuCores - - config.product.apiVersion - - overallStatus - register: host_facts - -- name: How to retrieve Product, Version, Build, Update info for ESXi from vCenter - block: - - name: Gather product version info for ESXi from vCenter - vmware_host_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_user }}" - password: "{{ vcenter_pass }}" - validate_certs: no - esxi_hostname: "{{ esxi_hostname }}" - schema: vsphere - properties: - - config.product - - config.option - register: gather_host_facts_result - - - name: Extract update level info from option properties - set_fact: - update_level_info: "{{ item.value }}" - loop: "{{ gather_host_facts_result.ansible_facts.config.option }}" - when: - - item.key == 'Misc.HostAgentUpdateLevel' - - - name: The output of Product, Version, Build, Update info for ESXi - debug: - msg: - - "Product : {{ gather_host_facts_result.ansible_facts.config.product.name }}" - - "Version : {{ gather_host_facts_result.ansible_facts.config.product.version }}" - - "Build : {{ gather_host_facts_result.ansible_facts.config.product.build }}" - - "Update : {{ update_level_info }}" -''' - -RETURN = r''' -ansible_facts: - description: system info about the host machine - returned: always - type: dict - sample: - { - "ansible_all_ipv4_addresses": [ - "10.76.33.200" - ], - "ansible_bios_date": "2011-01-01T00:00:00+00:00", - "ansible_bios_version": "0.5.1", - "ansible_datastore": [ - { - "free": "11.63 GB", - "name": "datastore1", - "total": "12.50 GB" - } - ], - "ansible_distribution": "VMware ESXi", - "ansible_distribution_build": "4887370", - "ansible_distribution_version": "6.5.0", - "ansible_hostname": "10.76.33.100", - "ansible_in_maintenance_mode": true, - "ansible_interfaces": [ - "vmk0" - ], - "ansible_memfree_mb": 2702, - "ansible_memtotal_mb": 4095, - "ansible_os_type": "vmnix-x86", - "ansible_processor": "Intel Xeon E312xx (Sandy Bridge)", - "ansible_processor_cores": 2, - "ansible_processor_count": 2, - "ansible_processor_vcpus": 2, - "ansible_product_name": "KVM", - "ansible_product_serial": "NA", - "ansible_system_vendor": "Red Hat", - "ansible_uptime": 1791680, - "ansible_uuid": "4c4c4544-0052-3410-804c-b2c04f4e3632", - "ansible_vmk0": { - "device": "vmk0", - "ipv4": { - "address": "10.76.33.100", - "netmask": "255.255.255.0" - }, - "macaddress": "52:54:00:56:7d:59", - "mtu": 1500 - }, - "vsan_cluster_uuid": null, - "vsan_node_uuid": null, - "vsan_health": "unknown", - "tags": [ - { - "category_id": "urn:vmomi:InventoryServiceCategory:8eb81431-b20d-49f5-af7b-126853aa1189:GLOBAL", - "category_name": "host_category_0001", - "description": "", - "id": "urn:vmomi:InventoryServiceTag:e9398232-46fd-461a-bf84-06128e182a4a:GLOBAL", - "name": "host_tag_0001" - } - ], - } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.common.text.formatters import bytes_to_human -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec, find_obj - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.vmware_rest_client import VmwareRestClient - - -class VMwareHostFactManager(PyVmomi): - def __init__(self, module): - super(VMwareHostFactManager, self).__init__(module) - esxi_host_name = self.params.get('esxi_hostname', None) - if self.is_vcenter(): - if esxi_host_name is None: - self.module.fail_json(msg="Connected to a vCenter system without specifying esxi_hostname") - self.host = self.get_all_host_objs(esxi_host_name=esxi_host_name) - if len(self.host) > 1: - self.module.fail_json(msg="esxi_hostname matched multiple hosts") - self.host = self.host[0] - else: - self.host = find_obj(self.content, [vim.HostSystem], None) - - if self.host is None: - self.module.fail_json(msg="Failed to find host system.") - - def all_facts(self): - ansible_facts = {} - ansible_facts.update(self.get_cpu_facts()) - ansible_facts.update(self.get_memory_facts()) - ansible_facts.update(self.get_datastore_facts()) - ansible_facts.update(self.get_network_facts()) - ansible_facts.update(self.get_system_facts()) - ansible_facts.update(self.get_vsan_facts()) - ansible_facts.update(self.get_cluster_facts()) - if self.params.get('show_tag'): - vmware_client = VmwareRestClient(self.module) - tag_info = { - 'tags': vmware_client.get_tags_for_hostsystem(hostsystem_mid=self.host._moId) - } - ansible_facts.update(tag_info) - - self.module.exit_json(changed=False, ansible_facts=ansible_facts) - - def get_cluster_facts(self): - cluster_facts = {'cluster': None} - if self.host.parent and isinstance(self.host.parent, vim.ClusterComputeResource): - cluster_facts.update(cluster=self.host.parent.name) - return cluster_facts - - def get_vsan_facts(self): - config_mgr = self.host.configManager.vsanSystem - if config_mgr is None: - return { - 'vsan_cluster_uuid': None, - 'vsan_node_uuid': None, - 'vsan_health': "unknown", - } - - status = config_mgr.QueryHostStatus() - return { - 'vsan_cluster_uuid': status.uuid, - 'vsan_node_uuid': status.nodeUuid, - 'vsan_health': status.health, - } - - def get_cpu_facts(self): - return { - 'ansible_processor': self.host.summary.hardware.cpuModel, - 'ansible_processor_cores': self.host.summary.hardware.numCpuCores, - 'ansible_processor_count': self.host.summary.hardware.numCpuPkgs, - 'ansible_processor_vcpus': self.host.summary.hardware.numCpuThreads, - } - - def get_memory_facts(self): - return { - 'ansible_memfree_mb': self.host.hardware.memorySize // 1024 // 1024 - self.host.summary.quickStats.overallMemoryUsage, - 'ansible_memtotal_mb': self.host.hardware.memorySize // 1024 // 1024, - } - - def get_datastore_facts(self): - facts = dict() - facts['ansible_datastore'] = [] - for store in self.host.datastore: - _tmp = { - 'name': store.summary.name, - 'total': bytes_to_human(store.summary.capacity), - 'free': bytes_to_human(store.summary.freeSpace), - } - facts['ansible_datastore'].append(_tmp) - return facts - - def get_network_facts(self): - facts = dict() - facts['ansible_interfaces'] = [] - facts['ansible_all_ipv4_addresses'] = [] - for nic in self.host.config.network.vnic: - device = nic.device - facts['ansible_interfaces'].append(device) - facts['ansible_all_ipv4_addresses'].append(nic.spec.ip.ipAddress) - _tmp = { - 'device': device, - 'ipv4': { - 'address': nic.spec.ip.ipAddress, - 'netmask': nic.spec.ip.subnetMask, - }, - 'macaddress': nic.spec.mac, - 'mtu': nic.spec.mtu, - } - facts['ansible_' + device] = _tmp - return facts - - def get_system_facts(self): - sn = 'NA' - for info in self.host.hardware.systemInfo.otherIdentifyingInfo: - if info.identifierType.key == 'ServiceTag': - sn = info.identifierValue - facts = { - 'ansible_distribution': self.host.config.product.name, - 'ansible_distribution_version': self.host.config.product.version, - 'ansible_distribution_build': self.host.config.product.build, - 'ansible_os_type': self.host.config.product.osType, - 'ansible_system_vendor': self.host.hardware.systemInfo.vendor, - 'ansible_hostname': self.host.summary.config.name, - 'ansible_product_name': self.host.hardware.systemInfo.model, - 'ansible_product_serial': sn, - 'ansible_bios_date': self.host.hardware.biosInfo.releaseDate, - 'ansible_bios_version': self.host.hardware.biosInfo.biosVersion, - 'ansible_uptime': self.host.summary.quickStats.uptime, - 'ansible_in_maintenance_mode': self.host.runtime.inMaintenanceMode, - 'ansible_uuid': self.host.hardware.systemInfo.uuid, - } - return facts - - def properties_facts(self): - ansible_facts = self.to_json(self.host, self.params.get('properties')) - if self.params.get('show_tag'): - vmware_client = VmwareRestClient(self.module) - tag_info = { - 'tags': vmware_client.get_tags_for_hostsystem(hostsystem_mid=self.host._moId) - } - ansible_facts.update(tag_info) - - self.module.exit_json(changed=False, ansible_facts=ansible_facts) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - esxi_hostname=dict(type='str', required=False), - show_tag=dict(type='bool', default=False), - schema=dict(type='str', choices=['summary', 'vsphere'], default='summary'), - properties=dict(type='list') - ) - module = AnsibleModule(argument_spec=argument_spec, - supports_check_mode=True) - - vm_host_manager = VMwareHostFactManager(module) - - if module.params['schema'] == 'summary': - vm_host_manager.all_facts() - else: - vm_host_manager.properties_facts() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_feature_info.py b/lib/ansible/modules/cloud/vmware/vmware_host_feature_info.py deleted file mode 100644 index 0a9d069ec0..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_feature_info.py +++ /dev/null @@ -1,143 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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_host_feature_info -short_description: Gathers info about an ESXi host's feature capability information -description: -- This module can be used to gather information about an ESXi host's feature capability information when ESXi hostname or Cluster name is given. -version_added: '2.9' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of the cluster from all host systems to be used for information gathering. - - If C(esxi_hostname) is not given, this parameter is required. - type: str - esxi_hostname: - description: - - ESXi hostname to gather information from. - - If C(cluster_name) is not given, this parameter is required. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather feature capability info about all ESXi Hosts in given Cluster - vmware_host_feature_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: cluster_name - delegate_to: localhost - register: all_cluster_hosts_info - -- name: Check if ESXi is vulnerable for Speculative Store Bypass Disable (SSBD) vulnerability - vmware_host_feature_info: - hostname: "{{ vcenter_server }}" - username: "{{ vcenter_user }}" - password: "{{ vcenter_pass }}" - validate_certs: no - esxi_hostname: "{{ esxi_hostname }}" - register: features_set -- set_fact: - ssbd : "{{ item.value }}" - loop: "{{ features_set.host_feature_info[esxi_hostname] |json_query(name) }}" - vars: - name: "[?key=='cpuid.SSBD']" -- assert: - that: - - ssbd|int == 1 - when: ssbd is defined -''' - -RETURN = r''' -hosts_feature_info: - description: metadata about host's feature capability information - returned: always - type: dict - sample: { - "10.76.33.226": [ - { - "feature_name": "cpuid.3DNOW", - "key": "cpuid.3DNOW", - "value": "0" - }, - { - "feature_name": "cpuid.3DNOWPLUS", - "key": "cpuid.3DNOWPLUS", - "value": "0" - }, - ] - } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class FeatureCapabilityInfoManager(PyVmomi): - def __init__(self, module): - super(FeatureCapabilityInfoManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - - def gather_host_feature_info(self): - host_feature_info = dict() - for host in self.hosts: - host_feature_capabilities = host.config.featureCapability - capability = [] - for fc in host_feature_capabilities: - temp_dict = { - 'key': fc.key, - 'feature_name': fc.featureName, - 'value': fc.value, - } - capability.append(temp_dict) - - host_feature_info[host.name] = capability - - return host_feature_info - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True, - ) - - host_capability_manager = FeatureCapabilityInfoManager(module) - module.exit_json(changed=False, - hosts_feature_info=host_capability_manager.gather_host_feature_info()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_firewall_info.py b/lib/ansible/modules/cloud/vmware/vmware_host_firewall_info.py deleted file mode 100644 index dd40d825b5..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_firewall_info.py +++ /dev/null @@ -1,164 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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_host_firewall_info -short_description: Gathers info about an ESXi host's firewall configuration information -description: -- This module can be used to gather information about an ESXi host's firewall configuration information when ESXi hostname or Cluster name is given. -version_added: '2.9' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of the cluster from which the ESXi host belong to. - - If C(esxi_hostname) is not given, this parameter is required. - type: str - esxi_hostname: - description: - - ESXi hostname to gather information from. - - If C(cluster_name) is not given, this parameter is required. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather firewall info about all ESXi Host in given Cluster - vmware_host_firewall_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: cluster_name - delegate_to: localhost - -- name: Gather firewall info about ESXi Host - vmware_host_firewall_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - delegate_to: localhost -''' - -RETURN = r''' -hosts_firewall_info: - description: metadata about host's firewall configuration - returned: on success - type: dict - sample: { - "esxi_hostname_0001": [ - { - "allowed_hosts": { - "all_ip": true, - "ip_address": [ - "10.10.10.1", - ], - "ip_network": [ - "11.111.112.0/22", - "192.168.10.1/24" - ], - }, - "enabled": true, - "key": "CIMHttpServer", - "rule": [ - { - "direction": "inbound", - "end_port": null, - "port": 5988, - "port_type": "dst", - "protocol": "tcp" - } - ], - "service": "sfcbd-watchdog" - }, - ] - } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class FirewallInfoManager(PyVmomi): - def __init__(self, module): - super(FirewallInfoManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - - @staticmethod - def normalize_rule_set(rule_obj): - rule_dict = dict() - rule_dict['key'] = rule_obj.key - rule_dict['service'] = rule_obj.service - rule_dict['enabled'] = rule_obj.enabled - rule_dict['rule'] = [] - - for rule in rule_obj.rule: - rule_set_dict = dict() - rule_set_dict['port'] = rule.port - rule_set_dict['end_port'] = rule.endPort - rule_set_dict['direction'] = rule.direction - rule_set_dict['port_type'] = rule.portType - rule_set_dict['protocol'] = rule.protocol - rule_dict['rule'].append(rule_set_dict) - - allowed_host = rule_obj.allowedHosts - rule_allow_host = dict() - rule_allow_host['ip_address'] = [ip for ip in allowed_host.ipAddress] - rule_allow_host['ip_network'] = [ip.network + "/" + str(ip.prefixLength) for ip in allowed_host.ipNetwork] - rule_allow_host['all_ip'] = allowed_host.allIp - rule_dict['allowed_hosts'] = rule_allow_host - return rule_dict - - def gather_host_firewall_info(self): - hosts_firewall_info = dict() - for host in self.hosts: - firewall_system = host.configManager.firewallSystem - if firewall_system: - hosts_firewall_info[host.name] = [] - for rule_set_obj in firewall_system.firewallInfo.ruleset: - hosts_firewall_info[host.name].append(self.normalize_rule_set(rule_obj=rule_set_obj)) - return hosts_firewall_info - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True - ) - - vmware_host_firewall = FirewallInfoManager(module) - module.exit_json(changed=False, hosts_firewall_info=vmware_host_firewall.gather_host_firewall_info()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_firewall_manager.py b/lib/ansible/modules/cloud/vmware/vmware_host_firewall_manager.py deleted file mode 100644 index 59398df737..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_firewall_manager.py +++ /dev/null @@ -1,400 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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_host_firewall_manager -short_description: Manage firewall configurations about an ESXi host -description: -- This module can be used to manage firewall configurations about an ESXi host when ESXi hostname or Cluster name is given. -version_added: '2.5' -author: -- Abhijeet Kasurde (@Akasurde) -- Aaron Longchamps (@alongchamps) -notes: -- Tested on vSphere 6.0, vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of the cluster. - - Firewall settings are applied to every ESXi host system in given cluster. - - If C(esxi_hostname) is not given, this parameter is required. - type: str - esxi_hostname: - description: - - ESXi hostname. - - Firewall settings are applied to this ESXi host system. - - If C(cluster_name) is not given, this parameter is required. - type: str - rules: - description: - - A list of Rule set which needs to be managed. - - Each member of list is rule set name and state to be set the rule. - - Both rule name and rule state are required parameters. - - Additional IPs and networks can also be specified - - Please see examples for more information. - default: [] - type: list -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Enable vvold rule set for all ESXi Host in given Cluster - vmware_host_firewall_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: cluster_name - rules: - - name: vvold - enabled: True - delegate_to: localhost - -- name: Enable vvold rule set for an ESXi Host - vmware_host_firewall_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - rules: - - name: vvold - enabled: True - delegate_to: localhost - -- name: Manage multiple rule set for an ESXi Host - vmware_host_firewall_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - rules: - - name: vvold - enabled: True - - name: CIMHttpServer - enabled: False - delegate_to: localhost - -- name: Manage IP and network based firewall permissions for ESXi - vmware_host_firewall_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - rules: - - name: gdbserver - enabled: True - allowed_hosts: - all_ip: False - ip_address: - - 192.168.20.10 - - 192.168.20.11 - - name: CIMHttpServer - enabled: True - allowed_hosts: - all_ip: False - ip_network: - - 192.168.100.0/24 - - name: remoteSerialPort - enabled: True - allowed_hosts: - all_ip: False - ip_address: - - 192.168.100.11 - ip_network: - - 192.168.200.0/24 - delegate_to: localhost -''' - -RETURN = r''' -rule_set_state: - description: - - dict with hostname as key and dict with firewall rule set facts as value - returned: success - type: dict - sample: { - "rule_set_state": { - "localhost.localdomain": { - "CIMHttpServer": { - "current_state": False, - "desired_state": False, - "previous_state": True, - "allowed_hosts": { - "current_allowed_all": True, - "previous_allowed_all": True, - "desired_allowed_all": True, - "current_allowed_ip": [], - "previous_allowed_ip": [], - "desired_allowed_ip": [], - "current_allowed_networks": [], - "previous_allowed_networks": [], - "desired_allowed_networks": [], - } - }, - "remoteSerialPort": { - "current_state": True, - "desired_state": True, - "previous_state": True, - "allowed_hosts": { - "current_allowed_all": False, - "previous_allowed_all": True, - "desired_allowed_all": False, - "current_allowed_ip": ["192.168.100.11"], - "previous_allowed_ip": [], - "desired_allowed_ip": ["192.168.100.11"], - "current_allowed_networks": ["192.168.200.0/24"], - "previous_allowed_networks": [], - "desired_allowed_networks": ["192.168.200.0/24"], - } - } - } - } - } -''' - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi -from ansible.module_utils._text import to_native -import socket - - -def is_ipaddress(value): - try: - socket.inet_aton(value) - except socket.error: - try: - socket.inet_pton(socket.AF_INET6, value) - except socket.error: - return False - return True - - -class VmwareFirewallManager(PyVmomi): - def __init__(self, module): - super(VmwareFirewallManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.options = self.params.get('options', dict()) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - self.firewall_facts = dict() - self.rule_options = self.module.params.get("rules") - self.gather_rule_set() - - def gather_rule_set(self): - for host in self.hosts: - self.firewall_facts[host.name] = {} - firewall_system = host.configManager.firewallSystem - if firewall_system: - for rule_set_obj in firewall_system.firewallInfo.ruleset: - temp_rule_dict = dict() - temp_rule_dict['enabled'] = rule_set_obj.enabled - allowed_host = rule_set_obj.allowedHosts - rule_allow_host = dict() - rule_allow_host['ip_address'] = allowed_host.ipAddress - rule_allow_host['ip_network'] = [ip.network + "/" + str(ip.prefixLength) for ip in allowed_host.ipNetwork] - rule_allow_host['all_ip'] = allowed_host.allIp - temp_rule_dict['allowed_hosts'] = rule_allow_host - self.firewall_facts[host.name][rule_set_obj.key] = temp_rule_dict - - def check_params(self): - rules_by_host = {} - for host in self.hosts: - rules_by_host[host.name] = self.firewall_facts[host.name].keys() - - for rule_option in self.rule_options: - rule_name = rule_option.get('name') - if rule_name is None: - self.module.fail_json(msg="Please specify rule.name for rule set" - " as it is required parameter.") - hosts_with_rule_name = [h for h, r in rules_by_host.items() if rule_name in r] - hosts_without_rule_name = set([i.name for i in self.hosts]) - set(hosts_with_rule_name) - if hosts_without_rule_name: - self.module.fail_json(msg="rule named '%s' wasn't found on hosts: %s" % ( - rule_name, hosts_without_rule_name)) - - if 'enabled' not in rule_option: - self.module.fail_json(msg="Please specify rules.enabled for rule set" - " %s as it is required parameter." % rule_name) - - allowed_hosts = rule_option.get('allowed_hosts', {}) - ip_addresses = allowed_hosts.get('ip_address', []) - ip_networks = allowed_hosts.get('ip_network', []) - for ip_address in ip_addresses: - try: - is_ipaddress(ip_address) - except ValueError: - self.module.fail_json(msg="The provided IP address %s is not a valid IP" - " for the rule %s" % (ip_address, rule_name)) - - for ip_network in ip_networks: - try: - is_ipaddress(ip_network) - except ValueError: - self.module.fail_json(msg="The provided IP network %s is not a valid network" - " for the rule %s" % (ip_network, rule_name)) - - def ensure(self): - """ - Function to ensure rule set configuration - - """ - fw_change_list = [] - enable_disable_changed = False - allowed_ip_changed = False - results = dict(changed=False, rule_set_state=dict()) - for host in self.hosts: - firewall_system = host.configManager.firewallSystem - if firewall_system is None: - continue - results['rule_set_state'][host.name] = {} - for rule_option in self.rule_options: - rule_name = rule_option.get('name', None) - - current_rule_state = self.firewall_facts[host.name][rule_name]['enabled'] - if current_rule_state != rule_option['enabled']: - try: - if not self.module.check_mode: - if rule_option['enabled']: - firewall_system.EnableRuleset(id=rule_name) - else: - firewall_system.DisableRuleset(id=rule_name) - # keep track of changes as we go - enable_disable_changed = True - except vim.fault.NotFound as not_found: - self.module.fail_json(msg="Failed to enable rule set %s as" - " rule set id is unknown : %s" % ( - rule_name, - to_native(not_found.msg))) - except vim.fault.HostConfigFault as host_config_fault: - self.module.fail_json(msg="Failed to enabled rule set %s as an internal" - " error happened while reconfiguring" - " rule set : %s" % ( - rule_name, - to_native(host_config_fault.msg))) - - # save variables here for comparison later and change tracking - # also covers cases where inputs may be null - permitted_networking = self.firewall_facts[host.name][rule_name] - rule_allows_all = permitted_networking['allowed_hosts']['all_ip'] - rule_allowed_ips = set(permitted_networking['allowed_hosts']['ip_address']) - rule_allowed_networks = set(permitted_networking['allowed_hosts']['ip_network']) - - allowed_hosts = rule_option.get('allowed_hosts', {}) - playbook_allows_all = allowed_hosts.get('all_ip', False) - playbook_allowed_ips = set(allowed_hosts.get('ip_address', [])) - playbook_allowed_networks = set(allowed_hosts.get('ip_network', [])) - - # compare what is configured on the firewall rule with what the playbook provides - allowed_all_ips_different = bool(rule_allows_all != playbook_allows_all) - ip_list_different = bool(rule_allowed_ips != playbook_allowed_ips) - ip_network_different = bool(rule_allowed_networks != playbook_allowed_networks) - - # apply everything here in one function call - if allowed_all_ips_different is True or ip_list_different is True or ip_network_different is True: - try: - allowed_ip_changed = True - if not self.module.check_mode: - # setup spec - firewall_spec = vim.host.Ruleset.RulesetSpec() - firewall_spec.allowedHosts = vim.host.Ruleset.IpList() - firewall_spec.allowedHosts.allIp = playbook_allows_all - firewall_spec.allowedHosts.ipAddress = list(playbook_allowed_ips) - firewall_spec.allowedHosts.ipNetwork = [] - - for i in playbook_allowed_networks: - address, mask = i.split('/') - tmp_ip_network_spec = vim.host.Ruleset.IpNetwork() - tmp_ip_network_spec.network = address - tmp_ip_network_spec.prefixLength = int(mask) - firewall_spec.allowedHosts.ipNetwork.append(tmp_ip_network_spec) - - firewall_system.UpdateRuleset(id=rule_name, spec=firewall_spec) - except vim.fault.NotFound as not_found: - self.module.fail_json(msg="Failed to configure rule set %s as" - " rule set id is unknown : %s" % (rule_name, - to_native(not_found.msg))) - except vim.fault.HostConfigFault as host_config_fault: - self.module.fail_json(msg="Failed to configure rule set %s as an internal" - " error happened while reconfiguring" - " rule set : %s" % (rule_name, - to_native(host_config_fault.msg))) - except vim.fault.RuntimeFault as runtime_fault: - self.module.fail_json(msg="Failed to configure the rule set %s as a runtime" - " error happened while applying the reconfiguration:" - " %s" % (rule_name, to_native(runtime_fault.msg))) - - results['rule_set_state'][host.name][rule_name] = { - 'current_state': rule_option['enabled'], - 'previous_state': current_rule_state, - 'desired_state': rule_option['enabled'], - 'allowed_hosts': { - 'current_allowed_all': playbook_allows_all, - 'previous_allowed_all': permitted_networking['allowed_hosts']['all_ip'], - 'desired_allowed_all': playbook_allows_all, - 'current_allowed_ip': playbook_allowed_ips, - 'previous_allowed_ip': set(permitted_networking['allowed_hosts']['ip_address']), - 'desired_allowed_ip': playbook_allowed_ips, - 'current_allowed_networks': playbook_allowed_networks, - 'previous_allowed_networks': set(permitted_networking['allowed_hosts']['ip_network']), - 'desired_allowed_networks': playbook_allowed_networks, - } - } - - if enable_disable_changed or allowed_ip_changed: - fw_change_list.append(True) - - if any(fw_change_list): - results['changed'] = True - self.module.exit_json(**results) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - rules=dict(type='list', default=list(), required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True - ) - - for rule_option in module.params.get("rules", []): - if 'allowed_hosts' in rule_option: - if isinstance(rule_option['allowed_hosts'], list): - if len(rule_option['allowed_hosts']) == 1: - allowed_hosts = rule_option['allowed_hosts'][0] - rule_option['allowed_hosts'] = allowed_hosts - module.deprecate('allowed_hosts should be a dict, not a list', '2.13') - - vmware_firewall_manager = VmwareFirewallManager(module) - vmware_firewall_manager.check_params() - vmware_firewall_manager.ensure() - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_hyperthreading.py b/lib/ansible/modules/cloud/vmware/vmware_host_hyperthreading.py deleted file mode 100644 index ad579e1e5e..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_hyperthreading.py +++ /dev/null @@ -1,261 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# -# 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_host_hyperthreading -short_description: Enables/Disables Hyperthreading optimization for an ESXi host system -description: -- This module can be used to enable or disable Hyperthreading optimization for ESXi host systems in given vCenter infrastructure. -- It also checks if Hyperthreading is activated/deactivated and if the host needs to be restarted. -- The module informs the user if Hyperthreading is enabled but inactive because the processor is vulnerable to L1 Terminal Fault (L1TF). -version_added: 2.8 -author: -- Christian Kotte (@ckotte) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - state: - description: - - Enable or disable Hyperthreading. - - You need to reboot the ESXi host if you change the configuration. - - Make sure that Hyperthreading is enabled in the BIOS. Otherwise, it will be enabled, but never activated. - type: str - choices: [ enabled, disabled ] - default: 'enabled' - esxi_hostname: - description: - - Name of the host system to work with. - - This parameter is required if C(cluster_name) is not specified. - type: str - cluster_name: - description: - - Name of the cluster from which all host systems will be used. - - This parameter is required if C(esxi_hostname) is not specified. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Enable Hyperthreading for an host system - vmware_host_hyperthreading: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - state: enabled - validate_certs: no - delegate_to: localhost - -- name: Disable Hyperthreading for an host system - vmware_host_hyperthreading: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - state: disabled - validate_certs: no - delegate_to: localhost - -- name: Disable Hyperthreading for all host systems from cluster - vmware_host_hyperthreading: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: '{{ cluster_name }}' - state: disabled - validate_certs: no - delegate_to: localhost -''' - -RETURN = r''' -results: - description: metadata about host system's Hyperthreading configuration - returned: always - type: dict - sample: { - "esxi01": { - "msg": "Hyperthreading is already enabled and active for host 'esxi01'", - "state_current": "active", - "state": "enabled", - }, - } -''' - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec -from ansible.module_utils._text import to_native - - -class VmwareHostHyperthreading(PyVmomi): - """Manage Hyperthreading for an ESXi host system""" - def __init__(self, module): - super(VmwareHostHyperthreading, self).__init__(module) - cluster_name = self.params.get('cluster_name') - esxi_host_name = self.params.get('esxi_hostname') - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - if not self.hosts: - self.module.fail_json(msg="Failed to find host system.") - - def ensure(self): - """Manage Hyperthreading for an ESXi host system""" - results = dict(changed=False, result=dict()) - desired_state = self.params.get('state') - host_change_list = [] - for host in self.hosts: - changed = False - results['result'][host.name] = dict(msg='') - - hyperthreading_info = host.config.hyperThread - - results['result'][host.name]['state'] = desired_state - if desired_state == 'enabled': - # Don't do anything if Hyperthreading is already enabled - if hyperthreading_info.config: - if hyperthreading_info.active: - results['result'][host.name]['changed'] = False - results['result'][host.name]['state_current'] = "active" - results['result'][host.name]['msg'] = "Hyperthreading is enabled and active" - if not hyperthreading_info.active: - # L1 Terminal Fault (L1TF)/Foreshadow mitigation workaround (https://kb.vmware.com/s/article/55806) - option_manager = host.configManager.advancedOption - try: - mitigation = option_manager.QueryOptions('VMkernel.Boot.hyperthreadingMitigation') - except vim.fault.InvalidName: - mitigation = None - if mitigation and mitigation[0].value: - results['result'][host.name]['changed'] = False - results['result'][host.name]['state_current'] = "enabled" - results['result'][host.name]['msg'] = ("Hyperthreading is enabled, but not active because the" - " processor is vulnerable to L1 Terminal Fault (L1TF).") - else: - changed = results['result'][host.name]['changed'] = True - results['result'][host.name]['state_current'] = "enabled" - results['result'][host.name]['msg'] = ("Hyperthreading is enabled, but not active." - " A reboot is required!") - # Enable Hyperthreading - else: - # Check if Hyperthreading is available - if hyperthreading_info.available: - if not self.module.check_mode: - try: - host.configManager.cpuScheduler.EnableHyperThreading() - changed = results['result'][host.name]['changed'] = True - results['result'][host.name]['state_previous'] = "disabled" - results['result'][host.name]['state_current'] = "enabled" - results['result'][host.name]['msg'] = ( - "Hyperthreading enabled for host. Reboot the host to activate it." - ) - except vmodl.fault.NotSupported as not_supported: - # This should never happen since Hyperthreading is available - self.module.fail_json( - msg="Failed to enable Hyperthreading for host '%s' : %s" % - (host.name, to_native(not_supported.msg)) - ) - except (vmodl.RuntimeFault, vmodl.MethodFault) as runtime_fault: - self.module.fail_json( - msg="Failed to enable Hyperthreading for host '%s' due to : %s" % - (host.name, to_native(runtime_fault.msg)) - ) - else: - changed = results['result'][host.name]['changed'] = True - results['result'][host.name]['state_previous'] = "disabled" - results['result'][host.name]['state_current'] = "enabled" - results['result'][host.name]['msg'] = "Hyperthreading will be enabled" - else: - self.module.fail_json(msg="Hyperthreading optimization is not available for host '%s'" % host.name) - elif desired_state == 'disabled': - # Don't do anything if Hyperthreading is already disabled - if not hyperthreading_info.config: - if not hyperthreading_info.active: - results['result'][host.name]['changed'] = False - results['result'][host.name]['state_current'] = "inactive" - results['result'][host.name]['msg'] = "Hyperthreading is disabled and inactive" - if hyperthreading_info.active: - changed = results['result'][host.name]['changed'] = True - results['result'][host.name]['state_current'] = "disabled" - results['result'][host.name]['msg'] = ("Hyperthreading is already disabled" - " but still active. A reboot is required!") - # Disable Hyperthreading - else: - # Check if Hyperthreading is available - if hyperthreading_info.available: - if not self.module.check_mode: - try: - host.configManager.cpuScheduler.DisableHyperThreading() - changed = results['result'][host.name]['changed'] = True - results['result'][host.name]['state_previous'] = "enabled" - results['result'][host.name]['state_current'] = "disabled" - results['result'][host.name]['msg'] = ( - "Hyperthreading disabled. Reboot the host to deactivate it." - ) - except vmodl.fault.NotSupported as not_supported: - # This should never happen since Hyperthreading is available - self.module.fail_json( - msg="Failed to disable Hyperthreading for host '%s' : %s" % - (host.name, to_native(not_supported.msg)) - ) - except (vmodl.RuntimeFault, vmodl.MethodFault) as runtime_fault: - self.module.fail_json( - msg="Failed to disable Hyperthreading for host '%s' due to : %s" % - (host.name, to_native(runtime_fault.msg)) - ) - else: - changed = results['result'][host.name]['changed'] = True - results['result'][host.name]['state_previous'] = "enabled" - results['result'][host.name]['state_current'] = "disabled" - results['result'][host.name]['msg'] = "Hyperthreading will be disabled" - else: - self.module.fail_json(msg="Hyperthreading optimization is not available for host '%s'" % host.name) - - host_change_list.append(changed) - - if any(host_change_list): - results['changed'] = True - self.module.exit_json(**results) - - -def main(): - """Main""" - argument_spec = vmware_argument_spec() - argument_spec.update( - state=dict(default='enabled', choices=['enabled', 'disabled']), - esxi_hostname=dict(type='str', required=False), - cluster_name=dict(type='str', required=False), - ) - - module = AnsibleModule(argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True - ) - - hyperthreading = VmwareHostHyperthreading(module) - hyperthreading.ensure() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_ipv6.py b/lib/ansible/modules/cloud/vmware/vmware_host_ipv6.py deleted file mode 100644 index e2affb1695..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_ipv6.py +++ /dev/null @@ -1,239 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# -# 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_host_ipv6 -short_description: Enables/Disables IPv6 support for an ESXi host system -description: -- This module can be used to enable or disable IPv6 support for ESXi host systems in given vCenter infrastructure. -- It also checks if the host needs to be restarted. -version_added: 2.8 -author: -- Christian Kotte (@ckotte) <christian.kotte@gmx.de> -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - state: - description: - - Enable or disable IPv6 support. - - You need to reboot the ESXi host if you change the configuration. - type: str - choices: [ enabled, disabled ] - default: 'enabled' - esxi_hostname: - description: - - Name of the host system to work with. - - This is required parameter if C(cluster_name) is not specified. - type: str - cluster_name: - description: - - Name of the cluster from which all host systems will be used. - - This is required parameter if C(esxi_hostname) is not specified. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Enable IPv6 for an host system - vmware_host_ipv6: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - state: enabled - validate_certs: no - delegate_to: localhost - -- name: Disable IPv6 for an host system - vmware_host_ipv6: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - state: disabled - validate_certs: no - delegate_to: localhost - -- name: Disable IPv6 for all host systems from cluster - vmware_host_ipv6: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: '{{ cluster_name }}' - state: disabled - validate_certs: no - delegate_to: localhost -''' - -RETURN = r''' -result: - description: metadata about host system's IPv6 configuration - returned: always - type: dict - sample: { - "esxi01": { - "changed": false, - "msg": "IPv6 is already enabled and active for host 'esxi01'", - }, - } -''' - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec -from ansible.module_utils._text import to_native - - -class VmwareHostIPv6(PyVmomi): - """Class to manage IPv6 for an ESXi host system""" - def __init__(self, module): - super(VmwareHostIPv6, self).__init__(module) - cluster_name = self.params.get('cluster_name') - esxi_host_name = self.params.get('esxi_hostname') - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - if not self.hosts: - self.module.fail_json(msg="Failed to find host system with given configuration.") - - def ensure(self): - """Manage IPv6 for an ESXi host system""" - results = dict(changed=False, result=dict()) - desired_state = self.module.params['state'] - - host_change_list = [] - for host in self.hosts: - changed = False - results['result'][host.name] = dict(msg='') - - host_network_system = host.configManager.networkSystem - host_network_info = host_network_system.networkInfo - - if desired_state == 'enabled': - # Don't do anything if IPv6 is already enabled - if host_network_info.atBootIpV6Enabled: - if host_network_info.ipV6Enabled: - results['result'][host.name]['msg'] = "IPv6 is already enabled and active for host '%s'" % \ - host.name - if not host_network_info.ipV6Enabled: - results['result'][host.name]['msg'] = ("IPv6 is already enabled for host '%s', but a reboot" - " is required!" % host.name) - # Enable IPv6 - else: - if not self.module.check_mode: - try: - config = vim.host.NetworkConfig() - config.ipV6Enabled = True - host_network_system.UpdateNetworkConfig(config, "modify") - changed = True - results['result'][host.name]['changed'] = True - results['result'][host.name]['msg'] = "IPv6 enabled for host '%s'" % host.name - except (vim.fault.AlreadyExists, vim.fault.NotFound): - self.module.fail_json(msg="Network entity specified in the configuration for host '%s'" - " already exists" % host.name) - except vmodl.fault.InvalidArgument as invalid_argument: - self.module.fail_json(msg="Invalid parameter specified for host '%s' : %s" % - (host.name, to_native(invalid_argument.msg))) - except vim.fault.HostConfigFault as config_fault: - self.module.fail_json(msg="Failed to enable IPv6 for host '%s' due to : %s" % - (host.name, to_native(config_fault.msg))) - except vmodl.fault.NotSupported as not_supported: - self.module.fail_json(msg="Failed to enable IPv6 for host '%s' due to : %s" % - (host.name, to_native(not_supported.msg))) - except (vmodl.RuntimeFault, vmodl.MethodFault) as runtime_fault: - self.module.fail_json(msg="Failed to enable IPv6 for host '%s' due to : %s" % - (host.name, to_native(runtime_fault.msg))) - else: - changed = True - results['result'][host.name]['changed'] = True - results['result'][host.name]['msg'] = "IPv6 will be enabled for host '%s'" % host.name - elif desired_state == 'disabled': - # Don't do anything if IPv6 is already disabled - if not host_network_info.atBootIpV6Enabled: - if not host_network_info.ipV6Enabled: - results['result'][host.name]['msg'] = "IPv6 is already disabled for host '%s'" % host.name - if host_network_info.ipV6Enabled: - changed = True - results['result'][host.name]['msg'] = ("IPv6 is already disabled for host '%s'," - " but a reboot is required!" % host.name) - # Disable IPv6 - else: - if not self.module.check_mode: - try: - config = vim.host.NetworkConfig() - config.ipV6Enabled = False - host_network_system.UpdateNetworkConfig(config, "modify") - changed = True - results['result'][host.name]['changed'] = True - results['result'][host.name]['msg'] = "IPv6 disabled for host '%s'" % host.name - except (vim.fault.AlreadyExists, vim.fault.NotFound): - self.module.fail_json(msg="Network entity specified in the configuration for host '%s'" - " already exists" % host.name) - except vmodl.fault.InvalidArgument as invalid_argument: - self.module.fail_json(msg="Invalid parameter specified for host '%s' : %s" % - (host.name, to_native(invalid_argument.msg))) - except vim.fault.HostConfigFault as config_fault: - self.module.fail_json(msg="Failed to disable IPv6 for host '%s' due to : %s" % - (host.name, to_native(config_fault.msg))) - except vmodl.fault.NotSupported as not_supported: - self.module.fail_json(msg="Failed to disable IPv6 for host '%s' due to : %s" % - (host.name, to_native(not_supported.msg))) - except (vmodl.RuntimeFault, vmodl.MethodFault) as runtime_fault: - self.module.fail_json(msg="Failed to disable IPv6 for host '%s' due to : %s" % - (host.name, to_native(runtime_fault.msg))) - else: - changed = True - results['result'][host.name]['changed'] = True - results['result'][host.name]['msg'] = "IPv6 will be disabled for host '%s'" % host.name - - host_change_list.append(changed) - - if any(host_change_list): - results['changed'] = True - self.module.exit_json(**results) - - -def main(): - """ - Main - """ - argument_spec = vmware_argument_spec() - argument_spec.update( - state=dict(default='enabled', choices=['enabled', 'disabled']), - esxi_hostname=dict(type='str', required=False), - cluster_name=dict(type='str', required=False), - ) - - module = AnsibleModule(argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True - ) - - ipv6 = VmwareHostIPv6(module) - ipv6.ensure() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_kernel_manager.py b/lib/ansible/modules/cloud/vmware/vmware_host_kernel_manager.py deleted file mode 100644 index ceef3db8e0..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_kernel_manager.py +++ /dev/null @@ -1,217 +0,0 @@ -#!/usr/bin/python - -# Copyright: (c) 2019, Aaron Longchamps, <a.j.longchamps@gmail.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_host_kernel_manager -short_description: Manage kernel module options on ESXi hosts -description: -- This module can be used to manage kernel module options on ESXi hosts. -- All connected ESXi hosts in scope will be configured when specified. -- If a host is not connected at time of configuration, it will be marked as such in the output. -- Kernel module options may require a reboot to take effect which is not covered here. -- You can use M(reboot) or M(vmware_host_powerstate) module to reboot all ESXi host systems. -version_added: '2.8' -author: -- Aaron Longchamps (@alongchamps) -notes: -- Tested on vSphere 6.0 -requirements: -- python >= 2.7 -- PyVmomi -options: - esxi_hostname: - description: - - Name of the ESXi host to work on. - - This parameter is required if C(cluster_name) is not specified. - type: str - cluster_name: - description: - - Name of the VMware cluster to work on. - - All ESXi hosts in this cluster will be configured. - - This parameter is required if C(esxi_hostname) is not specified. - type: str - kernel_module_name: - description: - - Name of the kernel module to be configured. - required: true - type: str - kernel_module_option: - description: - - Specified configurations will be applied to the given module. - - These values are specified in key=value pairs and separated by a space when there are multiple options. - required: true - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Configure IPv6 to be off via tcpip4 kernel module - vmware_host_kernel_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - kernel_module_name: "tcpip4" - kernel_module_option: "ipv6=0" - -- name: Using cluster_name, configure vmw_psp_rr options - vmware_host_kernel_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: '{{ virtual_cluster_name }}' - kernel_module_name: "vmw_psp_rr" - kernel_module_option: "maxPathsPerDevice=2" -''' - -RETURN = r''' -host_kernel_status: - description: - - dict with information on what was changed, by ESXi host in scope. - returned: success - type: dict - sample: { - "results": { - "myhost01.example.com": { - "changed": true, - "configured_options": "ipv6=0", - "msg": "Options have been changed on the kernel module", - "original_options": "ipv6=1" - } - } -} -''' - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi -from ansible.module_utils._text import to_native - - -class VmwareKernelManager(PyVmomi): - def __init__(self, module): - self.module = module - super(VmwareKernelManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - self.kernel_module_name = self.params.get('kernel_module_name') - self.kernel_module_option = self.params.get('kernel_module_option') - self.results = {} - - if not self.hosts: - self.module.fail_json(msg="Failed to find a host system that matches the specified criteria") - - # find kernel module options for a given kmod_name. If the name is not right, this will throw an exception - def get_kernel_module_option(self, host, kmod_name): - host_kernel_manager = host.configManager.kernelModuleSystem - - try: - return host_kernel_manager.QueryConfiguredModuleOptionString(self.kernel_module_name) - except vim.fault.NotFound as kernel_fault: - self.module.fail_json(msg="Failed to find kernel module on host '%s'. More information: %s" % (host.name, to_native(kernel_fault.msg))) - - # configure the provided kernel module with the specified options - def apply_kernel_module_option(self, host, kmod_name, kmod_option): - host_kernel_manager = host.configManager.kernelModuleSystem - - if host_kernel_manager: - try: - if not self.module.check_mode: - host_kernel_manager.UpdateModuleOptionString(kmod_name, kmod_option) - except vim.fault.NotFound as kernel_fault: - self.module.fail_json(msg="Failed to find kernel module on host '%s'. More information: %s" % (host.name, to_native(kernel_fault))) - except Exception as kernel_fault: - self.module.fail_json(msg="Failed to configure kernel module for host '%s' due to: %s" % (host.name, to_native(kernel_fault))) - - # evaluate our current configuration against desired options and save results - def check_host_configuration_state(self): - change_list = [] - - for host in self.hosts: - changed = False - msg = "" - self.results[host.name] = dict() - - if host.runtime.connectionState == "connected": - host_kernel_manager = host.configManager.kernelModuleSystem - - if host_kernel_manager: - # keep track of original options on the kernel module - original_options = self.get_kernel_module_option(host, self.kernel_module_name) - desired_options = self.kernel_module_option - - # apply as needed, also depending on check mode - if original_options != desired_options: - changed = True - if self.module.check_mode: - msg = "Options would be changed on the kernel module" - else: - self.apply_kernel_module_option(host, self.kernel_module_name, desired_options) - msg = "Options have been changed on the kernel module" - self.results[host.name]['configured_options'] = desired_options - else: - msg = "Options are already the same" - - change_list.append(changed) - self.results[host.name]['changed'] = changed - self.results[host.name]['msg'] = msg - self.results[host.name]['original_options'] = original_options - - else: - msg = "No kernel module manager found on host %s - impossible to configure." % host.name - self.results[host.name]['changed'] = changed - self.results[host.name]['msg'] = msg - else: - msg = "Host %s is disconnected and cannot be changed." % host.name - self.results[host.name]['changed'] = changed - self.results[host.name]['msg'] = msg - - self.module.exit_json(changed=any(change_list), host_kernel_status=self.results) - - -def main(): - argument_spec = vmware_argument_spec() - # add the arguments we're going to use for this module - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - kernel_module_name=dict(type='str', required=True), - kernel_module_option=dict(type='str', required=True), - ) - - # make sure we have a valid target cluster_name or esxi_hostname (not both) - # and also enable check mode - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - mutually_exclusive=[ - ['cluster_name', 'esxi_hostname'], - ], - ) - - vmware_host_config = VmwareKernelManager(module) - vmware_host_config.check_host_configuration_state() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_lockdown.py b/lib/ansible/modules/cloud/vmware/vmware_host_lockdown.py deleted file mode 100644 index f0a4ee5268..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_lockdown.py +++ /dev/null @@ -1,216 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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_host_lockdown -short_description: Manage administrator permission for the local administrative account for the ESXi host -description: -- This module can be used to manage administrator permission for the local administrative account for the host when ESXi hostname is given. -- All parameters and VMware objects values are case sensitive. -- This module is destructive as administrator permission are managed using APIs used, please read options carefully and proceed. -- Please specify C(hostname) as vCenter IP or hostname only, as lockdown operations are not possible from standalone ESXi server. -version_added: '2.5' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of cluster. - - All host systems from given cluster used to manage lockdown. - - Required parameter, if C(esxi_hostname) is not set. - type: str - esxi_hostname: - description: - - List of ESXi hostname to manage lockdown. - - Required parameter, if C(cluster_name) is not set. - - See examples for specifications. - type: list - state: - description: - - State of hosts system - - If set to C(present), all host systems will be set in lockdown mode. - - If host system is already in lockdown mode and set to C(present), no action will be taken. - - If set to C(absent), all host systems will be removed from lockdown mode. - - If host system is already out of lockdown mode and set to C(absent), no action will be taken. - default: present - choices: [ present, absent ] - version_added: 2.5 - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Enter host system into lockdown mode - vmware_host_lockdown: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - state: present - delegate_to: localhost - -- name: Exit host systems from lockdown mode - vmware_host_lockdown: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - state: absent - delegate_to: localhost - -- name: Enter host systems into lockdown mode - vmware_host_lockdown: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: - - '{{ esxi_hostname_1 }}' - - '{{ esxi_hostname_2 }}' - state: present - delegate_to: localhost - -- name: Exit host systems from lockdown mode - vmware_host_lockdown: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: - - '{{ esxi_hostname_1 }}' - - '{{ esxi_hostname_2 }}' - state: absent - delegate_to: localhost - -- name: Enter all host system from cluster into lockdown mode - vmware_host_lockdown: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: '{{ cluster_name }}' - state: present - delegate_to: localhost -''' - -RETURN = r''' -results: - description: metadata about state of Host system lock down - returned: always - type: dict - sample: { - "host_lockdown_state": { - "DC0_C0": { - "current_state": "present", - "previous_state": "absent", - "desired_state": "present", - }, - } - } -''' - -try: - from pyvmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi -from ansible.module_utils._text import to_native - - -class VmwareLockdownManager(PyVmomi): - def __init__(self, module): - super(VmwareLockdownManager, self).__init__(module) - if not self.is_vcenter(): - self.module.fail_json(msg="Lockdown operations are performed from vCenter only. " - "hostname %s is an ESXi server. Please specify hostname " - "as vCenter server." % self.module.params['hostname']) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - - def ensure(self): - """ - Function to manage internal state management - """ - results = dict(changed=False, host_lockdown_state=dict()) - change_list = [] - desired_state = self.params.get('state') - for host in self.hosts: - results['host_lockdown_state'][host.name] = dict(current_state='', - desired_state=desired_state, - previous_state='' - ) - changed = False - try: - if host.config.adminDisabled: - results['host_lockdown_state'][host.name]['previous_state'] = 'present' - if desired_state == 'absent': - host.ExitLockdownMode() - results['host_lockdown_state'][host.name]['current_state'] = 'absent' - changed = True - else: - results['host_lockdown_state'][host.name]['current_state'] = 'present' - elif not host.config.adminDisabled: - results['host_lockdown_state'][host.name]['previous_state'] = 'absent' - if desired_state == 'present': - host.EnterLockdownMode() - results['host_lockdown_state'][host.name]['current_state'] = 'present' - changed = True - else: - results['host_lockdown_state'][host.name]['current_state'] = 'absent' - except vim.fault.HostConfigFault as host_config_fault: - self.module.fail_json(msg="Failed to manage lockdown mode for esxi" - " hostname %s : %s" % (host.name, to_native(host_config_fault.msg))) - except vim.fault.AdminDisabled as admin_disabled: - self.module.fail_json(msg="Failed to manage lockdown mode as administrator " - "permission has been disabled for " - "esxi hostname %s : %s" % (host.name, to_native(admin_disabled.msg))) - except Exception as generic_exception: - self.module.fail_json(msg="Failed to manage lockdown mode due to generic exception for esxi " - "hostname %s : %s" % (host.name, to_native(generic_exception))) - change_list.append(changed) - - if any(change_list): - results['changed'] = True - - self.module.exit_json(**results) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='list', required=False), - state=dict(type='str', default='present', choices=['present', 'absent'], required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ] - ) - - vmware_lockdown_mgr = VmwareLockdownManager(module) - vmware_lockdown_mgr.ensure() - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_ntp.py b/lib/ansible/modules/cloud/vmware/vmware_host_ntp.py deleted file mode 100644 index 6f4d08e9e1..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_ntp.py +++ /dev/null @@ -1,391 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# 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_host_ntp -short_description: Manage NTP server configuration of an ESXi host -description: -- This module can be used to configure, add or remove NTP servers from an ESXi host. -- If C(state) is not given, the NTP servers will be configured in the exact sequence. -- User can specify an ESXi hostname or Cluster name. In case of cluster name, all ESXi hosts are updated. -version_added: '2.5' -author: -- Abhijeet Kasurde (@Akasurde) -- Christian Kotte (@ckotte) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - esxi_hostname: - description: - - Name of the host system to work with. - - This parameter is required if C(cluster_name) is not specified. - type: str - cluster_name: - description: - - Name of the cluster from which all host systems will be used. - - This parameter is required if C(esxi_hostname) is not specified. - type: str - ntp_servers: - description: - - "IP or FQDN of NTP server(s)." - - This accepts a list of NTP servers. For multiple servers, please look at the examples. - type: list - required: True - state: - description: - - "present: Add NTP server(s), if specified server(s) are absent else do nothing." - - "absent: Remove NTP server(s), if specified server(s) are present else do nothing." - - Specified NTP server(s) will be configured if C(state) isn't specified. - choices: [ present, absent ] - type: str - verbose: - description: - - Verbose output of the configuration change. - - Explains if an NTP server was added, removed, or if the NTP server sequence was changed. - type: bool - required: false - default: false - version_added: 2.8 -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Configure NTP servers for an ESXi Host - vmware_host_ntp: - hostname: vcenter01.example.local - username: administrator@vsphere.local - password: SuperSecretPassword - esxi_hostname: esx01.example.local - ntp_servers: - - 0.pool.ntp.org - - 1.pool.ntp.org - delegate_to: localhost - -- name: Set NTP servers for all ESXi Host in given Cluster - vmware_host_ntp: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: '{{ cluster_name }}' - state: present - ntp_servers: - - 0.pool.ntp.org - - 1.pool.ntp.org - delegate_to: localhost - -- name: Set NTP servers for an ESXi Host - vmware_host_ntp: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - state: present - ntp_servers: - - 0.pool.ntp.org - - 1.pool.ntp.org - delegate_to: localhost - -- name: Remove NTP servers for an ESXi Host - vmware_host_ntp: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - state: absent - ntp_servers: - - bad.server.ntp.org - delegate_to: localhost -''' - -RETURN = r''' -host_ntp_status: - description: metadata about host system's NTP configuration - returned: always - type: dict - sample: { - "esx01.example.local": { - "ntp_servers_changed": ["time1.example.local", "time2.example.local", "time3.example.local", "time4.example.local"], - "ntp_servers": ["time3.example.local", "time4.example.local"], - "ntp_servers_previous": ["time1.example.local", "time2.example.local"], - }, - "esx02.example.local": { - "ntp_servers_changed": ["time3.example.local"], - "ntp_servers_current": ["time1.example.local", "time2.example.local", "time3.example.local"], - "state": "present", - "ntp_servers_previous": ["time1.example.local", "time2.example.local"], - }, - } -''' - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi -from ansible.module_utils._text import to_native - - -class VmwareNtpConfigManager(PyVmomi): - """Class to manage configured NTP servers""" - - def __init__(self, module): - super(VmwareNtpConfigManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.ntp_servers = self.params.get('ntp_servers', list()) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - if not self.hosts: - self.module.fail_json(msg="Failed to find host system.") - self.results = {} - self.desired_state = self.params.get('state', None) - self.verbose = module.params.get('verbose', False) - - def update_ntp_servers(self, host, ntp_servers_configured, ntp_servers_to_change, operation='overwrite'): - """Update NTP server configuration""" - host_date_time_manager = host.configManager.dateTimeSystem - if host_date_time_manager: - # Prepare new NTP server list - if operation == 'overwrite': - new_ntp_servers = list(ntp_servers_to_change) - else: - new_ntp_servers = list(ntp_servers_configured) - if operation == 'add': - new_ntp_servers = new_ntp_servers + ntp_servers_to_change - elif operation == 'delete': - for server in ntp_servers_to_change: - if server in new_ntp_servers: - new_ntp_servers.remove(server) - - # build verbose message - if self.verbose: - message = self.build_changed_message( - ntp_servers_configured, - new_ntp_servers, - ntp_servers_to_change, - operation - ) - - ntp_config_spec = vim.host.NtpConfig() - ntp_config_spec.server = new_ntp_servers - date_config_spec = vim.host.DateTimeConfig() - date_config_spec.ntpConfig = ntp_config_spec - try: - if not self.module.check_mode: - host_date_time_manager.UpdateDateTimeConfig(date_config_spec) - if self.verbose: - self.results[host.name]['msg'] = message - except vim.fault.HostConfigFault as config_fault: - self.module.fail_json( - msg="Failed to configure NTP for host '%s' due to : %s" % - (host.name, to_native(config_fault.msg)) - ) - - return new_ntp_servers - - def check_host_state(self): - """Check ESXi host configuration""" - change_list = [] - changed = False - for host in self.hosts: - self.results[host.name] = dict() - ntp_servers_configured, ntp_servers_to_change = self.check_ntp_servers(host=host) - # add/remove NTP servers - if self.desired_state: - self.results[host.name]['state'] = self.desired_state - if ntp_servers_to_change: - self.results[host.name]['ntp_servers_changed'] = ntp_servers_to_change - operation = 'add' if self.desired_state == 'present' else 'delete' - new_ntp_servers = self.update_ntp_servers( - host=host, - ntp_servers_configured=ntp_servers_configured, - ntp_servers_to_change=ntp_servers_to_change, - operation=operation - ) - self.results[host.name]['ntp_servers_current'] = new_ntp_servers - self.results[host.name]['changed'] = True - change_list.append(True) - else: - self.results[host.name]['ntp_servers_current'] = ntp_servers_configured - if self.verbose: - self.results[host.name]['msg'] = ( - "NTP servers already added" if self.desired_state == 'present' - else "NTP servers already removed" - ) - self.results[host.name]['changed'] = False - change_list.append(False) - # overwrite NTP servers - else: - self.results[host.name]['ntp_servers'] = self.ntp_servers - if ntp_servers_to_change: - self.results[host.name]['ntp_servers_changed'] = self.get_differt_entries( - ntp_servers_configured, - ntp_servers_to_change - ) - self.update_ntp_servers( - host=host, - ntp_servers_configured=ntp_servers_configured, - ntp_servers_to_change=ntp_servers_to_change, - operation='overwrite' - ) - self.results[host.name]['changed'] = True - change_list.append(True) - else: - if self.verbose: - self.results[host.name]['msg'] = "NTP servers already configured" - self.results[host.name]['changed'] = False - change_list.append(False) - - if any(change_list): - changed = True - self.module.exit_json(changed=changed, host_ntp_status=self.results) - - def check_ntp_servers(self, host): - """Check configured NTP servers""" - update_ntp_list = [] - host_datetime_system = host.configManager.dateTimeSystem - if host_datetime_system: - ntp_servers_configured = host_datetime_system.dateTimeInfo.ntpConfig.server - # add/remove NTP servers - if self.desired_state: - for ntp_server in self.ntp_servers: - if self.desired_state == 'present' and ntp_server not in ntp_servers_configured: - update_ntp_list.append(ntp_server) - if self.desired_state == 'absent' and ntp_server in ntp_servers_configured: - update_ntp_list.append(ntp_server) - # overwrite NTP servers - else: - if ntp_servers_configured != self.ntp_servers: - for ntp_server in self.ntp_servers: - update_ntp_list.append(ntp_server) - if update_ntp_list: - self.results[host.name]['ntp_servers_previous'] = ntp_servers_configured - - return ntp_servers_configured, update_ntp_list - - def build_changed_message(self, ntp_servers_configured, new_ntp_servers, ntp_servers_to_change, operation): - """Build changed message""" - check_mode = 'would be ' if self.module.check_mode else '' - if operation == 'overwrite': - # get differences - add = self.get_not_in_list_one(new_ntp_servers, ntp_servers_configured) - remove = self.get_not_in_list_one(ntp_servers_configured, new_ntp_servers) - diff_servers = list(ntp_servers_configured) - if add and remove: - for server in add: - diff_servers.append(server) - for server in remove: - diff_servers.remove(server) - if new_ntp_servers != diff_servers: - message = ( - "NTP server %s %sadded and %s %sremoved and the server sequence %schanged as well" % - (self.array_to_string(add), check_mode, self.array_to_string(remove), check_mode, check_mode) - ) - else: - if new_ntp_servers != ntp_servers_configured: - message = ( - "NTP server %s %sreplaced with %s" % - (self.array_to_string(remove), check_mode, self.array_to_string(add)) - ) - else: - message = ( - "NTP server %s %sremoved and %s %sadded" % - (self.array_to_string(remove), check_mode, self.array_to_string(add), check_mode) - ) - elif add: - for server in add: - diff_servers.append(server) - if new_ntp_servers != diff_servers: - message = ( - "NTP server %s %sadded and the server sequence %schanged as well" % - (self.array_to_string(add), check_mode, check_mode) - ) - else: - message = "NTP server %s %sadded" % (self.array_to_string(add), check_mode) - elif remove: - for server in remove: - diff_servers.remove(server) - if new_ntp_servers != diff_servers: - message = ( - "NTP server %s %sremoved and the server sequence %schanged as well" % - (self.array_to_string(remove), check_mode, check_mode) - ) - else: - message = "NTP server %s %sremoved" % (self.array_to_string(remove), check_mode) - else: - message = "NTP server sequence %schanged" % check_mode - elif operation == 'add': - message = "NTP server %s %sadded" % (self.array_to_string(ntp_servers_to_change), check_mode) - elif operation == 'delete': - message = "NTP server %s %sremoved" % (self.array_to_string(ntp_servers_to_change), check_mode) - - return message - - @staticmethod - def get_not_in_list_one(list1, list2): - """Return entries that ore not in list one""" - return [x for x in list1 if x not in set(list2)] - - @staticmethod - def array_to_string(array): - """Return string from array""" - if len(array) > 2: - string = ( - ', '.join("'{0}'".format(element) for element in array[:-1]) + ', and ' - + "'{0}'".format(str(array[-1])) - ) - elif len(array) == 2: - string = ' and '.join("'{0}'".format(element) for element in array) - elif len(array) == 1: - string = "'{0}'".format(array[0]) - return string - - @staticmethod - def get_differt_entries(list1, list2): - """Return different entries of two lists""" - return [a for a in list1 + list2 if (a not in list1) or (a not in list2)] - - -def main(): - """Main""" - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - ntp_servers=dict(type='list', required=True), - state=dict(type='str', choices=['absent', 'present']), - verbose=dict(type='bool', default=False, required=False) - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True - ) - - vmware_host_ntp_config = VmwareNtpConfigManager(module) - vmware_host_ntp_config.check_host_state() - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_ntp_info.py b/lib/ansible/modules/cloud/vmware/vmware_host_ntp_info.py deleted file mode 100644 index 48dd0f41e3..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_ntp_info.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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_host_ntp_info -short_description: Gathers info about NTP configuration on an ESXi host -description: -- This module can be used to gather information about NTP configurations on an ESXi host. -version_added: '2.9' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of the cluster. - - NTP config information about each ESXi server will be returned for the given cluster. - - If C(esxi_hostname) is not given, this parameter is required. - type: str - esxi_hostname: - description: - - ESXi hostname. - - NTP config information about this ESXi server will be returned. - - If C(cluster_name) is not given, this parameter is required. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather NTP info about all ESXi Host in the given Cluster - vmware_host_ntp_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: cluster_name - delegate_to: localhost - register: cluster_host_ntp - -- name: Gather NTP info about ESXi Host - vmware_host_ntp_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - delegate_to: localhost - register: host_ntp -''' - -RETURN = r''' -hosts_ntp_info: - description: - - dict with hostname as key and dict with NTP infos as value - returned: hosts_ntp_info - type: dict - sample: { - "10.76.33.226": [ - { - "ntp_servers": [], - "time_zone_description": "UTC", - "time_zone_gmt_offset": 0, - "time_zone_identifier": "UTC", - "time_zone_name": "UTC" - } - ] - } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class VmwareNtpInfoManager(PyVmomi): - def __init__(self, module): - super(VmwareNtpInfoManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - - def gather_ntp_info(self): - hosts_info = {} - for host in self.hosts: - host_ntp_info = [] - host_date_time_manager = host.configManager.dateTimeSystem - if host_date_time_manager: - host_ntp_info.append( - dict( - time_zone_identifier=host_date_time_manager.dateTimeInfo.timeZone.key, - time_zone_name=host_date_time_manager.dateTimeInfo.timeZone.name, - time_zone_description=host_date_time_manager.dateTimeInfo.timeZone.description, - time_zone_gmt_offset=host_date_time_manager.dateTimeInfo.timeZone.gmtOffset, - ntp_servers=[ntp_server for ntp_server in host_date_time_manager.dateTimeInfo.ntpConfig.server] - ) - ) - hosts_info[host.name] = host_ntp_info - return hosts_info - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True, - ) - - vmware_host_ntp_config = VmwareNtpInfoManager(module) - module.exit_json(changed=False, hosts_ntp_info=vmware_host_ntp_config.gather_ntp_info()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_package_info.py b/lib/ansible/modules/cloud/vmware/vmware_host_package_info.py deleted file mode 100644 index b796b5d64e..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_package_info.py +++ /dev/null @@ -1,128 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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_host_package_info -short_description: Gathers info about available packages on an ESXi host -description: -- This module can be used to gather information about available packages and their status on an ESXi host. -version_added: '2.9' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of the cluster. - - Package information about each ESXi server will be returned for given cluster. - - If C(esxi_hostname) is not given, this parameter is required. - type: str - esxi_hostname: - description: - - ESXi hostname. - - Package information about this ESXi server will be returned. - - If C(cluster_name) is not given, this parameter is required. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather info about all ESXi Host in given Cluster - vmware_host_package_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: cluster_name - delegate_to: localhost - register: cluster_host_packages - -- name: Gather info about ESXi Host - vmware_host_package_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - delegate_to: localhost - register: host_packages -''' - -RETURN = r''' -hosts_package_info: - description: - - dict with hostname as key and dict with package information as value - returned: hosts_package_info - type: dict - sample: { "hosts_package_info": { "localhost.localdomain": []}} -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class VmwarePackageManager(PyVmomi): - def __init__(self, module): - super(VmwarePackageManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - - def gather_package_info(self): - hosts_info = {} - for host in self.hosts: - host_package_info = [] - host_pkg_mgr = host.configManager.imageConfigManager - if host_pkg_mgr: - pkgs = host_pkg_mgr.FetchSoftwarePackages() - for pkg in pkgs: - host_package_info.append(dict( - name=pkg.name, - version=pkg.version, - vendor=pkg.vendor, - summary=pkg.summary, - description=pkg.description, - acceptance_level=pkg.acceptanceLevel, - maintenance_mode_required=pkg.maintenanceModeRequired, - creation_date=pkg.creationDate, - )) - hosts_info[host.name] = host_package_info - return hosts_info - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True, - ) - - vmware_host_package_config = VmwarePackageManager(module) - module.exit_json(changed=False, hosts_package_info=vmware_host_package_config.gather_package_info()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_powermgmt_policy.py b/lib/ansible/modules/cloud/vmware/vmware_host_powermgmt_policy.py deleted file mode 100644 index c3e1f510ef..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_powermgmt_policy.py +++ /dev/null @@ -1,235 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# -# 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_host_powermgmt_policy -short_description: Manages the Power Management Policy of an ESXI host system -description: -- This module can be used to manage the Power Management Policy of ESXi host systems in given vCenter infrastructure. -version_added: 2.8 -author: -- Christian Kotte (@ckotte) <christian.kotte@gmx.de> -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - policy: - description: - - Set the Power Management Policy of the host system. - choices: [ 'high-performance', 'balanced', 'low-power', 'custom' ] - default: 'balanced' - type: str - esxi_hostname: - description: - - Name of the host system to work with. - - This is required parameter if C(cluster_name) is not specified. - type: str - cluster_name: - description: - - Name of the cluster from which all host systems will be used. - - This is required parameter if C(esxi_hostname) is not specified. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Set the Power Management Policy of a host system to high-performance - vmware_host_powermgmt_policy: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_host }}' - policy: high-performance - validate_certs: no - delegate_to: localhost - -- name: Set the Power Management Policy of all host systems from cluster to high-performance - vmware_host_powermgmt_policy: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: '{{ cluster_name }}' - policy: high-performance - validate_certs: no - delegate_to: localhost -''' - -RETURN = r''' -result: - description: metadata about host system's Power Management Policy - returned: always - type: dict - sample: { - "changed": true, - "result": { - "esxi01": { - "changed": true, - "current_state": "high-performance", - "desired_state": "high-performance", - "msg": "Power policy changed", - "previous_state": "balanced" - } - } - } -''' - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec -from ansible.module_utils._text import to_native - - -class VmwareHostPowerManagement(PyVmomi): - """ - Class to manage power management policy of an ESXi host system - """ - def __init__(self, module): - super(VmwareHostPowerManagement, self).__init__(module) - cluster_name = self.params.get('cluster_name') - esxi_host_name = self.params.get('esxi_hostname') - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - if not self.hosts: - self.module.fail_json(msg="Failed to find host system with given configuration.") - - def ensure(self): - """ - Manage power management policy of an ESXi host system - """ - results = dict(changed=False, result=dict()) - policy = self.params.get('policy') - host_change_list = [] - power_policies = { - 'high-performance': { - 'key': 1, - 'short_name': 'static' - }, - 'balanced': { - 'key': 2, - 'short_name': 'dynamic' - }, - 'low-power': { - 'key': 3, - 'short_name': 'low' - }, - 'custom': { - 'key': 4, - 'short_name': 'custom' - } - } - - for host in self.hosts: - changed = False - results['result'][host.name] = dict(msg='') - - power_system = host.configManager.powerSystem - - # get current power policy - power_system_info = power_system.info - current_host_power_policy = power_system_info.currentPolicy - - # the "name" and "description" parameters are pretty useless - # they store only strings containing "PowerPolicy.<shortName>.name" and "PowerPolicy.<shortName>.description" - if current_host_power_policy.shortName == "static": - current_policy = 'high-performance' - elif current_host_power_policy.shortName == "dynamic": - current_policy = 'balanced' - elif current_host_power_policy.shortName == "low": - current_policy = 'low-power' - elif current_host_power_policy.shortName == "custom": - current_policy = 'custom' - - results['result'][host.name]['desired_state'] = policy - - # Don't do anything if the power policy is already configured - if current_host_power_policy.key == power_policies[policy]['key']: - results['result'][host.name]['changed'] = changed - results['result'][host.name]['previous_state'] = current_policy - results['result'][host.name]['current_state'] = policy - results['result'][host.name]['msg'] = "Power policy is already configured" - else: - # get available power policies and check if policy is included - supported_policy = False - power_system_capability = power_system.capability - available_host_power_policies = power_system_capability.availablePolicy - for available_policy in available_host_power_policies: - if available_policy.shortName == power_policies[policy]['short_name']: - supported_policy = True - if supported_policy: - if not self.module.check_mode: - try: - power_system.ConfigurePowerPolicy(key=power_policies[policy]['key']) - changed = True - results['result'][host.name]['changed'] = True - results['result'][host.name]['msg'] = "Power policy changed" - except vmodl.fault.InvalidArgument: - self.module.fail_json(msg="Invalid power policy key provided for host '%s'" % host.name) - except vim.fault.HostConfigFault as host_config_fault: - self.module.fail_json(msg="Failed to configure power policy for host '%s': %s" % - (host.name, to_native(host_config_fault.msg))) - else: - changed = True - results['result'][host.name]['changed'] = True - results['result'][host.name]['msg'] = "Power policy will be changed" - results['result'][host.name]['previous_state'] = current_policy - results['result'][host.name]['current_state'] = policy - else: - changed = False - results['result'][host.name]['changed'] = changed - results['result'][host.name]['previous_state'] = current_policy - results['result'][host.name]['current_state'] = current_policy - self.module.fail_json(msg="Power policy '%s' isn't supported for host '%s'" % - (policy, host.name)) - - host_change_list.append(changed) - - if any(host_change_list): - results['changed'] = True - self.module.exit_json(**results) - - -def main(): - """ - Main - """ - argument_spec = vmware_argument_spec() - argument_spec.update( - policy=dict(type='str', default='balanced', - choices=['high-performance', 'balanced', 'low-power', 'custom']), - esxi_hostname=dict(type='str', required=False), - cluster_name=dict(type='str', required=False), - ) - - module = AnsibleModule(argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True - ) - - host_power_management = VmwareHostPowerManagement(module) - host_power_management.ensure() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_powerstate.py b/lib/ansible/modules/cloud/vmware/vmware_host_powerstate.py deleted file mode 100644 index 5b952c65e0..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_powerstate.py +++ /dev/null @@ -1,225 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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_host_powerstate -short_description: Manages power states of host systems in vCenter -description: -- This module can be used to manage power states of host systems in given vCenter infrastructure. -- User can set power state to 'power-down-to-standby', 'power-up-from-standby', 'shutdown-host' and 'reboot-host'. -- State 'reboot-host', 'shutdown-host' and 'power-down-to-standby' are not supported by all the host systems. -version_added: 2.6 -author: -- Abhijeet Kasurde (@Akasurde) -requirements: -- python >= 2.6 -- PyVmomi -options: - state: - description: - - Set the state of the host system. - choices: [ 'power-down-to-standby', 'power-up-from-standby', 'shutdown-host', 'reboot-host' ] - default: 'shutdown-host' - type: str - esxi_hostname: - description: - - Name of the host system to work with. - - This is required parameter if C(cluster_name) is not specified. - type: str - cluster_name: - description: - - Name of the cluster from which all host systems will be used. - - This is required parameter if C(esxi_hostname) is not specified. - type: str - force: - description: - - 'This parameter specify if the host should be proceeding with user defined powerstate - regardless of whether it is in maintenance mode.' - - 'If C(state) set to C(reboot-host) and C(force) as C(true), then host system is rebooted regardless of whether it is in maintenance mode.' - - 'If C(state) set to C(shutdown-host) and C(force) as C(true), then host system is shutdown regardless of whether it is in maintenance mode.' - - 'If C(state) set to C(power-down-to-standby) and C(force) to C(true), then all powered off VMs will evacuated.' - - 'Not applicable if C(state) set to C(power-up-from-standby).' - type: bool - default: False - timeout: - description: - - 'This parameter defines timeout for C(state) set to C(power-down-to-standby) or C(power-up-from-standby).' - - 'Ignored if C(state) set to C(reboot-host) or C(shutdown-host).' - - 'This parameter is defined in seconds.' - default: 600 - type: int -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Set the state of a host system to reboot - vmware_host_powerstate: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - esxi_hostname: '{{ esxi_hostname }}' - state: reboot-host - delegate_to: localhost - register: reboot_host - -- name: Set the state of a host system to power down to standby - vmware_host_powerstate: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - esxi_hostname: '{{ esxi_hostname }}' - state: power-down-to-standby - delegate_to: localhost - register: power_down - -- name: Set the state of all host systems from cluster to reboot - vmware_host_powerstate: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - cluster_name: '{{ cluster_name }}' - state: reboot-host - delegate_to: localhost - register: reboot_host -''' - -RETURN = r''' -result: - description: metadata about host system's state - returned: always - type: dict - sample: { - "esxi01": { - "msg": "power down 'esxi01' to standby", - "error": "", - }, - } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec, wait_for_task, TaskError -from ansible.module_utils._text import to_native - - -class VmwareHostPowerManager(PyVmomi): - def __init__(self, module): - super(VmwareHostPowerManager, self).__init__(module) - cluster_name = self.params.get('cluster_name') - esxi_host_name = self.params.get('esxi_hostname') - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - if not self.hosts: - self.module.fail_json(msg="Failed to find host system with given configuration.") - - def ensure(self): - """ - Function to manage internal state of host system - - """ - results = dict(changed=False, result=dict()) - state = self.params.get('state') - force = self.params.get('force') - timeout = self.params.get('timeout') - host_change_list = [] - for host in self.hosts: - changed = False - if not host.runtime.inMaintenanceMode and not force: - self.module.fail_json(msg="Current host system '%s' is not in maintenance mode," - " please specify 'force' as True to proceed." % host.name) - if host.runtime.connectionState == 'notResponding': - self.module.fail_json(msg="Current host system '%s' can not be set in '%s'" - " mode as the host system is not responding." % (host.name, state)) - - results['result'][host.name] = dict(msg='', error='') - if state == 'reboot-host' and not host.capability.rebootSupported: - self.module.fail_json(msg="Current host '%s' can not be rebooted as the host system" - " does not have capability to reboot." % host.name) - elif state == 'shutdown-host' and not host.capability.shutdownSupported: - self.module.fail_json(msg="Current host '%s' can not be shut down as the host system" - " does not have capability to shut down." % host.name) - elif state in ['power-down-to-standby', 'power-up-from-standby'] and not host.capability.standbySupported: - self.module.fail_json(msg="Current host '%s' can not be '%s' as the host system" - " does not have capability to standby supported." % (host.name, state)) - - if state == 'reboot-host': - task = host.RebootHost_Task(force) - verb = "reboot '%s'" % host.name - elif state == 'shutdown-host': - task = host.ShutdownHost_Task(force) - verb = "shutdown '%s'" % host.name - elif state == 'power-down-to-standby': - task = host.PowerDownHostToStandBy_Task(timeout, force) - verb = "power down '%s' to standby" % host.name - elif state == 'power-up-from-standby': - task = host.PowerUpHostFromStandBy_Task(timeout) - verb = "power up '%s' from standby" % host.name - - if not self.module.check_mode: - try: - success, result = wait_for_task(task) - if success: - changed = True - results['result'][host.name]['msg'] = verb - else: - results['result'][host.name]['error'] = result - except TaskError as task_error: - self.module.fail_json(msg="Failed to %s as host system due to : %s" % (verb, - str(task_error))) - except Exception as generic_exc: - self.module.fail_json(msg="Failed to %s due to generic exception : %s" % (host.name, - to_native(generic_exc))) - else: - # Check mode - changed = True - results['result'][host.name]['msg'] = verb - - host_change_list.append(changed) - - if any(host_change_list): - results['changed'] = True - self.module.exit_json(**results) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - state=dict(type='str', default='shutdown-host', - choices=['power-down-to-standby', 'power-up-from-standby', 'shutdown-host', 'reboot-host']), - esxi_hostname=dict(type='str', required=False), - cluster_name=dict(type='str', required=False), - force=dict(type='bool', default=False), - timeout=dict(type='int', default=600), - - ) - - module = AnsibleModule(argument_spec=argument_spec, - supports_check_mode=True, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ] - ) - - host_power_manager = VmwareHostPowerManager(module) - host_power_manager.ensure() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_scanhba.py b/lib/ansible/modules/cloud/vmware/vmware_host_scanhba.py deleted file mode 100644 index 16109d1365..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_scanhba.py +++ /dev/null @@ -1,152 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Ansible Project -# 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_host_scanhba -short_description: Rescan host HBA's and optionally refresh the storage system -description: -- This module can force a rescan of the hosts HBA subsystem which is needed when wanting to mount a new datastore. -- You could use this before using M(vmware_host_datastore) to mount a new datastore to ensure your device/volume is ready. -- You can also optionally force a Refresh of the Storage System in vCenter/ESXi Web Client. -- All parameters and VMware object names are case sensitive. -- You can supply an esxi_hostname or a cluster_name -version_added: '2.8' -author: -- Michael Eaton (@michaeldeaton) -notes: -- Tested on vSphere 6.0 -requirements: -- python >= 2.6 -- PyVmomi -options: - esxi_hostname: - description: - - ESXi hostname to Rescan the storage subsystem on. - required: false - type: str - cluster_name: - description: - - Cluster name to Rescan the storage subsystem on (this will run the rescan task on each host in the cluster). - required: false - type: str - refresh_storage: - description: - - Refresh the storage system in vCenter/ESXi Web Client for each host found - required: false - default: false - type: bool -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Recan HBA's for a given ESXi host and refresh storage system objects - vmware_host_scanhba: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ inventory_hostname }}' - refresh_storage: true - delegate_to: localhost - -- name: Rescan HBA's for a given cluster - all found hosts will be scanned - vmware_host_scanhba: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ inventory_hostname }}' - refresh_storage: true - delegate_to: localhost - -- name: Recan HBA's for a given ESXi host and don't refresh storage system objects - vmware_host_scanhba: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ inventory_hostname }}' - delegate_to: localhost -''' - -RETURN = r''' -result: - description: return confirmation of requested host and updated / refreshed storage system - returned: always - type: dict - sample: { - "esxi01.example.com": { - "rescaned_hba": "true", - "refreshed_storage": "true" - } - } -''' - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi, find_obj -from ansible.module_utils._text import to_native - - -class VmwareHbaScan(PyVmomi): - def __init__(self, module): - super(VmwareHbaScan, self).__init__(module) - - def scan(self): - esxi_host_name = self.params.get('esxi_hostname', None) - cluster_name = self.params.get('cluster_name', None) - refresh_storage = self.params.get('refresh_storage', bool) - hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - results = dict(changed=True, result=dict()) - - if not hosts: - self.module.fail_json(msg="Failed to find any hosts.") - - for host in hosts: - results['result'][host.name] = dict() - host.configManager.storageSystem.RescanAllHba() - if refresh_storage is True: - host.configManager.storageSystem.RefreshStorageSystem() - - results['result'][host.name]['rescaned_hba'] = True - results['result'][host.name]['refreshed_storage'] = refresh_storage - - self.module.exit_json(**results) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - esxi_hostname=dict(type='str', required=False), - cluster_name=dict(type='str', required=False), - refresh_storage=dict(type='bool', default=False, required=False) - ) - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=False - ) - - hbascan = VmwareHbaScan(module) - hbascan.scan() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_service_info.py b/lib/ansible/modules/cloud/vmware/vmware_host_service_info.py deleted file mode 100644 index aca8140ef8..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_service_info.py +++ /dev/null @@ -1,154 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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_host_service_info -short_description: Gathers info about an ESXi host's services -description: -- This module can be used to gather information about an ESXi host's services. -version_added: '2.9' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -- If source package name is not available then fact is populated as null. -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of the cluster. - - Service information about each ESXi server will be returned for given cluster. - - If C(esxi_hostname) is not given, this parameter is required. - type: str - esxi_hostname: - description: - - ESXi hostname. - - Service information about this ESXi server will be returned. - - If C(cluster_name) is not given, this parameter is required. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather info about all ESXi Host in given Cluster - vmware_host_service_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: cluster_name - delegate_to: localhost - register: cluster_host_services - -- name: Gather info about ESXi Host - vmware_host_service_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - delegate_to: localhost - register: host_services -''' - -RETURN = r''' -host_service_info: - description: - - dict with hostname as key and dict with host service config information - returned: always - type: dict - sample: { - "10.76.33.226": [ - { - "key": "DCUI", - "label": "Direct Console UI", - "policy": "on", - "required": false, - "running": true, - "uninstallable": false, - "source_package_name": "esx-base", - "source_package_desc": "This VIB contains all of the base functionality of vSphere ESXi." - }, - { - "key": "TSM", - "label": "ESXi Shell", - "policy": "off", - "required": false, - "running": false, - "uninstallable": false, - "source_package_name": "esx-base", - "source_package_desc": "This VIB contains all of the base functionality of vSphere ESXi." - }, - ] - } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class VmwareServiceManager(PyVmomi): - def __init__(self, module): - super(VmwareServiceManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - - def gather_host_info(self): - hosts_info = {} - for host in self.hosts: - host_service_info = [] - host_service_system = host.configManager.serviceSystem - if host_service_system and host_service_system.serviceInfo: - services = host_service_system.serviceInfo.service - for service in services: - host_service_info.append( - dict( - key=service.key, - label=service.label, - required=service.required, - uninstallable=service.uninstallable, - running=service.running, - policy=service.policy, - source_package_name=service.sourcePackage.sourcePackageName if service.sourcePackage else None, - source_package_desc=service.sourcePackage.description if service.sourcePackage else None, - ) - ) - hosts_info[host.name] = host_service_info - return hosts_info - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True, - ) - - vmware_host_service_config = VmwareServiceManager(module) - module.exit_json(changed=False, host_service_info=vmware_host_service_config.gather_host_info()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_service_manager.py b/lib/ansible/modules/cloud/vmware/vmware_host_service_manager.py deleted file mode 100644 index 54bbd3c948..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_service_manager.py +++ /dev/null @@ -1,226 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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_host_service_manager -short_description: Manage services on a given ESXi host -description: -- This module can be used to manage (start, stop, restart) services on a given ESXi host. -- If cluster_name is provided, specified service will be managed on all ESXi host belonging to that cluster. -- If specific esxi_hostname is provided, then specified service will be managed on given ESXi host only. -version_added: '2.5' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of the cluster. - - Service settings are applied to every ESXi host system/s in given cluster. - - If C(esxi_hostname) is not given, this parameter is required. - type: str - esxi_hostname: - description: - - ESXi hostname. - - Service settings are applied to this ESXi host system. - - If C(cluster_name) is not given, this parameter is required. - type: str - state: - description: - - Desired state of service. - - "State value 'start' and 'present' has same effect." - - "State value 'stop' and 'absent' has same effect." - choices: [ absent, present, restart, start, stop ] - type: str - default: 'start' - service_policy: - description: - - Set of valid service policy strings. - - If set C(on), then service should be started when the host starts up. - - If set C(automatic), then service should run if and only if it has open firewall ports. - - If set C(off), then Service should not be started when the host starts up. - choices: [ 'automatic', 'off', 'on' ] - type: str - service_name: - description: - - Name of Service to be managed. This is a brief identifier for the service, for example, ntpd, vxsyslogd etc. - - This value should be a valid ESXi service name. - required: True - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Start ntpd service setting for all ESXi Host in given Cluster - vmware_host_service_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: '{{ cluster_name }}' - service_name: ntpd - state: present - delegate_to: localhost - -- name: Start ntpd setting for an ESXi Host - vmware_host_service_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - service_name: ntpd - state: present - delegate_to: localhost - -- name: Start ntpd setting for an ESXi Host with Service policy - vmware_host_service_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - service_name: ntpd - service_policy: on - state: present - delegate_to: localhost - -- name: Stop ntpd setting for an ESXi Host - vmware_host_service_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - service_name: ntpd - state: absent - delegate_to: localhost -''' - -RETURN = r'''# -''' - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi -from ansible.module_utils._text import to_native - - -class VmwareServiceManager(PyVmomi): - def __init__(self, module): - super(VmwareServiceManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.options = self.params.get('options', dict()) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - self.desired_state = self.params.get('state') - self.desired_policy = self.params.get('service_policy', None) - self.service_name = self.params.get('service_name') - self.results = {} - - def service_ctrl(self): - changed = False - host_service_state = [] - for host in self.hosts: - actual_service_state, actual_service_policy = self.check_service_state(host=host, service_name=self.service_name) - host_service_system = host.configManager.serviceSystem - if host_service_system: - changed_state = False - self.results[host.name] = dict(service_name=self.service_name, - actual_service_state='running' if actual_service_state else 'stopped', - actual_service_policy=actual_service_policy, - desired_service_policy=self.desired_policy, - desired_service_state=self.desired_state, - error='', - ) - try: - if self.desired_state in ['start', 'present']: - if not actual_service_state: - if not self.module.check_mode: - host_service_system.StartService(id=self.service_name) - changed_state = True - elif self.desired_state in ['stop', 'absent']: - if actual_service_state: - if not self.module.check_mode: - host_service_system.StopService(id=self.service_name) - changed_state = True - elif self.desired_state == 'restart': - if not self.module.check_mode: - host_service_system.RestartService(id=self.service_name) - changed_state = True - - if self.desired_policy: - if actual_service_policy != self.desired_policy: - if not self.module.check_mode: - host_service_system.UpdateServicePolicy(id=self.service_name, - policy=self.desired_policy) - changed_state = True - - host_service_state.append(changed_state) - self.results[host.name].update(changed=changed_state) - except (vim.fault.InvalidState, vim.fault.NotFound, - vim.fault.HostConfigFault, vmodl.fault.InvalidArgument) as e: - self.results[host.name].update(changed=False, - error=to_native(e.msg)) - - if any(host_service_state): - changed = True - self.module.exit_json(changed=changed, host_service_status=self.results) - - def check_service_state(self, host, service_name): - host_service_system = host.configManager.serviceSystem - if host_service_system: - services = host_service_system.serviceInfo.service - for service in services: - if service.key == service_name: - return service.running, service.policy - - msg = "Failed to find '%s' service on host system '%s'" % (service_name, host.name) - cluster_name = self.params.get('cluster_name', None) - if cluster_name: - msg += " located on cluster '%s'" % cluster_name - msg += ", please check if you have specified a valid ESXi service name." - self.module.fail_json(msg=msg) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - state=dict(type='str', default='start', choices=['absent', 'present', 'restart', 'start', 'stop']), - service_name=dict(type='str', required=True), - service_policy=dict(type='str', choices=['automatic', 'off', 'on']), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True - ) - - vmware_host_service = VmwareServiceManager(module) - vmware_host_service.service_ctrl() - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_snmp.py b/lib/ansible/modules/cloud/vmware/vmware_host_snmp.py deleted file mode 100644 index e633e84198..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_snmp.py +++ /dev/null @@ -1,492 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# -# 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 = ''' ---- -module: vmware_host_snmp -short_description: Configures SNMP on an ESXi host system -description: -- This module can be used to configure the embedded SNMP agent on an ESXi host. -version_added: 2.8 -author: -- Christian Kotte (@ckotte) -notes: -- Tested on vSphere 6.5 -- You need to reset the agent (to factory defaults) if you want to clear all community strings, trap targets, or filters -- SNMP v3 configuration isn't implemented yet -requirements: -- python >= 2.6 -- PyVmomi -options: - state: - description: - - Enable, disable, or reset the SNMP agent. - type: str - choices: [ disabled, enabled, reset ] - default: disabled - community: - description: - - List of SNMP community strings. - type: list - snmp_port: - description: - - Port used by the SNMP agent. - type: int - default: 161 - trap_targets: - description: - - A list of trap targets. - - You need to use C(hostname), C(port), and C(community) for each trap target. - default: [] - type: list - trap_filter: - description: - - A list of trap oids for traps not to be sent by agent, - e.g. [ 1.3.6.1.4.1.6876.4.1.1.0, 1.3.6.1.4.1.6876.4.1.1.1 ] - - Use value C(reset) to clear settings. - type: list - send_trap: - description: - - Send a test trap to validate the configuration. - type: bool - default: false - hw_source: - description: - - Source hardware events from IPMI sensors or CIM Indications. - - The embedded SNMP agent receives hardware events either from IPMI sensors C(sensors) or CIM indications C(indications). - type: str - choices: [ indications, sensors ] - default: indications - log_level: - description: - - Syslog logging level. - type: str - choices: [ debug, info, warning, error ] - default: info -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Enable and configure SNMP community - vmware_host_snmp: - hostname: '{{ esxi_hostname }}' - username: '{{ esxi_username }}' - password: '{{ esxi_password }}' - community: [ test ] - state: enabled - validate_certs: no - delegate_to: localhost - -- name: Configure SNMP traps and filters - vmware_host_snmp: - hostname: '{{ esxi_hostname }}' - username: '{{ esxi_username }}' - password: '{{ esxi_password }}' - community: [ test ] - trap_targets: - - hostname: 192.168.1.100 - port: 162 - community: test123 - - hostname: 192.168.1.101 - port: 162 - community: test1234 - trap_filter: - - 1.3.6.1.4.1.6876.4.1.1.0 - - 1.3.6.1.4.1.6876.4.1.1.1 - state: enabled - validate_certs: no - delegate_to: localhost - -- name: Disable SNMP - vmware_host_snmp: - hostname: '{{ esxi_hostname }}' - username: '{{ esxi_username }}' - password: '{{ esxi_password }}' - state: disabled - validate_certs: no - delegate_to: localhost -''' - -RETURN = r''' -results: - description: metadata about host system's SNMP configuration - returned: always - type: dict - sample: { - "esxi01": { - "changed": false, - "community": ["test"], - "hw_source": "indications", - "msg": "SNMP already configured properly", - "port": 161, - "state": "enabled", - "trap_targets": [] - }, - } -''' - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec, find_obj -from ansible.module_utils._text import to_native - - -class VmwareHostSnmp(PyVmomi): - """Manage SNMP configuration for an ESXi host system""" - - def __init__(self, module): - super(VmwareHostSnmp, self).__init__(module) - - if self.is_vcenter(): - self.module.fail_json( - msg="You have to connect directly to the ESXi host. " - "It's not possible to configure SNMP through a vCenter connection." - ) - else: - self.host = find_obj(self.content, [vim.HostSystem], None) - if self.host is None: - self.module.fail_json(msg="Failed to find host system.") - - def ensure(self): - """Manage SNMP configuration for an ESXi host system""" - results = dict(changed=False, result=dict()) - snmp_state = self.params.get('state') - snmp_port = self.params.get('snmp_port') - community = self.params.get('community') - desired_trap_targets = self.params.get("trap_targets") - hw_source = self.params.get("hw_source") - log_level = self.params.get("log_level") - send_trap = self.params.get("send_trap") - trap_filter = self.params.get("trap_filter") - event_filter = None - if trap_filter: - event_filter = ';'.join(trap_filter) - changed = False - reset_hint = None - changed_list = [] - results = dict(msg='') - - snmp_system = self.host.configManager.snmpSystem - if snmp_system: - if snmp_system.configuration: - snmp_config_spec = snmp_system.configuration - else: - self.module.fail_json(msg="SNMP agent configuration isn't supported on the ESXi host") - else: - self.module.fail_json(msg="SNMP system isn't available on the ESXi host") - - # Check state - results['state'] = snmp_state - if snmp_state == 'reset': - changed = True - # Get previous config - if snmp_config_spec.enabled: - results['state_previous'] = 'enabled' - else: - results['state_previous'] = 'disabled' - results['port_previous'] = snmp_config_spec.port - results['community_previous'] = snmp_config_spec.readOnlyCommunities - results['trap_targets_previous'] = self.get_previous_targets(snmp_config_spec.trapTargets) - for option in snmp_config_spec.option: - if option.key == 'EnvEventSource' and option.value != hw_source: - results['hw_source_previous'] = option.value - if option.key == 'loglevel' and option.value != hw_source: - results['log_level_previous'] = option.value - if option.key == 'EventFilter' and option.value != hw_source: - results['trap_filter_previous'] = option.value.split(';') - # Build factory default config - destination = vim.host.SnmpSystem.SnmpConfigSpec.Destination() - destination.hostName = "" - destination.port = 0 - destination.community = "" - options = [] - options.append(self.create_option('EnvEventSource', 'indications')) - options.append(self.create_option('EventFilter', 'reset')) - snmp_config_spec = vim.host.SnmpSystem.SnmpConfigSpec() - # Looks like this value is causing the reset - snmp_config_spec.readOnlyCommunities = [""] - snmp_config_spec.trapTargets = [destination] - snmp_config_spec.port = 161 - snmp_config_spec.enabled = False - snmp_config_spec.option = options - else: - if snmp_state == 'enabled' and not snmp_config_spec.enabled: - changed = True - changed_list.append("state") - results['state_previous'] = 'disabled' - snmp_config_spec.enabled = True - elif snmp_state == 'disabled' and snmp_config_spec.enabled: - changed = True - changed_list.append("state") - results['state_previous'] = 'enabled' - snmp_config_spec.enabled = False - - # Check port - results['port'] = snmp_port - if snmp_config_spec.port != snmp_port: - changed = True - changed_list.append("port") - results['port_previous'] = snmp_config_spec.port - snmp_config_spec.port = snmp_port - - # Check read-only community strings - results['community'] = community - if snmp_config_spec.readOnlyCommunities != community: - changed = True - changed_list.append("community list") - results['community_previous'] = snmp_config_spec.readOnlyCommunities - if community: - snmp_config_spec.readOnlyCommunities = community - else: - # Doesn't work. Need to reset config instead - # snmp_config_spec.readOnlyCommunities = [] - reset_hint = True - - # Check trap targets - results['trap_targets'] = desired_trap_targets - if snmp_config_spec.trapTargets: - if desired_trap_targets: - temp_desired_targets = [] - # Loop through desired targets - for target in desired_trap_targets: - dest_hostname, dest_port, dest_community = self.check_if_options_are_valid(target) - trap_target_found = False - for trap_target in snmp_config_spec.trapTargets: - if trap_target.hostName == dest_hostname: - if trap_target.port != dest_port or trap_target.community != dest_community: - changed = True - changed_list.append("trap target '%s'" % dest_hostname) - trap_target_found = True - break - if not trap_target_found: - changed = True - changed_list.append("trap target '%s'" % dest_hostname) - # Build destination and add to temp target list - destination = self.build_destination(dest_hostname, dest_port, dest_community) - temp_desired_targets.append(destination) - # Loop through existing targets to find targets that need to be deleted - for trap_target in snmp_config_spec.trapTargets: - target_found = False - for target in desired_trap_targets: - if trap_target.hostName == target.get('hostname'): - target_found = True - break - if not target_found: - changed = True - changed_list.append("trap target '%s'" % trap_target.hostName) - # Configure trap targets if something has changed - if changed: - results['trap_targets_previous'] = self.get_previous_targets(snmp_config_spec.trapTargets) - snmp_config_spec.trapTargets = temp_desired_targets - else: - changed = True - changed_list.append("trap targets") - results['trap_targets_previous'] = self.get_previous_targets(snmp_config_spec.trapTargets) - # Doesn't work. Need to reset config instead - # snmp_config_spec.trapTargets = [] - reset_hint = True - else: - if desired_trap_targets: - changed = True - changed_list.append("trap targets") - results['trap_targets_previous'] = None - desired_targets = [] - for target in desired_trap_targets: - dest_hostname, dest_port, dest_community = self.check_if_options_are_valid(target) - destination = self.build_destination(dest_hostname, dest_port, dest_community) - desired_targets.append(destination) - snmp_config_spec.trapTargets = desired_targets - - # Check options - results['hw_source'] = hw_source - results['log_level'] = log_level - results['trap_filter'] = trap_filter - event_filter_found = False - if snmp_config_spec.option: - for option in snmp_config_spec.option: - if option.key == 'EnvEventSource' and option.value != hw_source: - changed = True - changed_list.append("HW source") - results['hw_source_previous'] = option.value - option.value = hw_source - if option.key == 'loglevel' and option.value != log_level: - changed = True - changed_list.append("log level") - results['log_level_previous'] = option.value - option.value = log_level - if option.key == 'EventFilter': - event_filter_found = True - if event_filter and option.value != event_filter: - changed = True - changed_list.append("trap filter") - results['trap_filter_previous'] = option.value.split(';') - option.value = event_filter - if trap_filter and not event_filter_found: - changed = True - changed_list.append("trap filter") - results['trap_filter_previous'] = [] - snmp_config_spec.option.append(self.create_option('EventFilter', event_filter)) - elif not trap_filter and event_filter_found: - changed = True - changed_list.append("trap filter") - # options = [] - for option in snmp_config_spec.option: - if option.key == 'EventFilter': - results['trap_filter_previous'] = option.value.split(';') - # else: - # options.append(option) - # Doesn't work. Need to reset config instead - # snmp_config_spec.option = options - reset_hint = True - - if changed: - if snmp_state == 'reset': - if self.module.check_mode: - message = "SNMP agent would be reset to factory defaults" - else: - message = "SNMP agent config reset to factory defaults" - else: - if self.module.check_mode: - changed_suffix = ' would be changed' - else: - changed_suffix = ' changed' - if len(changed_list) > 2: - message = ', '.join(changed_list[:-1]) + ', and ' + str(changed_list[-1]) - elif len(changed_list) == 2: - message = ' and '.join(changed_list) - elif len(changed_list) == 1: - message = changed_list[0] - message = "SNMP " + message + changed_suffix - if reset_hint: - message += ". Agent reset required!" - if not self.module.check_mode: - try: - snmp_system.ReconfigureSnmpAgent(snmp_config_spec) - except vim.fault.NotFound as not_found: - self.module.fail_json( - msg="Not found : %s" % to_native(not_found) - ) - except vim.fault.InsufficientResourcesFault as insufficient_resources: - self.module.fail_json( - msg="Insufficient resources : %s" % to_native(insufficient_resources) - ) - else: - message = "SNMP already configured properly" - if not snmp_state == 'reset' and send_trap and desired_trap_targets: - # Check if there was a change before - if changed: - message += " and " - else: - message += ", but " - changed = True - if self.module.check_mode: - message = message + "a test trap would be sent" - else: - try: - snmp_system.SendTestNotification() - message = message + "a test trap was sent" - except vim.fault.NotFound as not_found: - self.module.fail_json( - msg="Error during trap test : Not found : %s" % to_native(not_found) - ) - except vim.fault.InsufficientResourcesFault as insufficient_resources: - self.module.fail_json( - msg="Error during trap test : Insufficient resources : %s" % to_native(insufficient_resources) - ) - results['changed'] = changed - results['msg'] = message - - self.module.exit_json(**results) - - @staticmethod - def create_option(key, value): - """Create option""" - option = vim.KeyValue() - option.key = key - option.value = value - return option - - @staticmethod - def get_previous_targets(trap_targets): - """Get target entries from trap targets object""" - previous_targets = [] - for target in trap_targets: - temp = dict() - temp['hostname'] = target.hostName - temp['port'] = target.port - temp['community'] = target.community - previous_targets.append(temp) - return previous_targets - - @staticmethod - def build_destination(dest_hostname, dest_port, dest_community): - """Build destination spec""" - destination = vim.host.SnmpSystem.SnmpConfigSpec.Destination() - destination.hostName = dest_hostname - destination.port = dest_port - destination.community = dest_community - return destination - - def check_if_options_are_valid(self, target): - """Check if options are valid""" - dest_hostname = target.get('hostname', None) - if dest_hostname is None: - self.module.fail_json( - msg="Please specify hostname for the trap target as it's a required parameter" - ) - dest_port = target.get('port', None) - if dest_port is None: - self.module.fail_json( - msg="Please specify port for the trap target as it's a required parameter" - ) - dest_community = target.get('community', None) - if dest_community is None: - self.module.fail_json( - msg="Please specify community for the trap target as it's a required parameter" - ) - return dest_hostname, dest_port, dest_community - - -def main(): - """Main""" - argument_spec = vmware_argument_spec() - argument_spec.update( - state=dict(type='str', default='disabled', choices=['enabled', 'disabled', 'reset']), - snmp_port=dict(type='int', default=161), - community=dict(type='list', default=[]), - trap_targets=dict(type='list', default=list()), - trap_filter=dict(type='list'), - hw_source=dict(type='str', default='indications', choices=['indications', 'sensors']), - log_level=dict(type='str', default='info', choices=['debug', 'info', 'warning', 'error']), - send_trap=dict(type='bool', default=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True - ) - - host_snmp = VmwareHostSnmp(module) - host_snmp.ensure() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_ssl_info.py b/lib/ansible/modules/cloud/vmware/vmware_host_ssl_info.py deleted file mode 100644 index b76414a0fe..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_ssl_info.py +++ /dev/null @@ -1,149 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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_host_ssl_info -short_description: Gather info of ESXi host system about SSL -description: -- This module can be used to gather information of the SSL thumbprint information for a host. -version_added: '2.9' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of the cluster. - - SSL thumbprint information about all ESXi host system in the given cluster will be reported. - - If C(esxi_hostname) is not given, this parameter is required. - type: str - esxi_hostname: - description: - - ESXi hostname. - - SSL thumbprint information of this ESXi host system will be reported. - - If C(cluster_name) is not given, this parameter is required. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather SSL thumbprint information about all ESXi Hosts in given Cluster - vmware_host_ssl_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: '{{ cluster_name }}' - delegate_to: localhost - register: all_host_ssl_info - -- name: Get SSL Thumbprint info about "{{ esxi_hostname }}" - vmware_host_ssl_info: - hostname: "{{ vcenter_server }}" - username: "{{ vcenter_user }}" - password: "{{ vcenter_pass }}" - esxi_hostname: '{{ esxi_hostname }}' - register: ssl_info -- set_fact: - ssl_thumbprint: "{{ ssl_info['host_ssl_info'][esxi_hostname]['ssl_thumbprints'][0] }}" -- debug: - msg: "{{ ssl_thumbprint }}" -- name: Add ESXi Host to vCenter - vmware_host: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter_name: '{{ datacenter_name }}' - cluster_name: '{{ cluster_name }}' - esxi_hostname: '{{ esxi_hostname }}' - esxi_username: '{{ esxi_username }}' - esxi_password: '{{ esxi_password }}' - esxi_ssl_thumbprint: '{{ ssl_thumbprint }}' - state: present -''' - -RETURN = r''' -host_ssl_info: - description: - - dict with hostname as key and dict with SSL thumbprint related info - returned: info - type: dict - sample: - { - "10.76.33.215": { - "owner_tag": "", - "principal": "vpxuser", - "ssl_thumbprints": [ - "E3:E8:A9:20:8D:32:AE:59:C6:8D:A5:91:B0:20:EF:00:A2:7C:27:EE", - "F1:AC:DA:6E:D8:1E:37:36:4A:5C:07:E5:04:0B:87:C8:75:FB:42:01" - ] - } - } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class VMwareHostSslManager(PyVmomi): - def __init__(self, module): - super(VMwareHostSslManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - self.hosts_info = {} - - def gather_ssl_info(self): - for host in self.hosts: - self.hosts_info[host.name] = dict( - principal='', - owner_tag='', - ssl_thumbprints=[]) - - host_ssl_info_mgr = host.config.sslThumbprintInfo - if host_ssl_info_mgr: - self.hosts_info[host.name]['principal'] = host_ssl_info_mgr.principal - self.hosts_info[host.name]['owner_tag'] = host_ssl_info_mgr.ownerTag - self.hosts_info[host.name]['ssl_thumbprints'] = [i for i in host_ssl_info_mgr.sslThumbprints] - - self.module.exit_json(changed=False, host_ssl_info=self.hosts_info) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str'), - esxi_hostname=dict(type='str'), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True, - ) - - vmware_host_accept_config = VMwareHostSslManager(module) - vmware_host_accept_config.gather_ssl_info() - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_vmhba_info.py b/lib/ansible/modules/cloud/vmware/vmware_host_vmhba_info.py deleted file mode 100644 index 2f10d5b026..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_vmhba_info.py +++ /dev/null @@ -1,229 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# 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_host_vmhba_info -short_description: Gathers info about vmhbas available on the given ESXi host -description: -- This module can be used to gather information about vmhbas available on the given ESXi host. -- If C(cluster_name) is provided, then vmhba information about all hosts from given cluster will be returned. -- If C(esxi_hostname) is provided, then vmhba information about given host system will be returned. -version_added: '2.9' -author: -- Christian Kotte (@ckotte) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - esxi_hostname: - description: - - Name of the host system to work with. - - Vmhba information about this ESXi server will be returned. - - This parameter is required if C(cluster_name) is not specified. - type: str - cluster_name: - description: - - Name of the cluster from which all host systems will be used. - - Vmhba information about each ESXi server will be returned for the given cluster. - - This parameter is required if C(esxi_hostname) is not specified. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather info about vmhbas of all ESXi Host in the given Cluster - vmware_host_vmhba_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: '{{ cluster_name }}' - delegate_to: localhost - register: cluster_host_vmhbas - -- name: Gather info about vmhbas of an ESXi Host - vmware_host_vmhba_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - delegate_to: localhost - register: host_vmhbas -''' - -RETURN = r''' -hosts_vmhbas_info: - description: - - dict with hostname as key and dict with vmhbas information as value. - returned: hosts_vmhbas_info - type: dict - sample: - { - "10.76.33.204": { - "vmhba_details": [ - { - "adapter": "HPE Smart Array P440ar", - "bus": 3, - "device": "vmhba0", - "driver": "nhpsa", - "location": "0000:03:00.0", - "model": "Smart Array P440ar", - "node_wwn": "50:01:43:80:37:18:9e:a0", - "status": "unknown", - "type": "SAS" - }, - { - "adapter": "QLogic Corp ISP2532-based 8Gb Fibre Channel to PCI Express HBA", - "bus": 5, - "device": "vmhba1", - "driver": "qlnativefc", - "location": "0000:05:00.0", - "model": "ISP2532-based 8Gb Fibre Channel to PCI Express HBA", - "node_wwn": "57:64:96:32:15:90:23:95:82", - "port_type": "unknown", - "port_wwn": "57:64:96:32:15:90:23:95:82", - "speed": 8, - "status": "online", - "type": "Fibre Channel" - }, - { - "adapter": "QLogic Corp ISP2532-based 8Gb Fibre Channel to PCI Express HBA", - "bus": 8, - "device": "vmhba2", - "driver": "qlnativefc", - "location": "0000:08:00.0", - "model": "ISP2532-based 8Gb Fibre Channel to PCI Express HBA", - "node_wwn": "57:64:96:32:15:90:23:95:21", - "port_type": "unknown", - "port_wwn": "57:64:96:32:15:90:23:95:21", - "speed": 8, - "status": "online", - "type": "Fibre Channel" - } - ], - } - } -''' - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class HostVmhbaMgr(PyVmomi): - """Class to manage vmhba info""" - def __init__(self, module): - super(HostVmhbaMgr, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - if not self.hosts: - self.module.fail_json(msg="Failed to find host system.") - - def gather_host_vmhba_info(self): - """Gather vmhba info""" - hosts_vmhba_info = {} - for host in self.hosts: - host_vmhba_info = dict() - host_st_system = host.configManager.storageSystem - if host_st_system: - device_info = host_st_system.storageDeviceInfo - host_vmhba_info['vmhba_details'] = [] - for hba in device_info.hostBusAdapter: - hba_info = dict() - if hba.pci: - hba_info['location'] = hba.pci - for pci_device in host.hardware.pciDevice: - if pci_device.id == hba.pci: - hba_info['adapter'] = pci_device.vendorName + ' ' + pci_device.deviceName - break - else: - hba_info['location'] = 'PCI' - hba_info['device'] = hba.device - # contains type as string in format of 'key-vim.host.FibreChannelHba-vmhba1' - hba_type = hba.key.split(".")[-1].split("-")[0] - if hba_type == 'SerialAttachedHba': - hba_info['type'] = 'SAS' - elif hba_type == 'FibreChannelHba': - hba_info['type'] = 'Fibre Channel' - else: - hba_info['type'] = hba_type - hba_info['bus'] = hba.bus - hba_info['status'] = hba.status - hba_info['model'] = hba.model - hba_info['driver'] = hba.driver - try: - if isinstance(hba, (vim.host.FibreChannelHba, vim.host.FibreChannelOverEthernetHba)): - hba_info['node_wwn'] = self.format_number('%X' % hba.nodeWorldWideName) - else: - hba_info['node_wwn'] = self.format_number(hba.nodeWorldWideName) - except AttributeError: - pass - try: - if isinstance(hba, (vim.host.FibreChannelHba, vim.host.FibreChannelOverEthernetHba)): - hba_info['port_wwn'] = self.format_number('%X' % hba.portWorldWideName) - else: - hba_info['port_wwn'] = self.format_number(hba.portWorldWideName) - except AttributeError: - pass - try: - hba_info['port_type'] = hba.portType - except AttributeError: - pass - try: - hba_info['speed'] = hba.speed - except AttributeError: - pass - host_vmhba_info['vmhba_details'].append(hba_info) - - hosts_vmhba_info[host.name] = host_vmhba_info - return hosts_vmhba_info - - @staticmethod - def format_number(number): - """Format number""" - string = str(number) - return ':'.join(a + b for a, b in zip(string[::2], string[1::2])) - - -def main(): - """Main""" - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True, - ) - - host_vmhba_mgr = HostVmhbaMgr(module) - module.exit_json(changed=False, hosts_vmhbas_info=host_vmhba_mgr.gather_host_vmhba_info()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_host_vmnic_info.py b/lib/ansible/modules/cloud/vmware/vmware_host_vmnic_info.py deleted file mode 100644 index b2e1bc7dea..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_host_vmnic_info.py +++ /dev/null @@ -1,317 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# 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_host_vmnic_info -short_description: Gathers info about vmnics available on the given ESXi host -description: -- This module can be used to gather information about vmnics available on the given ESXi host. -- If C(cluster_name) is provided, then vmnic information about all hosts from given cluster will be returned. -- If C(esxi_hostname) is provided, then vmnic information about given host system will be returned. -- Additional details about vswitch and dvswitch with respective vmnic is also provided which is added in 2.7 version. -version_added: '2.9' -author: -- Abhijeet Kasurde (@Akasurde) -- Christian Kotte (@ckotte) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - capabilities: - description: - - Gather information about general capabilities (Auto negotiation, Wake On LAN, and Network I/O Control). - type: bool - default: false - directpath_io: - description: - - Gather information about DirectPath I/O capabilities and configuration. - type: bool - default: false - sriov: - description: - - Gather information about SR-IOV capabilities and configuration. - type: bool - default: false - esxi_hostname: - description: - - Name of the host system to work with. - - Vmnic information about this ESXi server will be returned. - - This parameter is required if C(cluster_name) is not specified. - type: str - cluster_name: - description: - - Name of the cluster from which all host systems will be used. - - Vmnic information about each ESXi server will be returned for the given cluster. - - This parameter is required if C(esxi_hostname) is not specified. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather info about vmnics of all ESXi Host in the given Cluster - vmware_host_vmnic_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: '{{ cluster_name }}' - delegate_to: localhost - register: cluster_host_vmnics - -- name: Gather info about vmnics of an ESXi Host - vmware_host_vmnic_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - delegate_to: localhost - register: host_vmnics -''' - -RETURN = r''' -hosts_vmnics_info: - description: - - dict with hostname as key and dict with vmnics information as value. - - for C(num_vmnics), only NICs starting with vmnic are counted. NICs like vusb* are not counted. - - details about vswitch and dvswitch was added in version 2.7. - - details about vmnics was added in version 2.8. - returned: hosts_vmnics_info - type: dict - sample: - { - "10.76.33.204": { - "all": [ - "vmnic0", - "vmnic1" - ], - "available": [], - "dvswitch": { - "dvs_0002": [ - "vmnic1" - ] - }, - "num_vmnics": 2, - "used": [ - "vmnic1", - "vmnic0" - ], - "vmnic_details": [ - { - "actual_duplex": "Full Duplex", - "actual_speed": 10000, - "adapter": "Intel(R) 82599 10 Gigabit Dual Port Network Connection", - "configured_duplex": "Auto negotiate", - "configured_speed": "Auto negotiate", - "device": "vmnic0", - "driver": "ixgbe", - "location": "0000:01:00.0", - "mac": "aa:bb:cc:dd:ee:ff", - "status": "Connected", - }, - { - "actual_duplex": "Full Duplex", - "actual_speed": 10000, - "adapter": "Intel(R) 82599 10 Gigabit Dual Port Network Connection", - "configured_duplex": "Auto negotiate", - "configured_speed": "Auto negotiate", - "device": "vmnic1", - "driver": "ixgbe", - "location": "0000:01:00.1", - "mac": "ab:ba:cc:dd:ee:ff", - "status": "Connected", - }, - ], - "vswitch": { - "vSwitch0": [ - "vmnic0" - ] - } - } - } -''' - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi, get_all_objs - - -class HostVmnicMgr(PyVmomi): - """Class to manage vmnic info""" - def __init__(self, module): - super(HostVmnicMgr, self).__init__(module) - self.capabilities = self.params.get('capabilities') - self.directpath_io = self.params.get('directpath_io') - self.sriov = self.params.get('sriov') - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - if not self.hosts: - self.module.fail_json(msg="Failed to find host system.") - - def find_dvs_by_uuid(self, uuid=None): - """Find DVS by it's UUID""" - dvs_obj = None - if uuid is None: - return dvs_obj - - dvswitches = get_all_objs(self.content, [vim.DistributedVirtualSwitch]) - for dvs in dvswitches: - if dvs.uuid == uuid: - dvs_obj = dvs - break - - return dvs_obj - - def gather_host_vmnic_info(self): - """Gather vmnic info""" - hosts_vmnic_info = {} - for host in self.hosts: - host_vmnic_info = dict(all=[], available=[], used=[], vswitch=dict(), dvswitch=dict()) - host_nw_system = host.configManager.networkSystem - if host_nw_system: - nw_config = host_nw_system.networkConfig - vmnics = [pnic.device for pnic in nw_config.pnic if pnic.device.startswith('vmnic')] - host_vmnic_info['all'] = [pnic.device for pnic in nw_config.pnic] - host_vmnic_info['num_vmnics'] = len(vmnics) - host_vmnic_info['vmnic_details'] = [] - for pnic in host.config.network.pnic: - pnic_info = dict() - if pnic.device.startswith('vmnic'): - if pnic.pci: - pnic_info['location'] = pnic.pci - for pci_device in host.hardware.pciDevice: - if pci_device.id == pnic.pci: - pnic_info['adapter'] = pci_device.vendorName + ' ' + pci_device.deviceName - break - else: - pnic_info['location'] = 'PCI' - pnic_info['device'] = pnic.device - pnic_info['driver'] = pnic.driver - if pnic.linkSpeed: - pnic_info['status'] = 'Connected' - pnic_info['actual_speed'] = pnic.linkSpeed.speedMb - pnic_info['actual_duplex'] = 'Full Duplex' if pnic.linkSpeed.duplex else 'Half Duplex' - else: - pnic_info['status'] = 'Disconnected' - pnic_info['actual_speed'] = 'N/A' - pnic_info['actual_duplex'] = 'N/A' - if pnic.spec.linkSpeed: - pnic_info['configured_speed'] = pnic.spec.linkSpeed.speedMb - pnic_info['configured_duplex'] = 'Full Duplex' if pnic.spec.linkSpeed.duplex else 'Half Duplex' - else: - pnic_info['configured_speed'] = 'Auto negotiate' - pnic_info['configured_duplex'] = 'Auto negotiate' - pnic_info['mac'] = pnic.mac - # General NIC capabilities - if self.capabilities: - pnic_info['nioc_status'] = 'Allowed' if pnic.resourcePoolSchedulerAllowed else 'Not allowed' - pnic_info['auto_negotiation_supported'] = pnic.autoNegotiateSupported - pnic_info['wake_on_lan_supported'] = pnic.wakeOnLanSupported - # DirectPath I/O and SR-IOV capabilities and configuration - if self.directpath_io: - pnic_info['directpath_io_supported'] = pnic.vmDirectPathGen2Supported - if self.directpath_io or self.sriov: - if pnic.pci: - for pci_device in host.configManager.pciPassthruSystem.pciPassthruInfo: - if pci_device.id == pnic.pci: - if self.directpath_io: - pnic_info['passthru_enabled'] = pci_device.passthruEnabled - pnic_info['passthru_capable'] = pci_device.passthruCapable - pnic_info['passthru_active'] = pci_device.passthruActive - if self.sriov: - try: - if pci_device.sriovCapable: - pnic_info['sriov_status'] = ( - 'Enabled' if pci_device.sriovEnabled else 'Disabled' - ) - pnic_info['sriov_active'] = \ - pci_device.sriovActive - pnic_info['sriov_virt_functions'] = \ - pci_device.numVirtualFunction - pnic_info['sriov_virt_functions_requested'] = \ - pci_device.numVirtualFunctionRequested - pnic_info['sriov_virt_functions_supported'] = \ - pci_device.maxVirtualFunctionSupported - else: - pnic_info['sriov_status'] = 'Not supported' - except AttributeError: - pnic_info['sriov_status'] = 'Not supported' - host_vmnic_info['vmnic_details'].append(pnic_info) - - vswitch_vmnics = [] - proxy_switch_vmnics = [] - if nw_config.vswitch: - for vswitch in nw_config.vswitch: - host_vmnic_info['vswitch'][vswitch.name] = [] - # Workaround for "AttributeError: 'NoneType' object has no attribute 'nicDevice'" - # this issue doesn't happen every time; vswitch.spec.bridge.nicDevice exists! - try: - for vnic in vswitch.spec.bridge.nicDevice: - vswitch_vmnics.append(vnic) - host_vmnic_info['vswitch'][vswitch.name].append(vnic) - except AttributeError: - pass - - if nw_config.proxySwitch: - for proxy_config in nw_config.proxySwitch: - dvs_obj = self.find_dvs_by_uuid(uuid=proxy_config.uuid) - if dvs_obj: - host_vmnic_info['dvswitch'][dvs_obj.name] = [] - for proxy_nic in proxy_config.spec.backing.pnicSpec: - proxy_switch_vmnics.append(proxy_nic.pnicDevice) - if dvs_obj: - host_vmnic_info['dvswitch'][dvs_obj.name].append(proxy_nic.pnicDevice) - - used_vmics = proxy_switch_vmnics + vswitch_vmnics - host_vmnic_info['used'] = used_vmics - host_vmnic_info['available'] = [pnic.device for pnic in nw_config.pnic if pnic.device not in used_vmics] - - hosts_vmnic_info[host.name] = host_vmnic_info - return hosts_vmnic_info - - -def main(): - """Main""" - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - capabilities=dict(type='bool', required=False, default=False), - directpath_io=dict(type='bool', required=False, default=False), - sriov=dict(type='bool', required=False, default=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True, - ) - - host_vmnic_mgr = HostVmnicMgr(module) - module.exit_json(changed=False, hosts_vmnics_info=host_vmnic_mgr.gather_host_vmnic_info()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_local_role_info.py b/lib/ansible/modules/cloud/vmware/vmware_local_role_info.py deleted file mode 100644 index 6918297f6f..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_local_role_info.py +++ /dev/null @@ -1,139 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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 = ''' ---- -module: vmware_local_role_info -short_description: Gather info about local roles on an ESXi host -description: - - This module can be used to gather information about local role info on an ESXi host -version_added: '2.9' -author: -- Abhijeet Kasurde (@Akasurde) -notes: - - Tested on ESXi 6.5 - - Be sure that the ESXi user used for login, has the appropriate rights to view roles - - The module returns a list of dict in version 2.8 and above. -requirements: - - "python >= 2.6" - - PyVmomi -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Gather info about local role from an ESXi - vmware_local_role_info: - hostname: '{{ esxi_hostname }}' - username: '{{ esxi_username }}' - password: '{{ esxi_password }}' - register: fact_details - delegate_to: localhost -- name: Get Admin privileges - set_fact: - admin_priv: "{{ fact_details.local_role_info['Admin']['privileges'] }}" -- debug: - msg: "{{ admin_priv }}" -''' - -RETURN = r''' -local_role_info: - description: Info about role present on ESXi host - returned: always - type: dict - sample: [ - { - "privileges": [ - "Alarm.Acknowledge", - "Alarm.Create", - "Alarm.Delete", - "Alarm.DisableActions", - ], - "role_id": -12, - "role_info_label": "Ansible User", - "role_info_summary": "Ansible Automation user", - "role_name": "AnsiUser1", - "role_system": true - }, - { - "privileges": [], - "role_id": -5, - "role_info_label": "No access", - "role_info_summary": "Used for restricting granted access", - "role_name": "NoAccess", - "role_system": true - }, - { - "privileges": [ - "System.Anonymous", - "System.View" - ], - "role_id": -3, - "role_info_label": "View", - "role_info_summary": "Visibility access (cannot be granted)", - "role_name": "View", - "role_system": true - } - ] -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec - - -class VMwareLocalRoleInfo(PyVmomi): - """Class to manage local role info""" - def __init__(self, module): - super(VMwareLocalRoleInfo, self).__init__(module) - self.module = module - self.params = module.params - - if self.content.authorizationManager is None: - self.module.fail_json( - msg="Failed to get local authorization manager settings.", - details="It seems that '%s' is a vCenter server instead of an ESXi server" % self.params['hostname'] - ) - - def gather_local_role_info(self): - """Gather info about local roles""" - results = list() - for role in self.content.authorizationManager.roleList: - results.append( - dict( - role_name=role.name, - role_id=role.roleId, - privileges=[priv_name for priv_name in role.privilege], - role_system=role.system, - role_info_label=role.info.label, - role_info_summary=role.info.summary, - ) - ) - - self.module.exit_json(changed=False, local_role_info=results) - - -def main(): - """Main""" - argument_spec = vmware_argument_spec() - module = AnsibleModule(argument_spec=argument_spec, - supports_check_mode=True) - - vmware_local_role_info = VMwareLocalRoleInfo(module) - vmware_local_role_info.gather_local_role_info() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_local_role_manager.py b/lib/ansible/modules/cloud/vmware/vmware_local_role_manager.py deleted file mode 100644 index 3b06a6c7a5..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_local_role_manager.py +++ /dev/null @@ -1,412 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: Abhijeet Kasurde <akasurde@redhat.com> -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# 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 = ''' ---- -module: vmware_local_role_manager -short_description: Manage local roles on an ESXi host -description: - - This module can be used to manage local roles on an ESXi host. -version_added: 2.5 -author: -- Abhijeet Kasurde (@Akasurde) -- Christian Kotte (@ckotte) -notes: - - Tested on ESXi 6.5 - - Be sure that the ESXi user used for login, has the appropriate rights to create / delete / edit roles -requirements: - - "python >= 2.6" - - PyVmomi -options: - local_role_name: - description: - - The local role name to be managed. - required: True - type: str - local_privilege_ids: - description: - - The list of privileges that role needs to have. - - Please see U(https://docs.vmware.com/en/VMware-vSphere/6.0/com.vmware.vsphere.security.doc/GUID-ED56F3C4-77D0-49E3-88B6-B99B8B437B62.html) - default: [] - type: list - state: - description: - - Indicate desired state of the role. - - If the role already exists when C(state=present), the role info is updated. - choices: ['present', 'absent'] - default: present - type: str - force_remove: - description: - - If set to C(False) then prevents the role from being removed if any permissions are using it. - default: False - type: bool - action: - description: - - This parameter is only valid while updating an existing role with privileges. - - C(add) will add the privileges to the existing privilege list. - - C(remove) will remove the privileges from the existing privilege list. - - C(set) will replace the privileges of the existing privileges with user defined list of privileges. - default: set - choices: [ add, remove, set ] - version_added: 2.8 - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Add local role to ESXi - vmware_local_role_manager: - hostname: '{{ esxi_hostname }}' - username: '{{ esxi_username }}' - password: '{{ esxi_password }}' - local_role_name: vmware_qa - state: present - delegate_to: localhost - -- name: Add local role with privileges to ESXi - vmware_local_role_manager: - hostname: '{{ esxi_hostname }}' - username: '{{ esxi_username }}' - password: '{{ esxi_password }}' - local_role_name: vmware_qa - local_privilege_ids: [ 'Folder.Create', 'Folder.Delete'] - state: present - delegate_to: localhost - -- name: Remove local role from ESXi - vmware_local_role_manager: - hostname: '{{ esxi_hostname }}' - username: '{{ esxi_username }}' - password: '{{ esxi_password }}' - local_role_name: vmware_qa - state: absent - delegate_to: localhost - -- name: Add a privilege to an existing local role - vmware_local_role_manager: - hostname: '{{ esxi_hostname }}' - username: '{{ esxi_username }}' - password: '{{ esxi_password }}' - local_role_name: vmware_qa - local_privilege_ids: [ 'Folder.Create' ] - action: add - delegate_to: localhost - -- name: Remove a privilege to an existing local role - vmware_local_role_manager: - hostname: '{{ esxi_hostname }}' - username: '{{ esxi_username }}' - password: '{{ esxi_password }}' - local_role_name: vmware_qa - local_privilege_ids: [ 'Folder.Create' ] - action: remove - delegate_to: localhost - -- name: Set a privilege to an existing local role - vmware_local_role_manager: - hostname: '{{ esxi_hostname }}' - username: '{{ esxi_username }}' - password: '{{ esxi_password }}' - local_role_name: vmware_qa - local_privilege_ids: [ 'Folder.Create' ] - action: set - delegate_to: localhost -''' - -RETURN = r''' -role_name: - description: Name of local role - returned: always - type: str -role_id: - description: ESXi generated local role id - returned: always - type: int -privileges: - description: List of privileges - returned: always - type: list -privileges_previous: - description: List of privileges of role before the update - returned: on update - type: list -# NOTE: the following keys are deprecated from 2.11 onwards -local_role_name: - description: Name of local role - returned: always - type: str -new_privileges: - description: List of privileges - returned: always - type: list -old_privileges: - description: List of privileges of role before the update - returned: on update - type: list -''' - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec - - -class VMwareLocalRoleManager(PyVmomi): - """Class to manage local roles""" - - def __init__(self, module): - super(VMwareLocalRoleManager, self).__init__(module) - self.module = module - self.params = module.params - self.role_name = self.params['local_role_name'] - self.state = self.params['state'] - self.priv_ids = self.params['local_privilege_ids'] - self.force = not self.params['force_remove'] - self.current_role = None - self.action = self.params['action'] - - if self.content.authorizationManager is None: - self.module.fail_json( - msg="Failed to get local authorization manager settings.", - details="It seems that '%s' is a vCenter server instead of an ESXi server" % self.params['hostname'] - ) - - def process_state(self): - """Process the state of the local role""" - local_role_manager_states = { - 'absent': { - 'present': self.state_remove_role, - 'absent': self.state_exit_unchanged, - }, - 'present': { - 'present': self.state_update_role, - 'absent': self.state_create_role, - } - } - try: - local_role_manager_states[self.state][self.check_local_role_manager_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 check_local_role_manager_state(self): - """Check local roles""" - auth_role = self.find_authorization_role() - if auth_role: - self.current_role = auth_role - return 'present' - return 'absent' - - def find_authorization_role(self): - """Find local role""" - desired_role = None - for role in self.content.authorizationManager.roleList: - if role.name == self.role_name: - desired_role = role - return desired_role - - def state_create_role(self): - """Create local role""" - role_id = None - results = dict() - results['role_name'] = self.role_name - results['privileges'] = self.priv_ids - # NOTE: the following code is deprecated from 2.11 onwards - results['local_role_name'] = self.role_name - results['new_privileges'] = self.priv_ids - - if self.module.check_mode: - results['msg'] = "Role would be created" - else: - try: - role_id = self.content.authorizationManager.AddAuthorizationRole( - name=self.role_name, - privIds=self.priv_ids - ) - results['role_id'] = role_id - results['msg'] = "Role created" - except vim.fault.AlreadyExists as already_exists: - self.module.fail_json( - msg="Failed to create role '%s' as the user specified role name already exists." % - self.role_name, details=already_exists.msg - ) - except vim.fault.InvalidName as invalid_name: - self.module.fail_json( - msg="Failed to create a role %s as the user specified role name is empty" % - self.role_name, details=invalid_name.msg - ) - except vmodl.fault.InvalidArgument as invalid_argument: - self.module.fail_json( - msg="Failed to create a role %s as the user specified privileges are unknown" % - self.role_name, etails=invalid_argument.msg - ) - self.module.exit_json(changed=True, result=results) - - def state_remove_role(self): - """Remove local role""" - results = dict() - results['role_name'] = self.role_name - results['role_id'] = self.current_role.roleId - # NOTE: the following code is deprecated from 2.11 onwards - results['local_role_name'] = self.role_name - if self.module.check_mode: - results['msg'] = "Role would be deleted" - else: - try: - self.content.authorizationManager.RemoveAuthorizationRole( - roleId=self.current_role.roleId, - failIfUsed=self.force - ) - results['msg'] = "Role deleted" - except vim.fault.NotFound as not_found: - self.module.fail_json( - msg="Failed to remove a role %s as the user specified role name does not exist." % - self.role_name, details=not_found.msg - ) - except vim.fault.RemoveFailed as remove_failed: - msg = "Failed to remove role '%s' as the user specified role name." % self.role_name - if self.force: - msg += " Use force_remove as True." - self.module.fail_json(msg=msg, details=remove_failed.msg) - except vmodl.fault.InvalidArgument as invalid_argument: - self.module.fail_json( - msg="Failed to remove a role %s as the user specified role is a system role" % - self.role_name, details=invalid_argument.msg - ) - self.module.exit_json(changed=True, result=results) - - def state_exit_unchanged(self): - """Don't do anything""" - results = dict() - results['role_name'] = self.role_name - # NOTE: the following code is deprecated from 2.11 onwards - results['local_role_name'] = self.role_name - results['msg'] = "Role not present" - self.module.exit_json(changed=False, result=results) - - def state_update_role(self): - """Update local role""" - changed = False - changed_privileges = [] - results = dict() - results['role_name'] = self.role_name - results['role_id'] = self.current_role.roleId - # NOTE: the following code is deprecated from 2.11 onwards - results['local_role_name'] = self.role_name - - current_privileges = self.current_role.privilege - results['privileges'] = current_privileges - # NOTE: the following code is deprecated from 2.11 onwards - results['new_privileges'] = current_privileges - - if self.action == 'add': - # Add to existing privileges - for priv in self.params['local_privilege_ids']: - if priv not in current_privileges: - changed_privileges.append(priv) - changed = True - if changed: - changed_privileges.extend(current_privileges) - elif self.action == 'set': - # Set given privileges - # Add system-defined privileges, "System.Anonymous", "System.View", and "System.Read". - self.params['local_privilege_ids'].extend(['System.Anonymous', 'System.Read', 'System.View']) - changed_privileges = self.params['local_privilege_ids'] - changes_applied = list(set(current_privileges) ^ set(changed_privileges)) - if changes_applied: - changed = True - elif self.action == 'remove': - changed_privileges = list(current_privileges) - # Remove given privileges from existing privileges - for priv in self.params['local_privilege_ids']: - if priv in current_privileges: - changed = True - changed_privileges.remove(priv) - - if changed: - results['privileges'] = changed_privileges - results['privileges_previous'] = current_privileges - # NOTE: the following code is deprecated from 2.11 onwards - results['new_privileges'] = changed_privileges - results['old_privileges'] = current_privileges - if self.module.check_mode: - results['msg'] = "Role privileges would be updated" - else: - try: - self.content.authorizationManager.UpdateAuthorizationRole( - roleId=self.current_role.roleId, - newName=self.current_role.name, - privIds=changed_privileges - ) - results['msg'] = "Role privileges updated" - except vim.fault.NotFound as not_found: - self.module.fail_json( - msg="Failed to update role. Please check privileges provided for update", details=not_found.msg - ) - except vim.fault.InvalidName as invalid_name: - self.module.fail_json( - msg="Failed to update role as role name is empty", details=invalid_name.msg - ) - except vim.fault.AlreadyExists as already_exists: - self.module.fail_json( - msg="Failed to update role", details=already_exists.msg - ) - except vmodl.fault.InvalidArgument as invalid_argument: - self.module.fail_json( - msg="Failed to update role as user specified role is system role which can not be changed", - details=invalid_argument.msg - ) - except vim.fault.NoPermission as no_permission: - self.module.fail_json( - msg="Failed to update role as current session doesn't have any privilege to update specified role", - details=no_permission.msg - ) - else: - results['msg'] = "Role privileges are properly configured" - - self.module.exit_json(changed=changed, result=results) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update(dict(local_role_name=dict(required=True, type='str'), - local_privilege_ids=dict(default=[], type='list'), - force_remove=dict(default=False, type='bool'), - action=dict(type='str', default='set', choices=[ - 'add', - 'set', - 'remove', - ]), - state=dict(default='present', choices=['present', 'absent'], type='str'))) - - module = AnsibleModule(argument_spec=argument_spec, - supports_check_mode=True) - - vmware_local_role_manager = VMwareLocalRoleManager(module) - vmware_local_role_manager.process_state() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_local_user_info.py b/lib/ansible/modules/cloud/vmware/vmware_local_user_info.py deleted file mode 100644 index ee3c56e0d8..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_local_user_info.py +++ /dev/null @@ -1,163 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# 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 = ''' ---- -module: vmware_local_user_info -short_description: Gather info about users on the given ESXi host -description: - - This module can be used to gather information about users present on the given ESXi host system in VMware infrastructure. - - All variables and VMware object names are case sensitive. - - User must hold the 'Authorization.ModifyPermissions' privilege to invoke this module. -version_added: "2.9" -author: -- Abhijeet Kasurde (@Akasurde) -- Christian Kotte (@ckotte) -notes: - - Tested on ESXi 6.5 -requirements: - - "python >= 2.6" - - PyVmomi -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather info about all Users on given ESXi host system - vmware_local_user_info: - hostname: '{{ esxi_hostname }}' - username: '{{ esxi_username }}' - password: '{{ esxi_password }}' - delegate_to: localhost - register: all_user_info -''' - -RETURN = r''' -local_user_info: - description: metadata about all local users - returned: always - type: dict - sample: [ - { - "role": "admin", - "description": "Administrator", - "group": false, - "user_id": 0, - "user_name": "root", - "shell_access": true - }, - { - "role": "admin", - "description": "DCUI User", - "group": false, - "user_id": 100, - "user_name": "dcui", - "shell_access": false - }, - ] -''' - -try: - from pyVmomi import vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec -from ansible.module_utils._text import to_native - - -class VMwareUserInfoManager(PyVmomi): - """Class to manage local user info""" - def __init__(self, module): - super(VMwareUserInfoManager, self).__init__(module) - - if self.is_vcenter(): - self.module.fail_json( - msg="Failed to get local account manager settings.", - details="It seems that '%s' is a vCenter server instead of an ESXi server" % self.module.params['hostname'] - ) - - def gather_user_info(self): - """Gather info about local users""" - results = dict(changed=False, local_user_info=[]) - search_string = '' - exact_match = False - find_users = True - find_groups = False - user_accounts = self.content.userDirectory.RetrieveUserGroups( - None, search_string, None, None, exact_match, find_users, find_groups - ) - if user_accounts: - for user in user_accounts: - temp_user = dict() - temp_user['user_name'] = user.principal - temp_user['description'] = user.fullName - temp_user['group'] = user.group - temp_user['user_id'] = user.id - temp_user['shell_access'] = user.shellAccess - temp_user['role'] = None - try: - permissions = self.content.authorizationManager.RetrieveEntityPermissions( - entity=self.content.rootFolder, - inherited=False - ) - except vmodl.fault.ManagedObjectNotFound as not_found: - self.module.fail_json( - msg="The entity doesn't exist" % to_native(not_found) - ) - for permission in permissions: - if permission.principal == user.principal: - temp_user['role'] = self.get_role_name(permission.roleId, self.content.authorizationManager.roleList) - break - - results['local_user_info'].append(temp_user) - self.module.exit_json(**results) - - @staticmethod - def get_role_name(role_id, role_list): - """Get role name from role ID""" - role_name = None - # Default role: No access - if role_id == -5: - role_name = 'no-access' - # Default role: Read-only - elif role_id == -2: - role_name = 'read-only' - # Default role: Administrator - elif role_id == -1: - role_name = 'admin' - # Custom roles - else: - for role in role_list: - if role.roleId == role_id: - role_name = role.name - break - return role_name - - -def main(): - """Main""" - argument_spec = vmware_argument_spec() - module = AnsibleModule(argument_spec=argument_spec, - supports_check_mode=True) - - vmware_local_user_info = VMwareUserInfoManager(module) - vmware_local_user_info.gather_user_info() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_local_user_manager.py b/lib/ansible/modules/cloud/vmware/vmware_local_user_manager.py deleted file mode 100644 index f6f7c83c45..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_local_user_manager.py +++ /dev/null @@ -1,189 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2016, IBM Corp -# Author(s): Andreas Nafpliotis <nafpliot@de.ibm.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 = ''' ---- -module: vmware_local_user_manager -short_description: Manage local users on an ESXi host -description: - - Manage local users on an ESXi host -version_added: "2.2" -author: -- Andreas Nafpliotis (@nafpliot-ibm) -notes: - - Tested on ESXi 6.0 - - Be sure that the ESXi user used for login, has the appropriate rights to create / delete / edit users -requirements: - - "python >= 2.6" - - PyVmomi installed -options: - local_user_name: - description: - - The local user name to be changed. - required: True - type: str - local_user_password: - description: - - The password to be set. - required: False - type: str - local_user_description: - description: - - Description for the user. - required: False - type: str - state: - description: - - Indicate desired state of the user. If the user already exists when C(state=present), the user info is updated - choices: ['present', 'absent'] - default: present - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Add local user to ESXi - vmware_local_user_manager: - hostname: esxi_hostname - username: root - password: vmware - local_user_name: foo - delegate_to: localhost -''' - -RETURN = '''# ''' - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec - - -class VMwareLocalUserManager(PyVmomi): - - def __init__(self, module): - super(VMwareLocalUserManager, self).__init__(module) - self.local_user_name = self.module.params['local_user_name'] - self.local_user_password = self.module.params['local_user_password'] - self.local_user_description = self.module.params['local_user_description'] - self.state = self.module.params['state'] - - if self.is_vcenter(): - self.module.fail_json(msg="Failed to get local account manager settings " - "from ESXi server: %s" % self.module.params['hostname'], - details="It seems that %s is a vCenter server instead of an " - "ESXi server" % self.module.params['hostname']) - - def process_state(self): - try: - local_account_manager_states = { - 'absent': { - 'present': self.state_remove_user, - 'absent': self.state_exit_unchanged, - }, - 'present': { - 'present': self.state_update_user, - 'absent': self.state_create_user, - } - } - - local_account_manager_states[self.state][self.check_local_user_manager_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 check_local_user_manager_state(self): - user_account = self.find_user_account() - if not user_account: - return 'absent' - else: - return 'present' - - def find_user_account(self): - searchStr = self.local_user_name - exactMatch = True - findUsers = True - findGroups = False - user_account = self.content.userDirectory.RetrieveUserGroups(None, searchStr, None, None, exactMatch, findUsers, findGroups) - return user_account - - def create_account_spec(self): - account_spec = vim.host.LocalAccountManager.AccountSpecification() - account_spec.id = self.local_user_name - account_spec.password = self.local_user_password - account_spec.description = self.local_user_description - return account_spec - - def state_create_user(self): - account_spec = self.create_account_spec() - - try: - self.content.accountManager.CreateUser(account_spec) - self.module.exit_json(changed=True) - 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) - - def state_update_user(self): - account_spec = self.create_account_spec() - - try: - self.content.accountManager.UpdateUser(account_spec) - self.module.exit_json(changed=True) - 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) - - def state_remove_user(self): - try: - self.content.accountManager.RemoveUser(self.local_user_name) - self.module.exit_json(changed=True) - 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) - - def state_exit_unchanged(self): - self.module.exit_json(changed=False) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update(dict(local_user_name=dict(required=True, type='str'), - local_user_password=dict(type='str', no_log=True), - local_user_description=dict(type='str'), - state=dict(default='present', choices=['present', 'absent'], type='str'))) - - module = AnsibleModule(argument_spec=argument_spec, - supports_check_mode=False) - - vmware_local_user_manager = VMwareLocalUserManager(module) - vmware_local_user_manager.process_state() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_maintenancemode.py b/lib/ansible/modules/cloud/vmware/vmware_maintenancemode.py deleted file mode 100644 index 64ebab7d4b..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_maintenancemode.py +++ /dev/null @@ -1,203 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2015, VMware, Inc. -# Copyright: (c) 2018, Ansible Project -# 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 = ''' ---- -module: vmware_maintenancemode -short_description: Place a host into maintenance mode -description: - - This module can be used for placing a ESXi host into maintenance mode. - - Support for VSAN compliant maintenance mode when selected. -author: -- Jay Jahns (@jjahns) <jjahns@vmware.com> -- Abhijeet Kasurde (@Akasurde) -version_added: "2.1" -notes: - - Tested on vSphere 5.5, 6.0 and 6.5 -requirements: - - "python >= 2.6" - - PyVmomi -options: - esxi_hostname: - description: - - Name of the host as defined in vCenter. - required: True - type: str - vsan: - description: - - Specify which VSAN compliant mode to enter. - choices: - - 'ensureObjectAccessibility' - - 'evacuateAllData' - - 'noAction' - required: False - aliases: [ 'vsan_mode' ] - type: str - evacuate: - description: - - If set to C(True), evacuate all powered off VMs. - default: False - required: False - type: bool - timeout: - description: - - Specify a timeout for the operation. - required: False - default: 0 - type: int - state: - description: - - Enter or exit maintenance mode. - choices: - - present - - absent - default: present - required: False - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Enter VSAN-Compliant Maintenance Mode - vmware_maintenancemode: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: "{{ esxi_hostname }}" - vsan: ensureObjectAccessibility - evacuate: yes - timeout: 3600 - state: present - delegate_to: localhost -''' - -RETURN = ''' -hostsystem: - description: Name of vim reference - returned: always - type: str - sample: "'vim.HostSystem:host-236'" -hostname: - description: Name of host in vCenter - returned: always - type: str - sample: "esxi.local.domain" -status: - description: Action taken - returned: always - type: str - sample: "ENTER" -''' - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, TaskError, vmware_argument_spec, wait_for_task -from ansible.module_utils._text import to_native - - -class VmwareMaintenanceMgr(PyVmomi): - def __init__(self, module): - super(VmwareMaintenanceMgr, self).__init__(module) - self.esxi_hostname = self.module.params.get('esxi_hostname') - self.vsan = self.module.params.get('vsan', None) - self.host = self.find_hostsystem_by_name(host_name=self.esxi_hostname) - if not self.host: - self.module.fail_json(msg='Host %s not found in vCenter' % self.esxi_hostname) - - def EnterMaintenanceMode(self): - if self.host.runtime.inMaintenanceMode: - self.module.exit_json(changed=False, - hostsystem=str(self.host), - hostname=self.esxi_hostname, - status='NO_ACTION', - msg='Host %s already in maintenance mode' % self.esxi_hostname) - - spec = vim.host.MaintenanceSpec() - - if self.vsan: - spec.vsanMode = vim.vsan.host.DecommissionMode() - spec.vsanMode.objectAction = self.vsan - - try: - task = self.host.EnterMaintenanceMode_Task(self.module.params['timeout'], - self.module.params['evacuate'], - spec) - - success, result = wait_for_task(task) - - self.module.exit_json(changed=success, - hostsystem=str(self.host), - hostname=self.esxi_hostname, - status='ENTER', - msg='Host %s entered maintenance mode' % self.esxi_hostname) - - except TaskError as e: - self.module.fail_json(msg='Host %s failed to enter maintenance mode due to %s' % (self.esxi_hostname, to_native(e))) - - def ExitMaintenanceMode(self): - if not self.host.runtime.inMaintenanceMode: - self.module.exit_json(changed=False, - hostsystem=str(self.host), - hostname=self.esxi_hostname, - status='NO_ACTION', - msg='Host %s not in maintenance mode' % self.esxi_hostname) - - try: - task = self.host.ExitMaintenanceMode_Task(self.module.params['timeout']) - - success, result = wait_for_task(task) - - self.module.exit_json(changed=success, - hostsystem=str(self.host), - hostname=self.esxi_hostname, - status='EXIT', - msg='Host %s exited maintenance mode' % self.esxi_hostname) - except TaskError as e: - self.module.fail_json(msg='Host %s failed to exit maintenance mode due to %s' % (self.esxi_hostname, to_native(e))) - - -def main(): - spec = vmware_argument_spec() - spec.update(dict(esxi_hostname=dict(type='str', required=True), - vsan=dict(type='str', - choices=['ensureObjectAccessibility', - 'evacuateAllData', - 'noAction'], - aliases=['vsan_mode'], - ), - evacuate=dict(type='bool', default=False), - timeout=dict(default=0, type='int'), - state=dict(required=False, default='present', choices=['present', 'absent']) - ) - ) - - module = AnsibleModule(argument_spec=spec) - - host_maintenance_mgr = VmwareMaintenanceMgr(module=module) - - if module.params['state'] == 'present': - host_maintenance_mgr.EnterMaintenanceMode() - elif module.params['state'] == 'absent': - host_maintenance_mgr.ExitMaintenanceMode() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_migrate_vmk.py b/lib/ansible/modules/cloud/vmware/vmware_migrate_vmk.py deleted file mode 100644 index 2bc2625173..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_migrate_vmk.py +++ /dev/null @@ -1,198 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2015, Joseph Callen <jcallen () csc.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 = ''' ---- -module: vmware_migrate_vmk -short_description: Migrate a VMK interface from VSS to VDS -description: - - Migrate a VMK interface from VSS to VDS -version_added: 2.0 -author: -- Joseph Callen (@jcpowermac) -- Russell Teague (@mtnbikenc) -notes: - - Tested on vSphere 5.5 -requirements: - - "python >= 2.6" - - PyVmomi -options: - esxi_hostname: - description: - - ESXi hostname to be managed - required: True - type: str - device: - description: - - VMK interface name - required: True - type: str - current_switch_name: - description: - - Switch VMK interface is currently on - required: True - type: str - current_portgroup_name: - description: - - Portgroup name VMK interface is currently on - required: True - type: str - migrate_switch_name: - description: - - Switch name to migrate VMK interface to - required: True - type: str - migrate_portgroup_name: - description: - - Portgroup name to migrate VMK interface to - required: True - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Migrate Management vmk - vmware_migrate_vmk: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: "{{ esxi_hostname }}" - device: vmk1 - current_switch_name: temp_vswitch - current_portgroup_name: esx-mgmt - migrate_switch_name: dvSwitch - migrate_portgroup_name: Management - delegate_to: localhost -''' -try: - from pyVmomi import vim, vmodl - HAS_PYVMOMI = True -except ImportError: - HAS_PYVMOMI = False - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import (vmware_argument_spec, find_dvs_by_name, find_hostsystem_by_name, - connect_to_api, find_dvspg_by_name) - - -class VMwareMigrateVmk(object): - - def __init__(self, module): - self.module = module - self.host_system = None - self.migrate_switch_name = self.module.params['migrate_switch_name'] - self.migrate_portgroup_name = self.module.params['migrate_portgroup_name'] - self.device = self.module.params['device'] - self.esxi_hostname = self.module.params['esxi_hostname'] - self.current_portgroup_name = self.module.params['current_portgroup_name'] - self.current_switch_name = self.module.params['current_switch_name'] - self.content = connect_to_api(module) - - def process_state(self): - try: - vmk_migration_states = { - 'migrate_vss_vds': self.state_migrate_vss_vds, - 'migrate_vds_vss': self.state_migrate_vds_vss, - 'migrated': self.state_exit_unchanged - } - - vmk_migration_states[self.check_vmk_current_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 state_exit_unchanged(self): - self.module.exit_json(changed=False) - - def state_migrate_vds_vss(self): - self.module.exit_json(changed=False, msg="Currently Not Implemented") - - def create_host_vnic_config(self, dv_switch_uuid, portgroup_key): - host_vnic_config = vim.host.VirtualNic.Config() - host_vnic_config.spec = vim.host.VirtualNic.Specification() - - host_vnic_config.changeOperation = "edit" - host_vnic_config.device = self.device - host_vnic_config.portgroup = "" - host_vnic_config.spec.distributedVirtualPort = vim.dvs.PortConnection() - host_vnic_config.spec.distributedVirtualPort.switchUuid = dv_switch_uuid - host_vnic_config.spec.distributedVirtualPort.portgroupKey = portgroup_key - - return host_vnic_config - - def create_port_group_config(self): - port_group_config = vim.host.PortGroup.Config() - port_group_config.spec = vim.host.PortGroup.Specification() - - port_group_config.changeOperation = "remove" - port_group_config.spec.name = self.current_portgroup_name - port_group_config.spec.vlanId = -1 - port_group_config.spec.vswitchName = self.current_switch_name - port_group_config.spec.policy = vim.host.NetworkPolicy() - - return port_group_config - - def state_migrate_vss_vds(self): - host_network_system = self.host_system.configManager.networkSystem - - dv_switch = find_dvs_by_name(self.content, self.migrate_switch_name) - pg = find_dvspg_by_name(dv_switch, self.migrate_portgroup_name) - - config = vim.host.NetworkConfig() - config.portgroup = [self.create_port_group_config()] - config.vnic = [self.create_host_vnic_config(dv_switch.uuid, pg.key)] - host_network_system.UpdateNetworkConfig(config, "modify") - self.module.exit_json(changed=True) - - def check_vmk_current_state(self): - self.host_system = find_hostsystem_by_name(self.content, self.esxi_hostname) - - for vnic in self.host_system.configManager.networkSystem.networkInfo.vnic: - if vnic.device == self.device: - # self.vnic = vnic - if vnic.spec.distributedVirtualPort is None: - if vnic.portgroup == self.current_portgroup_name: - return "migrate_vss_vds" - else: - dvs = find_dvs_by_name(self.content, self.current_switch_name) - if dvs is None: - return "migrated" - if vnic.spec.distributedVirtualPort.switchUuid == dvs.uuid: - return "migrate_vds_vss" - - -def main(): - - argument_spec = vmware_argument_spec() - argument_spec.update(dict(esxi_hostname=dict(required=True, type='str'), - device=dict(required=True, type='str'), - current_switch_name=dict(required=True, type='str'), - current_portgroup_name=dict(required=True, type='str'), - migrate_switch_name=dict(required=True, type='str'), - migrate_portgroup_name=dict(required=True, type='str'))) - - module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False) - - if not HAS_PYVMOMI: - module.fail_json(msg='pyvmomi required for this module') - - vmware_migrate_vmk = VMwareMigrateVmk(module) - vmware_migrate_vmk.process_state() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_object_role_permission.py b/lib/ansible/modules/cloud/vmware/vmware_object_role_permission.py deleted file mode 100644 index a3a03d0079..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_object_role_permission.py +++ /dev/null @@ -1,279 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright: (c) 2018, Derek Rushing <derek.rushing@geekops.com> -# Copyright: (c) 2018, VMware, Inc. -# SPDX-License-Identifier: GPL-3.0-or-later -# 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 = ''' ---- -module: vmware_object_role_permission -short_description: Manage local roles on an ESXi host -description: This module can be used to manage object permissions on the given host. -version_added: 2.8 -author: -- Derek Rushing (@kryptsi) -- Joseph Andreatta (@vmwjoseph) -notes: - - Tested on ESXi 6.5, vSphere 6.7 - - The ESXi login user must have the appropriate rights to administer permissions. - - Permissions for a distributed switch must be defined and managed on either the datacenter or a folder containing the switch. -requirements: - - "python >= 2.7" - - PyVmomi -options: - role: - description: - - The role to be assigned permission. - required: True - type: str - principal: - description: - - The user to be assigned permission. - - Required if C(group) is not specified. - type: str - group: - description: - - The group to be assigned permission. - - Required if C(principal) is not specified. - type: str - object_name: - description: - - The object name to assigned permission. - type: str - required: True - object_type: - description: - - The object type being targeted. - default: 'Folder' - choices: ['Folder', 'VirtualMachine', 'Datacenter', 'ResourcePool', - 'Datastore', 'Network', 'HostSystem', 'ComputeResource', - 'ClusterComputeResource', 'DistributedVirtualSwitch'] - type: str - recursive: - description: - - Should the permissions be recursively applied. - default: True - type: bool - state: - description: - - Indicate desired state of the object's permission. - - When C(state=present), the permission will be added if it doesn't already exist. - - When C(state=absent), the permission is removed if it exists. - choices: ['present', 'absent'] - default: present - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Assign user to VM folder - vmware_object_role_permission: - role: Admin - principal: user_bob - object_name: services - state: present - delegate_to: localhost - -- name: Remove user from VM folder - vmware_object_role_permission: - role: Admin - principal: user_bob - object_name: services - state: absent - delegate_to: localhost - -- name: Assign finance group to VM folder - vmware_object_role_permission: - role: Limited Users - group: finance - object_name: Accounts - state: present - delegate_to: localhost - -- name: Assign view_user Read Only permission at root folder - vmware_object_role_permission: - role: ReadOnly - principal: view_user - object_name: rootFolder - state: present - delegate_to: localhost -''' - -RETURN = r''' -changed: - description: whether or not a change was made to the object's role - returned: always - type: bool -''' - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils._text import to_native -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec, find_obj - - -class VMwareObjectRolePermission(PyVmomi): - def __init__(self, module): - super(VMwareObjectRolePermission, self).__init__(module) - self.module = module - self.params = module.params - self.is_group = False - - if self.params.get('principal', None) is not None: - self.applied_to = self.params['principal'] - elif self.params.get('group', None) is not None: - self.applied_to = self.params['group'] - self.is_group = True - - self.get_role() - self.get_object() - self.get_perms() - self.perm = self.setup_permission() - self.state = self.params['state'] - - def get_perms(self): - self.current_perms = self.content.authorizationManager.RetrieveEntityPermissions(self.current_obj, False) - - def same_permission(self, perm_one, perm_two): - return perm_one.principal.lower() == perm_two.principal.lower() \ - and perm_one.roleId == perm_two.roleId - - def get_state(self): - for perm in self.current_perms: - if self.same_permission(self.perm, perm): - return 'present' - return 'absent' - - def process_state(self): - local_permission_states = { - 'absent': { - 'present': self.remove_permission, - 'absent': self.state_exit_unchanged, - }, - 'present': { - 'present': self.state_exit_unchanged, - 'absent': self.add_permission, - } - } - try: - local_permission_states[self.state][self.get_state()]() - except vmodl.RuntimeFault as runtime_fault: - self.module.fail_json(msg=to_native(runtime_fault.msg)) - except vmodl.MethodFault as method_fault: - self.module.fail_json(msg=to_native(method_fault.msg)) - except Exception as e: - self.module.fail_json(msg=to_native(e)) - - def state_exit_unchanged(self): - self.module.exit_json(changed=False) - - def setup_permission(self): - perm = vim.AuthorizationManager.Permission() - perm.entity = self.current_obj - perm.group = self.is_group - perm.principal = self.applied_to - perm.roleId = self.role.roleId - perm.propagate = self.params['recursive'] - return perm - - def add_permission(self): - if not self.module.check_mode: - self.content.authorizationManager.SetEntityPermissions(self.current_obj, [self.perm]) - self.module.exit_json(changed=True) - - def remove_permission(self): - if not self.module.check_mode: - self.content.authorizationManager.RemoveEntityPermission(self.current_obj, self.applied_to, self.is_group) - self.module.exit_json(changed=True) - - def get_role(self): - for role in self.content.authorizationManager.roleList: - if role.name == self.params['role']: - self.role = role - return - self.module.fail_json(msg="Specified role (%s) was not found" % self.params['role']) - - def get_object(self): - # find_obj doesn't include rootFolder - if self.params['object_type'] == 'Folder' and self.params['object_name'] == 'rootFolder': - self.current_obj = self.content.rootFolder - return - try: - object_type = getattr(vim, self.params['object_type']) - except AttributeError: - self.module.fail_json(msg="Object type %s is not valid." % self.params['object_type']) - self.current_obj = find_obj(content=self.content, - vimtype=[getattr(vim, self.params['object_type'])], - name=self.params['object_name']) - - if self.current_obj is None: - self.module.fail_json( - msg="Specified object %s of type %s was not found." - % (self.params['object_name'], self.params['object_type']) - ) - if self.params['object_type'] == 'DistributedVirtualSwitch': - msg = "You are applying permissions to a Distributed vSwitch. " \ - "This will probably fail, since Distributed vSwitches inherits permissions " \ - "from the datacenter or a folder level. " \ - "Define permissions on the datacenter or the folder containing the switch." - self.module.warn(msg) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - dict( - role=dict(required=True, type='str'), - object_name=dict(required=True, type='str'), - object_type=dict( - type='str', - default='Folder', - choices=[ - 'Folder', - 'VirtualMachine', - 'Datacenter', - 'ResourcePool', - 'Datastore', - 'Network', - 'HostSystem', - 'ComputeResource', - 'ClusterComputeResource', - 'DistributedVirtualSwitch', - ], - ), - principal=dict(type='str'), - group=dict(type='str'), - recursive=dict(type='bool', default=True), - state=dict(default='present', choices=['present', 'absent'], type='str'), - ) - ) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - mutually_exclusive=[['principal', 'group']], - required_one_of=[['principal', 'group']], - ) - - vmware_object_permission = VMwareObjectRolePermission(module) - vmware_object_permission.process_state() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_portgroup.py b/lib/ansible/modules/cloud/vmware/vmware_portgroup.py deleted file mode 100644 index fb9a1bd863..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_portgroup.py +++ /dev/null @@ -1,1055 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2015, Joseph Callen <jcallen () csc.com> -# Copyright: (c) 2017, Ansible Project -# Copyright: (c) 2017, Abhijeet Kasurde <akasurde@redhat.com> -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# 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 = ''' ---- -module: vmware_portgroup -short_description: Create a VMware portgroup -description: - - Create a VMware Port Group on a VMware Standard Switch (vSS) for given ESXi host(s) or hosts of given cluster. -version_added: 2.0 -author: -- Joseph Callen (@jcpowermac) -- Russell Teague (@mtnbikenc) -- Abhijeet Kasurde (@Akasurde) -- Christian Kotte (@ckotte) -notes: - - Tested on vSphere 5.5 and 6.5 - - Complete configuration only tested on vSphere 6.5 - - 'C(inbound_policy) and C(rolling_order) are deprecated and will be removed in 2.11' - - Those two options are only used during portgroup creation. Updating isn't supported with those options. -requirements: - - "python >= 2.6" - - PyVmomi -options: - switch: - description: - - vSwitch to modify. - required: True - aliases: [ 'switch_name', 'vswitch' ] - type: str - portgroup: - description: - - Portgroup name to add. - required: True - aliases: [ 'portgroup_name' ] - type: str - vlan_id: - description: - - VLAN ID to assign to portgroup. - - Set to 0 (no VLAN tagging) by default. - required: False - default: 0 - aliases: [ 'vlan' ] - type: int - security: - description: - - Network policy specifies layer 2 security settings for a - portgroup such as promiscuous mode, where guest adapter listens - to all the packets, MAC address changes and forged transmits. - - Dict which configures the different security values for portgroup. - - 'Valid attributes are:' - - '- C(promiscuous_mode) (bool): indicates whether promiscuous mode is allowed. (default: None)' - - '- C(forged_transmits) (bool): indicates whether forged transmits are allowed. (default: None)' - - '- C(mac_changes) (bool): indicates whether mac changes are allowed. (default: None)' - required: False - version_added: "2.2" - aliases: [ 'security_policy', 'network_policy' ] - type: dict - teaming: - description: - - Dictionary which configures the different teaming values for portgroup. - - 'Valid attributes are:' - - '- C(load_balancing) (string): Network adapter teaming policy. C(load_balance_policy) is also alias to this option. (default: loadbalance_srcid)' - - ' - choices: [ loadbalance_ip, loadbalance_srcmac, loadbalance_srcid, failover_explicit ]' - - '- C(network_failure_detection) (string): Network failure detection. (default: link_status_only)' - - ' - choices: [ link_status_only, beacon_probing ]' - - '- C(notify_switches) (bool): Indicate whether or not to notify the physical switch if a link fails. (default: None)' - - '- C(failback) (bool): Indicate whether or not to use a failback when restoring links. (default: None)' - - '- C(active_adapters) (list): List of active adapters used for load balancing.' - - '- C(standby_adapters) (list): List of standby adapters used for failover.' - - '- All vmnics are used as active adapters if C(active_adapters) and C(standby_adapters) are not defined.' - - '- C(inbound_policy) (bool): Indicate whether or not the teaming policy is applied to inbound frames as well. Deprecated. (default: False)' - - '- C(rolling_order) (bool): Indicate whether or not to use a rolling policy when restoring links. Deprecated. (default: False)' - required: False - version_added: '2.6' - aliases: [ 'teaming_policy' ] - type: dict - traffic_shaping: - description: - - Dictionary which configures traffic shaping for the switch. - - 'Valid attributes are:' - - '- C(enabled) (bool): Status of Traffic Shaping Policy. (default: None)' - - '- C(average_bandwidth) (int): Average bandwidth (kbit/s). (default: None)' - - '- C(peak_bandwidth) (int): Peak bandwidth (kbit/s). (default: None)' - - '- C(burst_size) (int): Burst size (KB). (default: None)' - required: False - version_added: '2.9' - type: dict - cluster_name: - description: - - Name of cluster name for host membership. - - Portgroup will be created on all hosts of the given cluster. - - This option is required if C(hosts) is not specified. - version_added: "2.5" - aliases: [ 'cluster' ] - type: str - hosts: - description: - - List of name of host or hosts on which portgroup needs to be added. - - This option is required if C(cluster_name) is not specified. - aliases: [ esxi_hostname ] - version_added: "2.5" - type: list - state: - description: - - Determines if the portgroup should be present or not. - choices: - - 'present' - - 'absent' - version_added: '2.5' - default: present - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Add Management Network VM Portgroup - vmware_portgroup: - hostname: "{{ esxi_hostname }}" - username: "{{ esxi_username }}" - password: "{{ esxi_password }}" - switch: "{{ vswitch_name }}" - portgroup: "{{ portgroup_name }}" - vlan_id: "{{ vlan_id }}" - delegate_to: localhost - -- name: Add Portgroup with Promiscuous Mode Enabled - vmware_portgroup: - hostname: "{{ esxi_hostname }}" - username: "{{ esxi_username }}" - password: "{{ esxi_password }}" - switch: "{{ vswitch_name }}" - portgroup: "{{ portgroup_name }}" - security: - promiscuous_mode: True - delegate_to: localhost - -- name: Add Management Network VM Portgroup to specific hosts - vmware_portgroup: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - hosts: [esxi_hostname_one] - switch: "{{ vswitch_name }}" - portgroup: "{{ portgroup_name }}" - vlan_id: "{{ vlan_id }}" - delegate_to: localhost - -- name: Add Management Network VM Portgroup to all hosts in a cluster - vmware_portgroup: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: "{{ cluster_name }}" - switch: "{{ vswitch_name }}" - portgroup: "{{ portgroup_name }}" - vlan_id: "{{ vlan_id }}" - delegate_to: localhost - -- name: Remove Management Network VM Portgroup to all hosts in a cluster - vmware_portgroup: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: "{{ cluster_name }}" - switch: "{{ vswitch_name }}" - portgroup: "{{ portgroup_name }}" - vlan_id: "{{ vlan_id }}" - state: absent - delegate_to: localhost - -- name: Add Portgroup with all settings defined - vmware_portgroup: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: "{{ inventory_hostname }}" - switch: "{{ vswitch_name }}" - portgroup: "{{ portgroup_name }}" - vlan_id: 10 - security: - promiscuous_mode: False - mac_changes: False - forged_transmits: False - traffic_shaping: - enabled: True - average_bandwidth: 100000 - peak_bandwidth: 100000 - burst_size: 102400 - teaming: - load_balancing: failover_explicit - network_failure_detection: link_status_only - notify_switches: true - failback: true - active_adapters: - - vmnic0 - standby_adapters: - - vmnic1 - delegate_to: localhost - register: teaming_result -''' - -RETURN = r''' -result: - description: metadata about the portgroup - returned: always - type: dict - sample: { - "esxi01.example.com": { - "changed": true, - "failback": "No override", - "failover_active": "No override", - "failover_standby": "No override", - "failure_detection": "No override", - "load_balancing": "No override", - "msg": "Port Group added", - "notify_switches": "No override", - "portgroup": "vMotion", - "sec_forged_transmits": false, - "sec_mac_changes": false, - "sec_promiscuous_mode": false, - "traffic_shaping": "No override", - "vlan_id": 33, - "vswitch": "vSwitch1" - } - } -''' - - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec -from ansible.module_utils._text import to_native - - -class VMwareHostPortGroup(PyVmomi): - """Manage portgroup""" - - def __init__(self, module): - super(VMwareHostPortGroup, self).__init__(module) - self.switch_object = None - self.portgroup_object = None - hosts = self.params['hosts'] - cluster = self.params['cluster_name'] - self.portgroup = self.params['portgroup'] - self.switch = self.params['switch'] - self.vlan_id = self.params['vlan_id'] - if self.params['security']: - self.sec_promiscuous_mode = self.params['security'].get('promiscuous_mode') - self.sec_forged_transmits = self.params['security'].get('forged_transmits') - self.sec_mac_changes = self.params['security'].get('mac_changes') - else: - self.sec_promiscuous_mode = None - self.sec_forged_transmits = None - self.sec_mac_changes = None - if self.params['traffic_shaping']: - self.ts_enabled = self.params['traffic_shaping'].get('enabled') - for value in ['average_bandwidth', 'peak_bandwidth', 'burst_size']: - if not self.params['traffic_shaping'].get(value): - self.module.fail_json(msg="traffic_shaping.%s is a required parameter if traffic_shaping is enabled." % value) - self.ts_average_bandwidth = self.params['traffic_shaping'].get('average_bandwidth') - self.ts_peak_bandwidth = self.params['traffic_shaping'].get('peak_bandwidth') - self.ts_burst_size = self.params['traffic_shaping'].get('burst_size') - else: - self.ts_enabled = None - self.ts_average_bandwidth = None - self.ts_peak_bandwidth = None - self.ts_burst_size = None - if self.params['teaming']: - self.teaming_load_balancing = self.params['teaming'].get('load_balancing') - self.teaming_failure_detection = self.params['teaming'].get('network_failure_detection') - self.teaming_notify_switches = self.params['teaming'].get('notify_switches') - self.teaming_failback = self.params['teaming'].get('failback') - self.teaming_failover_order_active = self.params['teaming'].get('active_adapters') - self.teaming_failover_order_standby = self.params['teaming'].get('standby_adapters') - if self.teaming_failover_order_active is None: - self.teaming_failover_order_active = [] - if self.teaming_failover_order_standby is None: - self.teaming_failover_order_standby = [] - # NOTE: the following options are deprecated and should be removed in 2.11 - self.teaming_inbound_policy = self.module.params['teaming']['inbound_policy'] - self.teaming_rolling_order = self.module.params['teaming']['rolling_order'] - else: - self.teaming_load_balancing = None - self.teaming_failure_detection = None - self.teaming_notify_switches = None - self.teaming_failback = None - self.teaming_failover_order_active = None - self.teaming_failover_order_standby = None - # NOTE: the following options are deprecated and should be removed in 2.11 - self.teaming_inbound_policy = None - self.teaming_rolling_order = None - self.state = self.params['state'] - - self.hosts = self.get_all_host_objs(cluster_name=cluster, esxi_host_name=hosts) - if not self.hosts: - self.module.fail_json(msg="Failed to find host system with given configuration.") - - def process_state(self): - """Manage internal state of the portgroup""" - results = dict(changed=False, result=dict()) - host_change_list = [] - for host in self.hosts: - changed = False - results['result'][host.name] = dict() - switch_state = self.check_if_vswitch_exists(host_system=host) - if switch_state == 'absent': - self.module.fail_json(msg="The vSwitch '%s' doesn't exist on host '%s'" % (self.switch, host.name)) - portgroup_state = self.check_if_portgroup_exists(host_system=host) - if self.state == 'present' and portgroup_state == 'present': - changed, host_results = self.update_host_port_group( - host_system=host, - portgroup_object=self.portgroup_object - ) - elif self.state == 'present' and portgroup_state == 'absent': - changed, host_results = self.create_host_port_group(host_system=host) - elif self.state == 'absent' and portgroup_state == 'present': - changed, host_results = self.remove_host_port_group(host_system=host) - else: - host_results = dict() - host_results['changed'] = False - host_results['msg'] = "Port Group already deleted" - host_results['portgroup'] = self.portgroup - results['result'][host.name] = host_results - - host_change_list.append(changed) - - if any(host_change_list): - results['changed'] = True - self.module.exit_json(**results) - - def check_if_portgroup_exists(self, host_system): - """ - Check if portgroup exists - Returns: 'present' if portgroup exists or 'absent' if not - """ - self.portgroup_object = self.find_portgroup_by_name( - host_system=host_system, - portgroup_name=self.portgroup, - vswitch_name=self.switch - ) - if self.portgroup_object is None: - return 'absent' - return 'present' - - def find_portgroup_by_name(self, host_system, portgroup_name, vswitch_name): - """ - Find and return port group managed object - Args: - host_system: Name of Host System - portgroup_name: Name of the Port Group - vswitch_name: Name of the vSwitch - - Returns: Port Group managed object if found, else None - """ - portgroups = self.get_all_port_groups_by_host(host_system=host_system) - for portgroup in portgroups: - if portgroup.spec.name == portgroup_name and portgroup.spec.vswitchName != vswitch_name: - # portgroup names are unique; there can be only one portgroup with the same name per host - self.module.fail_json(msg="The portgroup already exists on vSwitch '%s'" % portgroup.spec.vswitchName) - if portgroup.spec.name == portgroup_name and portgroup.spec.vswitchName == vswitch_name: - return portgroup - return None - - def check_if_vswitch_exists(self, host_system): - """ - Check if vSwitch exists - Returns: 'present' if vSwitch exists or 'absent' if not - """ - self.switch_object = self.find_vswitch_by_name( - host_system=host_system, - vswitch_name=self.switch - ) - if self.switch_object is None: - return 'absent' - return 'present' - - @staticmethod - def find_vswitch_by_name(host_system, vswitch_name): - """ - Find and return vSwitch managed object - Args: - host: Host system managed object - vswitch_name: Name of vSwitch to find - - Returns: vSwitch managed object if found, else None - """ - for vss in host_system.configManager.networkSystem.networkInfo.vswitch: - if vss.name == vswitch_name: - return vss - return None - - def remove_host_port_group(self, host_system): - """ - Remove a Port Group from a given host - Args: - host_system: Name of Host System - """ - host_results = dict(changed=False, msg="") - - if self.module.check_mode: - host_results['msg'] = "Port Group would be removed" - else: - try: - host_system.configManager.networkSystem.RemovePortGroup(pgName=self.portgroup) - host_results['msg'] = "Port Group removed" - except vim.fault.NotFound as not_found: - self.module.fail_json( - msg="Failed to remove Portgroup as it was not found: %s" % to_native(not_found.msg) - ) - except vim.fault.ResourceInUse as resource_in_use: - self.module.fail_json( - msg="Failed to remove Portgroup as it is in use: %s" % to_native(resource_in_use.msg) - ) - except vim.fault.HostConfigFault as host_config_fault: - self.module.fail_json( - msg="Failed to remove Portgroup due to configuration failures: %s" % to_native(host_config_fault.msg) - ) - host_results['changed'] = True - host_results['portgroup'] = self.portgroup - host_results['vswitch'] = self.switch - - return True, host_results - - def create_host_port_group(self, host_system): - """Create Port Group on a given host - Args: - host_system: Name of Host System - """ - host_results = dict(changed=False, msg="") - - if self.module.check_mode: - host_results['msg'] = "Port Group would be added" - else: - port_group = vim.host.PortGroup.Config() - port_group.spec = vim.host.PortGroup.Specification() - port_group.spec.vswitchName = self.switch - port_group.spec.name = self.portgroup - port_group.spec.vlanId = self.vlan_id - port_group.spec.policy = self.create_network_policy() - - try: - host_system.configManager.networkSystem.AddPortGroup(portgrp=port_group.spec) - host_results['changed'] = True - host_results['msg'] = "Port Group added" - except vim.fault.AlreadyExists as already_exists: - self.module.fail_json( - msg="Failed to add Portgroup as it already exists: %s" % to_native(already_exists.msg) - ) - except vim.fault.NotFound as not_found: - self.module.fail_json( - msg="Failed to add Portgroup as vSwitch was not found: %s" % to_native(not_found.msg) - ) - except vim.fault.HostConfigFault as host_config_fault: - self.module.fail_json( - msg="Failed to add Portgroup due to host system configuration failure : %s" % - to_native(host_config_fault.msg) - ) - except vmodl.fault.InvalidArgument as invalid_argument: - self.module.fail_json( - msg="Failed to add Portgroup as VLAN id was not correct as per specifications: %s" % - to_native(invalid_argument.msg) - ) - host_results['changed'] = True - host_results['portgroup'] = self.portgroup - host_results['vswitch'] = self.switch - host_results['vlan_id'] = self.vlan_id - if self.sec_promiscuous_mode is None: - host_results['sec_promiscuous_mode'] = "No override" - else: - host_results['sec_promiscuous_mode'] = self.sec_promiscuous_mode - if self.sec_mac_changes is None: - host_results['sec_mac_changes'] = "No override" - else: - host_results['sec_mac_changes'] = self.sec_mac_changes - if self.sec_forged_transmits is None: - host_results['sec_forged_transmits'] = "No override" - else: - host_results['sec_forged_transmits'] = self.sec_forged_transmits - host_results['traffic_shaping'] = "No override" if self.ts_enabled is None else self.ts_enabled - host_results['load_balancing'] = "No override" if self.teaming_load_balancing is None \ - else self.teaming_load_balancing - host_results['notify_switches'] = "No override" if self.teaming_notify_switches is None \ - else self.teaming_notify_switches - host_results['failback'] = "No override" if self.teaming_failback is None else self.teaming_failback - host_results['failover_active'] = "No override" if self.teaming_failover_order_active is None \ - else self.teaming_failover_order_active - host_results['failover_standby'] = "No override" if self.teaming_failover_order_standby is None \ - else self.teaming_failover_order_standby - host_results['failure_detection'] = "No override" if self.teaming_failure_detection is None \ - else self.teaming_failure_detection - - return True, host_results - - def update_host_port_group(self, host_system, portgroup_object): - """Update a Port Group on a given host - Args: - host_system: Name of Host System - """ - changed = changed_security = False - changed_list = [] - host_results = dict(changed=False, msg="") - spec = portgroup_object.spec - - # Check VLAN ID - host_results['vlan_id'] = self.vlan_id - if spec.vlanId != self.vlan_id: - changed = True - changed_list.append("VLAN ID") - host_results['vlan_id_previous'] = spec.vlanId - spec.vlanId = self.vlan_id - - # Check security settings - if self.sec_promiscuous_mode is None: - host_results['sec_promiscuous_mode'] = "No override" - else: - host_results['sec_promiscuous_mode'] = self.sec_promiscuous_mode - if self.sec_mac_changes is None: - host_results['sec_mac_changes'] = "No override" - else: - host_results['sec_mac_changes'] = self.sec_mac_changes - if self.sec_forged_transmits is None: - host_results['sec_forged_transmits'] = "No override" - else: - host_results['sec_forged_transmits'] = self.sec_forged_transmits - if spec.policy.security: - promiscuous_mode_previous = spec.policy.security.allowPromiscuous - mac_changes_previous = spec.policy.security.macChanges - forged_transmits_previous = spec.policy.security.forgedTransmits - if promiscuous_mode_previous is not self.sec_promiscuous_mode: - spec.policy.security.allowPromiscuous = self.sec_promiscuous_mode - changed = changed_security = True - changed_list.append("Promiscuous mode") - if mac_changes_previous is not self.sec_mac_changes: - spec.policy.security.macChanges = self.sec_mac_changes - changed = changed_security = True - changed_list.append("MAC address changes") - if forged_transmits_previous is not self.sec_forged_transmits: - spec.policy.security.forgedTransmits = self.sec_forged_transmits - changed = changed_security = True - changed_list.append("Forged transmits") - if changed_security: - if self.sec_promiscuous_mode is None: - host_results['sec_promiscuous_mode_previous'] = "No override" - else: - host_results['sec_promiscuous_mode_previous'] = promiscuous_mode_previous - if self.sec_mac_changes is None: - host_results['sec_mac_changes_previous'] = "No override" - else: - host_results['sec_mac_changes'] = mac_changes_previous - if self.sec_forged_transmits is None: - host_results['sec_forged_transmits_previous'] = "No override" - else: - host_results['sec_forged_transmits_previous'] = forged_transmits_previous - else: - spec.policy.security = self.create_security_policy() - changed = True - changed_list.append("Security") - host_results['sec_promiscuous_mode_previous'] = "No override" - host_results['sec_mac_changes_previous'] = "No override" - host_results['sec_forged_transmits_previous'] = "No override" - - # Check traffic shaping - if self.ts_enabled is None: - host_results['traffic_shaping'] = "No override" - else: - host_results['traffic_shaping'] = self.ts_enabled - if self.ts_enabled: - ts_average_bandwidth = self.ts_average_bandwidth * 1000 - ts_peak_bandwidth = self.ts_peak_bandwidth * 1000 - ts_burst_size = self.ts_burst_size * 1024 - host_results['traffic_shaping_avg_bandw'] = ts_average_bandwidth - host_results['traffic_shaping_peak_bandw'] = ts_peak_bandwidth - host_results['traffic_shaping_burst'] = ts_burst_size - if spec.policy.shapingPolicy and spec.policy.shapingPolicy.enabled is not None: - if spec.policy.shapingPolicy.enabled: - if self.ts_enabled: - if spec.policy.shapingPolicy.averageBandwidth != ts_average_bandwidth: - changed = True - changed_list.append("Average bandwidth") - host_results['traffic_shaping_avg_bandw_previous'] = spec.policy.shapingPolicy.averageBandwidth - spec.policy.shapingPolicy.averageBandwidth = ts_average_bandwidth - if spec.policy.shapingPolicy.peakBandwidth != ts_peak_bandwidth: - changed = True - changed_list.append("Peak bandwidth") - host_results['traffic_shaping_peak_bandw_previous'] = spec.policy.shapingPolicy.peakBandwidth - spec.policy.shapingPolicy.peakBandwidth = ts_peak_bandwidth - if spec.policy.shapingPolicy.burstSize != ts_burst_size: - changed = True - changed_list.append("Burst size") - host_results['traffic_shaping_burst_previous'] = spec.policy.shapingPolicy.burstSize - spec.policy.shapingPolicy.burstSize = ts_burst_size - elif self.ts_enabled is False: - changed = True - changed_list.append("Traffic shaping") - host_results['traffic_shaping_previous'] = True - spec.policy.shapingPolicy.enabled = False - elif self.ts_enabled is None: - spec.policy.shapingPolicy = None - changed = True - changed_list.append("Traffic shaping") - host_results['traffic_shaping_previous'] = True - else: - if self.ts_enabled: - spec.policy.shapingPolicy = self.create_shaping_policy() - changed = True - changed_list.append("Traffic shaping") - host_results['traffic_shaping_previous'] = False - elif self.ts_enabled is False: - changed = True - changed_list.append("Traffic shaping") - host_results['traffic_shaping_previous'] = True - spec.policy.shapingPolicy.enabled = False - elif self.ts_enabled is None: - spec.policy.shapingPolicy = None - changed = True - changed_list.append("Traffic shaping") - host_results['traffic_shaping_previous'] = True - else: - if self.ts_enabled: - spec.policy.shapingPolicy = self.create_shaping_policy() - changed = True - changed_list.append("Traffic shaping") - host_results['traffic_shaping_previous'] = "No override" - elif self.ts_enabled is False: - changed = True - changed_list.append("Traffic shaping") - host_results['traffic_shaping_previous'] = "No override" - spec.policy.shapingPolicy.enabled = False - - # Check teaming - if spec.policy.nicTeaming: - # Check teaming policy - if self.teaming_load_balancing is None: - host_results['load_balancing'] = "No override" - else: - host_results['load_balancing'] = self.teaming_load_balancing - if spec.policy.nicTeaming.policy: - if spec.policy.nicTeaming.policy != self.teaming_load_balancing: - changed = True - changed_list.append("Load balancing") - host_results['load_balancing_previous'] = spec.policy.nicTeaming.policy - spec.policy.nicTeaming.policy = self.teaming_load_balancing - else: - if self.teaming_load_balancing: - changed = True - changed_list.append("Load balancing") - host_results['load_balancing_previous'] = "No override" - spec.policy.nicTeaming.policy = self.teaming_load_balancing - # Check teaming notify switches - if spec.policy.nicTeaming.notifySwitches is None: - host_results['notify_switches'] = "No override" - else: - host_results['notify_switches'] = self.teaming_notify_switches - if spec.policy.nicTeaming.notifySwitches is not None: - if self.teaming_notify_switches is not None: - if spec.policy.nicTeaming.notifySwitches is not self.teaming_notify_switches: - changed = True - changed_list.append("Notify switches") - host_results['notify_switches_previous'] = spec.policy.nicTeaming.notifySwitches - spec.policy.nicTeaming.notifySwitches = self.teaming_notify_switches - else: - changed = True - changed_list.append("Notify switches") - host_results['notify_switches_previous'] = spec.policy.nicTeaming.notifySwitches - spec.policy.nicTeaming.notifySwitches = None - else: - if self.teaming_notify_switches is not None: - changed = True - changed_list.append("Notify switches") - host_results['notify_switches_previous'] = "No override" - spec.policy.nicTeaming.notifySwitches = self.teaming_notify_switches - # Check failback - if spec.policy.nicTeaming.rollingOrder is None: - host_results['failback'] = "No override" - else: - host_results['failback'] = self.teaming_failback - if spec.policy.nicTeaming.rollingOrder is not None: - if self.teaming_failback is not None: - # this option is called 'failback' in the vSphere Client - # rollingOrder also uses the opposite value displayed in the client - if spec.policy.nicTeaming.rollingOrder is self.teaming_failback: - changed = True - changed_list.append("Failback") - host_results['failback_previous'] = not spec.policy.nicTeaming.rollingOrder - spec.policy.nicTeaming.rollingOrder = not self.teaming_failback - else: - changed = True - changed_list.append("Failback") - host_results['failback_previous'] = spec.policy.nicTeaming.rollingOrder - spec.policy.nicTeaming.rollingOrder = None - else: - if self.teaming_failback is not None: - changed = True - changed_list.append("Failback") - host_results['failback_previous'] = "No override" - spec.policy.nicTeaming.rollingOrder = not self.teaming_failback - # Check teaming failover order - if self.teaming_failover_order_active is None and self.teaming_failover_order_standby is None: - host_results['failover_active'] = "No override" - host_results['failover_standby'] = "No override" - else: - host_results['failover_active'] = self.teaming_failover_order_active - host_results['failover_standby'] = self.teaming_failover_order_standby - if spec.policy.nicTeaming.nicOrder: - if self.teaming_failover_order_active or self.teaming_failover_order_standby: - if spec.policy.nicTeaming.nicOrder.activeNic != self.teaming_failover_order_active: - changed = True - changed_list.append("Failover order active") - host_results['failover_active_previous'] = spec.policy.nicTeaming.nicOrder.activeNic - spec.policy.nicTeaming.nicOrder.activeNic = self.teaming_failover_order_active - if spec.policy.nicTeaming.nicOrder.standbyNic != self.teaming_failover_order_standby: - changed = True - changed_list.append("Failover order standby") - host_results['failover_standby_previous'] = spec.policy.nicTeaming.nicOrder.standbyNic - spec.policy.nicTeaming.nicOrder.standbyNic = self.teaming_failover_order_standby - else: - spec.policy.nicTeaming.nicOrder = None - changed = True - changed_list.append("Failover order") - if hasattr(spec.policy.nicTeaming.nicOrder, 'activeNic'): - host_results['failover_active_previous'] = spec.policy.nicTeaming.nicOrder.activeNic - else: - host_results['failover_active_previous'] = [] - if hasattr(spec.policy.nicTeaming.nicOrder, 'standbyNic'): - host_results['failover_standby_previous'] = spec.policy.nicTeaming.nicOrder.standbyNic - else: - host_results['failover_standby_previous'] = [] - else: - if self.teaming_failover_order_active or self.teaming_failover_order_standby: - changed = True - changed_list.append("Failover order") - host_results['failover_active_previous'] = "No override" - host_results['failover_standby_previous'] = "No override" - spec.policy.nicTeaming.nicOrder = self.create_nic_order_policy() - # Check teaming failure detection - if self.teaming_failure_detection is None: - host_results['failure_detection'] = "No override" - else: - host_results['failure_detection'] = self.teaming_failure_detection - if spec.policy.nicTeaming.failureCriteria and spec.policy.nicTeaming.failureCriteria.checkBeacon is not None: - if self.teaming_failure_detection == "link_status_only": - if spec.policy.nicTeaming.failureCriteria.checkBeacon is True: - changed = True - changed_list.append("Network failure detection") - host_results['failure_detection_previous'] = "beacon_probing" - spec.policy.nicTeaming.failureCriteria.checkBeacon = False - elif self.teaming_failure_detection == "beacon_probing": - if spec.policy.nicTeaming.failureCriteria.checkBeacon is False: - changed = True - changed_list.append("Network failure detection") - host_results['failure_detection_previous'] = "link_status_only" - spec.policy.nicTeaming.failureCriteria.checkBeacon = True - elif spec.policy.nicTeaming.failureCriteria.checkBeacon is not None: - changed = True - changed_list.append("Network failure detection") - host_results['failure_detection_previous'] = spec.policy.nicTeaming.failureCriteria.checkBeacon - spec.policy.nicTeaming.failureCriteria = None - else: - if self.teaming_failure_detection: - spec.policy.nicTeaming.failureCriteria = self.create_nic_failure_policy() - changed = True - changed_list.append("Network failure detection") - host_results['failure_detection_previous'] = "No override" - else: - spec.policy.nicTeaming = self.create_teaming_policy() - if spec.policy.nicTeaming: - changed = True - changed_list.append("Teaming and failover") - host_results['load_balancing_previous'] = "No override" - host_results['notify_switches_previous'] = "No override" - host_results['failback_previous'] = "No override" - host_results['failover_active_previous'] = "No override" - host_results['failover_standby_previous'] = "No override" - host_results['failure_detection_previous'] = "No override" - - if changed: - if self.module.check_mode: - changed_suffix = ' would be changed' - else: - changed_suffix = ' changed' - if len(changed_list) > 2: - message = ', '.join(changed_list[:-1]) + ', and ' + str(changed_list[-1]) - elif len(changed_list) == 2: - message = ' and '.join(changed_list) - elif len(changed_list) == 1: - message = changed_list[0] - message += changed_suffix - if not self.module.check_mode: - try: - host_system.configManager.networkSystem.UpdatePortGroup( - pgName=self.portgroup, - portgrp=spec - ) - except vim.fault.AlreadyExists as already_exists: - self.module.fail_json( - msg="Failed to update Portgroup as it would conflict with an existing port group: %s" % - to_native(already_exists.msg) - ) - except vim.fault.NotFound as not_found: - self.module.fail_json( - msg="Failed to update Portgroup as vSwitch was not found: %s" % - to_native(not_found.msg) - ) - except vim.fault.HostConfigFault as host_config_fault: - self.module.fail_json( - msg="Failed to update Portgroup due to host system configuration failure : %s" % - to_native(host_config_fault.msg) - ) - except vmodl.fault.InvalidArgument as invalid_argument: - self.module.fail_json( - msg="Failed to update Port Group '%s', this can be due to either of following :" - " 1. VLAN id was not correct as per specifications, 2. Network policy is invalid : %s" % - (self.portgroup, to_native(invalid_argument.msg)) - ) - else: - message = "Port Group already configured properly" - host_results['changed'] = changed - host_results['msg'] = message - host_results['portgroup'] = self.portgroup - host_results['vswitch'] = self.switch - - return changed, host_results - - def create_network_policy(self): - """ - Create a Network Policy - Returns: Network Policy object - """ - security_policy = None - shaping_policy = None - teaming_policy = None - - # Only configure security policy if an option is defined - if not all(option is None for option in [self.sec_promiscuous_mode, - self.sec_mac_changes, - self.sec_forged_transmits]): - security_policy = self.create_security_policy() - if self.ts_enabled: - shaping_policy = self.create_shaping_policy() - teaming_policy = self.create_teaming_policy() - - network_policy = vim.host.NetworkPolicy( - security=security_policy, - nicTeaming=teaming_policy, - shapingPolicy=shaping_policy - ) - - return network_policy - - def create_security_policy(self): - """ - Create a Security Policy - Returns: Security Policy object - """ - security_policy = vim.host.NetworkPolicy.SecurityPolicy() - security_policy.allowPromiscuous = self.sec_promiscuous_mode - security_policy.macChanges = self.sec_mac_changes - security_policy.forgedTransmits = self.sec_forged_transmits - return security_policy - - def create_shaping_policy(self): - """ - Create a Traffic Shaping Policy - Returns: Traffic Shaping Policy object - """ - shaping_policy = vim.host.NetworkPolicy.TrafficShapingPolicy() - shaping_policy.enabled = self.ts_enabled - shaping_policy.averageBandwidth = self.ts_average_bandwidth * 1000 - shaping_policy.peakBandwidth = self.ts_peak_bandwidth * 1000 - shaping_policy.burstSize = self.ts_burst_size * 1024 - return shaping_policy - - def create_teaming_policy(self): - """ - Create a NIC Teaming Policy - Returns: NIC Teaming Policy object - """ - # Only configure teaming policy if an option is defined - if not all(option is None for option in [self.teaming_load_balancing, - self.teaming_failure_detection, - self.teaming_notify_switches, - self.teaming_failback, - self.teaming_failover_order_active, - self.teaming_failover_order_standby]): - teaming_policy = vim.host.NetworkPolicy.NicTeamingPolicy() - teaming_policy.policy = self.teaming_load_balancing - # NOTE: 'teaming_inbound_policy' is deprecated and the following if statement should be removed in 2.11 - if self.teaming_inbound_policy: - teaming_policy.reversePolicy = self.teaming_inbound_policy - else: - # Deprecated since VI API 5.1. The system default (true) will be used - teaming_policy.reversePolicy = True - teaming_policy.notifySwitches = self.teaming_notify_switches - # NOTE: 'teaming_rolling_order' is deprecated and the following if statement should be removed in 2.11 - if self.teaming_rolling_order: - teaming_policy.rollingOrder = self.teaming_rolling_order - else: - # this option is called 'failback' in the vSphere Client - # rollingOrder also uses the opposite value displayed in the client - if self.teaming_failback is None: - teaming_policy.rollingOrder = None - else: - teaming_policy.rollingOrder = not self.teaming_failback - if self.teaming_failover_order_active is None and self.teaming_failover_order_standby is None: - teaming_policy.nicOrder = None - else: - teaming_policy.nicOrder = self.create_nic_order_policy() - if self.teaming_failure_detection is None: - teaming_policy.failureCriteria = None - else: - teaming_policy.failureCriteria = self.create_nic_failure_policy() - return teaming_policy - return None - - def create_nic_order_policy(self): - """ - Create a NIC order Policy - Returns: NIC order Policy object - """ - for active_nic in self.teaming_failover_order_active: - if active_nic not in self.switch_object.spec.bridge.nicDevice: - self.module.fail_json( - msg="NIC '%s' (active) is not configured on vSwitch '%s'" % (active_nic, self.switch) - ) - for standby_nic in self.teaming_failover_order_standby: - if standby_nic not in self.switch_object.spec.bridge.nicDevice: - self.module.fail_json( - msg="NIC '%s' (standby) is not configured on vSwitch '%s'" % (standby_nic, self.switch) - ) - nic_order = vim.host.NetworkPolicy.NicOrderPolicy() - nic_order.activeNic = self.teaming_failover_order_active - nic_order.standbyNic = self.teaming_failover_order_standby - return nic_order - - def create_nic_failure_policy(self): - """ - Create a NIC Failure Criteria Policy - Returns: NIC Failure Criteria Policy object - """ - failure_criteria = vim.host.NetworkPolicy.NicFailureCriteria() - if self.teaming_failure_detection == "link_status_only": - failure_criteria.checkBeacon = False - elif self.teaming_failure_detection == "beacon_probing": - failure_criteria.checkBeacon = True - elif self.teaming_failure_detection is None: - failure_criteria = None - # The following properties are deprecated since VI API 5.1. Default values are used - failure_criteria.fullDuplex = False - failure_criteria.percentage = 0 - failure_criteria.checkErrorPercent = False - failure_criteria.checkDuplex = False - failure_criteria.speed = 10 - failure_criteria.checkSpeed = 'minimum' - return failure_criteria - - -def main(): - """Main""" - argument_spec = vmware_argument_spec() - argument_spec.update(dict( - portgroup=dict(type='str', required=True, aliases=['portgroup_name']), - switch=dict(type='str', required=True, aliases=['switch_name', 'vswitch']), - vlan_id=dict(type='int', required=False, default=0, aliases=['vlan']), - hosts=dict(type='list', aliases=['esxi_hostname']), - cluster_name=dict(type='str', aliases=['cluster']), - state=dict(type='str', choices=['present', 'absent'], default='present'), - security=dict( - type='dict', - options=dict( - promiscuous_mode=dict(type='bool'), - forged_transmits=dict(type='bool'), - mac_changes=dict(type='bool'), - ), - aliases=['security_policy', 'network_policy'] - ), - traffic_shaping=dict( - type='dict', - options=dict( - enabled=dict(type='bool'), - average_bandwidth=dict(type='int'), - peak_bandwidth=dict(type='int'), - burst_size=dict(type='int'), - ), - ), - teaming=dict( - type='dict', - options=dict( - load_balancing=dict( - type='str', - choices=[ - None, - 'loadbalance_ip', - 'loadbalance_srcmac', - 'loadbalance_srcid', - 'failover_explicit', - ], - aliases=['load_balance_policy'], - ), - network_failure_detection=dict( - type='str', - choices=['link_status_only', 'beacon_probing'] - ), - notify_switches=dict(type='bool'), - failback=dict(type='bool'), - active_adapters=dict(type='list'), - standby_adapters=dict(type='list'), - # NOTE: Deprecated from 2.11 onwards - inbound_policy=dict(type='bool'), - rolling_order=dict(type='bool'), - ), - aliases=['teaming_policy'] - ), - )) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'hosts'], - ], - supports_check_mode=True - ) - - try: - host_portgroup = VMwareHostPortGroup(module) - host_portgroup.process_state() - except vmodl.RuntimeFault as runtime_fault: - module.fail_json(msg=to_native(runtime_fault.msg)) - except vmodl.MethodFault as method_fault: - module.fail_json(msg=to_native(method_fault.msg)) - except Exception as e: - module.fail_json(msg=to_native(e)) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_portgroup_info.py b/lib/ansible/modules/cloud/vmware/vmware_portgroup_info.py deleted file mode 100644 index e271834821..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_portgroup_info.py +++ /dev/null @@ -1,224 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# 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_portgroup_info -short_description: Gathers info about an ESXi host's Port Group configuration -description: -- This module can be used to gather information about an ESXi host's Port Group configuration when ESXi hostname or Cluster name is given. -version_added: '2.9' -author: -- Abhijeet Kasurde (@Akasurde) -- Christian Kotte (@ckotte) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - policies: - description: - - Gather information about Security, Traffic Shaping, as well as Teaming and failover. - - The property C(ts) stands for Traffic Shaping and C(lb) for Load Balancing. - type: bool - default: false - cluster_name: - description: - - Name of the cluster. - - Info will be returned for all hostsystem belonging to this cluster name. - - If C(esxi_hostname) is not given, this parameter is required. - type: str - esxi_hostname: - description: - - ESXi hostname to gather information from. - - If C(cluster_name) is not given, this parameter is required. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather portgroup info about all ESXi Host in given Cluster - vmware_portgroup_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: '{{ cluster_name }}' - delegate_to: localhost - -- name: Gather portgroup info about ESXi Host system - vmware_portgroup_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - delegate_to: localhost -''' - -RETURN = r''' -hosts_portgroup_info: - description: metadata about host's portgroup configuration - returned: on success - type: dict - sample: { - "esx01": [ - { - "failback": true, - "failover_active": ["vmnic0", "vmnic1"], - "failover_standby": [], - "failure_detection": "link_status_only", - "lb": "loadbalance_srcid", - "notify": true, - "portgroup": "Management Network", - "security": [false, false, false], - "ts": "No override", - "vlan_id": 0, - "vswitch": "vSwitch0" - }, - { - "failback": true, - "failover_active": ["vmnic2"], - "failover_standby": ["vmnic3"], - "failure_detection": "No override", - "lb": "No override", - "notify": true, - "portgroup": "vMotion", - "security": [false, false, false], - "ts": "No override", - "vlan_id": 33, - "vswitch": "vSwitch1" - } - ] - } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class PortgroupInfoManager(PyVmomi): - """Class to manage Port Group info""" - def __init__(self, module): - super(PortgroupInfoManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - if not self.hosts: - self.module.fail_json(msg="Failed to find host system.") - self.policies = self.params.get('policies') - - @staticmethod - def normalize_pg_info(portgroup_obj, policy_info): - """Create Port Group information""" - pg_info_dict = dict() - spec = portgroup_obj.spec - pg_info_dict['portgroup'] = spec.name - pg_info_dict['vlan_id'] = spec.vlanId - pg_info_dict['vswitch'] = spec.vswitchName - - if policy_info: - # Security info - if spec.policy.security: - promiscuous_mode = spec.policy.security.allowPromiscuous - mac_changes = spec.policy.security.macChanges - forged_transmits = spec.policy.security.forgedTransmits - pg_info_dict['security'] = ( - ["No override" if promiscuous_mode is None else promiscuous_mode, - "No override" if mac_changes is None else mac_changes, - "No override" if forged_transmits is None else forged_transmits] - ) - else: - pg_info_dict['security'] = ["No override", "No override", "No override"] - - # Traffic Shaping info - if spec.policy.shapingPolicy and spec.policy.shapingPolicy.enabled is not None: - pg_info_dict['ts'] = portgroup_obj.spec.policy.shapingPolicy.enabled - else: - pg_info_dict['ts'] = "No override" - - # Teaming and failover info - if spec.policy.nicTeaming: - if spec.policy.nicTeaming.policy is None: - pg_info_dict['lb'] = "No override" - else: - pg_info_dict['lb'] = spec.policy.nicTeaming.policy - if spec.policy.nicTeaming.notifySwitches is None: - pg_info_dict['notify'] = "No override" - else: - pg_info_dict['notify'] = spec.policy.nicTeaming.notifySwitches - if spec.policy.nicTeaming.rollingOrder is None: - pg_info_dict['failback'] = "No override" - else: - pg_info_dict['failback'] = not spec.policy.nicTeaming.rollingOrder - if spec.policy.nicTeaming.nicOrder is None: - pg_info_dict['failover_active'] = "No override" - pg_info_dict['failover_standby'] = "No override" - else: - pg_info_dict['failover_active'] = spec.policy.nicTeaming.nicOrder.activeNic - pg_info_dict['failover_standby'] = spec.policy.nicTeaming.nicOrder.standbyNic - if spec.policy.nicTeaming.failureCriteria and spec.policy.nicTeaming.failureCriteria.checkBeacon is None: - pg_info_dict['failure_detection'] = "No override" - else: - if spec.policy.nicTeaming.failureCriteria.checkBeacon: - pg_info_dict['failure_detection'] = "beacon_probing" - else: - pg_info_dict['failure_detection'] = "link_status_only" - else: - pg_info_dict['lb'] = "No override" - pg_info_dict['notify'] = "No override" - pg_info_dict['failback'] = "No override" - pg_info_dict['failover_active'] = "No override" - pg_info_dict['failover_standby'] = "No override" - pg_info_dict['failure_detection'] = "No override" - - return pg_info_dict - - def gather_host_portgroup_info(self): - """Gather Port Group info per ESXi host""" - hosts_pg_info = dict() - for host in self.hosts: - pgs = host.config.network.portgroup - hosts_pg_info[host.name] = [] - for portgroup in pgs: - hosts_pg_info[host.name].append( - self.normalize_pg_info(portgroup_obj=portgroup, policy_info=self.policies) - ) - return hosts_pg_info - - -def main(): - """Main""" - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - policies=dict(type='bool', required=False, default=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True - ) - - host_pg_mgr = PortgroupInfoManager(module) - module.exit_json(changed=False, hosts_portgroup_info=host_pg_mgr.gather_host_portgroup_info()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_resource_pool.py b/lib/ansible/modules/cloud/vmware/vmware_resource_pool.py deleted file mode 100644 index 5cc8e09a0a..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_resource_pool.py +++ /dev/null @@ -1,322 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2017, Davis Phillips davis.phillips@gmail.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 = ''' ---- -module: vmware_resource_pool -short_description: Add/remove resource pools to/from vCenter -description: - - This module can be used to add/remove a resource pool to/from vCenter -version_added: 2.3 -author: -- Davis Phillips (@dav1x) -notes: - - Tested on vSphere 6.5 -requirements: - - "python >= 2.6" - - PyVmomi -options: - datacenter: - description: - - Name of the datacenter to add the host. - required: True - type: str - cluster: - description: - - Name of the cluster to add the host. - required: True - type: str - resource_pool: - description: - - Resource pool name to manage. - required: True - type: str - cpu_expandable_reservations: - description: - - In a resource pool with an expandable reservation, the reservation on a resource pool can grow beyond the specified value. - default: True - type: bool - cpu_reservation: - description: - - Amount of resource that is guaranteed available to the virtual machine or resource pool. - default: 0 - type: int - cpu_limit: - description: - - The utilization of a virtual machine/resource pool will not exceed this limit, even if there are available resources. - - The default value -1 indicates no limit. - default: -1 - type: int - cpu_shares: - description: - - Memory shares are used in case of resource contention. - choices: - - high - - custom - - low - - normal - default: normal - type: str - mem_expandable_reservations: - description: - - In a resource pool with an expandable reservation, the reservation on a resource pool can grow beyond the specified value. - default: True - type: bool - mem_reservation: - description: - - Amount of resource that is guaranteed available to the virtual machine or resource pool. - default: 0 - type: int - mem_limit: - description: - - The utilization of a virtual machine/resource pool will not exceed this limit, even if there are available resources. - - The default value -1 indicates no limit. - default: -1 - type: int - mem_shares: - description: - - Memory shares are used in case of resource contention. - choices: - - high - - custom - - low - - normal - default: normal - type: str - state: - description: - - Add or remove the resource pool - default: 'present' - choices: - - 'present' - - 'absent' - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Add resource pool to vCenter - vmware_resource_pool: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: '{{ datacenter_name }}' - cluster: '{{ cluster_name }}' - resource_pool: '{{ resource_pool_name }}' - mem_shares: normal - mem_limit: -1 - mem_reservation: 0 - mem_expandable_reservations: yes - cpu_shares: normal - cpu_limit: -1 - cpu_reservation: 0 - cpu_expandable_reservations: yes - state: present - delegate_to: localhost -''' - -RETURN = """ -instance: - description: metadata about the new resource pool - returned: always - type: dict - sample: None -""" - -try: - from pyVmomi import vim, vmodl - HAS_PYVMOMI = True -except ImportError: - HAS_PYVMOMI = False - -from ansible.module_utils.vmware import get_all_objs, connect_to_api, vmware_argument_spec, find_datacenter_by_name, \ - find_cluster_by_name, wait_for_task, find_host_by_cluster_datacenter -from ansible.module_utils.basic import AnsibleModule - - -class VMwareResourcePool(object): - - def __init__(self, module): - self.module = module - self.datacenter = module.params['datacenter'] - self.cluster = module.params['cluster'] - self.resource_pool = module.params['resource_pool'] - self.hostname = module.params['hostname'] - self.username = module.params['username'] - self.password = module.params['password'] - self.state = module.params['state'] - self.mem_shares = module.params['mem_shares'] - self.mem_limit = module.params['mem_limit'] - self.mem_reservation = module.params['mem_reservation'] - self.mem_expandable_reservations = module.params[ - 'cpu_expandable_reservations'] - self.cpu_shares = module.params['cpu_shares'] - self.cpu_limit = module.params['cpu_limit'] - self.cpu_reservation = module.params['cpu_reservation'] - self.cpu_expandable_reservations = module.params[ - 'cpu_expandable_reservations'] - self.dc_obj = None - self.cluster_obj = None - self.host_obj = None - self.resource_pool_obj = None - self.content = connect_to_api(module) - - def select_resource_pool(self, host): - pool_obj = None - - resource_pools = get_all_objs(self.content, [vim.ResourcePool]) - - pool_selections = self.get_obj( - [vim.ResourcePool], - self.resource_pool, - return_all=True - ) - if pool_selections: - for p in pool_selections: - if p in resource_pools: - pool_obj = p - break - return pool_obj - - def get_obj(self, vimtype, name, return_all=False): - obj = list() - container = self.content.viewManager.CreateContainerView( - self.content.rootFolder, vimtype, True) - - for c in container.view: - if name in [c.name, c._GetMoId()]: - if return_all is False: - return c - else: - obj.append(c) - - if len(obj) > 0: - return obj - else: - # for backwards-compat - return None - - def process_state(self): - try: - rp_states = { - 'absent': { - 'present': self.state_remove_rp, - 'absent': self.state_exit_unchanged, - }, - 'present': { - 'present': self.state_exit_unchanged, - 'absent': self.state_add_rp, - } - } - - rp_states[self.state][self.check_rp_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 state_exit_unchanged(self): - self.module.exit_json(changed=False) - - def state_remove_rp(self): - changed = True - result = None - resource_pool = self.select_resource_pool(self.host_obj) - try: - task = self.resource_pool_obj.Destroy() - success, result = wait_for_task(task) - - except Exception: - self.module.fail_json(msg="Failed to remove resource pool '%s' '%s'" % ( - self.resource_pool, resource_pool)) - self.module.exit_json(changed=changed, result=str(result)) - - def state_add_rp(self): - changed = True - - rp_spec = vim.ResourceConfigSpec() - cpu_alloc = vim.ResourceAllocationInfo() - cpu_alloc.expandableReservation = self.cpu_expandable_reservations - cpu_alloc.limit = int(self.cpu_limit) - cpu_alloc.reservation = int(self.cpu_reservation) - cpu_alloc_shares = vim.SharesInfo() - cpu_alloc_shares.level = self.cpu_shares - cpu_alloc.shares = cpu_alloc_shares - rp_spec.cpuAllocation = cpu_alloc - mem_alloc = vim.ResourceAllocationInfo() - mem_alloc.limit = int(self.mem_limit) - mem_alloc.expandableReservation = self.mem_expandable_reservations - mem_alloc.reservation = int(self.mem_reservation) - mem_alloc_shares = vim.SharesInfo() - mem_alloc_shares.level = self.mem_shares - mem_alloc.shares = mem_alloc_shares - rp_spec.memoryAllocation = mem_alloc - - self.dc_obj = find_datacenter_by_name(self.content, self.datacenter) - if self.dc_obj is None: - self.module.fail_json(msg="Unable to find datacenter with name %s" % self.datacenter) - - self.cluster_obj = find_cluster_by_name(self.content, self.cluster, datacenter=self.dc_obj) - if self.cluster_obj is None: - self.module.fail_json(msg="Unable to find cluster with name %s" % self.cluster) - rootResourcePool = self.cluster_obj.resourcePool - rootResourcePool.CreateResourcePool(self.resource_pool, rp_spec) - - self.module.exit_json(changed=changed) - - def check_rp_state(self): - - self.host_obj, self.cluster_obj = find_host_by_cluster_datacenter(self.module, self.content, self.datacenter, - self.cluster, self.hostname) - self.resource_pool_obj = self.select_resource_pool(self.host_obj) - - if self.resource_pool_obj is None: - return 'absent' - else: - return 'present' - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update(dict(datacenter=dict(required=True, type='str'), - cluster=dict(required=True, type='str'), - resource_pool=dict(required=True, type='str'), - mem_shares=dict(type='str', default="normal", choices=[ - 'high', 'custom', 'normal', 'low']), - mem_limit=dict(type='int', default=-1), - mem_reservation=dict(type='int', default=0), - mem_expandable_reservations=dict( - type='bool', default="True"), - cpu_shares=dict(type='str', default="normal", choices=[ - 'high', 'custom', 'normal', 'low']), - cpu_limit=dict(type='int', default=-1), - cpu_reservation=dict(type='int', default=0), - cpu_expandable_reservations=dict( - type='bool', default="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_rp = VMwareResourcePool(module) - vmware_rp.process_state() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_resource_pool_info.py b/lib/ansible/modules/cloud/vmware/vmware_resource_pool_info.py deleted file mode 100644 index 78c848ca2a..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_resource_pool_info.py +++ /dev/null @@ -1,140 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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_resource_pool_info -short_description: Gathers info about resource pool information -description: -- This module can be used to gather information about all resource configuration information. -version_added: '2.9' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather resource pool info about all resource pools available - vmware_resource_pool_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - register: rp_info - delegate_to: localhost -''' - -RETURN = r''' -resource_pool_info: - description: metadata about resource pool configuration - returned: on success - type: list - sample: [ - { - "cpu_allocation_expandable_reservation": false, - "cpu_allocation_limit": 4121, - "cpu_allocation_overhead_limit": null, - "cpu_allocation_reservation": 4121, - "cpu_allocation_shares": 9000, - "cpu_allocation_shares_level": "custom", - "mem_allocation_expandable_reservation": false, - "mem_allocation_limit": 961, - "mem_allocation_overhead_limit": null, - "mem_allocation_reservation": 961, - "mem_allocation_shares": 9000, - "mem_allocation_shares_level": "custom", - "name": "Resources", - "overall_status": "green", - "owner": "DC0_H0", - "runtime_cpu_max_usage": 4121, - "runtime_cpu_overall_usage": 0, - "runtime_cpu_reservation_used": 0, - "runtime_cpu_reservation_used_vm": 0, - "runtime_cpu_unreserved_for_pool": 4121, - "runtime_cpu_unreserved_for_vm": 4121, - "runtime_memory_max_usage": 1007681536, - "runtime_memory_overall_usage": 0, - "runtime_memory_reservation_used": 0, - "runtime_memory_reservation_used_vm": 0, - "runtime_memory_unreserved_for_pool": 1007681536, - "runtime_memory_unreserved_for_vm": 1007681536 - }, - ] -''' - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi, get_all_objs - - -class ResourcePoolInfoManager(PyVmomi): - def __init__(self, module): - super(ResourcePoolInfoManager, self).__init__(module) - - def gather_rp_info(self): - resource_pool_info = [] - rps = get_all_objs(self.content, [vim.ResourcePool]) - for rp in rps: - tmp_info = dict( - name=rp.name, - cpu_allocation_reservation=rp.config.cpuAllocation.reservation, - cpu_allocation_expandable_reservation=rp.config.cpuAllocation.expandableReservation, - cpu_allocation_limit=rp.config.cpuAllocation.limit, - cpu_allocation_shares=rp.config.cpuAllocation.shares.shares, - cpu_allocation_shares_level=rp.config.cpuAllocation.shares.level, - cpu_allocation_overhead_limit=rp.config.cpuAllocation.overheadLimit, - mem_allocation_reservation=rp.config.memoryAllocation.reservation, - mem_allocation_expandable_reservation=rp.config.memoryAllocation.expandableReservation, - mem_allocation_limit=rp.config.memoryAllocation.limit, - mem_allocation_shares=rp.config.memoryAllocation.shares.shares, - mem_allocation_shares_level=rp.config.memoryAllocation.shares.level, - mem_allocation_overhead_limit=rp.config.memoryAllocation.overheadLimit, - owner=rp.owner.name, - overall_status=rp.summary.runtime.overallStatus, - runtime_cpu_reservation_used=rp.summary.runtime.cpu.reservationUsed, - runtime_cpu_reservation_used_vm=rp.summary.runtime.cpu.reservationUsedForVm, - runtime_cpu_unreserved_for_pool=rp.summary.runtime.cpu.unreservedForPool, - runtime_cpu_unreserved_for_vm=rp.summary.runtime.cpu.unreservedForVm, - runtime_cpu_overall_usage=rp.summary.runtime.cpu.overallUsage, - runtime_cpu_max_usage=rp.summary.runtime.cpu.maxUsage, - runtime_memory_reservation_used=rp.summary.runtime.memory.reservationUsed, - runtime_memory_reservation_used_vm=rp.summary.runtime.memory.reservationUsedForVm, - runtime_memory_unreserved_for_pool=rp.summary.runtime.memory.unreservedForPool, - runtime_memory_unreserved_for_vm=rp.summary.runtime.memory.unreservedForVm, - runtime_memory_overall_usage=rp.summary.runtime.memory.overallUsage, - runtime_memory_max_usage=rp.summary.runtime.memory.maxUsage, - ) - - resource_pool_info.append(tmp_info) - return resource_pool_info - - -def main(): - argument_spec = vmware_argument_spec() - module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) - - vmware_rp_mgr = ResourcePoolInfoManager(module) - module.exit_json(changed=False, resource_pool_info=vmware_rp_mgr.gather_rp_info()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_tag.py b/lib/ansible/modules/cloud/vmware/vmware_tag.py deleted file mode 100644 index b2c5e53adb..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_tag.py +++ /dev/null @@ -1,272 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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_tag -short_description: Manage VMware tags -description: -- This module can be used to create / delete / update VMware tags. -- Tag feature is introduced in vSphere 6 version, so this module is not supported in the earlier versions of vSphere. -- All variables and VMware object names are case sensitive. -version_added: '2.6' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -- vSphere Automation SDK -options: - tag_name: - description: - - The name of tag to manage. - required: True - type: str - tag_description: - description: - - The tag description. - - This is required only if C(state) is set to C(present). - - This parameter is ignored, when C(state) is set to C(absent). - - Process of updating tag only allows description change. - required: False - default: '' - type: str - category_id: - description: - - The unique ID generated by vCenter should be used to. - - User can get this unique ID from facts module. - required: False - type: str - state: - description: - - The state of tag. - - If set to C(present) and tag does not exists, then tag is created. - - If set to C(present) and tag exists, then tag is updated. - - If set to C(absent) and tag exists, then tag is deleted. - - If set to C(absent) and tag does not exists, no action is taken. - required: False - default: 'present' - choices: [ 'present', 'absent' ] - type: str -extends_documentation_fragment: vmware_rest_client.documentation -''' - -EXAMPLES = r''' -- name: Create a tag - vmware_tag: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - category_id: 'urn:vmomi:InventoryServiceCategory:e785088d-6981-4b1c-9fb8-1100c3e1f742:GLOBAL' - tag_name: Sample_Tag_0002 - tag_description: Sample Description - state: present - delegate_to: localhost - -- name: Update tag description - vmware_tag: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - tag_name: Sample_Tag_0002 - tag_description: Some fancy description - state: present - delegate_to: localhost - -- name: Delete tag - vmware_tag: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - tag_name: Sample_Tag_0002 - state: absent - delegate_to: localhost -''' - -RETURN = r''' -tag_status: - description: dictionary of tag metadata - returned: on success - type: dict - sample: { - "msg": "Tag 'Sample_Tag_0002' created.", - "tag_id": "urn:vmomi:InventoryServiceTag:bff91819-f529-43c9-80ca-1c9dfda09441:GLOBAL" - } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware_rest_client import VmwareRestClient -try: - from com.vmware.vapi.std.errors_client import Error -except ImportError: - pass - - -class VmwareTag(VmwareRestClient): - def __init__(self, module): - super(VmwareTag, self).__init__(module) - self.global_tags = dict() - # api_client to call APIs instead of individual service - self.tag_service = self.api_client.tagging.Tag - self.tag_name = self.params.get('tag_name') - self.get_all_tags() - self.category_service = self.api_client.tagging.Category - - def ensure_state(self): - """ - Manage internal states of tags - - """ - desired_state = self.params.get('state') - states = { - 'present': { - 'present': self.state_update_tag, - 'absent': self.state_create_tag, - }, - 'absent': { - 'present': self.state_delete_tag, - 'absent': self.state_unchanged, - } - } - states[desired_state][self.check_tag_status()]() - - def state_create_tag(self): - """ - Create tag - - """ - tag_spec = self.tag_service.CreateSpec() - tag_spec.name = self.tag_name - tag_spec.description = self.params.get('tag_description') - category_id = self.params.get('category_id', None) - if category_id is None: - self.module.fail_json(msg="'category_id' is required parameter while creating tag.") - - category_found = False - for category in self.category_service.list(): - category_obj = self.category_service.get(category) - if category_id == category_obj.id: - category_found = True - break - - if not category_found: - self.module.fail_json(msg="Unable to find category specified using 'category_id' - %s" % category_id) - - tag_spec.category_id = category_id - tag_id = '' - try: - tag_id = self.tag_service.create(tag_spec) - except Error as error: - self.module.fail_json(msg="%s" % self.get_error_message(error)) - - if tag_id: - self.module.exit_json(changed=True, - tag_status=dict(msg="Tag '%s' created." % tag_spec.name, tag_id=tag_id)) - self.module.exit_json(changed=False, - tag_status=dict(msg="No tag created", tag_id=tag_id)) - - def state_unchanged(self): - """ - Return unchanged state - - """ - self.module.exit_json(changed=False) - - def state_update_tag(self): - """ - Update tag - - """ - changed = False - tag_id = self.global_tags[self.tag_name]['tag_id'] - results = dict(msg="Tag %s is unchanged." % self.tag_name, - tag_id=tag_id) - tag_update_spec = self.tag_service.UpdateSpec() - tag_desc = self.global_tags[self.tag_name]['tag_description'] - desired_tag_desc = self.params.get('tag_description') - if tag_desc != desired_tag_desc: - tag_update_spec.description = desired_tag_desc - try: - self.tag_service.update(tag_id, tag_update_spec) - except Error as error: - self.module.fail_json(msg="%s" % self.get_error_message(error)) - - results['msg'] = 'Tag %s updated.' % self.tag_name - changed = True - - self.module.exit_json(changed=changed, tag_status=results) - - def state_delete_tag(self): - """ - Delete tag - - """ - tag_id = self.global_tags[self.tag_name]['tag_id'] - try: - self.tag_service.delete(tag_id=tag_id) - except Error as error: - self.module.fail_json(msg="%s" % self.get_error_message(error)) - self.module.exit_json(changed=True, - tag_status=dict(msg="Tag '%s' deleted." % self.tag_name, tag_id=tag_id)) - - def check_tag_status(self): - """ - Check if tag exists or not - Returns: 'present' if tag found, else 'absent' - - """ - if 'category_id' in self.params: - if self.tag_name in self.global_tags and self.params['category_id'] == self.global_tags[self.tag_name]['tag_category_id']: - ret = 'present' - else: - ret = 'absent' - else: - ret = 'present' if self.tag_name in self.global_tags else 'absent' - return ret - - def get_all_tags(self): - """ - Retrieve all tag information - - """ - for tag in self.tag_service.list(): - tag_obj = self.tag_service.get(tag) - self.global_tags[tag_obj.name] = dict( - tag_description=tag_obj.description, - tag_used_by=tag_obj.used_by, - tag_category_id=tag_obj.category_id, - tag_id=tag_obj.id - ) - - -def main(): - argument_spec = VmwareRestClient.vmware_client_argument_spec() - argument_spec.update( - tag_name=dict(type='str', required=True), - tag_description=dict(type='str', default='', required=False), - category_id=dict(type='str', required=False), - state=dict(type='str', choices=['present', 'absent'], default='present', required=False), - ) - module = AnsibleModule(argument_spec=argument_spec) - - vmware_tag = VmwareTag(module) - vmware_tag.ensure_state() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_tag_info.py b/lib/ansible/modules/cloud/vmware/vmware_tag_info.py deleted file mode 100644 index d23cc61f26..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_tag_info.py +++ /dev/null @@ -1,180 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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_tag_info -short_description: Manage VMware tag info -description: -- This module can be used to collect information about VMware tags. -- Tag feature is introduced in vSphere 6 version, so this module is not supported in the earlier versions of vSphere. -- All variables and VMware object names are case sensitive. -- This module was called C(vmware_tag_facts) before Ansible 2.9. The usage did not change. -- C(tag_facts) will be deprecated in Ansible 2.14, since it does not return multiple tags with same name and different category id. -- Please use C(tag_info) instead of C(tag_facts). -version_added: '2.6' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -- vSphere Automation SDK -extends_documentation_fragment: vmware_rest_client.documentation -''' - -EXAMPLES = r''' -- name: Get info about tag - vmware_tag_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - delegate_to: localhost - -- name: Get category id from the given tag - vmware_tag_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - delegate_to: localhost - register: tag_details -- debug: - msg: "{{ tag_details.tag_facts['fedora_machines']['tag_category_id'] }}" - -- name: Gather tag id from the given tag - vmware_tag_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - delegate_to: localhost - register: tag_results -- set_fact: - tag_id: "{{ item.tag_id }}" - loop: "{{ tag_results.tag_info|json_query(query) }}" - vars: - query: "[?tag_name==`tag0001`]" -- debug: var=tag_id -''' - -RETURN = r''' -tag_facts: - description: dictionary of tag metadata - returned: on success - type: dict - sample: { - "Sample_Tag_0002": { - "tag_category_id": "urn:vmomi:InventoryServiceCategory:6de17f28-7694-43ec-a783-d09c141819ae:GLOBAL", - "tag_description": "Sample Description", - "tag_id": "urn:vmomi:InventoryServiceTag:a141f212-0f82-4f05-8eb3-c49647c904c5:GLOBAL", - "tag_used_by": [] - }, - "fedora_machines": { - "tag_category_id": "urn:vmomi:InventoryServiceCategory:baa90bae-951b-4e87-af8c-be681a1ba30c:GLOBAL", - "tag_description": "", - "tag_id": "urn:vmomi:InventoryServiceTag:7d27d182-3ecd-4200-9d72-410cc6398a8a:GLOBAL", - "tag_used_by": [] - }, - "ubuntu_machines": { - "tag_category_id": "urn:vmomi:InventoryServiceCategory:89573410-29b4-4cac-87a4-127c084f3d50:GLOBAL", - "tag_description": "", - "tag_id": "urn:vmomi:InventoryServiceTag:7f3516d5-a750-4cb9-8610-6747eb39965d:GLOBAL", - "tag_used_by": [] - } - } - -tag_info: - description: list of tag metadata - returned: on success - type: list - sample: [ - { "tag_name": "Sample_Tag_0002", - "tag_category_id": "urn:vmomi:InventoryServiceCategory:6de17f28-7694-43ec-a783-d09c141819ae:GLOBAL", - "tag_description": "Sample Description", - "tag_id": "urn:vmomi:InventoryServiceTag:a141f212-0f82-4f05-8eb3-c49647c904c5:GLOBAL", - "tag_used_by": [] - }, - { "tag_name": "Sample_Tag_0002", - "tag_category_id": "urn:vmomi:InventoryServiceCategory:6de17f28-7694-43ec-a783-d09c141819ae:GLOBAL", - "tag_description": "", - "tag_id": "urn:vmomi:InventoryServiceTag:7d27d182-3ecd-4200-9d72-410cc6398a8a:GLOBAL", - "tag_used_by": [] - }, - { "tag_name": "ubuntu_machines", - "tag_category_id": "urn:vmomi:InventoryServiceCategory:89573410-29b4-4cac-87a4-127c084f3d50:GLOBAL", - "tag_description": "", - "tag_id": "urn:vmomi:InventoryServiceTag:7f3516d5-a750-4cb9-8610-6747eb39965d:GLOBAL", - "tag_used_by": [] - } - ] -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware_rest_client import VmwareRestClient - - -class VmTagInfoManager(VmwareRestClient): - def __init__(self, module): - """Constructor.""" - super(VmTagInfoManager, self).__init__(module) - - def get_all_tags(self): - """ - Retrieve all tag information. - """ - global_tag_info = list() - # Backward compatability - global_tags = dict() - tag_service = self.api_client.tagging.Tag - for tag in tag_service.list(): - tag_obj = tag_service.get(tag) - global_tags[tag_obj.name] = dict( - tag_description=tag_obj.description, - tag_used_by=tag_obj.used_by, - tag_category_id=tag_obj.category_id, - tag_id=tag_obj.id - ) - global_tag_info.append(dict( - tag_name=tag_obj.name, - tag_description=tag_obj.description, - tag_used_by=tag_obj.used_by, - tag_category_id=tag_obj.category_id, - tag_id=tag_obj.id - )) - - self.module.exit_json( - changed=False, - tag_facts=global_tags, - tag_info=global_tag_info - ) - - -def main(): - argument_spec = VmwareRestClient.vmware_client_argument_spec() - module = AnsibleModule(argument_spec=argument_spec, - supports_check_mode=True) - if module._name == 'vmware_tag_facts': - module.deprecate("The 'vmware_tag_facts' module has been renamed to 'vmware_tag_info'", version='2.13') - - vmware_tag_info = VmTagInfoManager(module) - vmware_tag_info.get_all_tags() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_tag_manager.py b/lib/ansible/modules/cloud/vmware/vmware_tag_manager.py deleted file mode 100644 index 770ff61c6e..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_tag_manager.py +++ /dev/null @@ -1,318 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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_tag_manager -short_description: Manage association of VMware tags with VMware objects -description: -- This module can be used to assign / remove VMware tags from the given VMware objects. -- Tag feature is introduced in vSphere 6 version, so this module is not supported in the earlier versions of vSphere. -- All variables and VMware object names are case sensitive. -version_added: 2.8 -author: -- Abhijeet Kasurde (@Akasurde) -- Frederic Van Reet (@GBrawl) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -- vSphere Automation SDK -options: - tag_names: - description: - - List of tag(s) to be managed. - - User can also specify category name by specifying colon separated value. For example, "category_name:tag_name". - - User can also specify tag and category as dict, when tag or category contains colon. - See example for more information. Added in version 2.10. - - User can skip category name if you have unique tag names. - required: True - type: list - state: - description: - - If C(state) is set to C(add) or C(present) will add the tags to the existing tag list of the given object. - - If C(state) is set to C(remove) or C(absent) will remove the tags from the existing tag list of the given object. - - If C(state) is set to C(set) will replace the tags of the given objects with the user defined list of tags. - default: add - choices: [ present, absent, add, remove, set ] - type: str - object_type: - description: - - Type of object to work with. - required: True - choices: [ VirtualMachine, Datacenter, ClusterComputeResource, HostSystem, DistributedVirtualSwitch, DistributedVirtualPortgroup ] - type: str - object_name: - description: - - Name of the object to work with. - - For DistributedVirtualPortgroups the format should be "switch_name:portgroup_name" - required: True - type: str -extends_documentation_fragment: vmware_rest_client.documentation -''' - -EXAMPLES = r''' -- name: Add tags to a virtual machine - vmware_tag_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - tag_names: - - Sample_Tag_0002 - - Category_0001:Sample_Tag_0003 - object_name: Fedora_VM - object_type: VirtualMachine - state: add - delegate_to: localhost - -- name: Specify tag and category as dict - vmware_tag_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - tag_names: - - tag: tag_0001 - category: cat_0001 - - tag: tag_0002 - category: cat_0002 - object_name: Fedora_VM - object_type: VirtualMachine - state: add - delegate_to: localhost - -- name: Remove a tag from a virtual machine - vmware_tag_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - tag_names: - - Sample_Tag_0002 - object_name: Fedora_VM - object_type: VirtualMachine - state: remove - delegate_to: localhost - -- name: Add tags to a distributed virtual switch - vmware_tag_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - tag_names: - - Sample_Tag_0003 - object_name: Switch_0001 - object_type: DistributedVirtualSwitch - state: add - delegate_to: localhost - -- name: Add tags to a distributed virtual portgroup - vmware_tag_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - tag_names: - - Sample_Tag_0004 - object_name: Switch_0001:Portgroup_0001 - object_type: DistributedVirtualPortgroup - state: add - delegate_to: localhost -''' - -RETURN = r''' -tag_status: - description: metadata about tags related to object configuration - returned: on success - type: list - sample: { - "current_tags": [ - "backup", - "security" - ], - "desired_tags": [ - "security" - ], - "previous_tags": [ - "backup", - "security" - ] - } -''' -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware_rest_client import VmwareRestClient -from ansible.module_utils.vmware import (PyVmomi, find_dvs_by_name, find_dvspg_by_name) -try: - from com.vmware.vapi.std_client import DynamicID - from com.vmware.vapi.std.errors_client import Error -except ImportError: - pass - - -class VmwareTagManager(VmwareRestClient): - def __init__(self, module): - """ - Constructor - """ - super(VmwareTagManager, self).__init__(module) - self.pyv = PyVmomi(module=module) - - self.object_type = self.params.get('object_type') - self.object_name = self.params.get('object_name') - self.managed_object = None - - if self.object_type == 'VirtualMachine': - self.managed_object = self.pyv.get_vm_or_template(self.object_name) - - if self.object_type == 'Datacenter': - self.managed_object = self.pyv.find_datacenter_by_name(self.object_name) - - if self.object_type == 'ClusterComputeResource': - self.managed_object = self.pyv.find_cluster_by_name(self.object_name) - - if self.object_type == 'HostSystem': - self.managed_object = self.pyv.find_hostsystem_by_name(self.object_name) - - if self.object_type == 'DistributedVirtualSwitch': - self.managed_object = find_dvs_by_name(self.pyv.content, self.object_name) - self.object_type = 'VmwareDistributedVirtualSwitch' - - if self.object_type == 'DistributedVirtualPortgroup': - dvs_name, pg_name = self.object_name.split(":", 1) - dv_switch = find_dvs_by_name(self.pyv.content, dvs_name) - if dv_switch is None: - self.module.fail_json(msg="A distributed virtual switch with name %s does not exist" % dvs_name) - self.managed_object = find_dvspg_by_name(dv_switch, pg_name) - - if self.managed_object is None: - self.module.fail_json(msg="Failed to find the managed object for %s with type %s" % (self.object_name, self.object_type)) - - if not hasattr(self.managed_object, '_moId'): - self.module.fail_json(msg="Unable to find managed object id for %s managed object" % self.object_name) - - self.dynamic_managed_object = DynamicID(type=self.object_type, id=self.managed_object._moId) - - self.tag_service = self.api_client.tagging.Tag - self.category_service = self.api_client.tagging.Category - self.tag_association_svc = self.api_client.tagging.TagAssociation - - self.tag_names = self.params.get('tag_names') - - def ensure_state(self): - """ - Manage the internal state of tags - - """ - results = dict( - changed=False, - tag_status=dict(), - ) - changed = False - action = self.params.get('state') - available_tag_obj = self.get_tags_for_object(tag_service=self.tag_service, - tag_assoc_svc=self.tag_association_svc, - dobj=self.dynamic_managed_object) - - _temp_prev_tags = ["%s:%s" % (tag['category_name'], tag['name']) for tag in self.get_tags_for_dynamic_obj(self.dynamic_managed_object)] - results['tag_status']['previous_tags'] = _temp_prev_tags - results['tag_status']['desired_tags'] = self.tag_names - - # Check if category and tag combination exists as per user request - removed_tags_for_set = False - for tag in self.tag_names: - category_obj, category_name, tag_name = None, None, None - if isinstance(tag, dict): - tag_name = tag.get('tag') - category_name = tag.get('category') - if category_name: - # User specified category - category_obj = self.search_svc_object_by_name(self.category_service, category_name) - if not category_obj: - self.module.fail_json(msg="Unable to find the category %s" % category_name) - elif isinstance(tag, str): - if ":" in tag: - # User specified category - category_name, tag_name = tag.split(":", 1) - category_obj = self.search_svc_object_by_name(self.category_service, category_name) - if not category_obj: - self.module.fail_json(msg="Unable to find the category %s" % category_name) - else: - # User specified only tag - tag_name = tag - - if category_name: - tag_obj = self.get_tag_by_category(tag_name=tag_name, category_name=category_name) - else: - tag_obj = self.get_tag_by_name(tag_name=tag_name) - - if not tag_obj: - self.module.fail_json(msg="Unable to find the tag %s" % tag_name) - - if action in ('add', 'present'): - if tag_obj not in available_tag_obj: - # Tag is not already applied - try: - self.tag_association_svc.attach(tag_id=tag_obj.id, object_id=self.dynamic_managed_object) - changed = True - except Error as error: - self.module.fail_json(msg="%s" % self.get_error_message(error)) - - elif action == 'set': - # Remove all tags first - try: - if not removed_tags_for_set: - for av_tag in available_tag_obj: - self.tag_association_svc.detach(tag_id=av_tag.id, object_id=self.dynamic_managed_object) - removed_tags_for_set = True - self.tag_association_svc.attach(tag_id=tag_obj.id, object_id=self.dynamic_managed_object) - changed = True - except Error as error: - self.module.fail_json(msg="%s" % self.get_error_message(error)) - - elif action in ('remove', 'absent'): - if tag_obj in available_tag_obj: - try: - self.tag_association_svc.detach(tag_id=tag_obj.id, object_id=self.dynamic_managed_object) - changed = True - except Error as error: - self.module.fail_json(msg="%s" % self.get_error_message(error)) - - _temp_curr_tags = ["%s:%s" % (tag['category_name'], tag['name']) for tag in self.get_tags_for_dynamic_obj(self.dynamic_managed_object)] - results['tag_status']['current_tags'] = _temp_curr_tags - results['changed'] = changed - self.module.exit_json(**results) - - -def main(): - argument_spec = VmwareRestClient.vmware_client_argument_spec() - argument_spec.update( - tag_names=dict(type='list', required=True), - state=dict(type='str', choices=['absent', 'add', 'present', 'remove', 'set'], default='add'), - object_name=dict(type='str', required=True), - object_type=dict(type='str', required=True, choices=['VirtualMachine', 'Datacenter', 'ClusterComputeResource', - 'HostSystem', 'DistributedVirtualSwitch', - 'DistributedVirtualPortgroup']), - ) - module = AnsibleModule(argument_spec=argument_spec) - - vmware_tag_manager = VmwareTagManager(module) - vmware_tag_manager.ensure_state() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_target_canonical_info.py b/lib/ansible/modules/cloud/vmware/vmware_target_canonical_info.py deleted file mode 100644 index 8745326cc7..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_target_canonical_info.py +++ /dev/null @@ -1,183 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2015, Joseph Callen <jcallen () csc.com> -# Copyright: (c) 2018, Ansible Project -# 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 = ''' ---- -module: vmware_target_canonical_info -short_description: Return canonical (NAA) from an ESXi host system -description: - - This module can be used to gather information about canonical (NAA) from an ESXi host based on SCSI target ID. -version_added: "2.9" -author: -- Joseph Callen (@jcpowermac) -- Abhijeet Kasurde (@Akasurde) -notes: -requirements: - - Tested on vSphere 5.5 and 6.5 - - PyVmomi installed -options: - target_id: - description: - - The target id based on order of scsi device. - - version 2.6 onwards, this parameter is optional. - required: False - type: int - cluster_name: - description: - - Name of the cluster. - - Info about all SCSI devices for all host system in the given cluster is returned. - - This parameter is required, if C(esxi_hostname) is not provided. - type: str - esxi_hostname: - description: - - Name of the ESXi host system. - - Info about all SCSI devices for the given ESXi host system is returned. - - This parameter is required, if C(cluster_name) is not provided. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Get Canonical name of particular target on particular ESXi host system - vmware_target_canonical_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - target_id: 7 - esxi_hostname: esxi_hostname - delegate_to: localhost - -- name: Get Canonical name of all target on particular ESXi host system - vmware_target_canonical_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - delegate_to: localhost - -- name: Get Canonical name of all ESXi hostname on particular Cluster - vmware_target_canonical_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: '{{ cluster_name }}' - delegate_to: localhost -''' - -RETURN = r""" -canonical: - description: metadata about SCSI Target device - returned: if host system and target id is given - type: str - sample: "mpx.vmhba0:C0:T0:L0" - -scsi_tgt_info: - description: metadata about all SCSI Target devices - returned: if host system or cluster is given - type: dict - sample: { - "DC0_C0_H0": { - "scsilun_canonical": { - "key-vim.host.ScsiDisk-0000000000766d686261303a303a30": "mpx.vmhba0:C0:T0:L0", - "key-vim.host.ScsiLun-0005000000766d686261313a303a30": "mpx.vmhba1:C0:T0:L0" - }, - "target_lun_uuid": { - "0": "key-vim.host.ScsiDisk-0000000000766d686261303a303a30" - } - }, - "DC0_C0_H1": { - "scsilun_canonical": { - "key-vim.host.ScsiDisk-0000000000766d686261303a303a30": "mpx.vmhba0:C0:T0:L0", - "key-vim.host.ScsiLun-0005000000766d686261313a303a30": "mpx.vmhba1:C0:T0:L0" - }, - "target_lun_uuid": { - "0": "key-vim.host.ScsiDisk-0000000000766d686261303a303a30" - } - }, - } -""" - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec - - -class ScsiTargetInfoManager(PyVmomi): - def __init__(self, module): - super(ScsiTargetInfoManager, self).__init__(module) - cluster_name = self.module.params.get('cluster_name') - self.esxi_hostname = self.module.params.get('esxi_hostname') - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=self.esxi_hostname) - - def gather_scsi_device_info(self): - """ - Function to gather information about SCSI target devices - - """ - scsi_tgt_info = {} - target_lun_uuid = {} - scsilun_canonical = {} - target_id = self.module.params['target_id'] - - for host in self.hosts: - # Associate the scsiLun key with the canonicalName (NAA) - for scsilun in host.config.storageDevice.scsiLun: - scsilun_canonical[scsilun.key] = scsilun.canonicalName - - # Associate target number with LUN uuid - for target in host.config.storageDevice.scsiTopology.adapter[0].target: - for lun in target.lun: - target_lun_uuid[target.target] = lun.scsiLun - - scsi_tgt_info[host.name] = dict( - scsilun_canonical=scsilun_canonical, - target_lun_uuid=target_lun_uuid) - - if target_id is not None and self.esxi_hostname is not None: - canonical = '' - temp_lun_data = scsi_tgt_info[self.esxi_hostname]['target_lun_uuid'] - if self.esxi_hostname in scsi_tgt_info and \ - target_id in temp_lun_data: - temp_scsi_data = scsi_tgt_info[self.esxi_hostname]['scsilun_canonical'] - temp_target = temp_lun_data[target_id] - canonical = temp_scsi_data[temp_target] - self.module.exit_json(changed=False, canonical=canonical) - - self.module.exit_json(changed=False, scsi_tgt_info=scsi_tgt_info) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - dict( - target_id=dict(required=False, type='int'), - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - ) - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True, - ) - - scsi_tgt_manager = ScsiTargetInfoManager(module) - scsi_tgt_manager.gather_scsi_device_info() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_vcenter_settings.py b/lib/ansible/modules/cloud/vmware/vmware_vcenter_settings.py deleted file mode 100644 index ff08e75adb..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_vcenter_settings.py +++ /dev/null @@ -1,696 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# -# 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 = ''' ---- -module: vmware_vcenter_settings -short_description: Configures general settings on a vCenter server -description: -- This module can be used to configure the vCenter server general settings (except the statistics). -- The statistics can be configured with the module C(vmware_vcenter_statistics). -version_added: 2.8 -author: -- Christian Kotte (@ckotte) -notes: -- Tested with vCenter Server Appliance (vCSA) 6.5 and 6.7 -requirements: -- python >= 2.6 -- PyVmomi -options: - database: - description: - - The database settings for vCenter server. - - 'Valid attributes are:' - - '- C(max_connections) (int): Maximum connections. (default: 50)' - - '- C(task_cleanup) (bool): Task cleanup. (default: true)' - - '- C(task_retention) (int): Task retention (days). (default: 30)' - - '- C(event_cleanup) (bool): Event cleanup. (default: true)' - - '- C(event_retention) (int): Event retention (days). (default: 30)' - type: dict - default: { - max_connections: 50, - task_cleanup: True, - task_retention: 30, - event_cleanup: True, - event_retention: 30, - } - runtime_settings: - description: - - The unique runtime settings for vCenter server. - - 'Valid attributes are:' - - '- C(unique_id) (int): vCenter server unique ID.' - - '- C(managed_address) (str): vCenter server managed address.' - - '- C(vcenter_server_name) (str): vCenter server name. (default: FQDN)' - type: dict - user_directory: - description: - - The user directory settings for the vCenter server installation. - - 'Valid attributes are:' - - '- C(timeout) (int): User directory timeout. (default: 60)' - - '- C(query_limit) (bool): Query limit. (default: true)' - - '- C(query_limit_size) (int): Query limit size. (default: 5000)' - - '- C(validation) (bool): Mail Validation. (default: true)' - - '- C(validation_period) (int): Validation period. (default: 1440)' - type: dict - default: { - timeout: 60, - query_limit: True, - query_limit_size: 5000, - validation: True, - validation_period: 1440, - } - mail: - description: - - The settings vCenter server uses to send email alerts. - - 'Valid attributes are:' - - '- C(server) (str): Mail server' - - '- C(sender) (str): Mail sender address' - type: dict - default: { - server: '', - sender: '', - } - snmp_receivers: - description: - - SNMP trap destinations for vCenter server alerts. - - 'Valid attributes are:' - - '- C(snmp_receiver_1_url) (str): Primary Receiver ULR. (default: "localhost")' - - '- C(snmp_receiver_1_enabled) (bool): Enable receiver. (default: True)' - - '- C(snmp_receiver_1_port) (int): Receiver port. (default: 162)' - - '- C(snmp_receiver_1_community) (str): Community string. (default: "public")' - - '- C(snmp_receiver_2_url) (str): Receiver 2 ULR. (default: "")' - - '- C(snmp_receiver_2_enabled) (bool): Enable receiver. (default: False)' - - '- C(snmp_receiver_2_port) (int): Receiver port. (default: 162)' - - '- C(snmp_receiver_2_community) (str): Community string. (default: "")' - - '- C(snmp_receiver_3_url) (str): Receiver 3 ULR. (default: "")' - - '- C(snmp_receiver_3_enabled) (bool): Enable receiver. (default: False)' - - '- C(snmp_receiver_3_port) (int): Receiver port. (default: 162)' - - '- C(snmp_receiver_3_community) (str): Community string. (default: "")' - - '- C(snmp_receiver_4_url) (str): Receiver 4 ULR. (default: "")' - - '- C(snmp_receiver_4_enabled) (bool): Enable receiver. (default: False)' - - '- C(snmp_receiver_4_port) (int): Receiver port. (default: 162)' - - '- C(snmp_receiver_4_community) (str): Community string. (default: "")' - type: dict - default: { - snmp_receiver_1_url: 'localhost', - snmp_receiver_1_enabled: True, - snmp_receiver_1_port: 162, - snmp_receiver_1_community: 'public', - snmp_receiver_2_url: '', - snmp_receiver_2_enabled: False, - snmp_receiver_2_port: 162, - snmp_receiver_2_community: '', - snmp_receiver_3_url: '', - snmp_receiver_3_enabled: False, - snmp_receiver_3_port: 162, - snmp_receiver_3_community: '', - snmp_receiver_4_url: '', - snmp_receiver_4_enabled: False, - snmp_receiver_4_port: 162, - snmp_receiver_4_community: '', - } - timeout_settings: - description: - - The vCenter server connection timeout for normal and long operations. - - 'Valid attributes are:' - - '- C(normal_operations) (int) (default: 30)' - - '- C(long_operations) (int) (default: 120)' - type: dict - default: { - normal_operations: 30, - long_operations: 120, - } - logging_options: - description: - - The level of detail that vCenter server usesfor log files. - type: str - choices: ['none', 'error', 'warning', 'info', 'verbose', 'trivia'] - default: 'info' -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Configure vCenter general settings - vmware_vcenter_settings: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - database: - max_connections: 50 - task_cleanup: true - task_retention: 30 - event_cleanup: true - event_retention: 30 - runtime_settings: - unique_id: 1 - managed_address: "{{ lookup('dig', inventory_hostname) }}" - vcenter_server_name: "{{ inventory_hostname }}" - user_directory: - timeout: 60 - query_limit: true - query_limit_size: 5000 - validation: true - validation_period: 1440 - mail: - server: mail.example.com - sender: vcenter@{{ inventory_hostname }} - snmp_receivers: - snmp_receiver_1_url: localhost - snmp_receiver_1_enabled: true - snmp_receiver_1_port: 162 - snmp_receiver_1_community: public - timeout_settings: - normal_operations: 30 - long_operations: 120 - logging_options: info - validate_certs: no - delegate_to: localhost -''' - -RETURN = r''' -results: - description: metadata about vCenter settings - returned: always - type: dict - sample: { - "changed": false, - "db_event_cleanup": true, - "db_event_retention": 30, - "db_max_connections": 50, - "db_task_cleanup": true, - "db_task_retention": 30, - "directory_query_limit": true, - "directory_query_limit_size": 5000, - "directory_timeout": 60, - "directory_validation": true, - "directory_validation_period": 1440, - "logging_options": "info", - "mail_sender": "vcenter@vcenter01.example.com", - "mail_server": "mail.example.com", - "msg": "vCenter settings already configured properly", - "runtime_managed_address": "192.168.1.10", - "runtime_server_name": "vcenter01.example.com", - "runtime_unique_id": 1, - "timeout_long_operations": 120, - "timeout_normal_operations": 30 - } -''' - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec -from ansible.module_utils._text import to_native - - -class VmwareVcenterSettings(PyVmomi): - """Manage settings for a vCenter server""" - - def __init__(self, module): - super(VmwareVcenterSettings, self).__init__(module) - - if not self.is_vcenter(): - self.module.fail_json(msg="You have to connect to a vCenter server!") - - def ensure(self): - """Manage settings for a vCenter server""" - result = dict(changed=False, msg='') - db_max_connections = self.params['database'].get('max_connections') - db_task_cleanup = self.params['database'].get('task_cleanup') - db_task_retention = self.params['database'].get('task_retention') - db_event_cleanup = self.params['database'].get('event_cleanup') - db_event_retention = self.params['database'].get('event_retention') - runtime_unique_id = self.params['runtime_settings'].get('unique_id') - runtime_managed_address = self.params['runtime_settings'].get('managed_address') - runtime_server_name = self.params['runtime_settings'].get('vcenter_server_name') - directory_timeout = self.params['user_directory'].get('timeout') - directory_query_limit = self.params['user_directory'].get('query_limit') - directory_query_limit_size = self.params['user_directory'].get('query_limit_size') - directory_validation = self.params['user_directory'].get('validation') - directory_validation_period = self.params['user_directory'].get('validation_period') - mail_server = self.params['mail'].get('server') - mail_sender = self.params['mail'].get('sender') - snmp_receiver_1_url = self.params['snmp_receivers'].get('snmp_receiver_1_url') - snmp_receiver_1_enabled = self.params['snmp_receivers'].get('snmp_receiver_1_enabled') - snmp_receiver_1_port = self.params['snmp_receivers'].get('snmp_receiver_1_port') - snmp_receiver_1_community = self.params['snmp_receivers'].get('snmp_receiver_1_community') - snmp_receiver_2_url = self.params['snmp_receivers'].get('snmp_receiver_2_url') - snmp_receiver_2_enabled = self.params['snmp_receivers'].get('snmp_receiver_2_enabled') - snmp_receiver_2_port = self.params['snmp_receivers'].get('snmp_receiver_2_port') - snmp_receiver_2_community = self.params['snmp_receivers'].get('snmp_receiver_2_community') - snmp_receiver_3_url = self.params['snmp_receivers'].get('snmp_receiver_3_url') - snmp_receiver_3_enabled = self.params['snmp_receivers'].get('snmp_receiver_3_enabled') - snmp_receiver_3_port = self.params['snmp_receivers'].get('snmp_receiver_3_port') - snmp_receiver_3_community = self.params['snmp_receivers'].get('snmp_receiver_3_community') - snmp_receiver_4_url = self.params['snmp_receivers'].get('snmp_receiver_4_url') - snmp_receiver_4_enabled = self.params['snmp_receivers'].get('snmp_receiver_4_enabled') - snmp_receiver_4_port = self.params['snmp_receivers'].get('snmp_receiver_4_port') - snmp_receiver_4_community = self.params['snmp_receivers'].get('snmp_receiver_4_community') - timeout_normal_operations = self.params['timeout_settings'].get('normal_operations') - timeout_long_operations = self.params['timeout_settings'].get('long_operations') - logging_options = self.params.get('logging_options') - changed = False - changed_list = [] - - # Check all general settings, except statistics - result['db_max_connections'] = db_max_connections - result['db_task_cleanup'] = db_task_cleanup - result['db_task_retention'] = db_task_retention - result['db_event_cleanup'] = db_event_cleanup - result['db_event_retention'] = db_event_retention - result['runtime_unique_id'] = runtime_unique_id - result['runtime_managed_address'] = runtime_managed_address - result['runtime_server_name'] = runtime_server_name - result['directory_timeout'] = directory_timeout - result['directory_query_limit'] = directory_query_limit - result['directory_query_limit_size'] = directory_query_limit_size - result['directory_validation'] = directory_validation - result['directory_validation_period'] = directory_validation_period - result['mail_server'] = mail_server - result['mail_sender'] = mail_sender - result['timeout_normal_operations'] = timeout_normal_operations - result['timeout_long_operations'] = timeout_long_operations - result['logging_options'] = logging_options - change_option_list = [] - option_manager = self.content.setting - for setting in option_manager.setting: - # Database - if setting.key == 'VirtualCenter.MaxDBConnection' and setting.value != db_max_connections: - changed = True - changed_list.append("DB max connections") - result['db_max_connections_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='VirtualCenter.MaxDBConnection', value=db_max_connections) - ) - if setting.key == 'task.maxAgeEnabled' and setting.value != db_task_cleanup: - changed = True - changed_list.append("DB task cleanup") - result['db_task_cleanup_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='task.maxAgeEnabled', value=db_task_cleanup) - ) - if setting.key == 'task.maxAge' and setting.value != db_task_retention: - changed = True - changed_list.append("DB task retention") - result['db_task_retention_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='task.maxAge', value=db_task_retention) - ) - if setting.key == 'event.maxAgeEnabled' and setting.value != db_event_cleanup: - changed = True - changed_list.append("DB event cleanup") - result['db_event_cleanup_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='event.maxAgeEnabled', value=db_event_cleanup) - ) - if setting.key == 'event.maxAge' and setting.value != db_event_retention: - changed = True - changed_list.append("DB event retention") - result['db_event_retention_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='event.maxAge', value=db_event_retention) - ) - # Runtime settings - if setting.key == 'instance.id' and setting.value != runtime_unique_id: - changed = True - changed_list.append("Instance ID") - result['runtime_unique_id_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='instance.id', value=runtime_unique_id) - ) - if setting.key == 'VirtualCenter.ManagedIP' and setting.value != runtime_managed_address: - changed = True - changed_list.append("Managed IP") - result['runtime_managed_address_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='VirtualCenter.ManagedIP', value=runtime_managed_address) - ) - if setting.key == 'VirtualCenter.InstanceName' and setting.value != runtime_server_name: - changed = True - changed_list.append("Server name") - result['runtime_server_name_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='VirtualCenter.InstanceName', value=runtime_server_name) - ) - # User directory - if setting.key == 'ads.timeout' and setting.value != directory_timeout: - changed = True - changed_list.append("Directory timeout") - result['directory_timeout_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='ads.timeout', value=directory_timeout) - ) - if setting.key == 'ads.maxFetchEnabled' and setting.value != directory_query_limit: - changed = True - changed_list.append("Query limit") - result['directory_query_limit_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='ads.maxFetchEnabled', value=directory_query_limit) - ) - if setting.key == 'ads.maxFetch' and setting.value != directory_query_limit_size: - changed = True - changed_list.append("Query limit size") - result['directory_query_limit_size_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='ads.maxFetch', value=directory_query_limit_size) - ) - if setting.key == 'ads.checkIntervalEnabled' and setting.value != directory_validation: - changed = True - changed_list.append("Validation") - result['directory_validation_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='ads.checkIntervalEnabled', value=directory_validation) - ) - if setting.key == 'ads.checkInterval' and setting.value != directory_validation_period: - changed = True - changed_list.append("Validation period") - result['directory_validation_period_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='ads.checkInterval', value=directory_validation_period) - ) - # Mail - if setting.key == 'mail.smtp.server' and setting.value != mail_server: - changed = True - changed_list.append("Mail server") - result['mail_server_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='mail.smtp.server', value=mail_server) - ) - if setting.key == 'mail.sender' and setting.value != mail_sender: - changed = True - changed_list.append("Mail sender") - result['mail_sender_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='mail.sender', value=mail_sender) - ) - # SNMP receivers - SNMP receiver #1 - if setting.key == 'snmp.receiver.1.enabled' and setting.value != snmp_receiver_1_enabled: - changed = True - changed_list.append("SNMP-1-enabled") - result['snmp_1_enabled_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='snmp.receiver.1.enabled', value=snmp_receiver_1_enabled) - ) - if setting.key == 'snmp.receiver.1.name' and setting.value != snmp_receiver_1_url: - changed = True - changed_list.append("SNMP-1-name") - result['snmp_1_url_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='snmp.receiver.1.name', value=snmp_receiver_1_url) - ) - if setting.key == 'snmp.receiver.1.port' and setting.value != snmp_receiver_1_port: - changed = True - changed_list.append("SNMP-1-port") - result['snmp_receiver_1_port_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='snmp.receiver.1.port', value=snmp_receiver_1_port) - ) - if setting.key == 'snmp.receiver.1.community' and setting.value != snmp_receiver_1_community: - changed = True - changed_list.append("SNMP-1-community") - result['snmp_1_community_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='snmp.receiver.1.community', value=snmp_receiver_1_community) - ) - # SNMP receivers - SNMP receiver #2 - if setting.key == 'snmp.receiver.2.enabled' and setting.value != snmp_receiver_2_enabled: - changed = True - changed_list.append("SNMP-2-enabled") - result['snmp_2_enabled_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='snmp.receiver.2.enabled', value=snmp_receiver_2_enabled) - ) - if setting.key == 'snmp.receiver.2.name' and setting.value != snmp_receiver_2_url: - changed = True - changed_list.append("SNMP-2-name") - result['snmp_2_url_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='snmp.receiver.2.name', value=snmp_receiver_2_url) - ) - if setting.key == 'snmp.receiver.2.port' and setting.value != snmp_receiver_2_port: - changed = True - changed_list.append("SNMP-2-port") - result['snmp_receiver_2_port_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='snmp.receiver.2.port', value=snmp_receiver_2_port) - ) - if setting.key == 'snmp.receiver.2.community' and setting.value != snmp_receiver_2_community: - changed = True - changed_list.append("SNMP-2-community") - result['snmp_2_community_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='snmp.receiver.2.community', value=snmp_receiver_2_community) - ) - # SNMP receivers - SNMP receiver #3 - if setting.key == 'snmp.receiver.3.enabled' and setting.value != snmp_receiver_3_enabled: - changed = True - changed_list.append("SNMP-3-enabled") - result['snmp_3_enabled_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='snmp.receiver.3.enabled', value=snmp_receiver_3_enabled) - ) - if setting.key == 'snmp.receiver.3.name' and setting.value != snmp_receiver_3_url: - changed = True - changed_list.append("SNMP-3-name") - result['snmp_3_url_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='snmp.receiver.3.name', value=snmp_receiver_3_url) - ) - if setting.key == 'snmp.receiver.3.port' and setting.value != snmp_receiver_3_port: - changed = True - changed_list.append("SNMP-3-port") - result['snmp_receiver_3_port_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='snmp.receiver.3.port', value=snmp_receiver_3_port) - ) - if setting.key == 'snmp.receiver.3.community' and setting.value != snmp_receiver_3_community: - changed = True - changed_list.append("SNMP-3-community") - result['snmp_3_community_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='snmp.receiver.3.community', value=snmp_receiver_3_community) - ) - # SNMP receivers - SNMP receiver #4 - if setting.key == 'snmp.receiver.4.enabled' and setting.value != snmp_receiver_4_enabled: - changed = True - changed_list.append("SNMP-4-enabled") - result['snmp_4_enabled_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='snmp.receiver.4.enabled', value=snmp_receiver_4_enabled) - ) - if setting.key == 'snmp.receiver.4.name' and setting.value != snmp_receiver_4_url: - changed = True - changed_list.append("SNMP-4-name") - result['snmp_4_url_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='snmp.receiver.4.name', value=snmp_receiver_4_url) - ) - if setting.key == 'snmp.receiver.4.port' and setting.value != snmp_receiver_4_port: - changed = True - changed_list.append("SNMP-4-port") - result['snmp_receiver_4_port_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='snmp.receiver.4.port', value=snmp_receiver_4_port) - ) - if setting.key == 'snmp.receiver.4.community' and setting.value != snmp_receiver_4_community: - changed = True - changed_list.append("SNMP-4-community") - result['snmp_4_community_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='snmp.receiver.4.community', value=snmp_receiver_4_community) - ) - # Timeout settings - if setting.key == 'client.timeout.normal' and setting.value != timeout_normal_operations: - changed = True - changed_list.append("Timeout normal") - result['timeout_normal_operations_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='client.timeout.normal', value=timeout_normal_operations) - ) - if setting.key == 'client.timeout.long' and setting.value != timeout_long_operations: - changed = True - changed_list.append("Timout long") - result['timeout_long_operations_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='client.timeout.long', value=timeout_long_operations) - ) - # Logging settings - if setting.key == 'log.level' and setting.value != logging_options: - changed = True - changed_list.append("Logging") - result['logging_options_previous'] = setting.value - change_option_list.append( - vim.option.OptionValue(key='log.level', value=logging_options) - ) - - if changed: - if self.module.check_mode: - changed_suffix = ' would be changed' - else: - changed_suffix = ' changed' - if len(changed_list) > 2: - message = ', '.join(changed_list[:-1]) + ', and ' + str(changed_list[-1]) - elif len(changed_list) == 2: - message = ' and '.join(changed_list) - elif len(changed_list) == 1: - message = changed_list[0] - message += changed_suffix - if not self.module.check_mode: - try: - option_manager.UpdateOptions(changedValue=change_option_list) - except (vmodl.fault.SystemError, vmodl.fault.InvalidArgument) as invalid_argument: - self.module.fail_json( - msg="Failed to update option(s) as one or more OptionValue contains an invalid value: %s" % - to_native(invalid_argument.msg) - ) - except vim.fault.InvalidName as invalid_name: - self.module.fail_json( - msg="Failed to update option(s) as one or more OptionValue objects refers to a " - "non-existent option : %s" % to_native(invalid_name.msg) - ) - else: - message = "vCenter settings already configured properly" - result['changed'] = changed - result['msg'] = message - - self.module.exit_json(**result) - - -def main(): - """Main""" - argument_spec = vmware_argument_spec() - argument_spec.update( - database=dict( - type='dict', - options=dict( - max_connections=dict(type='int', default=50), - task_cleanup=dict(type='bool', default=True), - task_retention=dict(type='int', default=30), - event_cleanup=dict(type='bool', default=True), - event_retention=dict(type='int', default=30), - ), - default=dict( - max_connections=50, - task_cleanup=True, - task_retention=30, - event_cleanup=True, - event_retention=30, - ), - ), - runtime_settings=dict( - type='dict', - options=dict( - unique_id=dict(type='int'), - managed_address=dict(type='str'), - vcenter_server_name=dict(type='str'), - ), - ), - user_directory=dict( - type='dict', - options=dict( - timeout=dict(type='int', default=60), - query_limit=dict(type='bool', default=True), - query_limit_size=dict(type='int', default=5000), - validation=dict(type='bool', default=True), - validation_period=dict(type='int', default=1440), - ), - default=dict( - timeout=60, - query_limit=True, - query_limit_size=5000, - validation=True, - validation_period=1440, - ), - ), - mail=dict( - type='dict', - options=dict( - server=dict(type='str'), - sender=dict(type='str'), - ), - default=dict( - server='', - sender='', - ), - ), - snmp_receivers=dict( - type='dict', - options=dict( - snmp_receiver_1_url=dict(type='str', default='localhost'), - snmp_receiver_1_enabled=dict(type='bool', default=True), - snmp_receiver_1_port=dict(type='int', default=162), - snmp_receiver_1_community=dict(type='str', default='public'), - snmp_receiver_2_url=dict(type='str', default=''), - snmp_receiver_2_enabled=dict(type='bool', default=False), - snmp_receiver_2_port=dict(type='int', default=162), - snmp_receiver_2_community=dict(type='str', default=''), - snmp_receiver_3_url=dict(type='str', default=''), - snmp_receiver_3_enabled=dict(type='bool', default=False), - snmp_receiver_3_port=dict(type='int', default=162), - snmp_receiver_3_community=dict(type='str', default=''), - snmp_receiver_4_url=dict(type='str', default=''), - snmp_receiver_4_enabled=dict(type='bool', default=False), - snmp_receiver_4_port=dict(type='int', default=162), - snmp_receiver_4_community=dict(type='str', default=''), - ), - default=dict( - snmp_receiver_1_url='localhost', - snmp_receiver_1_enabled=True, - snmp_receiver_1_port=162, - snmp_receiver_1_community='public', - snmp_receiver_2_url='', - snmp_receiver_2_enabled=False, - snmp_receiver_2_port=162, - snmp_receiver_2_community='', - snmp_receiver_3_url='', - snmp_receiver_3_enabled=False, - snmp_receiver_3_port=162, - snmp_receiver_3_community='', - snmp_receiver_4_url='', - snmp_receiver_4_enabled=False, - snmp_receiver_4_port=162, - snmp_receiver_4_community='', - ), - ), - timeout_settings=dict( - type='dict', - options=dict( - normal_operations=dict(type='int', default=30), - long_operations=dict(type='int', default=120), - ), - default=dict( - normal_operations=30, - long_operations=120, - ), - ), - logging_options=dict(default='info', choices=['none', 'error', 'warning', 'info', 'verbose', 'trivia']), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True - ) - - host_snmp = VmwareVcenterSettings(module) - host_snmp.ensure() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_vcenter_statistics.py b/lib/ansible/modules/cloud/vmware/vmware_vcenter_statistics.py deleted file mode 100644 index bbdd778df2..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_vcenter_statistics.py +++ /dev/null @@ -1,466 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# -# 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 = ''' ---- -module: vmware_vcenter_statistics -short_description: Configures statistics on a vCenter server -description: -- This module can be used to configure the vCenter server statistics. -- The remaining settings can be configured with the module C(vmware_vcenter_settings). -version_added: 2.8 -author: -- Christian Kotte (@ckotte) -notes: -- Tested with vCenter Server Appliance (vCSA) 6.5 and 6.7 -requirements: -- python >= 2.6 -- PyVmomi -options: - interval_past_day: - description: - - Settings for vCenter server past day statistic collection. - - 'Valid attributes are:' - - '- C(enabled) (bool): Past day statistics collection enabled. (default: True)' - - '- C(interval_minutes) (int): Interval duration (minutes). (choices: [1, 2, 3, 4, 5]) (default: 5)' - - '- C(save_for_days) (int): Save for (days). (choices: [1, 2, 3, 4, 5]) (default: 1)' - - '- C(level) (int): Statistics level. (choices: [1, 2, 3, 4]) (default: 1)' - type: dict - interval_past_week: - description: - - Settings for vCenter server past week statistic collection. - - 'Valid attributes are:' - - '- C(enabled) (bool): Past week statistics collection enabled. (default: True)' - - '- C(interval_minutes) (int): Interval duration (minutes). (choices: [30]) (default: 30)' - - '- C(save_for_weeks) (int): Save for (weeks). (choices: [1]) (default: 1)' - - '- C(level) (int): Statistics level. (choices: [1, 2, 3, 4]) (default: 1)' - type: dict - interval_past_month: - description: - - Settings for vCenter server past month statistic collection. - - 'Valid attributes are:' - - '- C(enabled) (bool): Past month statistics collection enabled. (default: True)' - - '- C(interval_hours) (int): Interval duration (hours). (choices: [2]) (default: 2)' - - '- C(save_for_months) (int): Save for (months). (choices: [1]) (default: 1)' - - '- C(level) (int): Statistics level. (choices: [1, 2, 3, 4]) (default: 1)' - type: dict - interval_past_year: - description: - - Settings for vCenter server past month statistic collection. - - 'Valid attributes are:' - - '- C(enabled) (bool): Past month statistics collection enabled. (default: True)' - - '- C(interval_days) (int): Interval duration (days). (choices: [1]) (default: 1)' - - '- C(save_for_years) (int): Save for (years). (choices: [1, 2, 3, 4, 5]) (default: 1)' - - '- C(level) (int): Statistics level. (choices: [1, 2, 3, 4]) (default: 1)' - type: dict -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Configure vCenter statistics - vmware_vcenter_statistics: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - interval_past_day: - enabled: true - interval_minutes: 5 - save_for_days: 1 - level: 1 - interval_past_week: - enabled: true - level: 1 - interval_past_month: - enabled: true - level: 1 - interval_past_year: - enabled: true - save_for_years: 1 - level: 1 - validate_certs: no - delegate_to: localhost -''' - -RETURN = r''' -results: - description: metadata about vCenter statistics settings - returned: always - type: dict - sample: { - "changed": false, - "msg": "vCenter statistics already configured properly", - "past_day_enabled": true, - "past_day_interval": 5, - "past_day_level": 1, - "past_day_save_for": 1, - "past_month_enabled": true, - "past_month_interval": 2, - "past_month_level": 1, - "past_month_save_for": 1, - "past_week_enabled": true, - "past_week_interval": 30, - "past_week_level": 1, - "past_week_save_for": 1, - "past_year_enabled": true, - "past_year_interval": 1, - "past_year_level": 1, - "past_year_save_for": 1 - } -''' - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec -from ansible.module_utils._text import to_native - - -# This is a helper class to sort the changes in a valid order -# "Greater than" means a change has to happen after another one. -# As an example, let's say self is daily (key == 1) and other is weekly (key == 2) -class ChangeHelper: - def __init__(self, old, new): - self.key = new.key - self.old = old - self.new = new - - def __eq__(self, other): - return ((self.key, self.new.enabled, self.new.level) == - (other.key, other.new.enabled, other.new.level)) - - def __gt__(self, other): - if self.key < other.key: - # You cannot disable daily if weekly is enabled, so later - if self.new.enabled < other.old.enabled: - return True - # Enabling daily is OK if weekly is disabled - elif self.new.enabled > other.old.enabled: - return False - # Otherwise, decreasing the daily level below the current weekly level has to be done later - else: - return self.new.level < other.old.level - else: - return not (other > self) - - def __ge__(self, other): - return (self > other) or (self == other) - - def __lt__(self, other): - return not (self >= other) - - def __le__(self, other): - return not (self > other) - - -class VmwareVcenterStatistics(PyVmomi): - """Manage statistics for a vCenter server""" - - def __init__(self, module): - super(VmwareVcenterStatistics, self).__init__(module) - - if not self.is_vcenter(): - self.module.fail_json(msg="You have to connect to a vCenter server!") - - def ensure(self): - """Manage statistics for a vCenter server""" - - DAILY_COUNTER = 1 - WEEKLY_COUNTER = 2 - MONTHLY_COUNTER = 3 - YEARLY_COUNTER = 4 - - result = dict(changed=False, msg='') - past_day_enabled = self.params['interval_past_day'].get('enabled', True) - past_day_seconds = self.params['interval_past_day'].get('interval_minutes', 5) * 60 - past_day_save_for_seconds = self.params['interval_past_day'].get('save_for_days', 1) * 86400 - past_day_level = self.params['interval_past_day'].get('level', 1) - past_week_enabled = self.params['interval_past_week'].get('enabled', True) - past_week_seconds = self.params['interval_past_week'].get('interval_minutes', 30) * 60 - past_week_save_for_seconds = self.params['interval_past_week'].get('save_for_weeks', 1) * 604800 - past_week_level = self.params['interval_past_week'].get('level', 1) - past_month_enabled = self.params['interval_past_month'].get('enabled', True) - past_month_seconds = self.params['interval_past_month'].get('interval_hours', 2) * 3600 - past_month_save_for_seconds = self.params['interval_past_month'].get('save_for_months', 1) * 2592000 - past_month_level = self.params['interval_past_month'].get('level', 1) - past_year_enabled = self.params['interval_past_year'].get('enabled', True) - past_year_seconds = self.params['interval_past_year'].get('interval_days', 1) * 86400 - past_year_save_for_seconds = self.params['interval_past_year'].get('save_for_years', 1) * 31536000 - past_year_level = self.params['interval_past_year'].get('level', 1) - - # Check if level options are valid - if past_year_level > past_month_level: - self.module.fail_json(msg="The statistics level for past year can't be higher than past month!") - if past_month_level > past_week_level: - self.module.fail_json(msg="The statistics level for past month can't be higher than past week!") - if past_week_level > past_day_level: - self.module.fail_json(msg="The statistics level for past week can't be higher than past day!") - - # Check if state options are valid - if not past_day_enabled and (past_week_enabled or past_month_enabled or past_year_enabled): - self.module.fail_json(msg="The intervals past week, month, and year need to be disabled as well!") - if not past_week_enabled and (past_month_enabled or past_year_enabled): - self.module.fail_json(msg="The intervals past month, and year need to be disabled as well!") - if not past_month_enabled and past_year_enabled: - self.module.fail_json(msg="The interval past year need to be disabled as well!") - if past_year_enabled and (not past_day_enabled or not past_week_enabled or not past_month_enabled): - self.module.fail_json(msg="The intervals past day, week, and month need to be enabled as well!") - if past_month_enabled and (not past_day_enabled or not past_week_enabled): - self.module.fail_json(msg="The intervals past day, and week need to be enabled as well!") - if past_week_enabled and (not past_day_enabled): - self.module.fail_json(msg="The intervals past day need to be enabled as well!") - - changed = False - changed_list = [] - - # Check statistics - result['past_day_enabled'] = past_day_enabled - result['past_day_interval'] = int(past_day_seconds / 60) - result['past_day_save_for'] = int(past_day_save_for_seconds / 86400) - result['past_day_level'] = past_day_level - result['past_week_enabled'] = past_week_enabled - result['past_week_interval'] = int(past_week_seconds / 60) - result['past_week_save_for'] = int(past_week_save_for_seconds / 604800) - result['past_week_level'] = past_week_level - result['past_month_enabled'] = past_month_enabled - result['past_month_interval'] = int(past_month_seconds / 3600) - result['past_month_save_for'] = int(past_month_save_for_seconds / 2592000) - result['past_month_level'] = past_month_level - result['past_year_enabled'] = past_year_enabled - result['past_year_interval'] = int(past_year_seconds / 86400) - result['past_year_save_for'] = int(past_year_save_for_seconds / 31536000) - result['past_year_level'] = past_year_level - change_statistics_list = [] - perf_manager = self.content.perfManager - for historical_interval in perf_manager.historicalInterval: - # Statistics for past day - if historical_interval.name == 'Past day' and ( - historical_interval.samplingPeriod != past_day_seconds - or historical_interval.length != past_day_save_for_seconds - or historical_interval.level != past_day_level - or historical_interval.enabled != past_day_enabled - ): - changed = True - changed_list.append("Past day interval") - if historical_interval.enabled != past_day_enabled: - result['past_day_enabled_previous'] = historical_interval.enabled - if historical_interval.samplingPeriod != past_day_seconds: - result['past_day_interval_previous'] = int(historical_interval.samplingPeriod / 60) - if historical_interval.length != past_day_save_for_seconds: - result['past_day_save_for_previous'] = int(historical_interval.length / 86400) - if historical_interval.level != past_day_level: - result['past_day_level_previous'] = historical_interval.level - - change_statistics_list.append( - ChangeHelper( - historical_interval, - vim.HistoricalInterval( - key=DAILY_COUNTER, - samplingPeriod=past_day_seconds, - name='Past day', - length=past_day_save_for_seconds, - level=past_day_level, - enabled=past_day_enabled - ) - ) - ) - - # Statistics for past week - if historical_interval.name == 'Past week' and ( - historical_interval.samplingPeriod != past_week_seconds - or historical_interval.length != past_week_save_for_seconds - or historical_interval.level != past_week_level - or historical_interval.enabled != past_week_enabled - ): - changed = True - changed_list.append("Past week interval") - if historical_interval.enabled != past_week_enabled: - result['past_week_enabled_previous'] = historical_interval.enabled - if historical_interval.samplingPeriod != past_week_seconds: - result['past_week_interval_previous'] = int(historical_interval.samplingPeriod / 60) - if historical_interval.length != past_week_save_for_seconds: - result['past_week_save_for_previous'] = int(historical_interval.length / 604800) - if historical_interval.level != past_week_level: - result['past_week_level_previous'] = historical_interval.level - - change_statistics_list.append( - ChangeHelper( - historical_interval, - vim.HistoricalInterval( - key=WEEKLY_COUNTER, - samplingPeriod=past_week_seconds, - name='Past week', - length=past_week_save_for_seconds, - level=past_week_level, - enabled=past_week_enabled - ) - ) - ) - - # Statistics for past month - if historical_interval.name == 'Past month' and ( - historical_interval.samplingPeriod != past_month_seconds - or historical_interval.length != past_month_save_for_seconds - or historical_interval.level != past_month_level - or historical_interval.enabled != past_month_enabled - ): - changed = True - changed_list.append("Past month interval") - if historical_interval.enabled != past_month_enabled: - result['past_month_enabled_previous'] = historical_interval.enabled - if historical_interval.samplingPeriod != past_month_seconds: - result['past_month_interval_previous'] = int(historical_interval.samplingPeriod / 3600) - if historical_interval.length != past_month_save_for_seconds: - result['past_month_save_for_previous'] = int(historical_interval.length / 2592000) - if historical_interval.level != past_month_level: - result['past_month_level_previous'] = historical_interval.level - - change_statistics_list.append( - ChangeHelper( - historical_interval, - vim.HistoricalInterval( - key=MONTHLY_COUNTER, - samplingPeriod=past_month_seconds, - name='Past month', - length=past_month_save_for_seconds, - level=past_month_level, - enabled=past_month_enabled - ) - ) - ) - - # Statistics for past year - if historical_interval.name == 'Past year' and ( - historical_interval.samplingPeriod != past_year_seconds - or historical_interval.length != past_year_save_for_seconds - or historical_interval.level != past_year_level - or historical_interval.enabled != past_year_enabled - ): - changed = True - changed_list.append("Past year interval") - if historical_interval.enabled != past_year_enabled: - result['past_year_enabled_previous'] = historical_interval.enabled - if historical_interval.samplingPeriod != past_year_seconds: - result['past_year_interval_previous'] = int(historical_interval.samplingPeriod / 86400) - if historical_interval.length != past_year_save_for_seconds: - result['past_year_save_for_previous'] = int(historical_interval.length / 31536000) - if historical_interval.level != past_year_level: - result['past_year_level_previous'] = historical_interval.level - - change_statistics_list.append( - ChangeHelper( - historical_interval, - vim.HistoricalInterval( - key=YEARLY_COUNTER, - samplingPeriod=past_year_seconds, - name='Past year', - length=past_year_save_for_seconds, - level=past_year_level, - enabled=past_year_enabled - ) - ) - ) - - if changed: - if self.module.check_mode: - changed_suffix = ' would be changed' - else: - changed_suffix = ' changed' - if len(changed_list) > 2: - message = ', '.join(changed_list[:-1]) + ', and ' + str(changed_list[-1]) - elif len(changed_list) == 2: - message = ' and '.join(changed_list) - elif len(changed_list) == 1: - message = changed_list[0] - message += changed_suffix - if not self.module.check_mode: - change_statistics_list.sort() - for statistic in change_statistics_list: - self.update_perf_interval(perf_manager, statistic.new) - else: - message = "vCenter statistics already configured properly" - result['changed'] = changed - result['msg'] = message - - self.module.exit_json(**result) - - def update_perf_interval(self, perf_manager, statistic): - """Update statistics interval""" - try: - perf_manager.UpdatePerfInterval(statistic) - except vmodl.fault.InvalidArgument as invalid_argument: - self.module.fail_json( - msg="The set of arguments passed to the function is not specified correctly or " - "the update does not conform to the rules: %s" % to_native(invalid_argument.msg) - ) - - -def main(): - """Main""" - argument_spec = vmware_argument_spec() - argument_spec.update( - interval_past_day=dict( - type='dict', - options=dict( - enabled=dict(type='bool', default=True), - interval_minutes=dict(type='int', choices=[1, 2, 3, 4, 5], default=5), - save_for_days=dict(type='int', choices=[1, 2, 3, 4, 5], default=1), - level=dict(type='int', choices=[1, 2, 3, 4], default=1), - ), - ), - interval_past_week=dict( - type='dict', - options=dict( - enabled=dict(type='bool', default=True), - interval_minutes=dict(type='int', choices=[30], default=30), - save_for_weeks=dict(type='int', choices=[1], default=1), - level=dict(type='int', choices=[1, 2, 3, 4], default=1), - ), - ), - interval_past_month=dict( - type='dict', - options=dict( - enabled=dict(type='bool', default=True), - interval_hours=dict(type='int', choices=[2], default=2), - save_for_months=dict(type='int', choices=[1], default=1), - level=dict(type='int', choices=[1, 2, 3, 4], default=1), - ), - ), - interval_past_year=dict( - type='dict', - options=dict( - enabled=dict(type='bool', default=True), - interval_days=dict(type='int', choices=[1], default=1), - save_for_years=dict(type='int', choices=[1, 2, 3, 4, 5], default=1), - level=dict(type='int', choices=[1, 2, 3, 4], default=1), - ), - ), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True - ) - - host_snmp = VmwareVcenterStatistics(module) - host_snmp.ensure() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_vm_host_drs_rule.py b/lib/ansible/modules/cloud/vmware/vmware_vm_host_drs_rule.py deleted file mode 100644 index 673cf5a53a..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_vm_host_drs_rule.py +++ /dev/null @@ -1,466 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Karsten Kaj Jakobsen <kj@patientsky.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''' ---- -author: - - "Karsten Kaj Jakobsen (@karstenjakobsen)" -description: - - "This module can be used to create VM-Host rules in a given cluster." -extends_documentation_fragment: vmware.documentation -module: vmware_vm_host_drs_rule -notes: - - "Tested on vSphere 6.5 and 6.7" -options: - affinity_rule: - default: true - description: - - "If set to C(True), the DRS rule will be an Affinity rule." - - "If set to C(False), the DRS rule will be an Anti-Affinity rule." - - "Effective only if C(state) is set to C(present)." - type: bool - datacenter: - aliases: - - datacenter_name - description: - - "Datacenter to search for given cluster. If not set, we use first cluster we encounter with C(cluster_name)." - required: false - type: str - cluster_name: - description: - - "Cluster to create VM-Host rule." - required: true - type: str - drs_rule_name: - description: - - "Name of rule to create or remove." - required: true - type: str - enabled: - default: false - description: - - "If set to C(True), the DRS rule will be enabled." - - "Effective only if C(state) is set to C(present)." - type: bool - host_group_name: - description: - - "Name of Host group to use with rule." - - "Effective only if C(state) is set to C(present)." - required: true - type: str - mandatory: - default: false - description: - - "If set to C(True), the DRS rule will be mandatory." - - "Effective only if C(state) is set to C(present)." - type: bool - state: - choices: - - present - - absent - default: present - description: - - "If set to C(present) and the rule doesn't exists then the rule will be created." - - "If set to C(absent) and the rule exists then the rule will be deleted." - required: true - type: str - vm_group_name: - description: - - "Name of VM group to use with rule." - - "Effective only if C(state) is set to C(present)." - required: true - type: str -requirements: - - "python >= 2.6" - - PyVmomi -short_description: "Creates vm/host group in a given cluster" -version_added: "2.8" - -''' - -EXAMPLES = r''' ---- -- name: "Create mandatory DRS Affinity rule for VM/Host" - vmware_vm_host_drs_rule: - hostname: "{{ vcenter_hostname }}" - password: "{{ vcenter_password }}" - username: "{{ vcenter_username }}" - validate_certs: False - cluster_name: DC0_C0 - drs_rule_name: drs_rule_host_aff_0001 - host_group_name: DC0_C0_HOST_GR1 - vm_group_name: DC0_C0_VM_GR1 - mandatory: True - enabled: True - affinity_rule: True -''' - -RETURN = r''' - -''' - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils._text import to_native -from ansible.module_utils.vmware import (PyVmomi, vmware_argument_spec, wait_for_task, find_cluster_by_name, - find_datacenter_by_name) - - -class VmwareVmHostRuleDrs(PyVmomi): - """ - Class to manage VM HOST DRS Rules - """ - - def __init__(self, module): - """ - Doctring: Init - """ - - super(VmwareVmHostRuleDrs, self).__init__(module) - - self.__datacenter_name = module.params.get('datacenter', None) - self.__datacenter_obj = None - self.__cluster_name = module.params['cluster_name'] - self.__cluster_obj = None - self.__vm_group_name = module.params.get('vm_group_name', None) - self.__host_group_name = module.params.get('host_group_name', None) - self.__rule_name = module.params['drs_rule_name'] - self.__enabled = module.params['enabled'] - self.__mandatory = module.params['mandatory'] - self.__affinity_rule = module.params['affinity_rule'] - self.__state = module.params['state'] - self.__msg = 'Nothing to see here...' - self.__result = dict() - self.__changed = False - - if self.__datacenter_name is not None: - - self.__datacenter_obj = find_datacenter_by_name(self.content, self.__datacenter_name) - - if self.__datacenter_obj is None and module.check_mode is False: - raise Exception("Datacenter '%s' not found" % self.__datacenter_name) - - self.__cluster_obj = find_cluster_by_name(content=self.content, - cluster_name=self.__cluster_name, - datacenter=self.__datacenter_obj) - - # Throw error if cluster does not exist - if self.__cluster_obj is None and module.check_mode is False: - raise Exception("Cluster '%s' not found" % self.__cluster_name) - - # Dont populate lists if we are deleting group - if self.__state == 'present': - # Get list of vm groups only if state is present - self.__vm_group_obj = self.__get_group_by_name(group_name=self.__vm_group_name) - self.__host_group_obj = self.__get_group_by_name(group_name=self.__host_group_name, host_group=True) - - def get_msg(self): - """ - Returns message for Ansible result - Args: none - - Returns: string - """ - return self.__msg - - def get_result(self): - """ - Returns result for Ansible - Args: none - - Returns: dict - """ - return self.__result - - def get_changed(self): - """ - Returns if anything changed - Args: none - - Returns: boolean - """ - return self.__changed - - def __get_group_by_name(self, group_name, cluster_obj=None, host_group=False): - """ - Return group - Args: - group_name: Group name - cluster_obj: Cluster managed object - - Returns: cluster_obj.configurationEx.group - - """ - if cluster_obj is None: - cluster_obj = self.__cluster_obj - - for group in cluster_obj.configurationEx.group: - - if not host_group and isinstance(group, vim.cluster.VmGroup): - if group.name == group_name: - return group - elif host_group and isinstance(group, vim.cluster.HostGroup): - if group.name == group_name: - return group - - raise Exception("Failed to find the group %s in given cluster %s" % (group_name, cluster_obj.name)) - - def __get_rule_key_by_name(self, cluster_obj=None, rule_name=None): - """ - Function to get a specific VM-Host DRS rule key by name - Args: - rule_name: Name of rule - cluster_obj: Cluster managed object - - Returns: Rule Object if found or None - - """ - - if cluster_obj is None: - cluster_obj = self.__cluster_obj - - if rule_name is None: - rule_name = self.__rule_name - - if rule_name: - rules_list = [rule for rule in cluster_obj.configuration.rule if rule.name == rule_name] - if rules_list: - return rules_list[0] - - # No rule found - return None - - def __normalize_vm_host_rule_spec(self, rule_obj, cluster_obj=None): - """ - Return human readable rule spec - Args: - rule_obj: Rule managed object - cluster_obj: Cluster managed object - - Returns: Dictionary with VM-Host DRS Rule info - - """ - if cluster_obj is None: - cluster_obj = self.__cluster_obj - - if not all([rule_obj, cluster_obj]): - return {} - - return dict(rule_key=rule_obj.key, - rule_enabled=rule_obj.enabled, - rule_name=rule_obj.name, - rule_mandatory=rule_obj.mandatory, - rule_uuid=rule_obj.ruleUuid, - rule_vm_group_name=rule_obj.vmGroupName, - rule_affine_host_group_name=rule_obj.affineHostGroupName, - rule_anti_affine_host_group_name=rule_obj.antiAffineHostGroupName, - rule_vms=self.__get_all_from_group(group_name=rule_obj.vmGroupName, - cluster_obj=cluster_obj), - rule_affine_hosts=self.__get_all_from_group(group_name=rule_obj.affineHostGroupName, - cluster_obj=cluster_obj, - host_group=True), - rule_anti_affine_hosts=self.__get_all_from_group(group_name=rule_obj.antiAffineHostGroupName, - cluster_obj=cluster_obj, - host_group=True), - rule_type="vm_host_rule" - ) - - def __get_all_from_group(self, group_name=None, cluster_obj=None, host_group=False): - """ - Return all VM / Host names using given group name - Args: - group_name: Rule name - cluster_obj: Cluster managed object - host_group: True if we want only host name from group - - Returns: List of VM-Host names belonging to given group object - - """ - obj_name_list = [] - - if not all([group_name, cluster_obj]): - return obj_name_list - - for group in cluster_obj.configurationEx.group: - if group.name == group_name: - if not host_group and isinstance(group, vim.cluster.VmGroup): - obj_name_list = [vm.name for vm in group.vm] - break - elif host_group and isinstance(group, vim.cluster.HostGroup): - obj_name_list = [host.name for host in group.host] - break - - return obj_name_list - - def __check_rule_has_changed(self, rule_obj, cluster_obj=None): - """ - Function to check if the rule being edited has changed - """ - - if cluster_obj is None: - cluster_obj = self.__cluster_obj - - existing_rule = self.__normalize_vm_host_rule_spec(rule_obj=rule_obj, cluster_obj=cluster_obj) - - # Check if anything has changed - if ((existing_rule['rule_enabled'] == self.__enabled) and - (existing_rule['rule_mandatory'] == self.__mandatory) and - (existing_rule['rule_vm_group_name'] == self.__vm_group_name) and - (existing_rule['rule_affine_host_group_name'] == self.__host_group_name or - existing_rule['rule_anti_affine_host_group_name'] == self.__host_group_name)): - - return False - else: - return True - - def create(self): - """ - Function to create a host VM-Host DRS rule if rule does not exist - """ - rule_obj = self.__get_rule_key_by_name(rule_name=self.__rule_name) - - # Check if rule exists - if rule_obj: - - operation = 'edit' - rule_changed = self.__check_rule_has_changed(rule_obj) - - else: - operation = 'add' - - # Check if anything has changed when editing - if operation == 'add' or (operation == 'edit' and rule_changed is True): - - rule = vim.cluster.VmHostRuleInfo() - - # Check if already rule exists - if rule_obj: - # This need to be set in order to edit a existing rule - rule.key = rule_obj.key - - rule.enabled = self.__enabled - rule.mandatory = self.__mandatory - rule.name = self.__rule_name - - if self.__affinity_rule: - rule.affineHostGroupName = self.__host_group_name - else: - rule.antiAffineHostGroupName = self.__host_group_name - - rule.vmGroupName = self.__vm_group_name - - rule_spec = vim.cluster.RuleSpec(info=rule, operation=operation) - config_spec = vim.cluster.ConfigSpecEx(rulesSpec=[rule_spec]) - - if not self.module.check_mode: - - task = self.__cluster_obj.ReconfigureEx(config_spec, modify=True) - wait_for_task(task) - - self.__changed = True - - rule_obj = self.__get_rule_key_by_name(rule_name=self.__rule_name) - self.__result = self.__normalize_vm_host_rule_spec(rule_obj) - - if operation == 'edit': - self.__msg = "Updated DRS rule `%s` successfully" % (self.__rule_name) - else: - self.__msg = "Created DRS rule `%s` successfully" % (self.__rule_name) - - # Delete - def delete(self, rule_name=None): - """ - Function to delete VM-Host DRS rule using name - """ - changed = False - - if rule_name is None: - rule_name = self.__rule_name - - rule_obj = self.__get_rule_key_by_name(rule_name=rule_name) - - if rule_obj is not None: - - rule_key = int(rule_obj.key) - rule_spec = vim.cluster.RuleSpec(removeKey=rule_key, operation='remove') - config_spec = vim.cluster.ConfigSpecEx(rulesSpec=[rule_spec]) - - if not self.module.check_mode: - - task = self.__cluster_obj.ReconfigureEx(config_spec, modify=True) - wait_for_task(task) - - self.__changed = True - - if self.__changed: - self.__msg = "Deleted DRS rule `%s` successfully" % (self.__rule_name) - else: - self.__msg = "DRS Rule `%s` does not exists or already deleted" % (self.__rule_name) - - -def main(): - - argument_spec = vmware_argument_spec() - - argument_spec.update(dict( - state=dict(type='str', default='present', choices=['absent', 'present']), - vm_group_name=dict(type='str', required=True), - host_group_name=dict(type='str', required=True), - cluster_name=dict(type='str', required=True), - datacenter=dict(type='str', required=False, aliases=['datacenter_name']), - drs_rule_name=dict(type='str', required=True), - enabled=dict(type='bool', default=False), - mandatory=dict(type='bool', default=False), - affinity_rule=dict(type='bool', default=True)) - ) - - required_if = [ - ['state', 'present', ['vm_group_name'], ['host_group_name']], - ] - - module = AnsibleModule(argument_spec=argument_spec, - required_if=required_if, - supports_check_mode=True) - - try: - # Create instance of VmwareDrsGroupManager - vm_host_drs = VmwareVmHostRuleDrs(module=module) - - if module.params['state'] == 'present': - vm_host_drs.create() - elif module.params['state'] == 'absent': - vm_host_drs.delete() - - # Set results - results = dict(msg=vm_host_drs.get_msg(), - failed=False, - changed=vm_host_drs.get_changed(), - result=vm_host_drs.get_result()) - - except Exception as error: - results = dict(failed=True, msg="Error: `%s`" % error) - - if results['failed']: - module.fail_json(**results) - else: - module.exit_json(**results) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_vm_info.py b/lib/ansible/modules/cloud/vmware/vmware_vm_info.py deleted file mode 100644 index a124b9d074..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_vm_info.py +++ /dev/null @@ -1,331 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2015, Joseph Callen <jcallen () csc.com> -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Fedor Vompe <f.vompe () comptek.ru> -# 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_vm_info -short_description: Return basic info pertaining to a VMware machine guest -description: -- Return basic information pertaining to a vSphere or ESXi virtual machine guest. -- Cluster name as fact is added in version 2.7. -- This module was called C(vmware_vm_facts) before Ansible 2.9. The usage did not change. -version_added: '2.0' -author: -- Joseph Callen (@jcpowermac) -- Abhijeet Kasurde (@Akasurde) -- Fedor Vompe (@sumkincpp) -notes: -- Tested on ESXi 6.7, vSphere 5.5 and vSphere 6.5 -- From 2.8 and onwards, information are returned as list of dict instead of dict. -requirements: -- python >= 2.6 -- PyVmomi -options: - vm_type: - description: - - If set to C(vm), then information are gathered for virtual machines only. - - If set to C(template), then information are gathered for virtual machine templates only. - - If set to C(all), then information are gathered for all virtual machines and virtual machine templates. - required: False - default: 'all' - choices: [ all, vm, template ] - version_added: 2.5 - type: str - show_attribute: - description: - - Attributes related to VM guest shown in information only when this is set C(true). - default: no - type: bool - version_added: 2.8 - folder: - description: - - Specify a folder location of VMs to gather information from. - - 'Examples:' - - ' folder: /ha-datacenter/vm' - - ' folder: ha-datacenter/vm' - - ' folder: /datacenter1/vm' - - ' folder: datacenter1/vm' - - ' folder: /datacenter1/vm/folder1' - - ' folder: datacenter1/vm/folder1' - - ' folder: /folder1/datacenter1/vm' - - ' folder: folder1/datacenter1/vm' - - ' folder: /folder1/datacenter1/vm/folder2' - type: str - version_added: 2.9 - show_tag: - description: - - Tags related to virtual machine are shown if set to C(True). - default: False - type: bool - version_added: 2.9 -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather all registered virtual machines - vmware_vm_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - delegate_to: localhost - register: vminfo - -- debug: - var: vminfo.virtual_machines - -- name: Gather only registered virtual machine templates - vmware_vm_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - vm_type: template - delegate_to: localhost - register: template_info - -- debug: - var: template_info.virtual_machines - -- name: Gather only registered virtual machines - vmware_vm_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - vm_type: vm - delegate_to: localhost - register: vm_info - -- debug: - var: vm_info.virtual_machines - -- name: Get UUID from given VM Name - block: - - name: Get virtual machine info - vmware_vm_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - folder: "/datacenter/vm/folder" - delegate_to: localhost - register: vm_info - - - debug: - msg: "{{ item.uuid }}" - with_items: - - "{{ vm_info.virtual_machines | json_query(query) }}" - vars: - query: "[?guest_name=='DC0_H0_VM0']" - -- name: Get Tags from given VM Name - block: - - name: Get virtual machine info - vmware_vm_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - folder: "/datacenter/vm/folder" - delegate_to: localhost - register: vm_info - - - debug: - msg: "{{ item.tags }}" - with_items: - - "{{ vm_info.virtual_machines | json_query(query) }}" - vars: - query: "[?guest_name=='DC0_H0_VM0']" - -- name: Gather all VMs from a specific folder - vmware_vm_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - folder: "/Asia-Datacenter1/vm/prod" - delegate_to: localhost - register: vm_info -''' - -RETURN = r''' -virtual_machines: - description: list of dictionary of virtual machines and their information - returned: success - type: list - sample: [ - { - "guest_name": "ubuntu_t", - "cluster": null, - "esxi_hostname": "10.76.33.226", - "guest_fullname": "Ubuntu Linux (64-bit)", - "ip_address": "", - "mac_address": [ - "00:50:56:87:a5:9a" - ], - "power_state": "poweredOff", - "uuid": "4207072c-edd8-3bd5-64dc-903fd3a0db04", - "vm_network": { - "00:50:56:87:a5:9a": { - "ipv4": [ - "10.76.33.228" - ], - "ipv6": [] - } - }, - "attributes": { - "job": "backup-prepare" - }, - "tags": [ - { - "category_id": "urn:vmomi:InventoryServiceCategory:b316cc45-f1a9-4277-811d-56c7e7975203:GLOBAL", - "category_name": "cat_0001", - "description": "", - "id": "urn:vmomi:InventoryServiceTag:43737ec0-b832-4abf-abb1-fd2448ce3b26:GLOBAL", - "name": "tag_0001" - } - ] - } - ] -''' - -try: - from pyVmomi import vim -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, get_all_objs, vmware_argument_spec, _get_vm_prop -from ansible.module_utils.vmware_rest_client import VmwareRestClient - - -class VmwareVmInfo(PyVmomi): - def __init__(self, module): - super(VmwareVmInfo, self).__init__(module) - - def get_tag_info(self, vm_dynamic_obj): - vmware_client = VmwareRestClient(self.module) - return vmware_client.get_tags_for_vm(vm_mid=vm_dynamic_obj._moId) - - def get_vm_attributes(self, vm): - return dict((x.name, v.value) for x in self.custom_field_mgr - for v in vm.customValue if x.key == v.key) - - # https://github.com/vmware/pyvmomi-community-samples/blob/master/samples/getallvms.py - def get_all_virtual_machines(self): - """ - Get all virtual machines and related configurations information - """ - folder = self.params.get('folder') - folder_obj = None - if folder: - folder_obj = self.content.searchIndex.FindByInventoryPath(folder) - if not folder_obj: - self.module.fail_json(msg="Failed to find folder specified by %(folder)s" % self.params) - - virtual_machines = get_all_objs(self.content, [vim.VirtualMachine], folder=folder_obj) - _virtual_machines = [] - - for vm in virtual_machines: - _ip_address = "" - summary = vm.summary - if summary.guest is not None: - _ip_address = summary.guest.ipAddress - if _ip_address is None: - _ip_address = "" - _mac_address = [] - all_devices = _get_vm_prop(vm, ('config', 'hardware', 'device')) - if all_devices: - for dev in all_devices: - if isinstance(dev, vim.vm.device.VirtualEthernetCard): - _mac_address.append(dev.macAddress) - - net_dict = {} - vmnet = _get_vm_prop(vm, ('guest', 'net')) - if vmnet: - for device in vmnet: - net_dict[device.macAddress] = dict() - net_dict[device.macAddress]['ipv4'] = [] - net_dict[device.macAddress]['ipv6'] = [] - for ip_addr in device.ipAddress: - if "::" in ip_addr: - net_dict[device.macAddress]['ipv6'].append(ip_addr) - else: - net_dict[device.macAddress]['ipv4'].append(ip_addr) - - esxi_hostname = None - esxi_parent = None - if summary.runtime.host: - esxi_hostname = summary.runtime.host.summary.config.name - esxi_parent = summary.runtime.host.parent - - cluster_name = None - if esxi_parent and isinstance(esxi_parent, vim.ClusterComputeResource): - cluster_name = summary.runtime.host.parent.name - - vm_attributes = dict() - if self.module.params.get('show_attribute'): - vm_attributes = self.get_vm_attributes(vm) - - vm_tags = list() - if self.module.params.get('show_tag'): - vm_tags = self.get_tag_info(vm) - - virtual_machine = { - "guest_name": summary.config.name, - "guest_fullname": summary.config.guestFullName, - "power_state": summary.runtime.powerState, - "ip_address": _ip_address, # Kept for backward compatibility - "mac_address": _mac_address, # Kept for backward compatibility - "uuid": summary.config.uuid, - "vm_network": net_dict, - "esxi_hostname": esxi_hostname, - "cluster": cluster_name, - "attributes": vm_attributes, - "tags": vm_tags - } - - vm_type = self.module.params.get('vm_type') - is_template = _get_vm_prop(vm, ('config', 'template')) - if vm_type == 'vm' and not is_template: - _virtual_machines.append(virtual_machine) - elif vm_type == 'template' and is_template: - _virtual_machines.append(virtual_machine) - elif vm_type == 'all': - _virtual_machines.append(virtual_machine) - return _virtual_machines - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - vm_type=dict(type='str', choices=['vm', 'all', 'template'], default='all'), - show_attribute=dict(type='bool', default='no'), - show_tag=dict(type='bool', default=False), - folder=dict(type='str'), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True - ) - if module._name == 'vmware_vm_facts': - module.deprecate("The 'vmware_vm_facts' module has been renamed to 'vmware_vm_info'", version='2.13') - - vmware_vm_info = VmwareVmInfo(module) - _virtual_machines = vmware_vm_info.get_all_virtual_machines() - - module.exit_json(changed=False, virtual_machines=_virtual_machines) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_vm_shell.py b/lib/ansible/modules/cloud/vmware/vmware_vm_shell.py deleted file mode 100644 index 01d50251ae..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_vm_shell.py +++ /dev/null @@ -1,371 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2015-16, Ritesh Khadgaray <khadgaray () gmail.com> -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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_vm_shell -short_description: Run commands in a VMware guest operating system -description: - - Module allows user to run common system administration commands in the guest operating system. -version_added: "2.1" -author: - - Ritesh Khadgaray (@ritzk) - - Abhijeet Kasurde (@Akasurde) -notes: - - Tested on vSphere 5.5, 6.0 and 6.5. - - Only the first match against vm_id is used, even if there are multiple matches. -requirements: - - "python >= 2.6" - - PyVmomi -options: - datacenter: - description: - - The datacenter hosting the virtual machine. - - If set, it will help to speed up virtual machine search. - type: str - cluster: - description: - - The cluster hosting the virtual machine. - - If set, it will help to speed up virtual machine search. - type: str - folder: - description: - - Destination folder, absolute or relative path to find an existing guest or create the new guest. - - The folder should include the datacenter. ESX's datacenter is ha-datacenter. - - 'Examples:' - - ' folder: /ha-datacenter/vm' - - ' folder: ha-datacenter/vm' - - ' folder: /datacenter1/vm' - - ' folder: datacenter1/vm' - - ' folder: /datacenter1/vm/folder1' - - ' folder: datacenter1/vm/folder1' - - ' folder: /folder1/datacenter1/vm' - - ' folder: folder1/datacenter1/vm' - - ' folder: /folder1/datacenter1/vm/folder2' - version_added: "2.4" - type: str - vm_id: - description: - - Name of the virtual machine to work with. - required: True - type: str - vm_id_type: - description: - - The VMware identification method by which the virtual machine will be identified. - default: vm_name - choices: ['uuid', 'instance_uuid', 'dns_name', 'inventory_path', 'vm_name'] - type: str - vm_username: - description: - - The user to login-in to the virtual machine. - required: True - type: str - vm_password: - description: - - The password used to login-in to the virtual machine. - required: True - type: str - vm_shell: - description: - - The absolute path to the program to start. - - On Linux, shell is executed via bash. - required: True - type: str - vm_shell_args: - description: - - The argument to the program. - - The characters which must be escaped to the shell also be escaped on the command line provided. - default: " " - type: str - vm_shell_env: - description: - - Comma separated list of environment variable, specified in the guest OS notation. - type: list - vm_shell_cwd: - description: - - The current working directory of the application from which it will be run. - type: str - wait_for_process: - description: - - If set to C(True), module will wait for process to complete in the given virtual machine. - default: False - type: bool - version_added: 2.7 - timeout: - description: - - Timeout in seconds. - - If set to positive integers, then C(wait_for_process) will honor this parameter and will exit after this timeout. - default: 3600 - version_added: 2.7 - type: int -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Run command inside a virtual machine - vmware_vm_shell: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter }}" - folder: "/{{datacenter}}/vm" - vm_id: "{{ vm_name }}" - vm_username: root - vm_password: superSecret - vm_shell: /bin/echo - vm_shell_args: " $var >> myFile " - vm_shell_env: - - "PATH=/bin" - - "VAR=test" - vm_shell_cwd: "/tmp" - delegate_to: localhost - register: shell_command_output - -- name: Run command inside a virtual machine with wait and timeout - vmware_vm_shell: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter }}" - folder: "/{{datacenter}}/vm" - vm_id: NameOfVM - vm_username: root - vm_password: superSecret - vm_shell: /bin/sleep - vm_shell_args: 100 - wait_for_process: True - timeout: 2000 - delegate_to: localhost - register: shell_command_with_wait_timeout - -- name: Change user password in the guest machine - vmware_vm_shell: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ datacenter }}" - folder: "/{{datacenter}}/vm" - vm_id: "{{ vm_name }}" - vm_username: sample - vm_password: old_password - vm_shell: "/bin/echo" - vm_shell_args: "-e 'old_password\nnew_password\nnew_password' | passwd sample > /tmp/$$.txt 2>&1" - delegate_to: localhost - -- name: Change hostname of guest machine - vmware_vm_shell: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ datacenter }}" - folder: "/{{datacenter}}/vm" - vm_id: "{{ vm_name }}" - vm_username: testUser - vm_password: SuperSecretPassword - vm_shell: "/usr/bin/hostnamectl" - vm_shell_args: "set-hostname new_hostname > /tmp/$$.txt 2>&1" - delegate_to: localhost -''' - -RETURN = r''' -results: - description: metadata about the new process after completion with wait_for_process - returned: on success - type: dict - sample: - { - "cmd_line": "\"/bin/sleep\" 1", - "end_time": "2018-04-26T05:03:21+00:00", - "exit_code": 0, - "name": "sleep", - "owner": "dev1", - "start_time": "2018-04-26T05:03:19+00:00", - "uuid": "564db1e2-a3ff-3b0e-8b77-49c25570bb66", - } -''' - -import time -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from ansible.module_utils._text import to_native -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import (PyVmomi, find_cluster_by_name, - find_datacenter_by_name, find_vm_by_id, - vmware_argument_spec) - - -class VMwareShellManager(PyVmomi): - def __init__(self, module): - super(VMwareShellManager, self).__init__(module) - datacenter_name = module.params['datacenter'] - cluster_name = module.params['cluster'] - folder = module.params['folder'] - self.pm = self.content.guestOperationsManager.processManager - self.timeout = self.params.get('timeout', 3600) - self.wait_for_pid = self.params.get('wait_for_process', False) - - datacenter = None - if datacenter_name: - datacenter = find_datacenter_by_name(self.content, datacenter_name) - if not datacenter: - module.fail_json(changed=False, msg="Unable to find %(datacenter)s datacenter" % module.params) - - cluster = None - if cluster_name: - cluster = find_cluster_by_name(self.content, cluster_name, datacenter) - if not cluster: - module.fail_json(changed=False, msg="Unable to find %(cluster)s cluster" % module.params) - - if module.params['vm_id_type'] == 'inventory_path': - vm = find_vm_by_id(self.content, - vm_id=module.params['vm_id'], - vm_id_type="inventory_path", - folder=folder) - else: - vm = find_vm_by_id(self.content, - vm_id=module.params['vm_id'], - vm_id_type=module.params['vm_id_type'], - datacenter=datacenter, - cluster=cluster) - - if not vm: - module.fail_json(msg='Unable to find virtual machine.') - - tools_status = vm.guest.toolsStatus - if tools_status in ['toolsNotInstalled', 'toolsNotRunning']: - self.module.fail_json(msg="VMwareTools is not installed or is not running in the guest." - " VMware Tools are necessary to run this module.") - - try: - self.execute_command(vm, module.params) - except vmodl.RuntimeFault as runtime_fault: - module.fail_json(changed=False, msg=to_native(runtime_fault.msg)) - except vmodl.MethodFault as method_fault: - module.fail_json(changed=False, msg=to_native(method_fault.msg)) - except Exception as e: - module.fail_json(changed=False, msg=to_native(e)) - - def execute_command(self, vm, params): - # https://github.com/vmware/pyvmomi-community-samples/blob/master/samples/execute_program_in_vm.py - vm_username = params['vm_username'] - vm_password = params['vm_password'] - program_path = params['vm_shell'] - args = params['vm_shell_args'] - env = params['vm_shell_env'] - cwd = params['vm_shell_cwd'] - - credentials = vim.vm.guest.NamePasswordAuthentication(username=vm_username, - password=vm_password) - cmd_spec = vim.vm.guest.ProcessManager.ProgramSpec(arguments=args, - envVariables=env, - programPath=program_path, - workingDirectory=cwd) - - res = self.pm.StartProgramInGuest(vm=vm, auth=credentials, spec=cmd_spec) - if self.wait_for_pid: - res_data = self.wait_for_process(vm, res, credentials) - results = dict(uuid=vm.summary.config.uuid, - owner=res_data.owner, - start_time=res_data.startTime.isoformat(), - end_time=res_data.endTime.isoformat(), - exit_code=res_data.exitCode, - name=res_data.name, - cmd_line=res_data.cmdLine) - - if res_data.exitCode != 0: - results['msg'] = "Failed to execute command" - results['changed'] = False - results['failed'] = True - self.module.fail_json(**results) - else: - results['changed'] = True - results['failed'] = False - self.module.exit_json(**results) - else: - self.module.exit_json(changed=True, uuid=vm.summary.config.uuid, msg=res) - - def process_exists_in_guest(self, vm, pid, creds): - res = self.pm.ListProcessesInGuest(vm, creds, pids=[pid]) - if not res: - self.module.fail_json( - changed=False, msg='ListProcessesInGuest: None (unexpected)') - res = res[0] - if res.exitCode is None: - return True, None - else: - return False, res - - def wait_for_process(self, vm, pid, creds): - start_time = time.time() - while True: - current_time = time.time() - process_status, res_data = self.process_exists_in_guest(vm, pid, creds) - if not process_status: - return res_data - elif current_time - start_time >= self.timeout: - self.module.fail_json( - msg="Timeout waiting for process to complete.", - vm=vm._moId, - pid=pid, - start_time=start_time, - current_time=current_time, - timeout=self.timeout) - else: - time.sleep(5) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - dict( - datacenter=dict(type='str'), - cluster=dict(type='str'), - folder=dict(type='str'), - vm_id=dict(type='str', required=True), - vm_id_type=dict(default='vm_name', type='str', - choices=['inventory_path', - 'uuid', - 'instance_uuid', - 'dns_name', - 'vm_name']), - vm_username=dict(type='str', required=True), - vm_password=dict(type='str', no_log=True, required=True), - vm_shell=dict(type='str', required=True), - vm_shell_args=dict(default=" ", type='str'), - vm_shell_env=dict(type='list'), - vm_shell_cwd=dict(type='str'), - wait_for_process=dict(type='bool', default=False), - timeout=dict(type='int', default=3600), - ) - ) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=False, - required_if=[ - ['vm_id_type', 'inventory_path', ['folder']] - ], - ) - - vm_shell_mgr = VMwareShellManager(module) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_vm_storage_policy_info.py b/lib/ansible/modules/cloud/vmware/vmware_vm_storage_policy_info.py deleted file mode 100644 index 2ec8cebd22..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_vm_storage_policy_info.py +++ /dev/null @@ -1,164 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2019, Ansible Project -# Copyright: (c) 2019, Abhijeet Kasurde <akasurde@redhat.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_vm_storage_policy_info -short_description: Gather information about vSphere storage profile defined storage policy information. -description: -- Returns basic information on vSphere storage profiles. -- A vSphere storage profile defines storage policy information that describes storage requirements - for virtual machines and storage capabilities of storage providers. -version_added: '2.9' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Get SPBM info - vmware_vm_storage_policy_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - delegate_to: localhost - register: profiles -''' - -RETURN = r''' -spbm_profiles: - description: list of dictionary of SPBM info - returned: success - type: list - sample: [ - { - "constraints_sub_profiles": [ - { - "rule_set_info": [ - { - "id": "hostFailuresToTolerate", - "value": 1 - }, - { - "id": "stripeWidth", - "value": 1 - }, - { - "id": "forceProvisioning", - "value": false - }, - { - "id": "proportionalCapacity", - "value": 0 - }, - { - "id": "cacheReservation", - "value": 0 - } - ], - "rule_set_name": "VSAN sub-profile" - } - ], - "description": "Storage policy used as default for vSAN datastores", - "id": "aa6d5a82-1c88-45da-85d3-3d74b91a5bad", - "name": "vSAN Default Storage Policy" - }, - ] -''' - -try: - from pyVmomi import pbm -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware_spbm import SPBM -from ansible.module_utils.vmware import vmware_argument_spec - - -class SPBMClient(SPBM): - def __init__(self, module): - super(SPBMClient, self).__init__(module) - - def show_capabilities(self, capabilities): - """ - Return property instance for given capabilities - """ - capabilities_info = [] - for capability in capabilities: - for constraint in capability.constraint: - if hasattr(constraint, 'propertyInstance'): - for propertyInstance in constraint.propertyInstance: - capabilities_info.append( - { - 'id': propertyInstance.id, - 'value': propertyInstance.value - } - ) - return capabilities_info - - def get_storage_policy_info(self): - self.get_spbm_connection() - - results = dict(changed=False, spbm_profiles=[]) - profile_manager = self.spbm_content.profileManager - profile_ids = profile_manager.PbmQueryProfile( - resourceType=pbm.profile.ResourceType(resourceType="STORAGE"), - profileCategory="REQUIREMENT" - ) - profiles = [] - if profile_ids: - profiles = profile_manager.PbmRetrieveContent(profileIds=profile_ids) - - for profile in profiles: - temp_profile_info = { - 'name': profile.name, - 'id': profile.profileId.uniqueId, - 'description': profile.description, - 'constraints_sub_profiles': [] - } - if hasattr(profile.constraints, 'subProfiles'): - subprofiles = profile.constraints.subProfiles - temp_sub_profiles = [] - for subprofile in subprofiles: - temp_sub_profiles.append({ - 'rule_set_name': subprofile.name, - 'rule_set_info': self.show_capabilities(subprofile.capability), - }) - temp_profile_info['constraints_sub_profiles'] = temp_sub_profiles - - results['spbm_profiles'].append(temp_profile_info) - - self.module.exit_json(**results) - - -def main(): - argument_spec = vmware_argument_spec() - - module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) - - spbm_client = SPBMClient(module) - spbm_client.get_storage_policy_info() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_vm_vm_drs_rule.py b/lib/ansible/modules/cloud/vmware/vmware_vm_vm_drs_rule.py deleted file mode 100644 index 2aae6ac5b3..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_vm_vm_drs_rule.py +++ /dev/null @@ -1,408 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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 = ''' ---- -module: vmware_vm_vm_drs_rule -short_description: Configure VMware DRS Affinity rule for virtual machine in given cluster -description: -- This module can be used to configure VMware DRS Affinity rule for virtual machine in given cluster. -version_added: 2.5 -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- "python >= 2.6" -- PyVmomi -options: - cluster_name: - description: - - Desired cluster name where virtual machines are present for the DRS rule. - required: True - type: str - vms: - description: - - List of virtual machines name for which DRS rule needs to be applied. - - Required if C(state) is set to C(present). - type: list - drs_rule_name: - description: - - The name of the DRS rule to manage. - required: True - type: str - enabled: - description: - - If set to C(True), the DRS rule will be enabled. - - Effective only if C(state) is set to C(present). - default: False - type: bool - mandatory: - description: - - If set to C(True), the DRS rule will be mandatory. - - Effective only if C(state) is set to C(present). - default: False - type: bool - affinity_rule: - description: - - If set to C(True), the DRS rule will be an Affinity rule. - - If set to C(False), the DRS rule will be an Anti-Affinity rule. - - Effective only if C(state) is set to C(present). - default: True - type: bool - state: - description: - - If set to C(present), then the DRS rule is created if not present. - - If set to C(present), then the DRS rule is already present, it updates to the given configurations. - - If set to C(absent), then the DRS rule is deleted if present. - required: False - default: present - choices: [ present, absent ] - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Create DRS Affinity Rule for VM-VM - vmware_vm_vm_drs_rule: - hostname: "{{ esxi_server }}" - username: "{{ esxi_username }}" - password: "{{ esxi_password }}" - cluster_name: "{{ cluster_name }}" - validate_certs: no - vms: - - vm1 - - vm2 - drs_rule_name: vm1-vm2-affinity-rule-001 - enabled: True - mandatory: True - affinity_rule: True - delegate_to: localhost - -- name: Create DRS Anti-Affinity Rule for VM-VM - vmware_vm_vm_drs_rule: - hostname: "{{ esxi_server }}" - username: "{{ esxi_username }}" - password: "{{ esxi_password }}" - cluster_name: "{{ cluster_name }}" - validate_certs: no - enabled: True - vms: - - vm1 - - vm2 - drs_rule_name: vm1-vm2-affinity-rule-001 - mandatory: True - affinity_rule: False - delegate_to: localhost - -- name: Delete DRS Affinity Rule for VM-VM - vmware_vm_vm_drs_rule: - hostname: "{{ esxi_server }}" - username: "{{ esxi_username }}" - password: "{{ esxi_password }}" - cluster_name: "{{ cluster_name }}" - validate_certs: no - drs_rule_name: vm1-vm2-affinity-rule-001 - state: absent - delegate_to: localhost -''' - -RETURN = r''' -result: - description: metadata about DRS VM and VM rule - returned: when state is present - type: dict - sample: { - "rule_enabled": false, - "rule_key": 20, - "rule_mandatory": true, - "rule_name": "drs_rule_0014", - "rule_uuid": "525f3bc0-253f-825a-418e-2ec93bffc9ae", - "rule_vms": [ - "VM_65", - "VM_146" - ] - } -''' - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils._text import to_native -from ansible.module_utils.vmware import (PyVmomi, vmware_argument_spec, wait_for_task, - find_vm_by_id, find_cluster_by_name) - - -class VmwareDrs(PyVmomi): - def __init__(self, module): - super(VmwareDrs, self).__init__(module) - self.vm_list = module.params['vms'] - self.cluster_name = module.params['cluster_name'] - self.rule_name = module.params['drs_rule_name'] - self.enabled = module.params['enabled'] - self.mandatory = module.params['mandatory'] - self.affinity_rule = module.params['affinity_rule'] - self.state = module.params['state'] - - # Sanity check for cluster - self.cluster_obj = find_cluster_by_name(content=self.content, - cluster_name=self.cluster_name) - if self.cluster_obj is None: - self.module.fail_json(msg="Failed to find the cluster %s" % self.cluster_name) - # Sanity check for virtual machines - self.vm_obj_list = [] - if self.state == 'present': - # Get list of VMs only if state is present - self.vm_obj_list = self.get_all_vms_info() - - # Getter - def get_all_vms_info(self, vms_list=None): - """ - Get all VM objects using name from given cluster - Args: - vms_list: List of VM names - - Returns: List of VM managed objects - - """ - vm_obj_list = [] - if vms_list is None: - vms_list = self.vm_list - - for vm_name in vms_list: - vm_obj = find_vm_by_id(content=self.content, vm_id=vm_name, - vm_id_type='vm_name', cluster=self.cluster_obj) - if vm_obj is None: - self.module.fail_json(msg="Failed to find the virtual machine %s " - "in given cluster %s" % (vm_name, - self.cluster_name)) - vm_obj_list.append(vm_obj) - return vm_obj_list - - def get_rule_key_by_name(self, cluster_obj=None, rule_name=None): - """ - Get a specific DRS rule key by name - Args: - rule_name: Name of rule - cluster_obj: Cluster managed object - - Returns: Rule Object if found or None - - """ - if cluster_obj is None: - cluster_obj = self.cluster_obj - - if rule_name: - rules_list = [rule for rule in cluster_obj.configuration.rule if rule.name == rule_name] - if rules_list: - return rules_list[0] - # No rule found - return None - - @staticmethod - def normalize_rule_spec(rule_obj=None): - """ - Return human readable rule spec - Args: - rule_obj: Rule managed object - - Returns: Dictionary with Rule info - - """ - if rule_obj is None: - return {} - return dict(rule_key=rule_obj.key, - rule_enabled=rule_obj.enabled, - rule_name=rule_obj.name, - rule_mandatory=rule_obj.mandatory, - rule_uuid=rule_obj.ruleUuid, - rule_vms=[vm.name for vm in rule_obj.vm], - rule_affinity=True if isinstance(rule_obj, vim.cluster.AffinityRuleSpec) else False, - ) - - # Create - def create(self): - """ - Create a DRS rule if rule does not exist - """ - rule_obj = self.get_rule_key_by_name(rule_name=self.rule_name) - if rule_obj is not None: - existing_rule = self.normalize_rule_spec(rule_obj=rule_obj) - if ((sorted(existing_rule['rule_vms']) == sorted(self.vm_list)) and - (existing_rule['rule_enabled'] == self.enabled) and - (existing_rule['rule_mandatory'] == self.mandatory) and - (existing_rule['rule_affinity'] == self.affinity_rule)): - self.module.exit_json(changed=False, result=existing_rule, msg="Rule already exists with the same configuration") - else: - changed, result = self.update_rule_spec(rule_obj) - return changed, result - else: - changed, result = self.create_rule_spec() - return changed, result - - def create_rule_spec(self): - """ - Create DRS rule - """ - changed = False - if self.affinity_rule: - rule = vim.cluster.AffinityRuleSpec() - else: - rule = vim.cluster.AntiAffinityRuleSpec() - - rule.vm = self.vm_obj_list - rule.enabled = self.enabled - rule.mandatory = self.mandatory - rule.name = self.rule_name - - rule_spec = vim.cluster.RuleSpec(info=rule, operation='add') - config_spec = vim.cluster.ConfigSpecEx(rulesSpec=[rule_spec]) - - try: - task = self.cluster_obj.ReconfigureEx(config_spec, modify=True) - changed, result = wait_for_task(task) - except vmodl.fault.InvalidRequest as e: - result = to_native(e.msg) - except Exception as e: - result = to_native(e) - - if changed: - rule_obj = self.get_rule_key_by_name(rule_name=self.rule_name) - result = self.normalize_rule_spec(rule_obj) - - return changed, result - - def update_rule_spec(self, rule_obj=None): - """ - Update DRS rule - """ - changed = False - - rule_obj.vm = self.vm_obj_list - - if (rule_obj.mandatory != self.mandatory): - rule_obj.mandatory = self.mandatory - - if (rule_obj.enabled != self.enabled): - rule_obj.enabled = self.enabled - - rule_spec = vim.cluster.RuleSpec(info=rule_obj, operation='edit') - config_spec = vim.cluster.ConfigSpec(rulesSpec=[rule_spec]) - - try: - task = self.cluster_obj.ReconfigureCluster_Task(config_spec, modify=True) - changed, result = wait_for_task(task) - except vmodl.fault.InvalidRequest as e: - result = to_native(e.msg) - except Exception as e: - result = to_native(e) - - if changed: - rule_obj = self.get_rule_key_by_name(rule_name=self.rule_name) - result = self.normalize_rule_spec(rule_obj) - - return changed, result - - # Delete - def delete(self, rule_name=None): - """ - Delete DRS rule using name - """ - changed = False - if rule_name is None: - rule_name = self.rule_name - - rule = self.get_rule_key_by_name(rule_name=rule_name) - if rule is not None: - rule_key = int(rule.key) - rule_spec = vim.cluster.RuleSpec(removeKey=rule_key, operation='remove') - config_spec = vim.cluster.ConfigSpecEx(rulesSpec=[rule_spec]) - try: - task = self.cluster_obj.ReconfigureEx(config_spec, modify=True) - changed, result = wait_for_task(task) - except vmodl.fault.InvalidRequest as e: - result = to_native(e.msg) - except Exception as e: - result = to_native(e) - else: - result = 'No rule named %s exists' % self.rule_name - return changed, result - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update(dict( - state=dict(type='str', default='present', choices=['absent', 'present']), - vms=dict(type='list'), - cluster_name=dict(type='str', required=True), - drs_rule_name=dict(type='str', required=True), - enabled=dict(type='bool', default=False), - mandatory=dict(type='bool', default=False), - affinity_rule=dict(type='bool', default=True), - ) - ) - - required_if = [ - ['state', 'present', ['vms']] - ] - module = AnsibleModule(argument_spec=argument_spec, - required_if=required_if, - supports_check_mode=True) - - results = dict(failed=False, changed=False) - state = module.params['state'] - vm_drs = VmwareDrs(module) - - if state == 'present': - # Add Rule - if module.check_mode: - results['changed'] = True - module.exit_json(**results) - changed, result = vm_drs.create() - if changed: - results['changed'] = changed - else: - results['failed'] = True - results['msg'] = "Failed to create DRS rule %s" % vm_drs.rule_name - results['result'] = result - elif state == 'absent': - # Delete Rule - if module.check_mode: - results['changed'] = True - module.exit_json(**results) - changed, result = vm_drs.delete() - if changed: - results['changed'] = changed - results['msg'] = "DRS rule %s deleted successfully." % vm_drs.rule_name - else: - if "No rule named" in result: - results['msg'] = result - module.exit_json(**results) - - results['failed'] = True - results['msg'] = "Failed to delete DRS rule %s" % vm_drs.rule_name - results['result'] = result - - if results['changed']: - module.exit_json(**results) - if results['failed']: - module.fail_json(**results) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_vm_vss_dvs_migrate.py b/lib/ansible/modules/cloud/vmware/vmware_vm_vss_dvs_migrate.py deleted file mode 100644 index 97834f62da..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_vm_vss_dvs_migrate.py +++ /dev/null @@ -1,156 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2015, Joseph Callen <jcallen () csc.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 = ''' ---- -module: vmware_vm_vss_dvs_migrate -short_description: Migrates a virtual machine from a standard vswitch to distributed -description: - - Migrates a virtual machine from a standard vswitch to distributed -version_added: 2.0 -author: -- Joseph Callen (@jcpowermac) -notes: - - Tested on vSphere 5.5 -requirements: - - "python >= 2.6" - - PyVmomi -options: - vm_name: - description: - - Name of the virtual machine to migrate to a dvSwitch - required: True - type: str - dvportgroup_name: - description: - - Name of the portgroup to migrate to the virtual machine to - required: True - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Migrate VCSA to vDS - vmware_vm_vss_dvs_migrate: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - vm_name: '{{ vm_name }}' - dvportgroup_name: '{{ distributed_portgroup_name }}' - delegate_to: localhost -''' - -try: - from pyVmomi import vim, vmodl - HAS_PYVMOMI = True -except ImportError: - HAS_PYVMOMI = False - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import (HAS_PYVMOMI, connect_to_api, get_all_objs, - vmware_argument_spec, wait_for_task) - - -class VMwareVmVssDvsMigrate(object): - def __init__(self, module): - self.module = module - self.content = connect_to_api(module) - self.vm = None - self.vm_name = module.params['vm_name'] - self.dvportgroup_name = module.params['dvportgroup_name'] - - def process_state(self): - vm_nic_states = { - 'absent': self.migrate_network_adapter_vds, - 'present': self.state_exit_unchanged, - } - - vm_nic_states[self.check_vm_network_state()]() - - def find_dvspg_by_name(self): - vmware_distributed_port_group = get_all_objs(self.content, [vim.dvs.DistributedVirtualPortgroup]) - for dvspg in vmware_distributed_port_group: - if dvspg.name == self.dvportgroup_name: - return dvspg - return None - - def find_vm_by_name(self): - virtual_machines = get_all_objs(self.content, [vim.VirtualMachine]) - for vm in virtual_machines: - if vm.name == self.vm_name: - return vm - return None - - def migrate_network_adapter_vds(self): - vm_configspec = vim.vm.ConfigSpec() - nic = vim.vm.device.VirtualEthernetCard.DistributedVirtualPortBackingInfo() - port = vim.dvs.PortConnection() - devicespec = vim.vm.device.VirtualDeviceSpec() - - pg = self.find_dvspg_by_name() - - if pg is None: - self.module.fail_json(msg="The standard portgroup was not found") - - dvswitch = pg.config.distributedVirtualSwitch - port.switchUuid = dvswitch.uuid - port.portgroupKey = pg.key - nic.port = port - - for device in self.vm.config.hardware.device: - if isinstance(device, vim.vm.device.VirtualEthernetCard): - devicespec.device = device - devicespec.operation = vim.vm.device.VirtualDeviceSpec.Operation.edit - devicespec.device.backing = nic - vm_configspec.deviceChange.append(devicespec) - - task = self.vm.ReconfigVM_Task(vm_configspec) - changed, result = wait_for_task(task) - self.module.exit_json(changed=changed, result=result) - - def state_exit_unchanged(self): - self.module.exit_json(changed=False) - - def check_vm_network_state(self): - try: - self.vm = self.find_vm_by_name() - - if self.vm is None: - self.module.fail_json(msg="A virtual machine with name %s does not exist" % self.vm_name) - for device in self.vm.config.hardware.device: - if isinstance(device, vim.vm.device.VirtualEthernetCard): - if isinstance(device.backing, vim.vm.device.VirtualEthernetCard.DistributedVirtualPortBackingInfo): - return 'present' - return 'absent' - 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) - - -def main(): - - argument_spec = vmware_argument_spec() - argument_spec.update(dict(vm_name=dict(required=True, type='str'), - dvportgroup_name=dict(required=True, type='str'))) - - module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False) - if not HAS_PYVMOMI: - module.fail_json(msg='pyvmomi is required for this module') - - vmware_vmnic_migrate = VMwareVmVssDvsMigrate(module) - vmware_vmnic_migrate.process_state() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_vmkernel.py b/lib/ansible/modules/cloud/vmware/vmware_vmkernel.py deleted file mode 100644 index 7dcc85bca1..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_vmkernel.py +++ /dev/null @@ -1,1106 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2015, Joseph Callen <jcallen () csc.com> -# Copyright: (c) 2017-18, Ansible Project -# Copyright: (c) 2017-18, Abhijeet Kasurde <akasurde@redhat.com> -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# 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 = ''' ---- -module: vmware_vmkernel -short_description: Manages a VMware VMkernel Adapter of an ESXi host. -description: - - This module can be used to manage the VMKernel adapters / VMKernel network interfaces of an ESXi host. - - The module assumes that the host is already configured with the Port Group in case of a vSphere Standard Switch (vSS). - - The module assumes that the host is already configured with the Distributed Port Group in case of a vSphere Distributed Switch (vDS). - - The module automatically migrates the VMKernel adapter from vSS to vDS or vice versa if present. -version_added: 2.0 -author: -- Joseph Callen (@jcpowermac) -- Russell Teague (@mtnbikenc) -- Abhijeet Kasurde (@Akasurde) -- Christian Kotte (@ckotte) -notes: - - The option C(device) need to be used with DHCP because otherwise it's not possible to check if a VMkernel device is already present - - You can only change from DHCP to static, and vSS to vDS, or vice versa, in one step, without creating a new device, with C(device) specified. - - You can only create the VMKernel adapter on a vDS if authenticated to vCenter and not if authenticated to ESXi. - - Tested on vSphere 5.5 and 6.5 -requirements: - - "python >= 2.6" - - PyVmomi -options: - vswitch_name: - description: - - The name of the vSwitch where to add the VMKernel interface. - - Required parameter only if C(state) is set to C(present). - - Optional parameter from version 2.5 and onwards. - type: str - aliases: ['vswitch'] - dvswitch_name: - description: - - The name of the vSphere Distributed Switch (vDS) where to add the VMKernel interface. - - Required parameter only if C(state) is set to C(present). - - Optional parameter from version 2.8 and onwards. - type: str - aliases: ['dvswitch'] - version_added: 2.8 - portgroup_name: - description: - - The name of the port group for the VMKernel interface. - required: True - aliases: ['portgroup'] - type: str - network: - description: - - A dictionary of network details. - - 'The following parameter is required:' - - ' - C(type) (string): Type of IP assignment (either C(dhcp) or C(static)).' - - 'The following parameters are required in case of C(type) is set to C(static):' - - ' - C(ip_address) (string): Static IP address (implies C(type: static)).' - - ' - C(subnet_mask) (string): Static netmask required for C(ip_address).' - - 'The following parameter is optional in case of C(type) is set to C(static):' - - ' - C(default_gateway) (string): Default gateway (Override default gateway for this adapter).' - - 'The following parameter is optional:' - - ' - C(tcpip_stack) (string): The TCP/IP stack for the VMKernel interface. Can be default, provisioning, vmotion, or vxlan. (default: default)' - type: dict - default: { - type: 'static', - tcpip_stack: 'default', - } - version_added: 2.5 - mtu: - description: - - The MTU for the VMKernel interface. - - The default value of 1500 is valid from version 2.5 and onwards. - default: 1500 - type: int - device: - description: - - Search VMkernel adapter by device name. - - The parameter is required only in case of C(type) is set to C(dhcp). - version_added: 2.8 - type: str - enable_vsan: - description: - - Enable VSAN traffic on the VMKernel adapter. - - This option is only allowed if the default TCP/IP stack is used. - type: bool - enable_vmotion: - description: - - Enable vMotion traffic on the VMKernel adapter. - - This option is only allowed if the default TCP/IP stack is used. - - You cannot enable vMotion on an additional adapter if you already have an adapter with the vMotion TCP/IP stack configured. - type: bool - enable_mgmt: - description: - - Enable Management traffic on the VMKernel adapter. - - This option is only allowed if the default TCP/IP stack is used. - type: bool - enable_ft: - description: - - Enable Fault Tolerance traffic on the VMKernel adapter. - - This option is only allowed if the default TCP/IP stack is used. - type: bool - enable_provisioning: - description: - - Enable Provisioning traffic on the VMKernel adapter. - - This option is only allowed if the default TCP/IP stack is used. - type: bool - version_added: 2.8 - enable_replication: - description: - - Enable vSphere Replication traffic on the VMKernel adapter. - - This option is only allowed if the default TCP/IP stack is used. - type: bool - version_added: 2.8 - enable_replication_nfc: - description: - - Enable vSphere Replication NFC traffic on the VMKernel adapter. - - This option is only allowed if the default TCP/IP stack is used. - type: bool - version_added: 2.8 - state: - description: - - If set to C(present), the VMKernel adapter will be created with the given specifications. - - If set to C(absent), the VMKernel adapter will be removed. - - If set to C(present) and VMKernel adapter exists, the configurations will be updated. - choices: [ present, absent ] - default: present - version_added: 2.5 - type: str - esxi_hostname: - description: - - Name of ESXi host to which VMKernel is to be managed. - - "From version 2.5 onwards, this parameter is required." - required: True - version_added: 2.5 - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Add Management vmkernel port using static network type - vmware_vmkernel: - hostname: '{{ esxi_hostname }}' - username: '{{ esxi_username }}' - password: '{{ esxi_password }}' - esxi_hostname: '{{ esxi_hostname }}' - vswitch_name: vSwitch0 - portgroup_name: PG_0001 - network: - type: 'static' - ip_address: 192.168.127.10 - subnet_mask: 255.255.255.0 - state: present - enable_mgmt: True - delegate_to: localhost - -- name: Add Management vmkernel port using DHCP network type - vmware_vmkernel: - hostname: '{{ esxi_hostname }}' - username: '{{ esxi_username }}' - password: '{{ esxi_password }}' - esxi_hostname: '{{ esxi_hostname }}' - vswitch_name: vSwitch0 - portgroup_name: PG_0002 - state: present - network: - type: 'dhcp' - enable_mgmt: True - delegate_to: localhost - -- name: Change IP allocation from static to dhcp - vmware_vmkernel: - hostname: '{{ esxi_hostname }}' - username: '{{ esxi_username }}' - password: '{{ esxi_password }}' - esxi_hostname: '{{ esxi_hostname }}' - vswitch_name: vSwitch0 - portgroup_name: PG_0002 - state: present - device: vmk1 - network: - type: 'dhcp' - enable_mgmt: True - delegate_to: localhost - -- name: Delete VMkernel port - vmware_vmkernel: - hostname: '{{ esxi_hostname }}' - username: '{{ esxi_username }}' - password: '{{ esxi_password }}' - esxi_hostname: '{{ esxi_hostname }}' - vswitch_name: vSwitch0 - portgroup_name: PG_0002 - state: absent - delegate_to: localhost - -- name: Add Management vmkernel port to Distributed Switch - vmware_vmkernel: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - dvswitch_name: dvSwitch1 - portgroup_name: dvPG_0001 - network: - type: 'static' - ip_address: 192.168.127.10 - subnet_mask: 255.255.255.0 - state: present - enable_mgmt: True - delegate_to: localhost - -- name: Add vMotion vmkernel port with vMotion TCP/IP stack - vmware_vmkernel: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - dvswitch_name: dvSwitch1 - portgroup_name: dvPG_0001 - network: - type: 'static' - ip_address: 192.168.127.10 - subnet_mask: 255.255.255.0 - tcpip_stack: vmotion - state: present - delegate_to: localhost -''' - -RETURN = r''' -result: - description: metadata about VMKernel name - returned: always - type: dict - sample: { - "changed": false, - "msg": "VMkernel Adapter already configured properly", - "device": "vmk1", - "ipv4": "static", - "ipv4_gw": "No override", - "ipv4_ip": "192.168.1.15", - "ipv4_sm": "255.255.255.0", - "mtu": 9000, - "services": "vMotion", - "switch": "vDS" - } -''' - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import ( - PyVmomi, TaskError, vmware_argument_spec, wait_for_task, - find_dvspg_by_name, find_dvs_by_name, get_all_objs -) -from ansible.module_utils._text import to_native - - -class PyVmomiHelper(PyVmomi): - """Class to manage VMkernel configuration of an ESXi host system""" - - def __init__(self, module): - super(PyVmomiHelper, self).__init__(module) - if self.params['network']: - self.network_type = self.params['network'].get('type') - self.ip_address = self.params['network'].get('ip_address', None) - self.subnet_mask = self.params['network'].get('subnet_mask', None) - self.default_gateway = self.params['network'].get('default_gateway', None) - self.tcpip_stack = self.params['network'].get('tcpip_stack') - self.device = self.params['device'] - if self.network_type == 'dhcp' and not self.device: - module.fail_json(msg="device is a required parameter when network type is set to 'dhcp'") - self.mtu = self.params['mtu'] - self.enable_vsan = self.params['enable_vsan'] - self.enable_vmotion = self.params['enable_vmotion'] - self.enable_mgmt = self.params['enable_mgmt'] - self.enable_ft = self.params['enable_ft'] - self.enable_provisioning = self.params['enable_provisioning'] - self.enable_replication = self.params['enable_replication'] - self.enable_replication_nfc = self.params['enable_replication_nfc'] - - self.vswitch_name = self.params['vswitch_name'] - self.vds_name = self.params['dvswitch_name'] - self.port_group_name = self.params['portgroup_name'] - - self.esxi_host_name = self.params['esxi_hostname'] - hosts = self.get_all_host_objs(esxi_host_name=self.esxi_host_name) - if hosts: - self.esxi_host_obj = hosts[0] - else: - self.module.fail_json( - msg="Failed to get details of ESXi server. Please specify esxi_hostname." - ) - - if self.network_type == 'static': - if self.module.params['state'] == 'absent': - pass - elif not self.ip_address: - module.fail_json(msg="ip_address is a required parameter when network type is set to 'static'") - elif not self.subnet_mask: - module.fail_json(msg="subnet_mask is a required parameter when network type is set to 'static'") - - # find Port Group - if self.vswitch_name: - self.port_group_obj = self.get_port_group_by_name( - host_system=self.esxi_host_obj, - portgroup_name=self.port_group_name, - vswitch_name=self.vswitch_name - ) - if not self.port_group_obj: - module.fail_json(msg="Portgroup '%s' not found on vSS '%s'" % (self.port_group_name, self.vswitch_name)) - elif self.vds_name: - self.dv_switch_obj = find_dvs_by_name(self.content, self.vds_name) - if not self.dv_switch_obj: - module.fail_json(msg="vDS '%s' not found" % self.vds_name) - self.port_group_obj = find_dvspg_by_name(self.dv_switch_obj, self.port_group_name) - if not self.port_group_obj: - module.fail_json(msg="Portgroup '%s' not found on vDS '%s'" % (self.port_group_name, self.vds_name)) - - # find VMkernel Adapter - if self.device: - self.vnic = self.get_vmkernel_by_device(device_name=self.device) - else: - # config change (e.g. DHCP to static, or vice versa); doesn't work with virtual port change - self.vnic = self.get_vmkernel_by_portgroup_new(port_group_name=self.port_group_name) - if not self.vnic and self.network_type == 'static': - # vDS to vSS or vSS to vSS (static IP) - self.vnic = self.get_vmkernel_by_ip(ip_address=self.ip_address) - - def get_port_group_by_name(self, host_system, portgroup_name, vswitch_name): - """ - Get specific port group by given name - Args: - host_system: Name of Host System - portgroup_name: Name of Port Group - vswitch_name: Name of the vSwitch - - Returns: List of port groups by given specifications - - """ - portgroups = self.get_all_port_groups_by_host(host_system=host_system) - - for portgroup in portgroups: - if portgroup.spec.vswitchName == vswitch_name and portgroup.spec.name == portgroup_name: - return portgroup - return None - - def ensure(self): - """ - Manage internal VMKernel management - Returns: NA - - """ - host_vmk_states = { - 'absent': { - 'present': self.host_vmk_delete, - 'absent': self.host_vmk_unchange, - }, - 'present': { - 'present': self.host_vmk_update, - 'absent': self.host_vmk_create, - } - } - - try: - host_vmk_states[self.module.params['state']][self.check_state()]() - except vmodl.RuntimeFault as runtime_fault: - self.module.fail_json(msg=to_native(runtime_fault.msg)) - except vmodl.MethodFault as method_fault: - self.module.fail_json(msg=to_native(method_fault.msg)) - - def get_vmkernel_by_portgroup_new(self, port_group_name=None): - """ - Check if vmkernel available or not - Args: - port_group_name: name of port group - - Returns: vmkernel managed object if vmkernel found, false if not - - """ - for vnic in self.esxi_host_obj.config.network.vnic: - # check if it's a vSS Port Group - if vnic.spec.portgroup == port_group_name: - return vnic - # check if it's a vDS Port Group - try: - if vnic.spec.distributedVirtualPort.portgroupKey == self.port_group_obj.key: - return vnic - except AttributeError: - pass - return False - - def get_vmkernel_by_ip(self, ip_address): - """ - Check if vmkernel available or not - Args: - ip_address: IP address of vmkernel device - - Returns: vmkernel managed object if vmkernel found, false if not - - """ - for vnic in self.esxi_host_obj.config.network.vnic: - if vnic.spec.ip.ipAddress == ip_address: - return vnic - return None - - def get_vmkernel_by_device(self, device_name): - """ - Check if vmkernel available or not - Args: - device_name: name of vmkernel device - - Returns: vmkernel managed object if vmkernel found, false if not - - """ - for vnic in self.esxi_host_obj.config.network.vnic: - if vnic.device == device_name: - return vnic - return None - - def check_state(self): - """ - Check internal state management - Returns: Present if found and absent if not found - - """ - return 'present' if self.vnic else 'absent' - - def host_vmk_delete(self): - """ - Delete VMKernel - Returns: NA - - """ - results = dict(changed=False, msg='') - vmk_device = self.vnic.device - try: - if self.module.check_mode: - results['msg'] = "VMkernel Adapter would be deleted" - else: - self.esxi_host_obj.configManager.networkSystem.RemoveVirtualNic(vmk_device) - results['msg'] = "VMkernel Adapter deleted" - results['changed'] = True - results['device'] = vmk_device - except vim.fault.NotFound as not_found: - self.module.fail_json( - msg="Failed to find vmk to delete due to %s" % - to_native(not_found.msg) - ) - except vim.fault.HostConfigFault as host_config_fault: - self.module.fail_json( - msg="Failed to delete vmk due host config issues : %s" % - to_native(host_config_fault.msg) - ) - - self.module.exit_json(**results) - - def host_vmk_unchange(self): - """ - Denote no change in VMKernel - Returns: NA - - """ - self.module.exit_json(changed=False) - - def host_vmk_update(self): - """ - Update VMKernel with given parameters - Returns: NA - - """ - changed = changed_settings = changed_vds = changed_services = \ - changed_service_vmotion = changed_service_mgmt = changed_service_ft = \ - changed_service_vsan = changed_service_prov = changed_service_rep = changed_service_rep_nfc = False - changed_list = [] - results = dict(changed=False, msg='') - - results['tcpip_stack'] = self.tcpip_stack - net_stack_instance_key = self.get_api_net_stack_instance(self.tcpip_stack) - if self.vnic.spec.netStackInstanceKey != net_stack_instance_key: - self.module.fail_json(msg="The TCP/IP stack cannot be changed on an existing VMkernel adapter!") - - # Check MTU - results['mtu'] = self.mtu - if self.vnic.spec.mtu != self.mtu: - changed_settings = True - changed_list.append("MTU") - results['mtu_previous'] = self.vnic.spec.mtu - - # Check IPv4 settings - results['ipv4'] = self.network_type - results['ipv4_ip'] = self.ip_address - results['ipv4_sm'] = self.subnet_mask - if self.default_gateway: - results['ipv4_gw'] = self.default_gateway - else: - results['ipv4_gw'] = "No override" - if self.vnic.spec.ip.dhcp: - if self.network_type == 'static': - changed_settings = True - changed_list.append("IPv4 settings") - results['ipv4_previous'] = "DHCP" - if not self.vnic.spec.ip.dhcp: - if self.network_type == 'dhcp': - changed_settings = True - changed_list.append("IPv4 settings") - results['ipv4_previous'] = "static" - elif self.network_type == 'static': - if self.ip_address != self.vnic.spec.ip.ipAddress: - changed_settings = True - changed_list.append("IP") - results['ipv4_ip_previous'] = self.vnic.spec.ip.ipAddress - if self.subnet_mask != self.vnic.spec.ip.subnetMask: - changed_settings = True - changed_list.append("SM") - results['ipv4_sm_previous'] = self.vnic.spec.ip.subnetMask - if self.default_gateway: - try: - if self.default_gateway != self.vnic.spec.ipRouteSpec.ipRouteConfig.defaultGateway: - changed_settings = True - changed_list.append("GW override") - results['ipv4_gw_previous'] = self.vnic.spec.ipRouteSpec.ipRouteConfig.defaultGateway - except AttributeError: - changed_settings = True - changed_list.append("GW override") - results['ipv4_gw_previous'] = "No override" - else: - try: - if self.vnic.spec.ipRouteSpec.ipRouteConfig.defaultGateway: - changed_settings = True - changed_list.append("GW override") - results['ipv4_gw_previous'] = self.vnic.spec.ipRouteSpec.ipRouteConfig.defaultGateway - except AttributeError: - pass - - # Check virtual port (vSS or vDS) - results['portgroup'] = self.port_group_name - dvs_uuid = None - if self.vswitch_name: - results['switch'] = self.vswitch_name - try: - if self.vnic.spec.distributedVirtualPort.switchUuid: - changed_vds = True - changed_list.append("Virtual Port") - dvs_uuid = self.vnic.spec.distributedVirtualPort.switchUuid - except AttributeError: - pass - if changed_vds: - results['switch_previous'] = self.find_dvs_by_uuid(dvs_uuid) - self.dv_switch_obj = find_dvs_by_name(self.content, results['switch_previous']) - results['portgroup_previous'] = self.find_dvspg_by_key( - self.dv_switch_obj, self.vnic.spec.distributedVirtualPort.portgroupKey - ) - elif self.vds_name: - results['switch'] = self.vds_name - try: - if self.vnic.spec.distributedVirtualPort.switchUuid != self.dv_switch_obj.uuid: - changed_vds = True - changed_list.append("Virtual Port") - dvs_uuid = self.vnic.spec.distributedVirtualPort.switchUuid - except AttributeError: - changed_vds = True - changed_list.append("Virtual Port") - if changed_vds: - results['switch_previous'] = self.find_dvs_by_uuid(dvs_uuid) - results['portgroup_previous'] = self.vnic.spec.portgroup - portgroups = self.get_all_port_groups_by_host(host_system=self.esxi_host_obj) - for portgroup in portgroups: - if portgroup.spec.name == self.vnic.spec.portgroup: - results['switch_previous'] = portgroup.spec.vswitchName - - results['services'] = self.create_enabled_services_string() - # Check configuration of service types (only if default TCP/IP stack is used) - if self.vnic.spec.netStackInstanceKey == 'defaultTcpipStack': - service_type_vmks = self.get_all_vmks_by_service_type() - if (self.enable_vmotion and self.vnic.device not in service_type_vmks['vmotion']) or \ - (not self.enable_vmotion and self.vnic.device in service_type_vmks['vmotion']): - changed_services = changed_service_vmotion = True - - if (self.enable_mgmt and self.vnic.device not in service_type_vmks['management']) or \ - (not self.enable_mgmt and self.vnic.device in service_type_vmks['management']): - changed_services = changed_service_mgmt = True - - if (self.enable_ft and self.vnic.device not in service_type_vmks['faultToleranceLogging']) or \ - (not self.enable_ft and self.vnic.device in service_type_vmks['faultToleranceLogging']): - changed_services = changed_service_ft = True - - if (self.enable_vsan and self.vnic.device not in service_type_vmks['vsan']) or \ - (not self.enable_vsan and self.vnic.device in service_type_vmks['vsan']): - changed_services = changed_service_vsan = True - - if (self.enable_provisioning and self.vnic.device not in service_type_vmks['vSphereProvisioning']) or \ - (not self.enable_provisioning and self.vnic.device in service_type_vmks['vSphereProvisioning']): - changed_services = changed_service_prov = True - - if (self.enable_replication and self.vnic.device not in service_type_vmks['vSphereReplication']) or \ - (not self.enable_provisioning and self.vnic.device in service_type_vmks['vSphereReplication']): - changed_services = changed_service_rep = True - - if (self.enable_replication_nfc and self.vnic.device not in service_type_vmks['vSphereReplicationNFC']) or \ - (not self.enable_provisioning and self.vnic.device in service_type_vmks['vSphereReplicationNFC']): - changed_services = changed_service_rep_nfc = True - if changed_services: - changed_list.append("services") - - if changed_settings or changed_vds or changed_services: - changed = True - if self.module.check_mode: - changed_suffix = ' would be updated' - else: - changed_suffix = ' updated' - if len(changed_list) > 2: - message = ', '.join(changed_list[:-1]) + ', and ' + str(changed_list[-1]) - elif len(changed_list) == 2: - message = ' and '.join(changed_list) - elif len(changed_list) == 1: - message = changed_list[0] - message = "VMkernel Adapter " + message + changed_suffix - if changed_settings or changed_vds: - vnic_config = vim.host.VirtualNic.Specification() - ip_spec = vim.host.IpConfig() - if self.network_type == 'dhcp': - ip_spec.dhcp = True - else: - ip_spec.dhcp = False - ip_spec.ipAddress = self.ip_address - ip_spec.subnetMask = self.subnet_mask - if self.default_gateway: - vnic_config.ipRouteSpec = vim.host.VirtualNic.IpRouteSpec() - vnic_config.ipRouteSpec.ipRouteConfig = vim.host.IpRouteConfig() - vnic_config.ipRouteSpec.ipRouteConfig.defaultGateway = self.default_gateway - else: - vnic_config.ipRouteSpec = vim.host.VirtualNic.IpRouteSpec() - vnic_config.ipRouteSpec.ipRouteConfig = vim.host.IpRouteConfig() - - vnic_config.ip = ip_spec - vnic_config.mtu = self.mtu - - if changed_vds: - if self.vswitch_name: - vnic_config.portgroup = self.port_group_name - elif self.vds_name: - vnic_config.distributedVirtualPort = vim.dvs.PortConnection() - vnic_config.distributedVirtualPort.switchUuid = self.dv_switch_obj.uuid - vnic_config.distributedVirtualPort.portgroupKey = self.port_group_obj.key - - try: - if not self.module.check_mode: - self.esxi_host_obj.configManager.networkSystem.UpdateVirtualNic(self.vnic.device, vnic_config) - except vim.fault.NotFound as not_found: - self.module.fail_json( - msg="Failed to update vmk as virtual network adapter cannot be found %s" % - to_native(not_found.msg) - ) - except vim.fault.HostConfigFault as host_config_fault: - self.module.fail_json( - msg="Failed to update vmk due to host config issues : %s" % - to_native(host_config_fault.msg) - ) - except vim.fault.InvalidState as invalid_state: - self.module.fail_json( - msg="Failed to update vmk as ipv6 address is specified in an ipv4 only system : %s" % - to_native(invalid_state.msg) - ) - except vmodl.fault.InvalidArgument as invalid_arg: - self.module.fail_json( - msg="Failed to update vmk as IP address or Subnet Mask in the IP configuration" - "are invalid or PortGroup does not exist : %s" % to_native(invalid_arg.msg) - ) - - if changed_services: - changed_list.append("Services") - services_previous = [] - vnic_manager = self.esxi_host_obj.configManager.virtualNicManager - - if changed_service_mgmt: - if self.vnic.device in service_type_vmks['management']: - services_previous.append('Mgmt') - operation = 'select' if self.enable_mgmt else 'deselect' - self.set_service_type( - vnic_manager=vnic_manager, vmk=self.vnic, service_type='management', operation=operation - ) - - if changed_service_vmotion: - if self.vnic.device in service_type_vmks['vmotion']: - services_previous.append('vMotion') - operation = 'select' if self.enable_vmotion else 'deselect' - self.set_service_type( - vnic_manager=vnic_manager, vmk=self.vnic, service_type='vmotion', operation=operation - ) - - if changed_service_ft: - if self.vnic.device in service_type_vmks['faultToleranceLogging']: - services_previous.append('FT') - operation = 'select' if self.enable_ft else 'deselect' - self.set_service_type( - vnic_manager=vnic_manager, vmk=self.vnic, service_type='faultToleranceLogging', operation=operation - ) - - if changed_service_prov: - if self.vnic.device in service_type_vmks['vSphereProvisioning']: - services_previous.append('Prov') - operation = 'select' if self.enable_provisioning else 'deselect' - self.set_service_type( - vnic_manager=vnic_manager, vmk=self.vnic, service_type='vSphereProvisioning', operation=operation - ) - - if changed_service_rep: - if self.vnic.device in service_type_vmks['vSphereReplication']: - services_previous.append('Repl') - operation = 'select' if self.enable_replication else 'deselect' - self.set_service_type( - vnic_manager=vnic_manager, vmk=self.vnic, service_type='vSphereReplication', operation=operation - ) - - if changed_service_rep_nfc: - if self.vnic.device in service_type_vmks['vSphereReplicationNFC']: - services_previous.append('Repl_NFC') - operation = 'select' if self.enable_replication_nfc else 'deselect' - self.set_service_type( - vnic_manager=vnic_manager, vmk=self.vnic, service_type='vSphereReplicationNFC', operation=operation - ) - - if changed_service_vsan: - if self.vnic.device in service_type_vmks['vsan']: - services_previous.append('VSAN') - if self.enable_vsan: - results['vsan'] = self.set_vsan_service_type() - else: - self.set_service_type( - vnic_manager=vnic_manager, vmk=self.vnic, service_type='vsan', operation=operation - ) - - results['services_previous'] = ', '.join(services_previous) - else: - message = "VMkernel Adapter already configured properly" - - results['changed'] = changed - results['msg'] = message - results['device'] = self.vnic.device - self.module.exit_json(**results) - - def find_dvs_by_uuid(self, uuid): - """ - Find DVS by UUID - Returns: DVS name - """ - dvs_list = get_all_objs(self.content, [vim.DistributedVirtualSwitch]) - for dvs in dvs_list: - if dvs.uuid == uuid: - return dvs.summary.name - return None - - def find_dvspg_by_key(self, dv_switch, portgroup_key): - """ - Find dvPortgroup by key - Returns: dvPortgroup name - """ - - portgroups = dv_switch.portgroup - - for portgroup in portgroups: - if portgroup.key == portgroup_key: - return portgroup.name - - return None - - def set_vsan_service_type(self): - """ - Set VSAN service type - Returns: result of UpdateVsan_Task - - """ - result = None - vsan_system = self.esxi_host_obj.configManager.vsanSystem - - vsan_port_config = vim.vsan.host.ConfigInfo.NetworkInfo.PortConfig() - vsan_port_config.device = self.vnic.device - - vsan_config = vim.vsan.host.ConfigInfo() - vsan_config.networkInfo = vim.vsan.host.ConfigInfo.NetworkInfo() - vsan_config.networkInfo.port = [vsan_port_config] - if not self.module.check_mode: - try: - vsan_task = vsan_system.UpdateVsan_Task(vsan_config) - wait_for_task(vsan_task) - except TaskError as task_err: - self.module.fail_json( - msg="Failed to set service type to vsan for %s : %s" % (self.vnic.device, to_native(task_err)) - ) - return result - - def host_vmk_create(self): - """ - Create VMKernel - Returns: NA - - """ - results = dict(changed=False, message='') - if self.vswitch_name: - results['switch'] = self.vswitch_name - elif self.vds_name: - results['switch'] = self.vds_name - results['portgroup'] = self.port_group_name - - vnic_config = vim.host.VirtualNic.Specification() - - ip_spec = vim.host.IpConfig() - results['ipv4'] = self.network_type - if self.network_type == 'dhcp': - ip_spec.dhcp = True - else: - ip_spec.dhcp = False - results['ipv4_ip'] = self.ip_address - results['ipv4_sm'] = self.subnet_mask - ip_spec.ipAddress = self.ip_address - ip_spec.subnetMask = self.subnet_mask - if self.default_gateway: - vnic_config.ipRouteSpec = vim.host.VirtualNic.IpRouteSpec() - vnic_config.ipRouteSpec.ipRouteConfig = vim.host.IpRouteConfig() - vnic_config.ipRouteSpec.ipRouteConfig.defaultGateway = self.default_gateway - vnic_config.ip = ip_spec - - results['mtu'] = self.mtu - vnic_config.mtu = self.mtu - - results['tcpip_stack'] = self.tcpip_stack - vnic_config.netStackInstanceKey = self.get_api_net_stack_instance(self.tcpip_stack) - - vmk_device = None - try: - if self.module.check_mode: - results['msg'] = "VMkernel Adapter would be created" - else: - if self.vswitch_name: - vmk_device = self.esxi_host_obj.configManager.networkSystem.AddVirtualNic( - self.port_group_name, - vnic_config - ) - elif self.vds_name: - vnic_config.distributedVirtualPort = vim.dvs.PortConnection() - vnic_config.distributedVirtualPort.switchUuid = self.dv_switch_obj.uuid - vnic_config.distributedVirtualPort.portgroupKey = self.port_group_obj.key - vmk_device = self.esxi_host_obj.configManager.networkSystem.AddVirtualNic(portgroup="", nic=vnic_config) - results['msg'] = "VMkernel Adapter created" - results['changed'] = True - results['device'] = vmk_device - if self.network_type != 'dhcp': - if self.default_gateway: - results['ipv4_gw'] = self.default_gateway - else: - results['ipv4_gw'] = "No override" - results['services'] = self.create_enabled_services_string() - except vim.fault.AlreadyExists as already_exists: - self.module.fail_json( - msg="Failed to add vmk as portgroup already has a virtual network adapter %s" % - to_native(already_exists.msg) - ) - except vim.fault.HostConfigFault as host_config_fault: - self.module.fail_json( - msg="Failed to add vmk due to host config issues : %s" % - to_native(host_config_fault.msg) - ) - except vim.fault.InvalidState as invalid_state: - self.module.fail_json( - msg="Failed to add vmk as ipv6 address is specified in an ipv4 only system : %s" % - to_native(invalid_state.msg) - ) - except vmodl.fault.InvalidArgument as invalid_arg: - self.module.fail_json( - msg="Failed to add vmk as IP address or Subnet Mask in the IP configuration " - "are invalid or PortGroup does not exist : %s" % to_native(invalid_arg.msg) - ) - - # do service type configuration - if self.tcpip_stack == 'default' and not all( - option is False for option in [self.enable_vsan, self.enable_vmotion, - self.enable_mgmt, self.enable_ft, - self.enable_provisioning, self.enable_replication, - self.enable_replication_nfc]): - self.vnic = self.get_vmkernel_by_device(device_name=vmk_device) - - # VSAN - if self.enable_vsan: - results['vsan'] = self.set_vsan_service_type() - - # Other service type - host_vnic_manager = self.esxi_host_obj.configManager.virtualNicManager - if self.enable_vmotion: - self.set_service_type(host_vnic_manager, self.vnic, 'vmotion') - - if self.enable_mgmt: - self.set_service_type(host_vnic_manager, self.vnic, 'management') - - if self.enable_ft: - self.set_service_type(host_vnic_manager, self.vnic, 'faultToleranceLogging') - - if self.enable_provisioning: - self.set_service_type(host_vnic_manager, self.vnic, 'vSphereProvisioning') - - if self.enable_replication: - self.set_service_type(host_vnic_manager, self.vnic, 'vSphereReplication') - - if self.enable_replication_nfc: - self.set_service_type(host_vnic_manager, self.vnic, 'vSphereReplicationNFC') - - self.module.exit_json(**results) - - def set_service_type(self, vnic_manager, vmk, service_type, operation='select'): - """ - Set service type to given VMKernel - Args: - vnic_manager: Virtual NIC manager object - vmk: VMkernel managed object - service_type: Name of service type - operation: Select to select service type, deselect to deselect service type - - """ - try: - if operation == 'select': - if not self.module.check_mode: - vnic_manager.SelectVnicForNicType(service_type, vmk.device) - elif operation == 'deselect': - if not self.module.check_mode: - vnic_manager.DeselectVnicForNicType(service_type, vmk.device) - except vmodl.fault.InvalidArgument as invalid_arg: - self.module.fail_json( - msg="Failed to %s VMK service type '%s' on '%s' due to : %s" % - (operation, service_type, vmk.device, to_native(invalid_arg.msg)) - ) - - def get_all_vmks_by_service_type(self): - """ - Return information about service types and VMKernel - Returns: Dictionary of service type as key and VMKernel list as value - - """ - service_type_vmk = dict( - vmotion=[], - vsan=[], - management=[], - faultToleranceLogging=[], - vSphereProvisioning=[], - vSphereReplication=[], - vSphereReplicationNFC=[], - ) - - for service_type in list(service_type_vmk): - vmks_list = self.query_service_type_for_vmks(service_type) - service_type_vmk[service_type] = vmks_list - return service_type_vmk - - def query_service_type_for_vmks(self, service_type): - """ - Return list of VMKernels - Args: - service_type: Name of service type - - Returns: List of VMKernel which belongs to that service type - - """ - vmks_list = [] - query = None - try: - query = self.esxi_host_obj.configManager.virtualNicManager.QueryNetConfig(service_type) - except vim.fault.HostConfigFault as config_fault: - self.module.fail_json( - msg="Failed to get all VMKs for service type %s due to host config fault : %s" % - (service_type, to_native(config_fault.msg)) - ) - except vmodl.fault.InvalidArgument as invalid_argument: - self.module.fail_json( - msg="Failed to get all VMKs for service type %s due to invalid arguments : %s" % - (service_type, to_native(invalid_argument.msg)) - ) - - if not query.selectedVnic: - return vmks_list - selected_vnics = [vnic for vnic in query.selectedVnic] - vnics_with_service_type = [vnic.device for vnic in query.candidateVnic if vnic.key in selected_vnics] - return vnics_with_service_type - - def create_enabled_services_string(self): - """Create services list""" - services = [] - if self.enable_mgmt: - services.append('Mgmt') - if self.enable_vmotion: - services.append('vMotion') - if self.enable_ft: - services.append('FT') - if self.enable_vsan: - services.append('VSAN') - if self.enable_provisioning: - services.append('Prov') - if self.enable_replication: - services.append('Repl') - if self.enable_replication_nfc: - services.append('Repl_NFC') - return ', '.join(services) - - @staticmethod - def get_api_net_stack_instance(tcpip_stack): - """Get TCP/IP stack instance name or key""" - net_stack_instance = None - if tcpip_stack == 'default': - net_stack_instance = 'defaultTcpipStack' - elif tcpip_stack == 'provisioning': - net_stack_instance = 'vSphereProvisioning' - # vmotion and vxlan stay the same - elif tcpip_stack == 'vmotion': - net_stack_instance = 'vmotion' - elif tcpip_stack == 'vxlan': - net_stack_instance = 'vxlan' - elif tcpip_stack == 'defaultTcpipStack': - net_stack_instance = 'default' - elif tcpip_stack == 'vSphereProvisioning': - net_stack_instance = 'provisioning' - # vmotion and vxlan stay the same - elif tcpip_stack == 'vmotion': - net_stack_instance = 'vmotion' - elif tcpip_stack == 'vxlan': - net_stack_instance = 'vxlan' - return net_stack_instance - - -def main(): - """Main""" - argument_spec = vmware_argument_spec() - argument_spec.update(dict( - esxi_hostname=dict(required=True, type='str'), - portgroup_name=dict(required=True, type='str', aliases=['portgroup']), - mtu=dict(required=False, type='int', default=1500), - device=dict(type='str'), - enable_vsan=dict(required=False, type='bool', default=False), - enable_vmotion=dict(required=False, type='bool', default=False), - enable_mgmt=dict(required=False, type='bool', default=False), - enable_ft=dict(required=False, type='bool', default=False), - enable_provisioning=dict(type='bool', default=False), - enable_replication=dict(type='bool', default=False), - enable_replication_nfc=dict(type='bool', default=False), - vswitch_name=dict(required=False, type='str', aliases=['vswitch']), - dvswitch_name=dict(required=False, type='str', aliases=['dvswitch']), - network=dict( - type='dict', - options=dict( - type=dict(type='str', default='static', choices=['static', 'dhcp']), - ip_address=dict(type='str'), - subnet_mask=dict(type='str'), - default_gateway=dict(type='str'), - tcpip_stack=dict(type='str', default='default', choices=['default', 'provisioning', 'vmotion', 'vxlan']), - ), - default=dict( - type='static', - tcpip_stack='default', - ), - ), - state=dict( - type='str', - default='present', - choices=['absent', 'present'] - ), - )) - - module = AnsibleModule(argument_spec=argument_spec, - mutually_exclusive=[ - ['vswitch_name', 'dvswitch_name'], - ['tcpip_stack', 'enable_vsan'], - ['tcpip_stack', 'enable_vmotion'], - ['tcpip_stack', 'enable_mgmt'], - ['tcpip_stack', 'enable_ft'], - ['tcpip_stack', 'enable_provisioning'], - ['tcpip_stack', 'enable_replication'], - ['tcpip_stack', 'enable_replication_nfc'], - ], - required_one_of=[ - ['vswitch_name', 'dvswitch_name'], - ['portgroup_name', 'device'], - ], - required_if=[ - ['state', 'present', ['portgroup_name']], - ['state', 'absent', ['device']] - ], - supports_check_mode=True) - - pyv = PyVmomiHelper(module) - pyv.ensure() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_vmkernel_info.py b/lib/ansible/modules/cloud/vmware/vmware_vmkernel_info.py deleted file mode 100644 index af4bdf591d..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_vmkernel_info.py +++ /dev/null @@ -1,203 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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_vmkernel_info -short_description: Gathers VMKernel info about an ESXi host -description: -- This module can be used to gather VMKernel information about an ESXi host from given ESXi hostname or cluster name. -version_added: '2.9' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of the cluster. - - VMKernel information about each ESXi server will be returned for the given cluster. - - If C(esxi_hostname) is not given, this parameter is required. - type: str - esxi_hostname: - description: - - ESXi hostname. - - VMKernel information about this ESXi server will be returned. - - If C(cluster_name) is not given, this parameter is required. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather VMKernel info about all ESXi Host in given Cluster - vmware_vmkernel_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: cluster_name - delegate_to: localhost - register: cluster_host_vmks - -- name: Gather VMKernel info about ESXi Host - vmware_vmkernel_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - delegate_to: localhost - register: host_vmks -''' - -RETURN = r''' -host_vmk_info: - description: metadata about VMKernel present on given host system - returned: success - type: dict - sample: - { - "10.76.33.208": [ - { - "device": "vmk0", - "dhcp": true, - "enable_ft": false, - "enable_management": true, - "enable_vmotion": false, - "enable_vsan": false, - "ipv4_address": "10.76.33.28", - "ipv4_subnet_mask": "255.255.255.0", - "key": "key-vim.host.VirtualNic-vmk0", - "mac": "52:54:00:12:50:ce", - "mtu": 1500, - "portgroup": "Management Network", - "stack": "defaultTcpipStack" - }, - ] - } - -''' - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi -from ansible.module_utils._text import to_native - - -class VmkernelInfoManager(PyVmomi): - def __init__(self, module): - super(VmkernelInfoManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - self.service_type_vmks = dict() - self.get_all_vmks_by_service_type() - - def get_all_vmks_by_service_type(self): - """ - Function to return information about service types and VMKernel - - """ - for host in self.hosts: - self.service_type_vmks[host.name] = dict(vmotion=[], vsan=[], management=[], faultToleranceLogging=[]) - for service_type in self.service_type_vmks[host.name].keys(): - vmks_list = self.query_service_type_for_vmks(host, service_type) - self.service_type_vmks[host.name][service_type] = vmks_list - - def query_service_type_for_vmks(self, host_system, service_type): - """ - Function to return list of VMKernels - Args: - host_system: Host system managed object - service_type: Name of service type - - Returns: List of VMKernel which belongs to that service type - - """ - vmks_list = [] - query = None - try: - query = host_system.configManager.virtualNicManager.QueryNetConfig(service_type) - except vim.fault.HostConfigFault as config_fault: - self.module.fail_json(msg="Failed to get all VMKs for service type %s due to" - " host config fault : %s" % (service_type, to_native(config_fault.msg))) - except vmodl.fault.InvalidArgument as invalid_argument: - self.module.fail_json(msg="Failed to get all VMKs for service type %s due to" - " invalid arguments : %s" % (service_type, to_native(invalid_argument.msg))) - except Exception as e: - self.module.fail_json(msg="Failed to get all VMKs for service type %s due to" - "%s" % (service_type, to_native(e))) - - if not query or not query.selectedVnic: - return vmks_list - selected_vnics = [vnic for vnic in query.selectedVnic] - vnics_with_service_type = [vnic.device for vnic in query.candidateVnic if vnic.key in selected_vnics] - return vnics_with_service_type - - def gather_host_vmk_info(self): - hosts_info = {} - - for host in self.hosts: - host_vmk_info = [] - host_network_system = host.config.network - if host_network_system: - vmks_config = host.config.network.vnic - for vmk in vmks_config: - host_vmk_info.append(dict( - device=vmk.device, - key=vmk.key, - portgroup=vmk.portgroup, - ipv4_address=vmk.spec.ip.ipAddress, - ipv4_subnet_mask=vmk.spec.ip.subnetMask, - dhcp=vmk.spec.ip.dhcp, - mac=vmk.spec.mac, - mtu=vmk.spec.mtu, - stack=vmk.spec.netStackInstanceKey, - enable_vsan=vmk.device in self.service_type_vmks[host.name]['vsan'], - enable_vmotion=vmk.device in self.service_type_vmks[host.name]['vmotion'], - enable_management=vmk.device in self.service_type_vmks[host.name]['management'], - enable_ft=vmk.device in self.service_type_vmks[host.name]['faultToleranceLogging'], - ) - ) - hosts_info[host.name] = host_vmk_info - return hosts_info - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True - ) - - vmware_vmk_config = VmkernelInfoManager(module) - module.exit_json(changed=False, host_vmk_info=vmware_vmk_config.gather_host_vmk_info()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_vmkernel_ip_config.py b/lib/ansible/modules/cloud/vmware/vmware_vmkernel_ip_config.py deleted file mode 100644 index 60046a017c..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_vmkernel_ip_config.py +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2015, Joseph Callen <jcallen () csc.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 = ''' ---- -module: vmware_vmkernel_ip_config -short_description: Configure the VMkernel IP Address -description: - - Configure the VMkernel IP Address -version_added: 2.0 -author: -- Joseph Callen (@jcpowermac) -- Russell Teague (@mtnbikenc) -notes: - - Tested on vSphere 5.5 -requirements: - - "python >= 2.6" - - PyVmomi -options: - vmk_name: - description: - - VMkernel interface name - required: True - type: str - ip_address: - description: - - IP address to assign to VMkernel interface - required: True - type: str - subnet_mask: - description: - - Subnet Mask to assign to VMkernel interface - required: True - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -# Example command from Ansible Playbook - -- name: Configure IP address on ESX host - vmware_vmkernel_ip_config: - hostname: '{{ esxi_hostname }}' - username: '{{ esxi_username }}' - password: '{{ esxi_password }}' - vmk_name: vmk0 - ip_address: 10.0.0.10 - subnet_mask: 255.255.255.0 - delegate_to: localhost -''' - -try: - from pyVmomi import vim, vmodl - HAS_PYVMOMI = True -except ImportError: - HAS_PYVMOMI = False - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import HAS_PYVMOMI, connect_to_api, get_all_objs, vmware_argument_spec - - -def configure_vmkernel_ip_address(host_system, vmk_name, ip_address, subnet_mask): - - host_config_manager = host_system.configManager - host_network_system = host_config_manager.networkSystem - - for vnic in host_network_system.networkConfig.vnic: - if vnic.device == vmk_name: - spec = vnic.spec - if spec.ip.ipAddress != ip_address: - spec.ip.dhcp = False - spec.ip.ipAddress = ip_address - spec.ip.subnetMask = subnet_mask - host_network_system.UpdateVirtualNic(vmk_name, spec) - return True - return False - - -def main(): - - argument_spec = vmware_argument_spec() - argument_spec.update(dict(vmk_name=dict(required=True, type='str'), - ip_address=dict(required=True, type='str'), - subnet_mask=dict(required=True, type='str'))) - - module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False) - - if not HAS_PYVMOMI: - module.fail_json(msg='pyvmomi is required for this module') - - vmk_name = module.params['vmk_name'] - ip_address = module.params['ip_address'] - subnet_mask = module.params['subnet_mask'] - - try: - content = connect_to_api(module, False) - host = get_all_objs(content, [vim.HostSystem]) - if not host: - module.fail_json(msg="Unable to locate Physical Host.") - host_system = list(host)[0] - changed = configure_vmkernel_ip_address(host_system, vmk_name, ip_address, subnet_mask) - module.exit_json(changed=changed) - except vmodl.RuntimeFault as runtime_fault: - module.fail_json(msg=runtime_fault.msg) - except vmodl.MethodFault as method_fault: - module.fail_json(msg=method_fault.msg) - except Exception as e: - module.fail_json(msg=str(e)) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_vmotion.py b/lib/ansible/modules/cloud/vmware/vmware_vmotion.py deleted file mode 100644 index 05ad8ee895..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_vmotion.py +++ /dev/null @@ -1,375 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2015, Bede Carroll <bc+github () bedecarroll.com> - -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# Copyright: (c) 2018, Ansible Project -# -# 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_vmotion -short_description: Move a virtual machine using vMotion, and/or its vmdks using storage vMotion. -description: - - Using VMware vCenter, move a virtual machine using vMotion to a different - host, and/or its vmdks to another datastore using storage vMotion. -version_added: 2.2 -author: -- Bede Carroll (@bedecarroll) -- Olivier Boukili (@oboukili) -notes: - - Tested on vSphere 6.0 -requirements: - - "python >= 2.6" - - pyVmomi -options: - vm_name: - description: - - Name of the VM to perform a vMotion on. - - This is required parameter, if C(vm_uuid) is not set. - - Version 2.6 onwards, this parameter is not a required parameter, unlike the previous versions. - aliases: ['vm'] - type: str - vm_uuid: - description: - - UUID of the virtual machine to perform a vMotion operation on. - - This is a required parameter, if C(vm_name) or C(moid) is not set. - aliases: ['uuid'] - version_added: 2.7 - type: str - moid: - description: - - Managed Object ID of the instance to manage if known, this is a unique identifier only within a single vCenter instance. - - This is required if C(vm_name) or C(vm_uuid) is not supplied. - version_added: '2.9' - type: str - use_instance_uuid: - description: - - Whether to use the VMware instance UUID rather than the BIOS UUID. - default: no - type: bool - version_added: '2.8' - destination_host: - description: - - Name of the destination host the virtual machine should be running on. - - Version 2.6 onwards, this parameter is not a required parameter, unlike the previous versions. - aliases: ['destination'] - type: str - destination_datastore: - description: - - Name of the destination datastore the virtual machine's vmdk should be moved on. - aliases: ['datastore'] - version_added: 2.7 - type: str - destination_resourcepool: - description: - - Name of the destination resource pool where the virtual machine should be running. - - Resource pool is required if vmotion is done between hosts which are part of different clusters or datacenters. - - if not passed, resource_pool object will be retrived from host_obj parent. - aliases: ['resource_pool'] - version_added: '2.10' - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Perform vMotion of virtual machine - vmware_vmotion: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - vm_name: 'vm_name_as_per_vcenter' - destination_host: 'destination_host_as_per_vcenter' - delegate_to: localhost - -- name: Perform vMotion of virtual machine - vmware_vmotion: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - moid: vm-42 - destination_host: 'destination_host_as_per_vcenter' - delegate_to: localhost - -- name: Perform vMotion of virtual machine to resource_pool - vmware_vmotion: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - moid: vm-42 - destination_host: 'destination_host_as_per_vcenter' - destination_resourcepool: 'destination_resourcepool_as_per_vcenter' - delegate_to: localhost - -- name: Perform storage vMotion of of virtual machine - vmware_vmotion: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - vm_name: 'vm_name_as_per_vcenter' - destination_datastore: 'destination_datastore_as_per_vcenter' - delegate_to: localhost - -- name: Perform storage vMotion and host vMotion of virtual machine - vmware_vmotion: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - vm_name: 'vm_name_as_per_vcenter' - destination_host: 'destination_host_as_per_vcenter' - destination_datastore: 'destination_datastore_as_per_vcenter' - delegate_to: localhost -''' - -RETURN = ''' -running_host: - description: List the host the virtual machine is registered to - returned: changed or success - type: str - sample: 'host1.example.com' -''' - -try: - from pyVmomi import vim, VmomiSupport -except ImportError: - pass - -from ansible.module_utils._text import to_native -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import (PyVmomi, find_hostsystem_by_name, - find_vm_by_id, find_datastore_by_name, - find_resource_pool_by_name, - vmware_argument_spec, wait_for_task, TaskError) - - -class VmotionManager(PyVmomi): - def __init__(self, module): - super(VmotionManager, self).__init__(module) - self.vm = None - self.vm_uuid = self.params.get('vm_uuid', None) - self.use_instance_uuid = self.params.get('use_instance_uuid', False) - self.vm_name = self.params.get('vm_name', None) - self.moid = self.params.get('moid') or None - result = dict() - - self.get_vm() - if self.vm is None: - vm_id = self.vm_uuid or self.vm_name or self.moid - self.module.fail_json(msg="Failed to find the virtual machine with %s" % vm_id) - - # Get Destination Host System if specified by user - dest_host_name = self.params.get('destination_host', None) - self.host_object = None - if dest_host_name is not None: - self.host_object = find_hostsystem_by_name(content=self.content, - hostname=dest_host_name) - - # Get Destination Datastore if specified by user - dest_datastore = self.params.get('destination_datastore', None) - self.datastore_object = None - if dest_datastore is not None: - self.datastore_object = find_datastore_by_name(content=self.content, - datastore_name=dest_datastore) - - # At-least one of datastore, host system is required to migrate - if self.datastore_object is None and self.host_object is None: - self.module.fail_json(msg="Unable to find destination datastore" - " and destination host system.") - - # Get Destination resourcepool - dest_resourcepool = self.params.get('destination_resourcepool', None) - self.resourcepool_object = None - if dest_resourcepool: - self.resourcepool_object = find_resource_pool_by_name(content=self.content, - resource_pool_name=dest_resourcepool) - elif not dest_resourcepool and dest_host_name: - self.resourcepool_object = self.host_object.parent.resourcePool - # Fail if resourcePool object is not found - if self.resourcepool_object is None: - self.module.fail_json(msg="Unable to destination resource pool object which is required") - - # Check if datastore is required, this check is required if destination - # and source host system does not share same datastore. - host_datastore_required = [] - for vm_datastore in self.vm.datastore: - if self.host_object and vm_datastore not in self.host_object.datastore: - host_datastore_required.append(True) - else: - host_datastore_required.append(False) - - if any(host_datastore_required) and dest_datastore is None: - msg = "Destination host system does not share" \ - " datastore ['%s'] with source host system ['%s'] on which" \ - " virtual machine is located. Please specify destination_datastore" \ - " to rectify this problem." % ("', '".join([ds.name for ds in self.host_object.datastore]), - "', '".join([ds.name for ds in self.vm.datastore])) - - self.module.fail_json(msg=msg) - - storage_vmotion_needed = True - change_required = True - - if self.host_object and self.datastore_object: - # We have both host system and datastore object - if not self.datastore_object.summary.accessible: - # Datastore is not accessible - self.module.fail_json(msg='Destination datastore %s is' - ' not accessible.' % dest_datastore) - - if self.datastore_object not in self.host_object.datastore: - # Datastore is not associated with host system - self.module.fail_json(msg="Destination datastore %s provided" - " is not associated with destination" - " host system %s. Please specify" - " datastore value ['%s'] associated with" - " the given host system." % (dest_datastore, - dest_host_name, - "', '".join([ds.name for ds in self.host_object.datastore]))) - - if self.vm.runtime.host.name == dest_host_name and dest_datastore in [ds.name for ds in self.vm.datastore]: - change_required = False - - if self.host_object and self.datastore_object is None: - if self.vm.runtime.host.name == dest_host_name: - # VM is already located on same host - change_required = False - - storage_vmotion_needed = False - - elif self.datastore_object and self.host_object is None: - if self.datastore_object in self.vm.datastore: - # VM is already located on same datastore - change_required = False - - if not self.datastore_object.summary.accessible: - # Datastore is not accessible - self.module.fail_json(msg='Destination datastore %s is' - ' not accessible.' % dest_datastore) - - if module.check_mode: - result['running_host'] = module.params['destination_host'] - result['changed'] = True - module.exit_json(**result) - - if change_required: - # Migrate VM and get Task object back - task_object = self.migrate_vm() - # Wait for task to complete - try: - wait_for_task(task_object) - except TaskError as task_error: - self.module.fail_json(msg=to_native(task_error)) - # If task was a success the VM has moved, update running_host and complete module - if task_object.info.state == vim.TaskInfo.State.success: - # The storage layout is not automatically refreshed, so we trigger it to get coherent module return values - if storage_vmotion_needed: - self.vm.RefreshStorageInfo() - result['running_host'] = module.params['destination_host'] - result['changed'] = True - module.exit_json(**result) - else: - msg = 'Unable to migrate virtual machine due to an error, please check vCenter' - if task_object.info.error is not None: - msg += " : %s" % task_object.info.error - module.fail_json(msg=msg) - else: - try: - host = self.vm.summary.runtime.host - result['running_host'] = host.summary.config.name - except vim.fault.NoPermission: - result['running_host'] = 'NA' - result['changed'] = False - module.exit_json(**result) - - def migrate_vm(self): - """ - Migrate virtual machine and return the task. - """ - relocate_spec = vim.vm.RelocateSpec(host=self.host_object, - datastore=self.datastore_object, - pool=self.resourcepool_object) - task_object = self.vm.Relocate(relocate_spec) - return task_object - - def get_vm(self): - """ - Find unique virtual machine either by UUID or Name. - Returns: virtual machine object if found, else None. - - """ - vms = [] - if self.vm_uuid: - if not self.use_instance_uuid: - vm_obj = find_vm_by_id(self.content, vm_id=self.params['vm_uuid'], vm_id_type="uuid") - elif self.use_instance_uuid: - vm_obj = find_vm_by_id(self.content, vm_id=self.params['vm_uuid'], vm_id_type="instance_uuid") - vms = [vm_obj] - elif self.vm_name: - objects = self.get_managed_objects_properties(vim_type=vim.VirtualMachine, properties=['name']) - for temp_vm_object in objects: - if len(temp_vm_object.propSet) != 1: - continue - if temp_vm_object.obj.name == self.vm_name: - vms.append(temp_vm_object.obj) - break - elif self.moid: - vm_obj = VmomiSupport.templateOf('VirtualMachine')(self.moid, self.si._stub) - if vm_obj: - vms.append(vm_obj) - - if len(vms) > 1: - self.module.fail_json(msg="Multiple virtual machines with same name %s found." - " Please specify vm_uuid instead of vm_name." % self.vm_name) - - if vms: - self.vm = vms[0] - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - dict( - vm_name=dict(aliases=['vm']), - vm_uuid=dict(aliases=['uuid']), - moid=dict(type='str'), - use_instance_uuid=dict(type='bool', default=False), - destination_host=dict(aliases=['destination']), - destination_resourcepool=dict(aliases=['resource_pool']), - destination_datastore=dict(aliases=['datastore']) - ) - ) - - module = AnsibleModule( - argument_spec=argument_spec, - supports_check_mode=True, - required_one_of=[ - ['destination_host', 'destination_datastore'], - ['vm_uuid', 'vm_name', 'moid'], - ], - mutually_exclusive=[ - ['vm_uuid', 'vm_name', 'moid'], - ], - ) - - vmotion_manager = VmotionManager(module) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_vsan_cluster.py b/lib/ansible/modules/cloud/vmware/vmware_vsan_cluster.py deleted file mode 100644 index ea55bf6965..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_vsan_cluster.py +++ /dev/null @@ -1,125 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2015, Russell Teague <rteague2 () csc.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 = ''' ---- -module: vmware_vsan_cluster -short_description: Configure VSAN clustering on an ESXi host -description: - - This module can be used to configure VSAN clustering on an ESXi host -version_added: 2.0 -author: -- Russell Teague (@mtnbikenc) -notes: - - Tested on vSphere 5.5 -requirements: - - "python >= 2.6" - - PyVmomi -options: - cluster_uuid: - description: - - Desired cluster UUID - required: False - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Configure VMware VSAN Cluster - hosts: deploy_node - tags: - - vsan - tasks: - - name: Configure VSAN on first host - vmware_vsan_cluster: - hostname: "{{ groups['esxi'][0] }}" - username: "{{ esxi_username }}" - password: "{{ site_password }}" - delegate_to: localhost - register: vsan_cluster - - - name: Configure VSAN on remaining hosts - vmware_vsan_cluster: - hostname: "{{ item }}" - username: "{{ esxi_username }}" - password: "{{ site_password }}" - cluster_uuid: "{{ vsan_cluster.cluster_uuid }}" - delegate_to: localhost - loop: "{{ groups['esxi'][1:] }}" -''' - -try: - from pyVmomi import vim, vmodl - HAS_PYVMOMI = True -except ImportError: - HAS_PYVMOMI = False - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import (HAS_PYVMOMI, connect_to_api, get_all_objs, vmware_argument_spec, - wait_for_task) - - -def create_vsan_cluster(host_system, new_cluster_uuid): - host_config_manager = host_system.configManager - vsan_system = host_config_manager.vsanSystem - - vsan_config = vim.vsan.host.ConfigInfo() - vsan_config.enabled = True - - if new_cluster_uuid is not None: - vsan_config.clusterInfo = vim.vsan.host.ConfigInfo.ClusterInfo() - vsan_config.clusterInfo.uuid = new_cluster_uuid - - vsan_config.storageInfo = vim.vsan.host.ConfigInfo.StorageInfo() - vsan_config.storageInfo.autoClaimStorage = True - - task = vsan_system.UpdateVsan_Task(vsan_config) - changed, result = wait_for_task(task) - - host_status = vsan_system.QueryHostStatus() - cluster_uuid = host_status.uuid - - return changed, result, cluster_uuid - - -def main(): - - argument_spec = vmware_argument_spec() - argument_spec.update(dict(cluster_uuid=dict(required=False, type='str'))) - - module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False) - - if not HAS_PYVMOMI: - module.fail_json(msg='pyvmomi is required for this module') - - new_cluster_uuid = module.params['cluster_uuid'] - - try: - content = connect_to_api(module, False) - host = get_all_objs(content, [vim.HostSystem]) - if not host: - module.fail_json(msg="Unable to locate Physical Host.") - host_system = list(host)[0] - changed, result, cluster_uuid = create_vsan_cluster(host_system, new_cluster_uuid) - module.exit_json(changed=changed, result=result, cluster_uuid=cluster_uuid) - - except vmodl.RuntimeFault as runtime_fault: - module.fail_json(msg=runtime_fault.msg) - except vmodl.MethodFault as method_fault: - module.fail_json(msg=method_fault.msg) - except Exception as e: - module.fail_json(msg=str(e)) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_vsan_health_info.py b/lib/ansible/modules/cloud/vmware/vmware_vsan_health_info.py deleted file mode 100644 index 71fc58c539..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_vsan_health_info.py +++ /dev/null @@ -1,181 +0,0 @@ -#!/usr/bin/python - -# Copyright: (c) 2019, OVH SAS -# 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 = ''' ---- -module: vmware_vsan_health_info - -short_description: Gather information about a VMware vSAN cluster's health - -version_added: "2.10" - -description: - - "Gather information about a VMware vSAN cluster's health" - -options: - cluster_name: - description: - - Name of the vSAN cluster. - required: true - type: str - fetch_from_cache: - description: - - C(True) to return the result from cache directly instead of running the full health check. - required: false - default: false - type: bool - -requirements: - - PyVmomi - - VMware vSAN Python's SDK - -extends_documentation_fragment: - - vmware.documentation - -author: - - Erwan Quelin (@equelin) -''' - -EXAMPLES = ''' -- name: Gather health info from a vSAN's cluster - hosts: localhost - gather_facts: 'no' - vmware_vsan_health_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: 'vSAN01' - fetch_from_cache: False -''' - -RETURN = ''' -vsan_health_info: - description: vSAN cluster health info - returned: on success - type: dict - sample: { - "_vimtype": "vim.cluster.VsanClusterHealthSummary", - "burnInTest": null, - "clusterStatus": { - "_vimtype": "vim.cluster.VsanClusterHealthSystemStatusResult", - "goalState": "installed", - "status": "green", - "trackedHostsStatus": [ - { - "_vimtype": "vim.host.VsanHostHealthSystemStatusResult", - "hostname": "esxi01.example.com", - "issues": [], - "status": "green" - }, - { - "_vimtype": "vim.host.VsanHostHealthSystemStatusResult", - "hostname": "esxi04.example.com", - "issues": [], - "status": "green" - }, - { - "_vimtype": "vim.host.VsanHostHealthSystemStatusResult", - "hostname": "esxi02.example.com", - "issues": [], - "status": "green" - }, - { - "_vimtype": "vim.host.VsanHostHealthSystemStatusResult", - "hostname": "esxi03.example.com", - "issues": [], - "status": "green" - } - ], - "untrackedHosts": [] - } - } -''' - -import json -import traceback - -try: - from pyVmomi import vim, vmodl, VmomiSupport - HAS_PYVMOMI = True - HAS_PYVMOMIJSON = hasattr(VmomiSupport, 'VmomiJSONEncoder') -except ImportError: - PYVMOMI_IMP_ERR = traceback.format_exc() - HAS_PYVMOMI = False - HAS_PYVMOMIJSON = False - -try: - import vsanapiutils - import vsanmgmtObjects - HAS_VSANPYTHONSDK = True -except ImportError: - VSANPYTHONSDK_IMP_ERR = traceback.format_exc() - HAS_VSANPYTHONSDK = False - -from ansible.module_utils.basic import AnsibleModule, missing_required_lib -from ansible.module_utils.vmware import connect_to_api, vmware_argument_spec, find_cluster_by_name - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(required=True, type='str'), - fetch_from_cache=dict(required=False, type='bool') - ) - - module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) - - if not HAS_PYVMOMI: - module.fail_json(msg=missing_required_lib('PyVmomi'), exception=PYVMOMI_IMP_ERR) - - if not HAS_VSANPYTHONSDK: - module.fail_json(msg=missing_required_lib('vSAN Management SDK for Python'), exception=VSANPYTHONSDK_IMP_ERR) - - if not HAS_PYVMOMIJSON: - module.fail_json(msg='The installed version of pyvmomi lacks JSON output support; need pyvmomi>6.7.1') - - try: - si, content = connect_to_api(module, True, True) - except Exception as e: - module.fail_json(msg=e.msg) - - client_stub = si._GetStub() - ssl_context = client_stub.schemeArgs.get('context') - - cluster = find_cluster_by_name(content, module.params['cluster_name']) - - if not cluster: - module.fail_json(msg="Failed to find cluster %s" % module.params['cluster_name']) - - apiVersion = vsanapiutils.GetLatestVmodlVersion(module.params['hostname']) - vcMos = vsanapiutils.GetVsanVcMos(client_stub, context=ssl_context, version=apiVersion) - - vsanClusterHealthSystem = vcMos['vsan-cluster-health-system'] - - try: - clusterHealth = vsanClusterHealthSystem.VsanQueryVcClusterHealthSummary( - cluster=cluster, - fetchFromCache=module.params['fetch_from_cache'] - ) - except vmodl.fault.NotFound as not_found: - module.fail_json(msg=not_found.msg) - except vmodl.fault.RuntimeFault as runtime_fault: - module.fail_json(msg=runtime_fault.msg) - - health = json.dumps(clusterHealth, cls=VmomiSupport.VmomiJSONEncoder, sort_keys=True, strip_dynamic=True) - - module.exit_json(changed=False, vsan_health_info=health) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_vspan_session.py b/lib/ansible/modules/cloud/vmware/vmware_vspan_session.py deleted file mode 100644 index aa103debf7..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_vspan_session.py +++ /dev/null @@ -1,631 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, CrySyS Lab <www.crysys.hu> -# Copyright: (c) 2018, Peter Gyorgy <gyorgy.peter@edu.bme.hu> -# 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 = ''' ---- -module: vmware_vspan_session -short_description: Create or remove a Port Mirroring session. -description: - - This module can be used to create, delete or edit different kind of port mirroring sessions. -version_added: '2.8' -author: -- Peter Gyorgy (@gyorgypeter) -notes: - - Tested on vSphere 6.7 -requirements: - - "python > = 2.6" - - PyVmomi -options: - switch: - description: - - The name of the distributed vSwitch on which to add or remove the mirroring session. - required: True - aliases: [ 'switch_name' ] - type: str - name: - description: - - Name of the session. - required: True - type: str - state: - choices: - - 'present' - - 'absent' - description: - - Create or remove the session. - required: True - type: str - session_type: - default: 'dvPortMirror' - choices: - - 'encapsulatedRemoteMirrorSource' - - 'remoteMirrorDest' - - 'remoteMirrorSource' - - 'dvPortMirror' - description: - - Select the mirroring type. - - '- C(encapsulatedRemoteMirrorSource) (str): In encapsulatedRemoteMirrorSource session, Distributed Ports - can be used as source entities, and Ip address can be used as destination entities.' - - '- C(remoteMirrorDest) (str): In remoteMirrorDest session, vlan Ids can be used as source entities, and - Distributed Ports can be used as destination entities.' - - '- C(remoteMirrorSource) (str): In remoteMirrorSource session, Distributed Ports can be used as source - entities, and uplink ports name can be used as destination entities.' - - '- C(dvPortMirror) (str): In dvPortMirror session, Distributed Ports can be used as both source and - destination entities.' - required: False - type: str - enabled: - type: bool - default: True - description: - - Whether the session is enabled. - description: - description: - - The description for the session. - required: False - type: str - source_port_transmitted: - description: - - Source port for which transmitted packets are mirrored. - required: False - type: str - source_port_received: - description: - - Source port for which received packets are mirrored. - required: False - type: str - destination_port: - description: - - Destination port that received the mirrored packets. Also any port designated in the value of this - property can not match the source port in any of the Distributed Port Mirroring session. - required: False - type: str - encapsulation_vlan_id: - description: - - VLAN ID used to encapsulate the mirrored traffic. - required: False - type: int - strip_original_vlan: - description: - - Whether to strip the original VLAN tag. if false, the original VLAN tag will be preserved on the mirrored - traffic. If encapsulationVlanId has been set and this property is false, the frames will be double tagged - with the original VLAN ID as the inner tag. - type: bool - required: False - mirrored_packet_length: - description: - - An integer that describes how much of each frame to mirror. If unset, all of the frame would be mirrored. - Setting this property to a smaller value is useful when the consumer will look only at the headers. - The value cannot be less than 60. - required: False - type: int - normal_traffic_allowed: - description: - - Whether or not destination ports can send and receive "normal" traffic. Setting this to false will make - mirror ports be used solely for mirroring and not double as normal access ports. - type: bool - required: False - sampling_rate: - description: - - Sampling rate of the session. If its value is n, one of every n packets is mirrored. - Valid values are between 1 to 65535, and default value is 1. - type: int - required: False - source_vm_transmitted: - description: - - With this parameter it is possible, to add a NIC of a VM to a port mirroring session. - - 'Valid attributes are:' - - '- C(name) (str): Name of the VM' - - '- C(nic_label) (bool): Label of the Network Interface Card to use.' - type: dict - source_vm_received: - description: - - With this parameter it is possible, to add a NIC of a VM to a port mirroring session. - - 'Valid attributes are:' - - '- C(name) (str): Name of the VM' - - '- C(nic_label) (bool): Label of the Network Interface Card to use.' - type: dict - destination_vm: - description: - - With this parameter it is possible, to add a NIC of a VM to a port mirroring session. - - 'Valid attributes are:' - - '- C(name) (str): Name of the VM' - - '- C(nic_label) (bool): Label of the Network Interface Card to use.' - required: False - type: dict -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Create distributed mirroring session. - vmware_vspan_session: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - switch_name: dvSwitch - state: present - name: Basic Session - enabled: True - description: "Example description" - source_port_transmitted: 817 - source_port_received: 817 - destination_port: 815 - delegate_to: localhost - -- name: Create remote destination mirroring session. - vmware_vspan_session: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - switch_name: dvSwitch - state: present - name: Remote Session - enabled: True - description: "Example description" - source_port_received: 105 - destination_port: 815 - session_type: "remoteMirrorDest" - delegate_to: localhost - -- name: Create remote destination mirroring session. - vmware_vspan_session: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - switch_name: dvSwitch - state: absent - name: Remote Session - delegate_to: localhost -''' - -RETURN = """# -""" - -try: - from pyVmomi import vim, vmodl -except ImportError as e: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import (vmware_argument_spec, PyVmomi, find_dvs_by_name, - find_vm_by_name, wait_for_task) - - -class VMwareVspanSession(PyVmomi): - def __init__(self, module): - super(VMwareVspanSession, self).__init__(module) - self.switch = module.params['switch'] - self.name = module.params['name'] - self.session_type = module.params['session_type'] - self.enabled = module.params['enabled'] - self.state = module.params['state'] - self.description = module.params['description'] - self.source_port_transmitted = module.params['source_port_transmitted'] - self.source_port_received = module.params['source_port_received'] - self.destination_port = module.params['destination_port'] - self.encapsulation_vlan_id = module.params['encapsulation_vlan_id'] - self.strip_original_vlan = module.params['strip_original_vlan'] - self.mirrored_packet_length = module.params['mirrored_packet_length'] - self.normal_traffic_allowed = module.params['normal_traffic_allowed'] - self.sampling_rate = module.params['sampling_rate'] - self.dv_switch = find_dvs_by_name(self.content, self.switch) - if self.dv_switch is None: - self.module.fail_json(msg="There is no dvSwitch with the name: {0:s}.".format(self.switch)) - self.operation = None - self.modified_ports = dict() - self.deleted_session = None - if module.params['source_vm_transmitted'] is not None: - if (module.params['source_vm_transmitted']['name'] is None or - module.params['source_vm_transmitted']['nic_label'] is None): - self.module.fail_json(msg="Please provide both VM name and NIC Label") - self.source_vm_transmitted_name = module.params['source_vm_transmitted']['name'] - self.source_vm_transmitted_nic_label = module.params['source_vm_transmitted']['nic_label'] - if module.params['source_vm_received'] is not None: - if (module.params['source_vm_received']['name'] is None or - module.params['source_vm_received']['nic_label'] is None): - self.module.fail_json(msg="Please provide both VM name and NIC Label") - self.source_vm_received_name = module.params['source_vm_received']['name'] - self.source_vm_received_nic_label = module.params['source_vm_received']['nic_label'] - if module.params['destination_vm'] is not None: - if (module.params['destination_vm']['name'] is None or - module.params['destination_vm']['nic_label'] is None): - self.module.fail_json(msg="Please provide both VM name and NIC Label") - self.destination_vm_name = module.params['destination_vm']['name'] - self.destination_vm_nic_label = module.params['destination_vm']['nic_label'] - - def set_operation(self): - """Sets the operation according to state""" - if self.state == 'absent': - self.operation = 'remove' - elif self.state == 'present' and self.find_session_by_name() is None: - self.operation = 'add' - else: - self.operation = 'edit' - - def find_session_by_name(self): - """Finds a session by name - Returns - ------- - vim.dvs.VmwareDistributedVirtualSwitch.VspanSession - The session if there was a session by the given name, else returns None - """ - for vspan_session in self.dv_switch.config.vspanSession: - if vspan_session.name == self.name: - return vspan_session - return None - - def get_vm_port(self, vm_name, nic_label): - """Finds the port of the VM - Returns - ------- - str - the port number as a string, or None if the NIC couldnt be found - """ - vm = find_vm_by_name(self.content, vm_name) - if vm is None: - self.module.fail_json(msg="There is no VM with the name: {0:s}.".format(vm_name)) - for hardware in vm.config.hardware.device: - if isinstance(hardware, vim.vm.device.VirtualVmxnet3): - if hardware.deviceInfo.label == nic_label: - return hardware.backing.port.portKey - return None - - def set_port_for_vm(self): - """Sets the ports, to the VM's specified port.""" - if hasattr(self, 'source_vm_transmitted_name') and hasattr(self, 'source_vm_transmitted_nic_label'): - port = self.get_vm_port(self.source_vm_transmitted_name, self.source_vm_transmitted_nic_label) - if port is not None: - self.source_port_transmitted = port - else: - self.module.fail_json( - msg="No port could be found for VM: {0:s} NIC: {1:s}".format(self.source_vm_transmitted_name, - self.source_vm_transmitted_nic_label)) - if hasattr(self, 'source_vm_received_name') and hasattr(self, 'source_vm_received_nic_label'): - port = self.get_vm_port(self.source_vm_received_name, self.source_vm_received_nic_label) - if port is not None: - self.source_port_received = port - else: - self.module.fail_json( - msg="No port could be found for VM: {0:s} NIC: {1:s}".format(self.source_vm_received_name, - self.source_vm_received_nic_label)) - if hasattr(self, 'destination_vm_name') and hasattr(self, 'destination_vm_nic_label'): - port = self.get_vm_port(self.destination_vm_name, self.destination_vm_nic_label) - if port is not None: - self.destination_port = port - else: - self.module.fail_json( - msg="No port could be found for VM: {0:s} NIC: {1:s}".format(self.destination_vm_name, - self.destination_vm_nic_label)) - - def process_operation(self): - """Calls the create or delete function based on the operation""" - self.set_operation() - if self.operation == 'remove': - results = self.remove_vspan_session() - self.module.exit_json(**results) - if self.operation == 'add': - self.set_port_for_vm() - results = self.add_vspan_session() - self.module.exit_json(**results) - if self.operation == 'edit': - self.remove_vspan_session() - self.set_port_for_vm() - results = self.add_vspan_session() - self.module.exit_json(**results) - - def set_port_security_promiscuous(self, ports, state): - """Set the given port to the given promiscuous state. - Parameters - ---------- - port : str[] - PortKey - state: bool - State of the promiscuous mode, if true its allowed, else not. - """ - # Creating the new port policy - port_spec = [] - vim_bool = vim.BoolPolicy(value=state) - port_policy = vim.dvs.VmwareDistributedVirtualSwitch.SecurityPolicy(allowPromiscuous=vim_bool) - port_settings = vim.dvs.VmwareDistributedVirtualSwitch.VmwarePortConfigPolicy(securityPolicy=port_policy) - for port in ports: - temp_port_spec = vim.dvs.DistributedVirtualPort.ConfigSpec( - operation="edit", - key=port, - setting=port_settings - ) - port_spec.append(temp_port_spec) - - task = self.dv_switch.ReconfigureDVPort_Task(port_spec) - try: - wait_for_task(task) - except Exception: - self.restore_original_state() - self.module.fail_json(msg=task.info.error.msg) - - def turn_off_promiscuous(self): - """Disable all promiscuous mode ports, and give them back in a list. - Returns - ------- - list - Contains every port, where promiscuous mode has been turned off - """ - # Ports that are in mirror sessions - ports = [] - ports_of_selected_session = [] - for vspan_session in self.dv_switch.config.vspanSession: - if vspan_session.sourcePortReceived is not None: - session_ports = vspan_session.sourcePortReceived.portKey - for port in session_ports: - if vspan_session.name == self.name: - ports_of_selected_session.append(port) - elif not(port in ports): - ports.append(port) - if vspan_session.sourcePortTransmitted is not None: - session_ports = vspan_session.sourcePortTransmitted.portKey - for port in session_ports: - if vspan_session.name == self.name: - ports_of_selected_session.append(port) - elif not(port in ports): - ports.append(port) - if vspan_session.destinationPort is not None: - session_ports = vspan_session.destinationPort.portKey - for port in session_ports: - if vspan_session.name == self.name: - ports_of_selected_session.append(port) - elif not(port in ports): - ports.append(port) - promiscuous_ports = [] - if ports: - dv_ports = self.dv_switch.FetchDVPorts(vim.dvs.PortCriteria(portKey=ports)) - # If a port is promiscuous set disable it, and add it to the array to enable it after the changes are made. - for dv_port in dv_ports: - if dv_port.config.setting.securityPolicy.allowPromiscuous.value: - self.set_port_security_promiscuous([dv_port.key], False) - self.modified_ports.update({dv_port.key: True}) - promiscuous_ports.append(dv_port.key) - if ports_of_selected_session: - current_dv_ports = self.dv_switch.FetchDVPorts(vim.dvs.PortCriteria(portKey=ports_of_selected_session)) - for dv_port in current_dv_ports: - if dv_port.config.setting.securityPolicy.allowPromiscuous.value: - self.set_port_security_promiscuous([dv_port.key], False) - self.modified_ports.update({dv_port.key: True}) - # Return the promiscuous ports array, to set them back after the config is finished. - return promiscuous_ports - - def delete_mirroring_session(self, key): - """Deletes the mirroring session. - Parameters - ---------- - key : str - Key of the Session - """ - session = vim.dvs.VmwareDistributedVirtualSwitch.VspanSession( - key=key - ) - config_version = self.dv_switch.config.configVersion - s_spec = vim.dvs.VmwareDistributedVirtualSwitch.VspanConfigSpec(vspanSession=session, operation="remove") - c_spec = vim.dvs.VmwareDistributedVirtualSwitch.ConfigSpec(vspanConfigSpec=[s_spec], configVersion=config_version) - task = self.dv_switch.ReconfigureDvs_Task(c_spec) - try: - wait_for_task(task) - except Exception: - self.restore_original_state() - self.module.fail_json(msg=task.info.error.msg) - - def restore_original_state(self): - """In case of failure restore, the changes we made.""" - for port, state in self.modified_ports.items(): - self.set_port_security_promiscuous([port], state) - if self.deleted_session is not None: - session = self.deleted_session - config_version = self.dv_switch.config.configVersion - s_spec = vim.dvs.VmwareDistributedVirtualSwitch.VspanConfigSpec(vspanSession=session, operation="add") - c_spec = vim.dvs.VmwareDistributedVirtualSwitch.ConfigSpec(vspanConfigSpec=[s_spec], configVersion=config_version) - # Revert the delete - task = self.dv_switch.ReconfigureDvs_Task(c_spec) - try: - wait_for_task(task) - except Exception: - self.restore_original_state() - self.module.fail_json(msg=task.info.error.msg) - - def remove_vspan_session(self): - """Calls the necessary functions to delete a VSpanSession.""" - results = dict(changed=False, result="") - mirror_session = self.find_session_by_name() - if mirror_session is None: - results['result'] = "There is no VSpanSession with the name: {0:s}.".format(self.name) - return results - promiscuous_ports = self.turn_off_promiscuous() - session_key = mirror_session.key - # Delete Mirroring Session - self.delete_mirroring_session(session_key) - # Session - self.deleted_session = mirror_session - # Set back the promiscuous ports - if promiscuous_ports: - self.set_port_security_promiscuous(promiscuous_ports, True) - results['changed'] = True - results['result'] = 'VSpan Session has been deleted' - return results - - def check_if_session_name_is_free(self): - """Checks whether the name is used or not - Returns - ------- - bool - True if the name is free and False if it is used. - """ - for vspan_session in self.dv_switch.config.vspanSession: - if vspan_session.name == self.name: - return False - return True - - def create_vspan_session(self): - """Builds up the session, adds the parameters that we specified, then creates it on the vSwitch""" - - session = vim.dvs.VmwareDistributedVirtualSwitch.VspanSession( - name=self.name, - enabled=True - ) - if self.session_type is not None: - session.sessionType = self.session_type - if self.session_type == 'encapsulatedRemoteMirrorSource': - if self.source_port_received is not None: - port = vim.dvs.VmwareDistributedVirtualSwitch.VspanPorts(portKey=str(self.source_port_received)) - if not self.dv_switch.FetchDVPorts(vim.dvs.PortCriteria(portKey=port.portKey)): - self.module.fail_json(msg="Couldn't find port: {0:s}".format(self.source_port_received)) - session.sourcePortReceived = port - if self.source_port_transmitted is not None: - port = vim.dvs.VmwareDistributedVirtualSwitch.VspanPorts(portKey=str(self.source_port_transmitted)) - if not self.dv_switch.FetchDVPorts(vim.dvs.PortCriteria(portKey=port.portKey)): - self.module.fail_json(msg="Couldn't find port: {0:s}".format(self.source_port_transmitted)) - session.sourcePortTransmitted = port - if self.destination_port is not None: - port = vim.dvs.VmwareDistributedVirtualSwitch.VspanPorts(ipAddress=str(self.destination_port)) - session.destinationPort = port - if self.session_type == 'remoteMirrorSource': - if self.source_port_received is not None: - port = vim.dvs.VmwareDistributedVirtualSwitch.VspanPorts(portKey=str(self.source_port_received)) - if not self.dv_switch.FetchDVPorts(vim.dvs.PortCriteria(portKey=port.portKey)): - self.module.fail_json(msg="Couldn't find port: {0:s}".format(self.source_port_received)) - session.sourcePortReceived = port - if self.source_port_transmitted is not None: - port = vim.dvs.VmwareDistributedVirtualSwitch.VspanPorts(portKey=str(self.source_port_transmitted)) - if not self.dv_switch.FetchDVPorts(vim.dvs.PortCriteria(portKey=port.portKey)): - self.module.fail_json(msg="Couldn't find port: {0:s}".format(self.source_port_transmitted)) - session.sourcePortTransmitted = port - if self.destination_port is not None: - port = vim.dvs.VmwareDistributedVirtualSwitch.VspanPorts(uplinkPortName=str(self.destination_port)) - session.destinationPort = port - if self.session_type == 'remoteMirrorDest': - if self.source_port_received is not None: - port = vim.dvs.VmwareDistributedVirtualSwitch.VspanPorts(vlans=[int(self.source_port_received)]) - if int(self.source_port_received) not in self.dv_switch.QueryUsedVlanIdInDvs(): - self.module.fail_json(msg="Couldn't find vlan: {0:s}".format(self.source_port_received)) - session.sourcePortReceived = port - if self.destination_port is not None: - port = vim.dvs.VmwareDistributedVirtualSwitch.VspanPorts(portKey=str(self.destination_port)) - if not self.dv_switch.FetchDVPorts(vim.dvs.PortCriteria(portKey=port.portKey)): - self.module.fail_json(msg="Couldn't find port: {0:s}".format(self.destination_port)) - session.destinationPort = port - if self.session_type == 'dvPortMirror': - if self.source_port_received is not None: - port = vim.dvs.VmwareDistributedVirtualSwitch.VspanPorts(portKey=str(self.source_port_received)) - if not self.dv_switch.FetchDVPorts(vim.dvs.PortCriteria(portKey=port.portKey)): - self.module.fail_json(msg="Couldn't find port: {0:s}".format(self.source_port_received)) - session.sourcePortReceived = port - if self.source_port_transmitted is not None: - port = vim.dvs.VmwareDistributedVirtualSwitch.VspanPorts(portKey=str(self.source_port_transmitted)) - if not self.dv_switch.FetchDVPorts(vim.dvs.PortCriteria(portKey=port.portKey)): - self.module.fail_json(msg="Couldn't find port: {0:s}".format(self.source_port_transmitted)) - session.sourcePortTransmitted = port - if self.destination_port is not None: - port = vim.dvs.VmwareDistributedVirtualSwitch.VspanPorts(portKey=str(self.destination_port)) - if not self.dv_switch.FetchDVPorts(vim.dvs.PortCriteria(portKey=port.portKey)): - self.module.fail_json(msg="Couldn't find port: {0:s}".format(self.destination_port)) - session.destinationPort = port - if self.description is not None: - session.description = self.description - if self.encapsulation_vlan_id is not None: - session.encapsulationVlanId = self.encapsulation_vlan_id - if self.strip_original_vlan is not None: - session.stripOriginalVlan = self.strip_original_vlan - if self.mirrored_packet_length is not None: - session.mirroredPacketLength = self.mirrored_packet_length - if self.normal_traffic_allowed is not None: - session.normalTrafficAllowed = self.normal_traffic_allowed - if self.sampling_rate is not None: - session.samplingRate = self.sampling_rate - config_version = self.dv_switch.config.configVersion - s_spec = vim.dvs.VmwareDistributedVirtualSwitch.VspanConfigSpec(vspanSession=session, operation="add") - c_spec = vim.dvs.VmwareDistributedVirtualSwitch.ConfigSpec(vspanConfigSpec=[s_spec], configVersion=config_version) - task = self.dv_switch.ReconfigureDvs_Task(c_spec) - try: - wait_for_task(task) - except Exception: - self.restore_original_state() - self.module.fail_json(msg=task.info.error.msg) - - def add_vspan_session(self): - """Calls the necessary functions to create a VSpanSession""" - results = dict(changed=False, result="") - promiscous_ports = self.turn_off_promiscuous() - if not self.check_if_session_name_is_free(): - self.module.fail_json(msg="There is another VSpan Session with the name: {0:s}.".format(self.name)) - # Locate the ports, we want to use - dv_ports = None - ports = [str(self.source_port_received), str(self.source_port_transmitted), str(self.destination_port)] - if ports: - dv_ports = self.dv_switch.FetchDVPorts(vim.dvs.PortCriteria(portKey=ports)) - for dv_port in dv_ports: - if dv_port.config.setting.securityPolicy.allowPromiscuous.value: - self.set_port_security_promiscuous([dv_port.key], False) - self.modified_ports.update({dv_port.key: True}) - # Now we can create the VspanSession - self.create_vspan_session() - # Finally we can set the destination port to promiscuous mode - if self.session_type == 'dvPortMirror' or self.session_type == 'remoteMirrorDest': - self.set_port_security_promiscuous([str(self.destination_port)], True) - # Set Back the Promiscuous ports - if promiscous_ports: - self.set_port_security_promiscuous(promiscous_ports, True) - results['changed'] = True - results['result'] = 'Mirroring session has been created.' - return results - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update(dict( - switch=dict(type='str', required=True, aliases=['switch_name']), - name=dict(type='str', required=True), - state=dict(type='str', required=True, choices=['present', 'absent']), - session_type=dict(type='str', default='dvPortMirror', choices=['dvPortMirror', - 'encapsulatedRemoteMirrorSource', - 'remoteMirrorDest', - 'remoteMirrorSource']), - enabled=dict(type='bool', default=True), - description=dict(type='str'), - source_port_transmitted=dict(type='str'), - source_port_received=dict(type='str'), - destination_port=dict(type='str'), - encapsulation_vlan_id=dict(type='int'), - strip_original_vlan=dict(type='bool'), - mirrored_packet_length=dict(type='int'), - normal_traffic_allowed=dict(type='bool'), - sampling_rate=dict(type='int'), - source_vm_transmitted=dict(type='dict', - options=dict( - name=dict(type='str'), - nic_label=dict(type='str'))), - source_vm_received=dict(type='dict', - options=dict( - name=dict(type='str'), - nic_label=dict(type='str'))), - destination_vm=dict(type='dict', - options=dict( - name=dict(type='str'), - nic_label=dict(type='str'))), - )) - module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False) - session = VMwareVspanSession(module) - session.process_operation() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_vswitch.py b/lib/ansible/modules/cloud/vmware/vmware_vswitch.py deleted file mode 100644 index 0a5fbb6813..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_vswitch.py +++ /dev/null @@ -1,414 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2015, Joseph Callen <jcallen () csc.com> -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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 = ''' ---- -module: vmware_vswitch -short_description: Manage a VMware Standard Switch to an ESXi host. -description: -- This module can be used to add, remove and update a VMware Standard Switch to an ESXi host. -version_added: 2.0 -author: -- Joseph Callen (@jcpowermac) -- Russell Teague (@mtnbikenc) -- Abhijeet Kasurde (@Akasurde) <akasurde@redhat.com> -notes: -- Tested on vSphere 5.5 and 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - switch: - description: - - vSwitch name to add. - - Alias C(switch) is added in version 2.4. - required: yes - aliases: [ switch_name ] - type: str - nics: - description: - - A list of vmnic names or vmnic name to attach to vSwitch. - - Alias C(nics) is added in version 2.4. - aliases: [ nic_name ] - default: [] - type: list - number_of_ports: - description: - - Number of port to configure on vSwitch. - default: 128 - type: int - mtu: - description: - - MTU to configure on vSwitch. - default: 1500 - type: int - state: - description: - - Add or remove the switch. - default: present - choices: [ absent, present ] - type: str - esxi_hostname: - description: - - Manage the vSwitch using this ESXi host system. - version_added: "2.5" - aliases: [ 'host' ] - type: str -extends_documentation_fragment: -- vmware.documentation -''' - -EXAMPLES = ''' -- name: Add a VMware vSwitch - vmware_vswitch: - hostname: '{{ esxi_hostname }}' - username: '{{ esxi_username }}' - password: '{{ esxi_password }}' - switch: vswitch_name - nics: vmnic_name - mtu: 9000 - delegate_to: localhost - -- name: Add a VMware vSwitch without any physical NIC attached - vmware_vswitch: - hostname: '{{ esxi_hostname }}' - username: '{{ esxi_username }}' - password: '{{ esxi_password }}' - switch: vswitch_0001 - mtu: 9000 - delegate_to: localhost - -- name: Add a VMware vSwitch with multiple NICs - vmware_vswitch: - hostname: '{{ esxi_hostname }}' - username: '{{ esxi_username }}' - password: '{{ esxi_password }}' - switch: vmware_vswitch_0004 - nics: - - vmnic1 - - vmnic2 - mtu: 9000 - delegate_to: localhost - -- name: Add a VMware vSwitch to a specific host system - vmware_vswitch: - hostname: '{{ esxi_hostname }}' - username: '{{ esxi_username }}' - password: '{{ esxi_password }}' - esxi_hostname: DC0_H0 - switch_name: vswitch_001 - nic_name: vmnic0 - mtu: 9000 - delegate_to: localhost -''' - -RETURN = """ -result: - description: information about performed operation - returned: always - type: str - sample: "vSwitch 'vSwitch_1002' is created successfully" -""" - -try: - from pyVmomi import vim, vmodl -except ImportError: - pass - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import PyVmomi, vmware_argument_spec -from ansible.module_utils._text import to_native - - -class VMwareHostVirtualSwitch(PyVmomi): - def __init__(self, module): - super(VMwareHostVirtualSwitch, self).__init__(module) - self.host_system = None - self.vss = None - self.switch = module.params['switch'] - self.number_of_ports = module.params['number_of_ports'] - self.nics = module.params['nics'] - self.mtu = module.params['mtu'] - self.state = module.params['state'] - esxi_hostname = module.params['esxi_hostname'] - - hosts = self.get_all_host_objs(esxi_host_name=esxi_hostname) - if hosts: - self.host_system = hosts[0] - else: - self.module.fail_json(msg="Failed to get details of ESXi server." - " Please specify esxi_hostname.") - - if self.params.get('state') == 'present': - # Gather information about all vSwitches and Physical NICs - network_manager = self.host_system.configManager.networkSystem - available_pnic = [pnic.device for pnic in network_manager.networkInfo.pnic] - self.available_vswitches = dict() - for available_vswitch in network_manager.networkInfo.vswitch: - used_pnic = [] - for pnic in available_vswitch.pnic: - # vSwitch contains all PNICs as string in format of 'key-vim.host.PhysicalNic-vmnic0' - m_pnic = pnic.split("-", 3)[-1] - used_pnic.append(m_pnic) - self.available_vswitches[available_vswitch.name] = dict(pnic=used_pnic, - mtu=available_vswitch.mtu, - num_ports=available_vswitch.spec.numPorts, - ) - for desired_pnic in self.nics: - if desired_pnic not in available_pnic: - # Check if pnic does not exists - self.module.fail_json(msg="Specified Physical NIC '%s' does not" - " exists on given ESXi '%s'." % (desired_pnic, - self.host_system.name)) - for vswitch in self.available_vswitches: - if desired_pnic in self.available_vswitches[vswitch]['pnic'] and vswitch != self.switch: - # Check if pnic is already part of some other vSwitch - self.module.fail_json(msg="Specified Physical NIC '%s' is already used" - " by vSwitch '%s'." % (desired_pnic, vswitch)) - - def process_state(self): - """ - Manage internal state of vSwitch - """ - vswitch_states = { - 'absent': { - 'present': self.state_destroy_vswitch, - 'absent': self.state_exit_unchanged, - }, - 'present': { - 'present': self.state_update_vswitch, - 'absent': self.state_create_vswitch, - } - } - - try: - vswitch_states[self.state][self.check_vswitch_configuration()]() - except vmodl.RuntimeFault as runtime_fault: - self.module.fail_json(msg=to_native(runtime_fault.msg)) - except vmodl.MethodFault as method_fault: - self.module.fail_json(msg=to_native(method_fault.msg)) - except Exception as e: - self.module.fail_json(msg=to_native(e)) - - def state_create_vswitch(self): - """ - Create a virtual switch - - Source from - https://github.com/rreubenur/pyvmomi-community-samples/blob/patch-1/samples/create_vswitch.py - - """ - - results = dict(changed=False, result="") - vss_spec = vim.host.VirtualSwitch.Specification() - vss_spec.numPorts = self.number_of_ports - vss_spec.mtu = self.mtu - if self.nics: - vss_spec.bridge = vim.host.VirtualSwitch.BondBridge(nicDevice=self.nics) - try: - network_mgr = self.host_system.configManager.networkSystem - if network_mgr: - network_mgr.AddVirtualSwitch(vswitchName=self.switch, - spec=vss_spec) - results['changed'] = True - results['result'] = "vSwitch '%s' is created successfully" % self.switch - else: - self.module.fail_json(msg="Failed to find network manager for ESXi system") - except vim.fault.AlreadyExists as already_exists: - results['result'] = "vSwitch with name %s already exists: %s" % (self.switch, - to_native(already_exists.msg)) - except vim.fault.ResourceInUse as resource_used: - self.module.fail_json(msg="Failed to add vSwitch '%s' as physical network adapter" - " being bridged is already in use: %s" % (self.switch, - to_native(resource_used.msg))) - except vim.fault.HostConfigFault as host_config_fault: - self.module.fail_json(msg="Failed to add vSwitch '%s' due to host" - " configuration fault : %s" % (self.switch, - to_native(host_config_fault.msg))) - except vmodl.fault.InvalidArgument as invalid_argument: - self.module.fail_json(msg="Failed to add vSwitch '%s', this can be due to either of following :" - " 1. vSwitch Name exceeds the maximum allowed length," - " 2. Number of ports specified falls out of valid range," - " 3. Network policy is invalid," - " 4. Beacon configuration is invalid : %s" % (self.switch, - to_native(invalid_argument.msg))) - except vmodl.fault.SystemError as system_error: - self.module.fail_json(msg="Failed to add vSwitch '%s' due to : %s" % (self.switch, - to_native(system_error.msg))) - except Exception as generic_exc: - self.module.fail_json(msg="Failed to add vSwitch '%s' due to" - " generic exception : %s" % (self.switch, - to_native(generic_exc))) - self.module.exit_json(**results) - - def state_exit_unchanged(self): - """ - Declare exit without unchanged - """ - self.module.exit_json(changed=False) - - def state_destroy_vswitch(self): - """ - Remove vSwitch from configuration - - """ - results = dict(changed=False, result="") - - try: - self.host_system.configManager.networkSystem.RemoveVirtualSwitch(self.vss.name) - results['changed'] = True - results['result'] = "vSwitch '%s' removed successfully." % self.vss.name - except vim.fault.NotFound as vswitch_not_found: - results['result'] = "vSwitch '%s' not available. %s" % (self.switch, - to_native(vswitch_not_found.msg)) - except vim.fault.ResourceInUse as vswitch_in_use: - self.module.fail_json(msg="Failed to remove vSwitch '%s' as vSwitch" - " is used by several virtual" - " network adapters: %s" % (self.switch, - to_native(vswitch_in_use.msg))) - except vim.fault.HostConfigFault as host_config_fault: - self.module.fail_json(msg="Failed to remove vSwitch '%s' due to host" - " configuration fault : %s" % (self.switch, - to_native(host_config_fault.msg))) - except Exception as generic_exc: - self.module.fail_json(msg="Failed to remove vSwitch '%s' due to generic" - " exception : %s" % (self.switch, - to_native(generic_exc))) - - self.module.exit_json(**results) - - def state_update_vswitch(self): - """ - Update vSwitch - - """ - results = dict(changed=False, result="No change in vSwitch '%s'" % self.switch) - vswitch_pnic_info = self.available_vswitches[self.switch] - remain_pnic = [] - for desired_pnic in self.nics: - if desired_pnic not in vswitch_pnic_info['pnic']: - remain_pnic.append(desired_pnic) - - diff = False - # Update all nics - all_nics = vswitch_pnic_info['pnic'] - if remain_pnic: - all_nics += remain_pnic - diff = True - - if vswitch_pnic_info['mtu'] != self.mtu or \ - vswitch_pnic_info['num_ports'] != self.number_of_ports: - diff = True - - try: - if diff: - vss_spec = vim.host.VirtualSwitch.Specification() - if all_nics: - vss_spec.bridge = vim.host.VirtualSwitch.BondBridge(nicDevice=all_nics) - vss_spec.numPorts = self.number_of_ports - vss_spec.mtu = self.mtu - - network_mgr = self.host_system.configManager.networkSystem - if network_mgr: - network_mgr.UpdateVirtualSwitch(vswitchName=self.switch, - spec=vss_spec) - results['changed'] = True - results['result'] = "vSwitch '%s' is updated successfully" % self.switch - else: - self.module.fail_json(msg="Failed to find network manager for ESXi system.") - except vim.fault.ResourceInUse as resource_used: - self.module.fail_json(msg="Failed to update vSwitch '%s' as physical network adapter" - " being bridged is already in use: %s" % (self.switch, - to_native(resource_used.msg))) - except vim.fault.NotFound as not_found: - self.module.fail_json(msg="Failed to update vSwitch with name '%s'" - " as it does not exists: %s" % (self.switch, - to_native(not_found.msg))) - - except vim.fault.HostConfigFault as host_config_fault: - self.module.fail_json(msg="Failed to update vSwitch '%s' due to host" - " configuration fault : %s" % (self.switch, - to_native(host_config_fault.msg))) - except vmodl.fault.InvalidArgument as invalid_argument: - self.module.fail_json(msg="Failed to update vSwitch '%s', this can be due to either of following :" - " 1. vSwitch Name exceeds the maximum allowed length," - " 2. Number of ports specified falls out of valid range," - " 3. Network policy is invalid," - " 4. Beacon configuration is invalid : %s" % (self.switch, - to_native(invalid_argument.msg))) - except vmodl.fault.SystemError as system_error: - self.module.fail_json(msg="Failed to update vSwitch '%s' due to : %s" % (self.switch, - to_native(system_error.msg))) - except vmodl.fault.NotSupported as not_supported: - self.module.fail_json(msg="Failed to update vSwitch '%s' as network adapter teaming policy" - " is set but is not supported : %s" % (self.switch, - to_native(not_supported.msg))) - except Exception as generic_exc: - self.module.fail_json(msg="Failed to update vSwitch '%s' due to" - " generic exception : %s" % (self.switch, - to_native(generic_exc))) - self.module.exit_json(**results) - - def check_vswitch_configuration(self): - """ - Check if vSwitch exists - Returns: 'present' if vSwitch exists or 'absent' if not - - """ - self.vss = self.find_vswitch_by_name(self.host_system, self.switch) - if self.vss is None: - return 'absent' - else: - return 'present' - - @staticmethod - def find_vswitch_by_name(host, vswitch_name): - """ - Find and return vSwitch managed object - Args: - host: Host system managed object - vswitch_name: Name of vSwitch to find - - Returns: vSwitch managed object if found, else None - - """ - for vss in host.configManager.networkSystem.networkInfo.vswitch: - if vss.name == vswitch_name: - return vss - return None - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update(dict( - switch=dict(type='str', required=True, aliases=['switch_name']), - nics=dict(type='list', aliases=['nic_name'], default=[]), - number_of_ports=dict(type='int', default=128), - mtu=dict(type='int', default=1500), - state=dict(type='str', default='present', choices=['absent', 'present'])), - esxi_hostname=dict(type='str', aliases=['host']), - ) - - module = AnsibleModule(argument_spec=argument_spec, - supports_check_mode=False) - - host_virtual_switch = VMwareHostVirtualSwitch(module) - host_virtual_switch.process_state() - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vmware_vswitch_info.py b/lib/ansible/modules/cloud/vmware/vmware_vswitch_info.py deleted file mode 100644 index 0732547df5..0000000000 --- a/lib/ansible/modules/cloud/vmware/vmware_vswitch_info.py +++ /dev/null @@ -1,157 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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_vswitch_info -short_description: Gathers info about an ESXi host's vswitch configurations -description: -- This module can be used to gather information about an ESXi host's vswitch configurations when ESXi hostname or Cluster name is given. -- The vSphere Client shows the value for the number of ports as elastic from vSphere 5.5 and above. -- Other tools like esxcli might show the number of ports as 1536 or 5632. -- See U(https://kb.vmware.com/s/article/2064511) for more details. -version_added: '2.9' -author: -- Abhijeet Kasurde (@Akasurde) -notes: -- Tested on vSphere 6.5 -requirements: -- python >= 2.6 -- PyVmomi -options: - cluster_name: - description: - - Name of the cluster. - - Info about vswitch belonging to every ESXi host systems under this cluster will be returned. - - If C(esxi_hostname) is not given, this parameter is required. - type: str - esxi_hostname: - description: - - ESXi hostname to gather information from. - - If C(cluster_name) is not given, this parameter is required. - type: str -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = r''' -- name: Gather vswitch info about all ESXi Host in given Cluster - vmware_vswitch_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: '{{ cluster_name }}' - delegate_to: localhost - register: all_hosts_vswitch_info - -- name: Gather firewall info about ESXi Host - vmware_vswitch_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: '{{ esxi_hostname }}' - delegate_to: localhost - register: all_vswitch_info -''' - -RETURN = r''' -hosts_vswitch_info: - description: metadata about host's vswitch configuration - returned: on success - type: dict - sample: { - "10.76.33.218": { - "vSwitch0": { - "mtu": 1500, - "num_ports": 128, - "pnics": [ - "vmnic0" - ] - }, - "vSwitch_0011": { - "mtu": 1500, - "num_ports": 128, - "pnics": [ - "vmnic2", - "vmnic1" - ] - }, - }, - } -''' - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.vmware import vmware_argument_spec, PyVmomi - - -class VswitchInfoManager(PyVmomi): - """Class to gather vSwitch info""" - def __init__(self, module): - super(VswitchInfoManager, self).__init__(module) - cluster_name = self.params.get('cluster_name', None) - esxi_host_name = self.params.get('esxi_hostname', None) - self.hosts = self.get_all_host_objs(cluster_name=cluster_name, esxi_host_name=esxi_host_name) - if not self.hosts: - self.module.fail_json(msg="Failed to find host system.") - - @staticmethod - def serialize_pnics(vswitch_obj): - """Get pnic names""" - pnics = [] - for pnic in vswitch_obj.pnic: - # vSwitch contains all PNICs as string in format of 'key-vim.host.PhysicalNic-vmnic0' - pnics.append(pnic.split("-", 3)[-1]) - return pnics - - def gather_vswitch_info(self): - """Gather vSwitch info""" - hosts_vswitch_info = dict() - for host in self.hosts: - network_manager = host.configManager.networkSystem - if network_manager: - temp_switch_dict = dict() - for available_vswitch in network_manager.networkInfo.vswitch: - temp_switch_dict[available_vswitch.name] = dict( - pnics=self.serialize_pnics(available_vswitch), - mtu=available_vswitch.mtu, - # we need to use the spec to get the ports - # otherwise, the output might be different compared to the vswitch config module - # (e.g. 5632 ports instead of 128) - num_ports=available_vswitch.spec.numPorts - ) - hosts_vswitch_info[host.name] = temp_switch_dict - return hosts_vswitch_info - - -def main(): - """Main""" - argument_spec = vmware_argument_spec() - argument_spec.update( - cluster_name=dict(type='str', required=False), - esxi_hostname=dict(type='str', required=False), - ) - - module = AnsibleModule( - argument_spec=argument_spec, - required_one_of=[ - ['cluster_name', 'esxi_hostname'], - ], - supports_check_mode=True - ) - - vmware_vswitch_mgr = VswitchInfoManager(module) - module.exit_json(changed=False, hosts_vswitch_info=vmware_vswitch_mgr.gather_vswitch_info()) - - -if __name__ == "__main__": - main() diff --git a/lib/ansible/modules/cloud/vmware/vsphere_copy.py b/lib/ansible/modules/cloud/vmware/vsphere_copy.py deleted file mode 100644 index 3ded0d9673..0000000000 --- a/lib/ansible/modules/cloud/vmware/vsphere_copy.py +++ /dev/null @@ -1,228 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2015, Dag Wieers (@dagwieers) <dag@wieers.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 = ''' ---- -module: vsphere_copy -short_description: Copy a file to a VMware datastore -description: - - Upload files to a VMware datastore through a vCenter REST API. -version_added: 2.0 -author: -- Dag Wieers (@dagwieers) -options: - hostname: - version_added: "2.9" - aliases: ['host'] - port: - version_added: "2.9" - username: - version_added: "2.9" - aliases: ['login'] - src: - description: - - The file to push to vCenter. - required: true - type: str - datacenter: - description: - - The datacenter on the vCenter server that holds the datastore. - required: false - type: str - datastore: - description: - - The datastore to push files to. - required: true - type: str - path: - description: - - The file to push to the datastore. - required: true - type: str - timeout: - description: - - The timeout in seconds for the upload to the datastore. - default: 10 - type: int - version_added: "2.8" - -notes: - - "This module ought to be run from a system that can access the vCenter or the ESXi directly and has the file to transfer. - It can be the normal remote target or you can change it either by using C(transport: local) or using C(delegate_to)." - - Tested on vSphere 5.5 and ESXi 6.7 -extends_documentation_fragment: vmware.documentation -''' - -EXAMPLES = ''' -- name: Copy file to datastore using delegate_to - vsphere_copy: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - src: /some/local/file - datacenter: DC1 Someplace - datastore: datastore1 - path: some/remote/file - delegate_to: localhost - -- name: Copy file to datastore when datacenter is inside folder called devel - vsphere_copy: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - src: /some/local/file - datacenter: devel/DC1 - datastore: datastore1 - path: some/remote/file - delegate_to: localhost - -- name: Copy file to datastore using other_system - vsphere_copy: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - src: /other/local/file - datacenter: DC2 Someplace - datastore: datastore2 - path: other/remote/file - delegate_to: other_system -''' - -import atexit -import errno -import mmap -import os -import socket -import traceback - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.six.moves.urllib.parse import urlencode, quote -from ansible.module_utils._text import to_native -from ansible.module_utils.urls import open_url -from ansible.module_utils.vmware import vmware_argument_spec - - -def vmware_path(datastore, datacenter, path): - ''' Constructs a URL path that vSphere accepts reliably ''' - path = "/folder/%s" % quote(path.lstrip("/")) - # Due to a software bug in vSphere, it fails to handle ampersand in datacenter names - # The solution is to do what vSphere does (when browsing) and double-encode ampersands, maybe others ? - if not path.startswith("/"): - path = "/" + path - params = dict(dsName=datastore) - if datacenter: - datacenter = datacenter.replace('&', '%26') - params["dcPath"] = datacenter - params = urlencode(params) - return "%s?%s" % (path, params) - - -def main(): - argument_spec = vmware_argument_spec() - argument_spec.update(dict( - hostname=dict(required=False, aliases=['host']), - username=dict(required=False, aliases=['login']), - src=dict(required=True, aliases=['name']), - datacenter=dict(required=False), - datastore=dict(required=True), - dest=dict(required=True, aliases=['path']), - timeout=dict(default=10, type='int')) - ) - - module = AnsibleModule( - argument_spec=argument_spec, - # Implementing check-mode using HEAD is impossible, since size/date is not 100% reliable - supports_check_mode=False, - ) - - if module.params.get('host'): - module.deprecate("The 'host' option is being replaced by 'hostname'", version='2.12') - if module.params.get('login'): - module.deprecate("The 'login' option is being replaced by 'username'", version='2.12') - - hostname = module.params['hostname'] - username = module.params['username'] - password = module.params.get('password') - src = module.params.get('src') - datacenter = module.params.get('datacenter') - datastore = module.params.get('datastore') - dest = module.params.get('dest') - validate_certs = module.params.get('validate_certs') - timeout = module.params.get('timeout') - - try: - fd = open(src, "rb") - atexit.register(fd.close) - except Exception as e: - module.fail_json(msg="Failed to open src file %s" % to_native(e)) - - if os.stat(src).st_size == 0: - data = '' - else: - data = mmap.mmap(fd.fileno(), 0, access=mmap.ACCESS_READ) - atexit.register(data.close) - - remote_path = vmware_path(datastore, datacenter, dest) - - if not all([hostname, username, password]): - module.fail_json(msg="One of following parameter is missing - hostname, username, password") - url = 'https://%s%s' % (hostname, remote_path) - - headers = { - "Content-Type": "application/octet-stream", - "Content-Length": str(len(data)), - } - - try: - r = open_url(url, data=data, headers=headers, method='PUT', timeout=timeout, - url_username=username, url_password=password, validate_certs=validate_certs, - force_basic_auth=True) - except socket.error as e: - if isinstance(e.args, tuple): - if len(e.args) > 0: - if e[0] == errno.ECONNRESET: - # vSphere resets connection if the file is in use and cannot be replaced - module.fail_json(msg='Failed to upload, image probably in use', status=None, errno=e[0], reason=to_native(e), url=url) - else: - module.fail_json(msg=to_native(e)) - else: - module.fail_json(msg=str(e), status=None, errno=e[0], reason=str(e), - url=url, exception=traceback.format_exc()) - except Exception as e: - error_code = -1 - try: - if isinstance(e[0], int): - error_code = e[0] - except (KeyError, TypeError): - pass - module.fail_json(msg=to_native(e), status=None, errno=error_code, - reason=to_native(e), url=url, exception=traceback.format_exc()) - - status = r.getcode() - if 200 <= status < 300: - module.exit_json(changed=True, status=status, reason=r.msg, url=url) - else: - length = r.headers.get('content-length', None) - if r.headers.get('transfer-encoding', '').lower() == 'chunked': - chunked = 1 - else: - chunked = 0 - - module.fail_json(msg='Failed to upload', errno=None, status=status, reason=r.msg, length=length, headers=dict(r.headers), chunked=chunked, url=url) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/modules/cloud/vmware/vsphere_file.py b/lib/ansible/modules/cloud/vmware/vsphere_file.py deleted file mode 100644 index 942b6daa70..0000000000 --- a/lib/ansible/modules/cloud/vmware/vsphere_file.py +++ /dev/null @@ -1,355 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: (c) 2017, Dag Wieers (@dagwieers) <dag@wieers.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: vsphere_file -short_description: Manage files on a vCenter datastore -description: -- Manage files on a vCenter datastore. -version_added: '2.8' -author: -- Dag Wieers (@dagwieers) -options: - host: - description: - - The vCenter server on which the datastore is available. - type: str - required: true - aliases: [ hostname ] - username: - description: - - The user name to authenticate on the vCenter server. - type: str - required: true - password: - description: - - The password to authenticate on the vCenter server. - type: str - required: true - datacenter: - description: - - The datacenter on the vCenter server that holds the datastore. - type: str - required: true - datastore: - description: - - The datastore on the vCenter server to push files to. - type: str - required: true - path: - description: - - The file or directory on the datastore on the vCenter server. - type: str - required: true - aliases: [ dest ] - validate_certs: - description: - - If C(no), SSL certificates will not be validated. This should only be - set to C(no) when no other option exists. - type: bool - default: yes - timeout: - description: - - The timeout in seconds for the upload to the datastore. - type: int - default: 10 - state: - description: - - The state of or the action on the provided path. - - If C(absent), the file will be removed. - - If C(directory), the directory will be created. - - If C(file), more information of the (existing) file will be returned. - - If C(touch), an empty file will be created if the path does not exist. - type: str - choices: [ absent, directory, file, touch ] - default: file -notes: -- The vSphere folder API does not allow to remove directory objects. -''' - -EXAMPLES = r''' -- name: Create an empty file on a datastore - vsphere_file: - host: '{{ vhost }}' - username: '{{ vuser }}' - password: '{{ vpass }}' - datacenter: DC1 Someplace - datastore: datastore1 - path: some/remote/file - state: touch - delegate_to: localhost - -- name: Create a directory on a datastore - vsphere_file: - host: '{{ vhost }}' - username: '{{ vuser }}' - password: '{{ vpass }}' - src: /other/local/file - datacenter: DC2 Someplace - datastore: datastore2 - path: other/remote/file - state: directory - delegate_to: localhost - -- name: Query a file on a datastore - vsphere_file: - host: '{{ vhost }}' - username: '{{ vuser }}' - password: '{{ vpass }}' - datacenter: DC1 Someplace - datastore: datastore1 - path: some/remote/file - state: touch - delegate_to: localhost - ignore_errors: yes - -- name: Delete a file on a datastore - vsphere_file: - host: '{{ vhost }}' - username: '{{ vuser }}' - password: '{{ vpass }}' - datacenter: DC2 Someplace - datastore: datastore2 - path: other/remote/file - state: absent - delegate_to: localhost -''' - -RETURN = r''' -''' - -import socket -import sys - -from ansible.module_utils.basic import AnsibleModule -from ansible.module_utils.six import PY2 -from ansible.module_utils.six.moves.urllib.error import HTTPError -from ansible.module_utils.six.moves.urllib.parse import quote, urlencode -from ansible.module_utils.urls import open_url -from ansible.module_utils._text import to_native - - -def vmware_path(datastore, datacenter, path): - ''' Constructs a URL path that VSphere accepts reliably ''' - path = '/folder/{path}'.format(path=quote(path.strip('/'))) - # Due to a software bug in vSphere, it fails to handle ampersand in datacenter names - # The solution is to do what vSphere does (when browsing) and double-encode ampersands, maybe others ? - datacenter = datacenter.replace('&', '%26') - if not path.startswith('/'): - path = '/' + path - params = dict(dsName=datastore) - if datacenter: - params['dcPath'] = datacenter - return '{0}?{1}'.format(path, urlencode(params)) - - -def main(): - - module = AnsibleModule( - argument_spec=dict( - host=dict(type='str', required=True, aliases=['hostname']), - username=dict(type='str', required=True), - password=dict(type='str', required=True, no_log=True), - datacenter=dict(type='str', required=True), - datastore=dict(type='str', required=True), - path=dict(type='str', required=True, aliases=['dest']), - state=dict(type='str', default='file', choices=['absent', 'directory', 'file', 'touch']), - timeout=dict(type='int', default=10), - validate_certs=dict(type='bool', default=True), - ), - supports_check_mode=True, - ) - - host = module.params.get('host') - username = module.params.get('username') - password = module.params.get('password') - src = module.params.get('src') - datacenter = module.params.get('datacenter') - datastore = module.params.get('datastore') - path = module.params.get('path') - validate_certs = module.params.get('validate_certs') - timeout = module.params.get('timeout') - state = module.params.get('state') - - remote_path = vmware_path(datastore, datacenter, path) - url = 'https://%s%s' % (host, remote_path) - - result = dict( - path=path, - size=None, - state=state, - status=None, - url=url, - ) - - # Check if the file/directory exists - try: - r = open_url(url, method='HEAD', timeout=timeout, - url_username=username, url_password=password, - validate_certs=validate_certs, force_basic_auth=True) - except HTTPError as e: - r = e - except socket.error as e: - module.fail_json(msg=to_native(e), errno=e[0], reason=to_native(e), **result) - except Exception as e: - module.fail_json(msg=to_native(e), errno=dir(e), reason=to_native(e), **result) - - if PY2: - sys.exc_clear() # Avoid false positive traceback in fail_json() on Python 2 - - status = r.getcode() - if status == 200: - exists = True - result['size'] = int(r.headers.get('content-length', None)) - elif status == 404: - exists = False - else: - result['reason'] = r.msg - result['status'] = status - module.fail_json(msg="Failed to query for file '%s'" % path, errno=None, headers=dict(r.headers), **result) - - if state == 'absent': - if not exists: - module.exit_json(changed=False, **result) - - if module.check_mode: - result['reason'] = 'No Content' - result['status'] = 204 - else: - try: - r = open_url(url, method='DELETE', timeout=timeout, - url_username=username, url_password=password, - validate_certs=validate_certs, force_basic_auth=True) - except HTTPError as e: - r = e - except socket.error as e: - module.fail_json(msg=to_native(e), errno=e[0], reason=to_native(e), **result) - except Exception as e: - module.fail_json(msg=to_native(e), errno=e[0], reason=to_native(e), **result) - - if PY2: - sys.exc_clear() # Avoid false positive traceback in fail_json() on Python 2 - - result['reason'] = r.msg - result['status'] = r.getcode() - - if result['status'] == 405: - result['state'] = 'directory' - module.fail_json(msg='Directories cannot be removed with this module', errno=None, headers=dict(r.headers), **result) - elif result['status'] != 204: - module.fail_json(msg="Failed to remove '%s'" % path, errno=None, headers=dict(r.headers), **result) - - result['size'] = None - module.exit_json(changed=True, **result) - - # NOTE: Creating a file in a non-existing directory, then remove the file - elif state == 'directory': - if exists: - module.exit_json(changed=False, **result) - - if module.check_mode: - result['reason'] = 'Created' - result['status'] = 201 - else: - # Create a temporary file in the new directory - remote_path = vmware_path(datastore, datacenter, path + '/foobar.tmp') - temp_url = 'https://%s%s' % (host, remote_path) - - try: - r = open_url(temp_url, method='PUT', timeout=timeout, - url_username=username, url_password=password, - validate_certs=validate_certs, force_basic_auth=True) - except HTTPError as e: - r = e - except socket.error as e: - module.fail_json(msg=to_native(e), errno=e[0], reason=to_native(e), **result) - except Exception as e: - module.fail_json(msg=to_native(e), errno=e[0], reason=to_native(e), **result) - - if PY2: - sys.exc_clear() # Avoid false positive traceback in fail_json() on Python 2 - - result['reason'] = r.msg - result['status'] = r.getcode() - if result['status'] != 201: - result['url'] = temp_url - module.fail_json(msg='Failed to create temporary file', errno=None, headers=dict(r.headers), **result) - - try: - r = open_url(temp_url, method='DELETE', timeout=timeout, - url_username=username, url_password=password, - validate_certs=validate_certs, force_basic_auth=True) - except HTTPError as e: - r = e - except socket.error as e: - module.fail_json(msg=to_native(e), errno=e[0], reason=to_native(e), **result) - except Exception as e: - module.fail_json(msg=to_native(e), errno=e[0], reason=to_native(e), **result) - - if PY2: - sys.exc_clear() # Avoid false positive traceback in fail_json() on Python 2 - - status = r.getcode() - if status != 204: - result['reason'] = r.msg - result['status'] = status - module.warn('Failed to remove temporary file ({reason})'.format(**result)) - - module.exit_json(changed=True, **result) - - elif state == 'file': - - if not exists: - result['state'] = 'absent' - result['status'] = status - module.fail_json(msg="File '%s' is absent, cannot continue" % path, **result) - - result['status'] = status - module.exit_json(changed=False, **result) - - elif state == 'touch': - if exists: - result['state'] = 'file' - module.exit_json(changed=False, **result) - - if module.check_mode: - result['reason'] = 'Created' - result['status'] = 201 - else: - try: - r = open_url(url, method='PUT', timeout=timeout, - url_username=username, url_password=password, - validate_certs=validate_certs, force_basic_auth=True) - except HTTPError as e: - r = e - except socket.error as e: - module.fail_json(msg=to_native(e), errno=e[0], reason=to_native(e), **result) - except Exception as e: - module.fail_json(msg=to_native(e), errno=e[0], reason=to_native(e), **result) - - if PY2: - sys.exc_clear() # Avoid false positive traceback in fail_json() on Python 2 - - result['reason'] = r.msg - result['status'] = r.getcode() - if result['status'] != 201: - module.fail_json(msg="Failed to touch '%s'" % path, errno=None, headers=dict(r.headers), **result) - - result['size'] = 0 - result['state'] = 'file' - module.exit_json(changed=True, **result) - - -if __name__ == '__main__': - main() diff --git a/lib/ansible/plugins/connection/vmware_tools.py b/lib/ansible/plugins/connection/vmware_tools.py deleted file mode 100644 index 6ce4f8731f..0000000000 --- a/lib/ansible/plugins/connection/vmware_tools.py +++ /dev/null @@ -1,579 +0,0 @@ -# Copyright: (c) 2018, Deric Crago <deric.crago@gmail.com> -# Copyright: (c) 2018, Ansible Project -# 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 - -import re -from os.path import exists, getsize -from socket import gaierror -from ssl import SSLError -from time import sleep -import traceback - -REQUESTS_IMP_ERR = None -try: - import requests - HAS_REQUESTS = True -except ImportError: - REQUESTS_IMP_ERR = traceback.format_exc() - HAS_REQUESTS = False - -try: - from requests.packages import urllib3 - HAS_URLLIB3 = True -except ImportError: - try: - import urllib3 - HAS_URLLIB3 = True - except ImportError: - HAS_URLLIB3 = False - -from ansible.errors import AnsibleError, AnsibleFileNotFound, AnsibleConnectionFailure -from ansible.module_utils._text import to_bytes, to_native -from ansible.plugins.connection import ConnectionBase -from ansible.module_utils.basic import missing_required_lib - -try: - from pyVim.connect import Disconnect, SmartConnect, SmartConnectNoSSL - from pyVmomi import vim, vmodl - - HAS_PYVMOMI = True -except ImportError: - HAS_PYVMOMI = False - PYVMOMI_IMP_ERR = traceback.format_exc() - - -DOCUMENTATION = """ - author: Deric Crago <deric.crago@gmail.com> - connection: vmware_tools - short_description: Execute tasks inside a VM via VMware Tools - description: - - Use VMware tools to run tasks in, or put/fetch files to guest operating systems running in VMware infrastructure. - - In case of Windows VMs, set C(ansible_shell_type) to C(powershell). - - Does not work with 'become'. - version_added: "2.8" - requirements: - - pyvmomi (Python library) - - requests (Python library) - options: - vmware_host: - description: - - FQDN or IP Address for the connection (vCenter or ESXi Host). - env: - - name: VI_SERVER - - name: VMWARE_HOST - vars: - - name: ansible_host - - name: ansible_vmware_host - required: True - vmware_user: - description: - - Username for the connection. - - "Requires the following permissions on the VM: - - VirtualMachine.GuestOperations.Execute - - VirtualMachine.GuestOperations.Modify - - VirtualMachine.GuestOperations.Query" - env: - - name: VI_USERNAME - - name: VMWARE_USER - vars: - - name: ansible_vmware_user - required: True - vmware_password: - description: - - Password for the connection. - env: - - name: VI_PASSWORD - - name: VMWARE_PASSWORD - vars: - - name: ansible_vmware_password - required: True - vmware_port: - description: - - Port for the connection. - env: - - name: VI_PORTNUMBER - - name: VMWARE_PORT - vars: - - name: ansible_port - - name: ansible_vmware_port - required: False - default: 443 - validate_certs: - description: - - Verify SSL for the connection. - - "Note: This will validate certs for both C(vmware_host) and the ESXi host running the VM." - env: - - name: VMWARE_VALIDATE_CERTS - vars: - - name: ansible_vmware_validate_certs - default: True - type: bool - vm_path: - description: - - VM path absolute to the connection. - - "vCenter Example: C(Datacenter/vm/Discovered virtual machine/testVM)." - - "ESXi Host Example: C(ha-datacenter/vm/testVM)." - - Must include VM name, appended to 'folder' as would be passed to M(vmware_guest). - - Needs to include I(vm) between the Datacenter and the rest of the VM path. - - Datacenter default value for ESXi server is C(ha-datacenter). - - Folder I(vm) is not visible in the vSphere Web Client but necessary for VMware API to work. - vars: - - name: ansible_vmware_guest_path - required: True - vm_user: - description: - - VM username. - vars: - - name: ansible_user - - name: ansible_vmware_tools_user - required: True - vm_password: - description: - - Password for the user in guest operating system. - vars: - - name: ansible_password - - name: ansible_vmware_tools_password - required: True - exec_command_sleep_interval: - description: - - Time in seconds to sleep between execution of command. - vars: - - name: ansible_vmware_tools_exec_command_sleep_interval - default: 0.5 - type: float - file_chunk_size: - description: - - File chunk size. - - "(Applicable when writing a file to disk, example: using the C(fetch) module.)" - vars: - - name: ansible_vmware_tools_file_chunk_size - default: 128 - type: integer - executable: - description: - - shell to use for execution inside container - default: /bin/sh - ini: - - section: defaults - key: executable - env: - - name: ANSIBLE_EXECUTABLE - vars: - - name: ansible_executable - - name: ansible_vmware_tools_executable -""" - -EXAMPLES = r''' -# example vars.yml ---- -ansible_connection: vmware_tools - -ansible_vmware_host: vcenter.example.com -ansible_vmware_user: administrator@vsphere.local -ansible_vmware_password: Secr3tP4ssw0rd!12 -ansible_vmware_validate_certs: no # default is yes - -# vCenter Connection VM Path Example -ansible_vmware_guest_path: DATACENTER/vm/FOLDER/{{ inventory_hostname }} -# ESXi Connection VM Path Example -ansible_vmware_guest_path: ha-datacenter/vm/{{ inventory_hostname }} - -ansible_vmware_tools_user: root -ansible_vmware_tools_password: MyR00tPassw0rD - -# if the target VM guest is Windows set the 'ansible_shell_type' to 'powershell' -ansible_shell_type: powershell - - -# example playbook_linux.yml ---- -- name: Test VMware Tools Connection Plugin for Linux - hosts: linux - tasks: - - command: whoami - - - ping: - - - copy: - src: foo - dest: /home/user/foo - - - fetch: - src: /home/user/foo - dest: linux-foo - flat: yes - - - file: - path: /home/user/foo - state: absent - - -# example playbook_windows.yml ---- -- name: Test VMware Tools Connection Plugin for Windows - hosts: windows - tasks: - - win_command: whoami - - - win_ping: - - - win_copy: - src: foo - dest: C:\Users\user\foo - - - fetch: - src: C:\Users\user\foo - dest: windows-foo - flat: yes - - - win_file: - path: C:\Users\user\foo - state: absent -''' - - -class Connection(ConnectionBase): - """VMware Tools Connection.""" - - transport = "vmware_tools" - - @property - def vmware_host(self): - """Read-only property holding the connection address.""" - return self.get_option("vmware_host") - - @property - def validate_certs(self): - """Read-only property holding whether the connection should validate certs.""" - return self.get_option("validate_certs") - - @property - def authManager(self): - """Guest Authentication Manager.""" - return self._si.content.guestOperationsManager.authManager - - @property - def fileManager(self): - """Guest File Manager.""" - return self._si.content.guestOperationsManager.fileManager - - @property - def processManager(self): - """Guest Process Manager.""" - return self._si.content.guestOperationsManager.processManager - - @property - def windowsGuest(self): - """Return if VM guest family is windows.""" - return self.vm.guest.guestFamily == "windowsGuest" - - def __init__(self, *args, **kwargs): - """init.""" - super(Connection, self).__init__(*args, **kwargs) - if hasattr(self, "_shell") and self._shell.SHELL_FAMILY == "powershell": - self.module_implementation_preferences = (".ps1", ".exe", "") - self.become_methods = ["runas"] - self.allow_executable = False - self.has_pipelining = False - self.allow_extras = True - self._si = None - - def _establish_connection(self): - connection_kwargs = { - "host": self.vmware_host, - "user": self.get_option("vmware_user"), - "pwd": self.get_option("vmware_password"), - "port": self.get_option("vmware_port"), - } - - if self.validate_certs: - connect = SmartConnect - else: - if HAS_URLLIB3: - urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) - connect = SmartConnectNoSSL - - try: - self._si = connect(**connection_kwargs) - except SSLError: - raise AnsibleError("SSL Error: Certificate verification failed.") - except (gaierror): - raise AnsibleError("Connection Error: Unable to connect to '%s'." % to_native(connection_kwargs["host"])) - except vim.fault.InvalidLogin as e: - raise AnsibleError("Connection Login Error: %s" % to_native(e.msg)) - - def _establish_vm(self, check_vm_credentials=True): - searchIndex = self._si.content.searchIndex - self.vm = searchIndex.FindByInventoryPath(self.get_option("vm_path")) - - if self.vm is None: - raise AnsibleError("Unable to find VM by path '%s'" % to_native(self.get_option("vm_path"))) - - self.vm_auth = vim.NamePasswordAuthentication( - username=self.get_option("vm_user"), password=self.get_option("vm_password"), interactiveSession=False - ) - - try: - if check_vm_credentials: - self.authManager.ValidateCredentialsInGuest(vm=self.vm, auth=self.vm_auth) - except vim.fault.InvalidPowerState as e: - raise AnsibleError("VM Power State Error: %s" % to_native(e.msg)) - except vim.fault.RestrictedVersion as e: - raise AnsibleError("Restricted Version Error: %s" % to_native(e.msg)) - except vim.fault.GuestOperationsUnavailable as e: - raise AnsibleError("VM Guest Operations (VMware Tools) Error: %s" % to_native(e.msg)) - except vim.fault.InvalidGuestLogin as e: - raise AnsibleError("VM Login Error: %s" % to_native(e.msg)) - except vim.fault.NoPermission as e: - raise AnsibleConnectionFailure("No Permission Error: %s %s" % (to_native(e.msg), to_native(e.privilegeId))) - except vmodl.fault.SystemError as e: - if e.reason == 'vix error codes = (3016, 0).\n': - raise AnsibleConnectionFailure( - "Connection failed, is the vm currently rebooting? Reason: %s" % ( - to_native(e.reason) - ) - ) - else: - raise AnsibleConnectionFailure("Connection failed. Reason %s" % (to_native(e.reason))) - except vim.fault.GuestOperationsUnavailable: - raise AnsibleConnectionFailure("Cannot connect to guest. Native error: GuestOperationsUnavailable") - - def _connect(self, check_vm_credentials=True): - if not HAS_REQUESTS: - raise AnsibleError("%s : %s" % (missing_required_lib('requests'), REQUESTS_IMP_ERR)) - - if not HAS_PYVMOMI: - raise AnsibleError("%s : %s" % (missing_required_lib('PyVmomi'), PYVMOMI_IMP_ERR)) - - super(Connection, self)._connect() - - if not self.connected: - self._establish_connection() - self._establish_vm(check_vm_credentials=check_vm_credentials) - self._connected = True - - def close(self): - """Close connection.""" - super(Connection, self).close() - - Disconnect(self._si) - self._connected = False - - def reset(self): - """Reset the connection to vcenter.""" - # TODO: Fix persistent connection implementation currently ansible creates new connections to vcenter for each task - # therefore we're currently closing a non existing connection here and establish a connection just for being thrown away - # right afterwards. - self.close() - self._connect(check_vm_credentials=False) - - def create_temporary_file_in_guest(self, prefix="", suffix=""): - """Create a temporary file in the VM.""" - try: - return self.fileManager.CreateTemporaryFileInGuest(vm=self.vm, auth=self.vm_auth, prefix=prefix, suffix=suffix) - except vim.fault.NoPermission as e: - raise AnsibleError("No Permission Error: %s %s" % (to_native(e.msg), to_native(e.privilegeId))) - except vmodl.fault.SystemError as e: - if e.reason == 'vix error codes = (3016, 0).\n': - raise AnsibleConnectionFailure( - "Connection failed, is the vm currently rebooting? Reason: %s" % ( - to_native(e.reason) - ) - ) - else: - raise AnsibleConnectionFailure("Connection failed. Reason %s" % (to_native(e.reason))) - except vim.fault.GuestOperationsUnavailable: - raise AnsibleConnectionFailure("Cannot connect to guest. Native error: GuestOperationsUnavailable") - - def _get_program_spec_program_path_and_arguments(self, cmd): - if self.windowsGuest: - ''' - we need to warp the execution of powershell into a cmd /c because - the call otherwise fails with "Authentication or permission failure" - #FIXME: Fix the unecessary invocation of cmd and run the command directly - ''' - program_path = "cmd.exe" - arguments = "/c %s" % cmd - else: - program_path = self.get_option("executable") - arguments = re.sub(r"^%s\s*" % program_path, "", cmd) - - return program_path, arguments - - def _get_guest_program_spec(self, cmd, stdout, stderr): - guest_program_spec = vim.GuestProgramSpec() - - program_path, arguments = self._get_program_spec_program_path_and_arguments(cmd) - - arguments += " 1> %s 2> %s" % (stdout, stderr) - - guest_program_spec.programPath = program_path - guest_program_spec.arguments = arguments - - return guest_program_spec - - def _get_pid_info(self, pid): - try: - processes = self.processManager.ListProcessesInGuest(vm=self.vm, auth=self.vm_auth, pids=[pid]) - except vim.fault.NoPermission as e: - raise AnsibleError("No Permission Error: %s %s" % (to_native(e.msg), to_native(e.privilegeId))) - except vmodl.fault.SystemError as e: - # https://pubs.vmware.com/vsphere-6-5/index.jsp?topic=%2Fcom.vmware.wssdk.smssdk.doc%2Fvmodl.fault.SystemError.html - # https://github.com/ansible/ansible/issues/57607 - if e.reason == 'vix error codes = (1, 0).\n': - raise AnsibleConnectionFailure( - "Connection failed, Netlogon service stopped or dcpromo in progress. Reason: %s" % ( - to_native(e.reason) - ) - ) - else: - raise AnsibleConnectionFailure("Connection plugin failed. Reason: %s" % (to_native(e.reason))) - except vim.fault.GuestOperationsUnavailable: - raise AnsibleConnectionFailure("Cannot connect to guest. Native error: GuestOperationsUnavailable") - except vim.fault.InvalidGuestLogin: - raise AnsibleConnectionFailure("Guest login failed. Native error: InvalidGuestLogin") - - return processes[0] - - def _fix_url_for_hosts(self, url): - """ - Fix url if connection is a host. - - The host part of the URL is returned as '*' if the hostname to be used is the name of the server to which the call was made. For example, if the call is - made to esx-svr-1.domain1.com, and the file is available for download from http://esx-svr-1.domain1.com/guestFile?id=1&token=1234, the URL returned may - be http://*/guestFile?id=1&token=1234. The client replaces the asterisk with the server name on which it invoked the call. - - https://code.vmware.com/apis/358/vsphere#/doc/vim.vm.guest.FileManager.FileTransferInformation.html - """ - return url.replace("*", self.vmware_host) - - def _fetch_file_from_vm(self, guestFilePath): - try: - fileTransferInformation = self.fileManager.InitiateFileTransferFromGuest(vm=self.vm, auth=self.vm_auth, guestFilePath=guestFilePath) - except vim.fault.NoPermission as e: - raise AnsibleError("No Permission Error: %s %s" % (to_native(e.msg), to_native(e.privilegeId))) - except vmodl.fault.SystemError as e: - if e.reason == 'vix error codes = (3016, 0).\n': - raise AnsibleConnectionFailure( - "Connection failed, is the vm currently rebooting? Reason: %s" % ( - to_native(e.reason) - ) - ) - else: - raise AnsibleConnectionFailure("Connection failed. Reason %s" % (to_native(e.reason))) - except vim.fault.GuestOperationsUnavailable: - raise AnsibleConnectionFailure("Cannot connect to guest. Native error: GuestOperationsUnavailable") - - url = self._fix_url_for_hosts(fileTransferInformation.url) - response = requests.get(url, verify=self.validate_certs, stream=True) - - if response.status_code != 200: - raise AnsibleError("Failed to fetch file") - - return response - - def delete_file_in_guest(self, filePath): - """Delete file from VM.""" - try: - self.fileManager.DeleteFileInGuest(vm=self.vm, auth=self.vm_auth, filePath=filePath) - except vim.fault.NoPermission as e: - raise AnsibleError("No Permission Error: %s %s" % (to_native(e.msg), to_native(e.privilegeId))) - except vmodl.fault.SystemError as e: - if e.reason == 'vix error codes = (3016, 0).\n': - raise AnsibleConnectionFailure( - "Connection failed, is the vm currently rebooting? Reason: %s" % ( - to_native(e.reason) - ) - ) - else: - raise AnsibleConnectionFailure("Connection failed. Reason %s" % (to_native(e.reason))) - except vim.fault.GuestOperationsUnavailable: - raise AnsibleConnectionFailure("Cannot connect to guest. Native error: GuestOperationsUnavailable") - - def exec_command(self, cmd, in_data=None, sudoable=True): - """Execute command.""" - super(Connection, self).exec_command(cmd, in_data=in_data, sudoable=sudoable) - - stdout = self.create_temporary_file_in_guest(suffix=".stdout") - stderr = self.create_temporary_file_in_guest(suffix=".stderr") - - guest_program_spec = self._get_guest_program_spec(cmd, stdout, stderr) - - try: - pid = self.processManager.StartProgramInGuest(vm=self.vm, auth=self.vm_auth, spec=guest_program_spec) - except vim.fault.NoPermission as e: - raise AnsibleError("No Permission Error: %s %s" % (to_native(e.msg), to_native(e.privilegeId))) - except vim.fault.FileNotFound as e: - raise AnsibleError("StartProgramInGuest Error: %s" % to_native(e.msg)) - except vmodl.fault.SystemError as e: - if e.reason == 'vix error codes = (3016, 0).\n': - raise AnsibleConnectionFailure( - "Connection failed, is the vm currently rebooting? Reason: %s" % ( - to_native(e.reason) - ) - ) - else: - raise AnsibleConnectionFailure("Connection failed. Reason %s" % (to_native(e.reason))) - except vim.fault.GuestOperationsUnavailable: - raise AnsibleConnectionFailure("Cannot connect to guest. Native error: GuestOperationsUnavailable") - - pid_info = self._get_pid_info(pid) - - while pid_info.endTime is None: - sleep(self.get_option("exec_command_sleep_interval")) - pid_info = self._get_pid_info(pid) - - stdout_response = self._fetch_file_from_vm(stdout) - self.delete_file_in_guest(stdout) - - stderr_response = self._fetch_file_from_vm(stderr) - self.delete_file_in_guest(stderr) - - return pid_info.exitCode, stdout_response.text, stderr_response.text - - def fetch_file(self, in_path, out_path): - """Fetch file.""" - super(Connection, self).fetch_file(in_path, out_path) - - in_path_response = self._fetch_file_from_vm(in_path) - - with open(out_path, "wb") as fd: - for chunk in in_path_response.iter_content(chunk_size=self.get_option("file_chunk_size")): - fd.write(chunk) - - def put_file(self, in_path, out_path): - """Put file.""" - super(Connection, self).put_file(in_path, out_path) - - if not exists(to_bytes(in_path, errors="surrogate_or_strict")): - raise AnsibleFileNotFound("file or module does not exist: '%s'" % to_native(in_path)) - - try: - put_url = self.fileManager.InitiateFileTransferToGuest( - vm=self.vm, auth=self.vm_auth, guestFilePath=out_path, fileAttributes=vim.GuestFileAttributes(), fileSize=getsize(in_path), overwrite=True - ) - except vim.fault.NoPermission as e: - raise AnsibleError("No Permission Error: %s %s" % (to_native(e.msg), to_native(e.privilegeId))) - except vmodl.fault.SystemError as e: - if e.reason == 'vix error codes = (3016, 0).\n': - raise AnsibleConnectionFailure( - "Connection failed, is the vm currently rebooting? Reason: %s" % ( - to_native(e.reason) - ) - ) - else: - raise AnsibleConnectionFailure("Connection failed. Reason %s" % (to_native(e.reason))) - except vim.fault.GuestOperationsUnavailable: - raise AnsibleConnectionFailure("Cannot connect to guest. Native error: GuestOperationsUnavailable") - - url = self._fix_url_for_hosts(put_url) - - # file size of 'in_path' must be greater than 0 - with open(in_path, "rb") as fd: - response = requests.put(url, verify=self.validate_certs, data=fd) - - if response.status_code != 200: - raise AnsibleError("File transfer failed") diff --git a/lib/ansible/plugins/doc_fragments/vca.py b/lib/ansible/plugins/doc_fragments/vca.py deleted file mode 100644 index 1da072ccf5..0000000000 --- a/lib/ansible/plugins/doc_fragments/vca.py +++ /dev/null @@ -1,66 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright: (c) 2016, Charles Paul <cpaul@ansible.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - - -class ModuleDocFragment(object): - # Parameters for VCA modules - DOCUMENTATION = r''' -options: - username: - description: - - The vca username or email address, if not set the environment variable C(VCA_USER) is checked for the username. - type: str - aliases: [ user ] - password: - description: - - The vca password, if not set the environment variable C(VCA_PASS) is checked for the password. - type: str - aliases: [ pass, passwd] - org: - description: - - The org to login to for creating vapp. - - This option is required when the C(service_type) is I(vdc). - type: str - instance_id: - description: - - The instance ID in a vchs environment to be used for creating the vapp. - type: str - host: - description: - - The authentication host to be used when service type is vcd. - type: str - api_version: - description: - - The API version to be used with the vca. - type: str - default: "5.7" - service_type: - description: - - The type of service we are authenticating against. - type: str - choices: [ vca, vcd, vchs ] - default: vca - state: - description: - - Whether the object should be added or removed. - type: str - choices: [ absent, present ] - default: present - validate_certs: - description: - - If the certificates of the authentication is to be verified. - type: bool - default: yes - aliases: [ verify_certs ] - vdc_name: - description: - - The name of the vdc where the gateway is located. - type: str - gateway_name: - description: - - The name of the gateway of the vdc where the rule should be added. - type: str - default: gateway -''' diff --git a/lib/ansible/plugins/doc_fragments/vmware.py b/lib/ansible/plugins/doc_fragments/vmware.py deleted file mode 100644 index fdc70d4c3f..0000000000 --- a/lib/ansible/plugins/doc_fragments/vmware.py +++ /dev/null @@ -1,121 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright: (c) 2016, Charles Paul <cpaul@ansible.com> -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2019, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - - -class ModuleDocFragment(object): - # Parameters for VMware modules - DOCUMENTATION = r''' -options: - hostname: - description: - - The hostname or IP address of the vSphere vCenter or ESXi server. - - If the value is not specified in the task, the value of environment variable C(VMWARE_HOST) will be used instead. - - Environment variable support added in Ansible 2.6. - type: str - username: - description: - - The username of the vSphere vCenter or ESXi server. - - If the value is not specified in the task, the value of environment variable C(VMWARE_USER) will be used instead. - - Environment variable support added in Ansible 2.6. - type: str - aliases: [ admin, user ] - password: - description: - - The password of the vSphere vCenter or ESXi server. - - If the value is not specified in the task, the value of environment variable C(VMWARE_PASSWORD) will be used instead. - - Environment variable support added in Ansible 2.6. - type: str - aliases: [ pass, pwd ] - validate_certs: - description: - - Allows connection when SSL certificates are not valid. Set to C(false) when certificates are not trusted. - - If the value is not specified in the task, the value of environment variable C(VMWARE_VALIDATE_CERTS) will be used instead. - - Environment variable support added in Ansible 2.6. - - If set to C(yes), please make sure Python >= 2.7.9 is installed on the given machine. - type: bool - default: yes - port: - description: - - The port number of the vSphere vCenter or ESXi server. - - If the value is not specified in the task, the value of environment variable C(VMWARE_PORT) will be used instead. - - Environment variable support added in Ansible 2.6. - type: int - default: 443 - version_added: '2.5' - proxy_host: - description: - - Address of a proxy that will receive all HTTPS requests and relay them. - - The format is a hostname or a IP. - - If the value is not specified in the task, the value of environment variable C(VMWARE_PROXY_HOST) will be used instead. - - This feature depends on a version of pyvmomi greater than v6.7.1.2018.12 - type: str - version_added: '2.9' - required: False - proxy_port: - description: - - Port of the HTTP proxy that will receive all HTTPS requests and relay them. - - If the value is not specified in the task, the value of environment variable C(VMWARE_PROXY_PORT) will be used instead. - type: int - version_added: '2.9' - required: False -''' - - # This doc fragment is specific to vcenter modules like vcenter_license - VCENTER_DOCUMENTATION = r''' -options: - hostname: - description: - - The hostname or IP address of the vSphere vCenter server. - - If the value is not specified in the task, the value of environment variable C(VMWARE_HOST) will be used instead. - - Environment variable supported added in Ansible 2.6. - type: str - username: - description: - - The username of the vSphere vCenter server. - - If the value is not specified in the task, the value of environment variable C(VMWARE_USER) will be used instead. - - Environment variable supported added in Ansible 2.6. - type: str - aliases: [ admin, user ] - password: - description: - - The password of the vSphere vCenter server. - - If the value is not specified in the task, the value of environment variable C(VMWARE_PASSWORD) will be used instead. - - Environment variable supported added in Ansible 2.6. - type: str - aliases: [ pass, pwd ] - validate_certs: - description: - - Allows connection when SSL certificates are not valid. Set to C(false) when certificates are not trusted. - - If the value is not specified in the task, the value of environment variable C(VMWARE_VALIDATE_CERTS) will be used instead. - - Environment variable supported added in Ansible 2.6. - - If set to C(yes), please make sure Python >= 2.7.9 is installed on the given machine. - type: bool - default: yes - port: - description: - - The port number of the vSphere vCenter server. - - If the value is not specified in the task, the value of environment variable C(VMWARE_PORT) will be used instead. - - Environment variable supported added in Ansible 2.6. - type: int - default: 443 - version_added: '2.5' - proxy_host: - description: - - Address of a proxy that will receive all HTTPS requests and relay them. - - The format is a hostname or a IP. - - If the value is not specified in the task, the value of environment variable C(VMWARE_PROXY_HOST) will be used instead. - type: str - version_added: '2.9' - required: False - proxy_port: - description: - - Port of the HTTP proxy that will receive all HTTPS requests and relay them. - - If the value is not specified in the task, the value of environment variable C(VMWARE_PROXY_PORT) will be used instead. - type: int - version_added: '2.9' - required: False - ''' diff --git a/lib/ansible/plugins/doc_fragments/vmware_rest_client.py b/lib/ansible/plugins/doc_fragments/vmware_rest_client.py deleted file mode 100644 index 4ef45f915a..0000000000 --- a/lib/ansible/plugins/doc_fragments/vmware_rest_client.py +++ /dev/null @@ -1,49 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - - -class ModuleDocFragment(object): - # Parameters for VMware REST Client based modules - DOCUMENTATION = r''' -options: - hostname: - description: - - The hostname or IP address of the vSphere vCenter server. - - If the value is not specified in the task, the value of environment variable C(VMWARE_HOST) will be used instead. - type: str - username: - description: - - The username of the vSphere vCenter server. - - If the value is not specified in the task, the value of environment variable C(VMWARE_USER) will be used instead. - type: str - aliases: [ admin, user ] - password: - description: - - The password of the vSphere vCenter server. - - If the value is not specified in the task, the value of environment variable C(VMWARE_PASSWORD) will be used instead. - type: str - aliases: [ pass, pwd ] - validate_certs: - description: - - Allows connection when SSL certificates are not valid. - - Set to C(no) when certificates are not trusted. - - If the value is not specified in the task, the value of environment variable C(VMWARE_VALIDATE_CERTS) will be used instead. - type: bool - default: yes - port: - description: - - The port number of the vSphere vCenter. - - If the value is not specified in the task, the value of environment variable C(VMWARE_PORT) will be used instead. - type: int - default: 443 - version_added: '2.10' - protocol: - description: - - The connection to protocol. - type: str - choices: [ http, https ] - default: https -''' diff --git a/lib/ansible/plugins/httpapi/vmware.py b/lib/ansible/plugins/httpapi/vmware.py deleted file mode 100644 index 96bfa31969..0000000000 --- a/lib/ansible/plugins/httpapi/vmware.py +++ /dev/null @@ -1,85 +0,0 @@ -# Copyright: (c) 2018 Red Hat Inc. -# Copyright: (c) 2019, Ansible Project -# Copyright: (c) 2019, Abhijeet Kasurde <akasurde@redhat.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 - -DOCUMENTATION = """ ---- -author: Abhijeet Kasurde (Akasurde) -httpapi : vmware -short_description: HttpApi Plugin for VMware REST API -description: - - This HttpApi plugin provides methods to connect to VMware vCenter over a HTTP(S)-based APIs. -version_added: "2.10" -""" - -import json - -from ansible.module_utils.basic import to_text -from ansible.errors import AnsibleConnectionFailure -from ansible.module_utils.six.moves.urllib.error import HTTPError -from ansible.plugins.httpapi import HttpApiBase -from ansible.module_utils.connection import ConnectionError - -BASE_HEADERS = { - 'Content-Type': 'application/json', - 'Accept': 'application/json', -} - - -class HttpApi(HttpApiBase): - def login(self, username, password): - if username and password: - payload = {} - url = '/rest/com/vmware/cis/session' - response, response_data = self.send_request(url, payload) - else: - raise AnsibleConnectionFailure('Username and password are required for login') - - if response == 404: - raise ConnectionError(response_data) - - if not response_data.get('value'): - raise ConnectionError('Server returned response without token info during connection authentication: %s' % response) - - self.connection._session_uid = "vmware-api-session-id:%s" % response_data['value'] - self.connection._token = response_data['value'] - - def logout(self): - response, dummy = self.send_request('/rest/com/vmware/cis/session', None, method='DELETE') - - def get_session_uid(self): - return self.connection._session_uid - - def get_session_token(self): - return self.connection._token - - def send_request(self, path, body_params, method='POST'): - data = json.dumps(body_params) if body_params else '{}' - - try: - self._display_request(method=method) - response, response_data = self.connection.send(path, data, method=method, headers=BASE_HEADERS, force_basic_auth=True) - response_value = self._get_response_value(response_data) - - return response.getcode(), self._response_to_json(response_value) - except AnsibleConnectionFailure as e: - return 404, 'Object not found' - except HTTPError as e: - return e.code, json.loads(e.read()) - - def _display_request(self, method='POST'): - self.connection.queue_message('vvvv', 'Web Services: %s %s' % (method, self.connection._url)) - - def _get_response_value(self, response_data): - return to_text(response_data.getvalue()) - - def _response_to_json(self, response_text): - try: - return json.loads(response_text) if response_text else {} - # JSONDecodeError only available on Python 3.5+ - except ValueError: - raise ConnectionError('Invalid JSON response: %s' % response_text) diff --git a/lib/ansible/plugins/inventory/vmware_vm_inventory.py b/lib/ansible/plugins/inventory/vmware_vm_inventory.py deleted file mode 100644 index 816b6471c5..0000000000 --- a/lib/ansible/plugins/inventory/vmware_vm_inventory.py +++ /dev/null @@ -1,477 +0,0 @@ -# -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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 - -DOCUMENTATION = ''' - name: vmware_vm_inventory - plugin_type: inventory - short_description: VMware Guest inventory source - version_added: "2.7" - author: - - Abhijeet Kasurde (@Akasurde) - description: - - Get virtual machines as inventory hosts from VMware environment. - - Uses any file which ends with vmware.yml, vmware.yaml, vmware_vm_inventory.yml, or vmware_vm_inventory.yaml as a YAML configuration file. - - The inventory_hostname is always the 'Name' and UUID of the virtual machine. UUID is added as VMware allows virtual machines with the same name. - extends_documentation_fragment: - - inventory_cache - requirements: - - "Python >= 2.7" - - "PyVmomi" - - "requests >= 2.3" - - "vSphere Automation SDK - For tag feature" - - "vCloud Suite SDK - For tag feature" - options: - hostname: - description: Name of vCenter or ESXi server. - required: True - env: - - name: VMWARE_HOST - - name: VMWARE_SERVER - username: - description: Name of vSphere admin user. - required: True - env: - - name: VMWARE_USER - - name: VMWARE_USERNAME - password: - description: Password of vSphere admin user. - required: True - env: - - name: VMWARE_PASSWORD - port: - description: Port number used to connect to vCenter or ESXi Server. - default: 443 - env: - - name: VMWARE_PORT - validate_certs: - description: - - Allows connection when SSL certificates are not valid. Set to C(false) when certificates are not trusted. - default: True - type: boolean - env: - - name: VMWARE_VALIDATE_CERTS - with_tags: - description: - - Include tags and associated virtual machines. - - Requires 'vSphere Automation SDK' library to be installed on the given controller machine. - - Please refer following URLs for installation steps - - 'https://code.vmware.com/web/sdk/65/vsphere-automation-python' - default: False - type: boolean - properties: - description: - - Specify the list of VMware schema properties associated with the VM. - - These properties will be populated in hostvars of the given VM. - - Each value in the list specifies the path to a specific property in VM object. - type: list - default: [ 'name', 'config.cpuHotAddEnabled', 'config.cpuHotRemoveEnabled', - 'config.instanceUuid', 'config.hardware.numCPU', 'config.template', - 'config.name', 'guest.hostName', 'guest.ipAddress', - 'guest.guestId', 'guest.guestState', 'runtime.maxMemoryUsage', - 'customValue' - ] - version_added: "2.9" -''' - -EXAMPLES = ''' -# Sample configuration file for VMware Guest dynamic inventory - plugin: vmware_vm_inventory - strict: False - hostname: 10.65.223.31 - username: administrator@vsphere.local - password: Esxi@123$% - validate_certs: False - with_tags: True - -# Gather minimum set of properties for VMware guest - plugin: vmware_vm_inventory - strict: False - hostname: 10.65.223.31 - username: administrator@vsphere.local - password: Esxi@123$% - validate_certs: False - with_tags: False - properties: - - 'name' - - 'guest.ipAddress' -''' - -import ssl -import atexit -from ansible.errors import AnsibleError, AnsibleParserError - -try: - # requests is required for exception handling of the ConnectionError - import requests - HAS_REQUESTS = True -except ImportError: - HAS_REQUESTS = False - -try: - from pyVim import connect - from pyVmomi import vim, vmodl - HAS_PYVMOMI = True -except ImportError: - HAS_PYVMOMI = False - -try: - from com.vmware.vapi.std_client import DynamicID - from vmware.vapi.vsphere.client import create_vsphere_client - HAS_VSPHERE = True -except ImportError: - HAS_VSPHERE = False - - -from ansible.plugins.inventory import BaseInventoryPlugin, Cacheable - - -class BaseVMwareInventory: - def __init__(self, hostname, username, password, port, validate_certs, with_tags): - self.hostname = hostname - self.username = username - self.password = password - self.port = port - self.with_tags = with_tags - self.validate_certs = validate_certs - self.content = None - self.rest_content = None - - def do_login(self): - """ - Check requirements and do login - """ - self.check_requirements() - self.content = self._login() - if self.with_tags: - self.rest_content = self._login_vapi() - - def _login_vapi(self): - """ - Login to vCenter API using REST call - Returns: connection object - - """ - session = requests.Session() - session.verify = self.validate_certs - if not self.validate_certs: - # Disable warning shown at stdout - requests.packages.urllib3.disable_warnings() - - server = self.hostname - if self.port: - server += ":" + str(self.port) - client = create_vsphere_client(server=server, - username=self.username, - password=self.password, - session=session) - if client is None: - raise AnsibleError("Failed to login to %s using %s" % (server, self.username)) - return client - - def _login(self): - """ - Login to vCenter or ESXi server - Returns: connection object - - """ - if self.validate_certs and not hasattr(ssl, 'SSLContext'): - raise AnsibleError('pyVim does not support changing verification mode with python < 2.7.9. Either update ' - 'python or set validate_certs to false in configuration YAML file.') - - ssl_context = None - if not self.validate_certs and hasattr(ssl, 'SSLContext'): - ssl_context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) - ssl_context.verify_mode = ssl.CERT_NONE - - service_instance = None - try: - service_instance = connect.SmartConnect(host=self.hostname, user=self.username, - pwd=self.password, sslContext=ssl_context, - port=self.port) - except vim.fault.InvalidLogin as e: - raise AnsibleParserError("Unable to log on to vCenter or ESXi API at %s:%s as %s: %s" % (self.hostname, self.port, self.username, e.msg)) - except vim.fault.NoPermission as e: - raise AnsibleParserError("User %s does not have required permission" - " to log on to vCenter or ESXi API at %s:%s : %s" % (self.username, self.hostname, self.port, e.msg)) - except (requests.ConnectionError, ssl.SSLError) as e: - raise AnsibleParserError("Unable to connect to vCenter or ESXi API at %s on TCP/%s: %s" % (self.hostname, self.port, e)) - except vmodl.fault.InvalidRequest as e: - # Request is malformed - raise AnsibleParserError("Failed to get a response from server %s:%s as " - "request is malformed: %s" % (self.hostname, self.port, e.msg)) - except Exception as e: - raise AnsibleParserError("Unknown error while connecting to vCenter or ESXi API at %s:%s : %s" % (self.hostname, self.port, e)) - - if service_instance is None: - raise AnsibleParserError("Unknown error while connecting to vCenter or ESXi API at %s:%s" % (self.hostname, self.port)) - - atexit.register(connect.Disconnect, service_instance) - return service_instance.RetrieveContent() - - def check_requirements(self): - """ Check all requirements for this inventory are satisified""" - if not HAS_REQUESTS: - raise AnsibleParserError('Please install "requests" Python module as this is required' - ' for VMware Guest dynamic inventory plugin.') - elif not HAS_PYVMOMI: - raise AnsibleParserError('Please install "PyVmomi" Python module as this is required' - ' for VMware Guest dynamic inventory plugin.') - if HAS_REQUESTS: - # Pyvmomi 5.5 and onwards requires requests 2.3 - # https://github.com/vmware/pyvmomi/blob/master/requirements.txt - required_version = (2, 3) - requests_version = requests.__version__.split(".")[:2] - try: - requests_major_minor = tuple(map(int, requests_version)) - except ValueError: - raise AnsibleParserError("Failed to parse 'requests' library version.") - - if requests_major_minor < required_version: - raise AnsibleParserError("'requests' library version should" - " be >= %s, found: %s." % (".".join([str(w) for w in required_version]), - requests.__version__)) - - if not HAS_VSPHERE and self.with_tags: - raise AnsibleError("Unable to find 'vSphere Automation SDK' Python library which is required." - " Please refer this URL for installation steps" - " - https://code.vmware.com/web/sdk/65/vsphere-automation-python") - - if not all([self.hostname, self.username, self.password]): - raise AnsibleError("Missing one of the following : hostname, username, password. Please read " - "the documentation for more information.") - - def _get_managed_objects_properties(self, vim_type, properties=None): - """ - Look up a Managed Object Reference in vCenter / ESXi Environment - :param vim_type: Type of vim object e.g, for datacenter - vim.Datacenter - :param properties: List of properties related to vim object e.g. Name - :return: local content object - """ - # Get Root Folder - root_folder = self.content.rootFolder - - if properties is None: - properties = ['name'] - - # Create Container View with default root folder - mor = self.content.viewManager.CreateContainerView(root_folder, [vim_type], True) - - # Create Traversal spec - traversal_spec = vmodl.query.PropertyCollector.TraversalSpec( - name="traversal_spec", - path='view', - skip=False, - type=vim.view.ContainerView - ) - - # Create Property Spec - property_spec = vmodl.query.PropertyCollector.PropertySpec( - type=vim_type, # Type of object to retrieved - all=False, - pathSet=properties - ) - - # Create Object Spec - object_spec = vmodl.query.PropertyCollector.ObjectSpec( - obj=mor, - skip=True, - selectSet=[traversal_spec] - ) - - # Create Filter Spec - filter_spec = vmodl.query.PropertyCollector.FilterSpec( - objectSet=[object_spec], - propSet=[property_spec], - reportMissingObjectsInResults=False - ) - - return self.content.propertyCollector.RetrieveContents([filter_spec]) - - @staticmethod - def _get_object_prop(vm, attributes): - """Safely get a property or return None""" - result = vm - for attribute in attributes: - try: - result = getattr(result, attribute) - except (AttributeError, IndexError): - return None - return result - - -class InventoryModule(BaseInventoryPlugin, Cacheable): - - NAME = 'vmware_vm_inventory' - - def verify_file(self, path): - """ - Verify plugin configuration file and mark this plugin active - Args: - path: Path of configuration YAML file - Returns: True if everything is correct, else False - """ - valid = False - if super(InventoryModule, self).verify_file(path): - if path.endswith(('vmware.yaml', 'vmware.yml', 'vmware_vm_inventory.yaml', 'vmware_vm_inventory.yml')): - valid = True - - return valid - - def parse(self, inventory, loader, path, cache=True): - """ - Parses the inventory file - """ - super(InventoryModule, self).parse(inventory, loader, path, cache=cache) - - cache_key = self.get_cache_key(path) - - config_data = self._read_config_data(path) - - # set _options from config data - self._consume_options(config_data) - - self.pyv = BaseVMwareInventory( - hostname=self.get_option('hostname'), - username=self.get_option('username'), - password=self.get_option('password'), - port=self.get_option('port'), - with_tags=self.get_option('with_tags'), - validate_certs=self.get_option('validate_certs') - ) - - self.pyv.do_login() - - self.pyv.check_requirements() - - source_data = None - if cache: - cache = self.get_option('cache') - - update_cache = False - if cache: - try: - source_data = self._cache[cache_key] - except KeyError: - update_cache = True - - using_current_cache = cache and not update_cache - cacheable_results = self._populate_from_source(source_data, using_current_cache) - - if update_cache: - self._cache[cache_key] = cacheable_results - - def _populate_from_cache(self, source_data): - """ Populate cache using source data """ - hostvars = source_data.pop('_meta', {}).get('hostvars', {}) - for group in source_data: - if group == 'all': - continue - else: - self.inventory.add_group(group) - hosts = source_data[group].get('hosts', []) - for host in hosts: - self._populate_host_vars([host], hostvars.get(host, {}), group) - self.inventory.add_child('all', group) - - def _populate_from_source(self, source_data, using_current_cache): - """ - Populate inventory data from direct source - - """ - if using_current_cache: - self._populate_from_cache(source_data) - return source_data - - cacheable_results = {'_meta': {'hostvars': {}}} - hostvars = {} - objects = self.pyv._get_managed_objects_properties(vim_type=vim.VirtualMachine, - properties=['name']) - - if self.pyv.with_tags: - tag_svc = self.pyv.rest_content.tagging.Tag - tag_association = self.pyv.rest_content.tagging.TagAssociation - - tags_info = dict() - tags = tag_svc.list() - for tag in tags: - tag_obj = tag_svc.get(tag) - tags_info[tag_obj.id] = tag_obj.name - if tag_obj.name not in cacheable_results: - cacheable_results[tag_obj.name] = {'hosts': []} - self.inventory.add_group(tag_obj.name) - - for vm_obj in objects: - for vm_obj_property in vm_obj.propSet: - # VMware does not provide a way to uniquely identify VM by its name - # i.e. there can be two virtual machines with same name - # Appending "_" and VMware UUID to make it unique - if not vm_obj.obj.config: - # Sometime orphaned VMs return no configurations - continue - - current_host = vm_obj_property.val + "_" + vm_obj.obj.config.uuid - - if current_host not in hostvars: - hostvars[current_host] = {} - self.inventory.add_host(current_host) - - host_ip = vm_obj.obj.guest.ipAddress - if host_ip: - self.inventory.set_variable(current_host, 'ansible_host', host_ip) - - self._populate_host_properties(vm_obj, current_host) - - # Only gather facts related to tag if vCloud and vSphere is installed. - if HAS_VSPHERE and self.pyv.with_tags: - # Add virtual machine to appropriate tag group - vm_mo_id = vm_obj.obj._GetMoId() - vm_dynamic_id = DynamicID(type='VirtualMachine', id=vm_mo_id) - attached_tags = tag_association.list_attached_tags(vm_dynamic_id) - - for tag_id in attached_tags: - self.inventory.add_child(tags_info[tag_id], current_host) - cacheable_results[tags_info[tag_id]]['hosts'].append(current_host) - - # Based on power state of virtual machine - vm_power = str(vm_obj.obj.summary.runtime.powerState) - if vm_power not in cacheable_results: - cacheable_results[vm_power] = {'hosts': []} - self.inventory.add_group(vm_power) - cacheable_results[vm_power]['hosts'].append(current_host) - self.inventory.add_child(vm_power, current_host) - - # Based on guest id - vm_guest_id = vm_obj.obj.config.guestId - if vm_guest_id and vm_guest_id not in cacheable_results: - cacheable_results[vm_guest_id] = {'hosts': []} - self.inventory.add_group(vm_guest_id) - cacheable_results[vm_guest_id]['hosts'].append(current_host) - self.inventory.add_child(vm_guest_id, current_host) - - for host in hostvars: - h = self.inventory.get_host(host) - cacheable_results['_meta']['hostvars'][h.name] = h.vars - - return cacheable_results - - def _populate_host_properties(self, vm_obj, current_host): - # Load VM properties in host_vars - vm_properties = self.get_option('properties') or [] - - field_mgr = self.pyv.content.customFieldsManager.field - - for vm_prop in vm_properties: - if vm_prop == 'customValue': - for cust_value in vm_obj.obj.customValue: - self.inventory.set_variable(current_host, - [y.name for y in field_mgr if y.key == cust_value.key][0], - cust_value.value) - else: - vm_value = self.pyv._get_object_prop(vm_obj.obj, vm_prop.split(".")) - self.inventory.set_variable(current_host, vm_prop, vm_value) diff --git a/test/integration/targets/inventory_vmware_vm_inventory/aliases b/test/integration/targets/inventory_vmware_vm_inventory/aliases deleted file mode 100644 index 8a4d29b3a9..0000000000 --- a/test/integration/targets/inventory_vmware_vm_inventory/aliases +++ /dev/null @@ -1,3 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -destructive diff --git a/test/integration/targets/inventory_vmware_vm_inventory/ansible.cfg b/test/integration/targets/inventory_vmware_vm_inventory/ansible.cfg deleted file mode 100644 index 158f5849fa..0000000000 --- a/test/integration/targets/inventory_vmware_vm_inventory/ansible.cfg +++ /dev/null @@ -1,8 +0,0 @@ -[defaults] -inventory = test-config.vmware.yaml - -[inventory] -enable_plugins = vmware_vm_inventory -cache = True -cache_plugin = jsonfile -cache_connection = inventory_cache diff --git a/test/integration/targets/inventory_vmware_vm_inventory/runme.sh b/test/integration/targets/inventory_vmware_vm_inventory/runme.sh deleted file mode 100755 index e220624a59..0000000000 --- a/test/integration/targets/inventory_vmware_vm_inventory/runme.sh +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/env bash - -[[ -n "$DEBUG" || -n "$ANSIBLE_DEBUG" ]] && set -x - -set -euo pipefail - -# Required to differentiate between Python 2 and 3 environ -PYTHON=${ANSIBLE_TEST_PYTHON_INTERPRETER:-python} - -export ANSIBLE_CONFIG=ansible.cfg -export VMWARE_SERVER="${VCENTER_HOSTNAME}" -export VMWARE_USERNAME="${VCENTER_USERNAME}" -export VMWARE_PASSWORD="${VCENTER_PASSWORD}" -port=5000 -VMWARE_CONFIG=test-config.vmware.yaml -inventory_cache="$(pwd)/inventory_cache" - -cat > "$VMWARE_CONFIG" <<VMWARE_YAML -plugin: vmware_vm_inventory -strict: False -validate_certs: False -with_tags: False -VMWARE_YAML - -cleanup() { - echo "Cleanup" - if [ -f "${VMWARE_CONFIG}" ]; then - rm -f "${VMWARE_CONFIG}" - fi - if [ -d "${inventory_cache}" ]; then - echo "Removing ${inventory_cache}" - rm -rf "${inventory_cache}" - fi - echo "Done" - exit 0 -} - -trap cleanup INT TERM EXIT - -echo "DEBUG: Using ${VCENTER_HOSTNAME} with username ${VCENTER_USERNAME} and password ${VCENTER_PASSWORD}" - -echo "Kill all previous instances" -curl "http://${VCENTER_HOSTNAME}:${port}/killall" > /dev/null 2>&1 - -echo "Start new VCSIM server" -curl "http://${VCENTER_HOSTNAME}:${port}/spawn?datacenter=1&cluster=1&folder=0" > /dev/null 2>&1 - -echo "Debugging new instances" -curl "http://${VCENTER_HOSTNAME}:${port}/govc_find" - -# Get inventory -ansible-inventory -i ${VMWARE_CONFIG} --list - -echo "Check if cache is working for inventory plugin" -if [ ! -n "$(find "${inventory_cache}" -maxdepth 1 -name 'vmware_vm_inventory_*' -print -quit)" ]; then - echo "Cache directory not found. Please debug" - exit 1 -fi -echo "Cache is working" - -# Get inventory using YAML -ansible-inventory -i ${VMWARE_CONFIG} --list --yaml - -# Install TOML for --toml -${PYTHON} -m pip freeze | grep toml > /dev/null 2>&1 -TOML_TEST_RESULT=$? -if [ $TOML_TEST_RESULT -ne 0 ]; then - echo "Installing TOML package" - ${PYTHON} -m pip install toml -else - echo "TOML package already exists, skipping installation" -fi - -# Get inventory using TOML -ansible-inventory -i ${VMWARE_CONFIG} --list --toml -TOML_INVENTORY_LIST_RESULT=$? -if [ $TOML_INVENTORY_LIST_RESULT -ne 0 ]; then - echo "Inventory plugin failed to list inventory host using --toml, please debug" - exit 1 -fi - -# Test playbook with given inventory -ansible-playbook -i ${VMWARE_CONFIG} test_vmware_vm_inventory.yml --connection=local "$@" diff --git a/test/integration/targets/inventory_vmware_vm_inventory/test_vmware_vm_inventory.yml b/test/integration/targets/inventory_vmware_vm_inventory/test_vmware_vm_inventory.yml deleted file mode 100644 index 88e2be9bd1..0000000000 --- a/test/integration/targets/inventory_vmware_vm_inventory/test_vmware_vm_inventory.yml +++ /dev/null @@ -1,24 +0,0 @@ -# Test code for the vmware guest dynamic plugin module -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - ---- -- name: Test VMware Guest Dynamic Inventroy Plugin - hosts: localhost - tasks: - - name: store the vcenter container ip - set_fact: - vcsim: "{{ lookup('env', 'VCENTER_HOSTNAME') }}" - - - name: Check that there are 'all' and 'otherGuest' groups present in inventory - assert: - that: "'{{ item }}' in {{ groups.keys() | list }}" - with_items: - - all - - otherGuest - - - name: Check if Hostname and other details are populated in hostvars - assert: - that: - - hostvars[item].name is defined - with_items: "{{ groups['all'] }}" diff --git a/test/integration/targets/script_inventory_vmware_inventory/aliases b/test/integration/targets/script_inventory_vmware_inventory/aliases deleted file mode 100644 index 17d4e97ab7..0000000000 --- a/test/integration/targets/script_inventory_vmware_inventory/aliases +++ /dev/null @@ -1,7 +0,0 @@ -shippable/vcenter/group2 -cloud/vcenter -destructive -needs/file/contrib/inventory/vmware_inventory.py -needs/file/contrib/inventory/vmware_inventory.ini -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/script_inventory_vmware_inventory/runme.sh b/test/integration/targets/script_inventory_vmware_inventory/runme.sh deleted file mode 100755 index fcfc1c8c13..0000000000 --- a/test/integration/targets/script_inventory_vmware_inventory/runme.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env bash - -[[ -n "$DEBUG" || -n "$ANSIBLE_DEBUG" ]] && set -x - -set -euo pipefail - -contrib_dir=../../../../contrib/inventory - -echo "DEBUG: using ${contrib_dir}" - -export ANSIBLE_CONFIG=ansible.cfg -export VMWARE_SERVER="${VCENTER_HOSTNAME}" -export VMWARE_USERNAME="${VCENTER_USERNAME}" -export VMWARE_PASSWORD="${VCENTER_PASSWORD}" - -VMWARE_CONFIG=${contrib_dir}/vmware_inventory.ini - - -trap cleanup INT TERM EXIT - -# Remove default inventory config file -if [ -f "${VMWARE_CONFIG}" ]; -then - echo "DEBUG: Creating backup of ${VMWARE_CONFIG}" - cp "${VMWARE_CONFIG}" "${VMWARE_CONFIG}.bk" -fi - -cat > "${VMWARE_CONFIG}" <<VMWARE_INI -[vmware] -server=${VMWARE_SERVER} -username=${VMWARE_USERNAME} -password=${VMWARE_PASSWORD} -validate_certs=False -VMWARE_INI - -function cleanup { - # Revert back to previous one - if [ -f "${VMWARE_CONFIG}.bk" ]; then - echo "DEBUG: Cleanup ${VMWARE_CONFIG}" - mv "${VMWARE_CONFIG}.bk" "${VMWARE_CONFIG}" - fi -} - -echo "DEBUG: Using ${VCENTER_HOSTNAME} with username ${VCENTER_USERNAME} and password ${VCENTER_PASSWORD}" - -echo "Kill all previous instances" -curl "http://${VCENTER_HOSTNAME}:5000/killall" > /dev/null 2>&1 - -echo "Start new VCSIM server" -curl "http://${VCENTER_HOSTNAME}:5000/spawn?datacenter=1&cluster=1&folder=0" > /dev/null 2>&1 - -echo "Debugging new instances" -curl "http://${VCENTER_HOSTNAME}:5000/govc_find" - -# Get inventory -ansible-playbook -i ./vmware_inventory.sh "./test_vmware_inventory.yml" --connection=local "$@" - -echo "DEBUG: Done" diff --git a/test/integration/targets/script_inventory_vmware_inventory/test_vmware_inventory.yml b/test/integration/targets/script_inventory_vmware_inventory/test_vmware_inventory.yml deleted file mode 100644 index 035d1d16ec..0000000000 --- a/test/integration/targets/script_inventory_vmware_inventory/test_vmware_inventory.yml +++ /dev/null @@ -1,18 +0,0 @@ -# Test code for the vmware guest contrib inventory -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - ---- -- name: Test VMware guest contrib inventroy script - hosts: localhost - tasks: - - name: store the vcenter container ip - set_fact: - vcsim: "{{ lookup('env', 'VCENTER_HOSTNAME') }}" - - - name: Check that groups present in inventory - assert: - that: - - "'{{item}}' in groups" - with_items: - - all diff --git a/test/integration/targets/script_inventory_vmware_inventory/vmware_inventory.sh b/test/integration/targets/script_inventory_vmware_inventory/vmware_inventory.sh deleted file mode 100755 index 5ec1972e3f..0000000000 --- a/test/integration/targets/script_inventory_vmware_inventory/vmware_inventory.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -python.py "../../../../contrib/inventory/vmware_inventory.py" "$@" diff --git a/test/integration/targets/vcenter_folder/aliases b/test/integration/targets/vcenter_folder/aliases deleted file mode 100644 index be8c5b72ff..0000000000 --- a/test/integration/targets/vcenter_folder/aliases +++ /dev/null @@ -1,3 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vcenter_folder/meta/main.yml b/test/integration/targets/vcenter_folder/meta/main.yml deleted file mode 100644 index 828342c2da..0000000000 --- a/test/integration/targets/vcenter_folder/meta/main.yml +++ /dev/null @@ -1,2 +0,0 @@ -dependencies: - - prepare_vmware_tests diff --git a/test/integration/targets/vcenter_folder/tasks/main.yml b/test/integration/targets/vcenter_folder/tasks/main.yml deleted file mode 100644 index 56cc503892..0000000000 --- a/test/integration/targets/vcenter_folder/tasks/main.yml +++ /dev/null @@ -1,216 +0,0 @@ -# Test code for the vcenter_folder module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: Create all types of folder in check mode - vcenter_folder: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ dc1 }}" - folder_name: "{{ item }}_folder" - folder_type: "{{ item }}" - state: present - register: all_folder_results - with_items: - - vm - - host - - datastore - - network - check_mode: yes - -- debug: - msg: "{{ all_folder_results }}" - -- name: ensure everything for {{ dc1 }} - assert: - that: - - all_folder_results.changed - -- name: Create all types of folder - vcenter_folder: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ dc1 }}" - folder_name: "{{ item }}_folder" - folder_type: "{{ item }}" - state: present - register: all_folder_results - with_items: - - vm - - host - - datastore - - network - -- debug: - msg: "{{ all_folder_results }}" - -- name: ensure everything for {{ dc1 }} - assert: - that: - - all_folder_results.changed - -- name: Create all types of sub folder in check mode - vcenter_folder: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ dc1 }}" - folder_name: "sub_{{ item }}_folder" - parent_folder: 'vm_folder' - state: present - register: all_folder_results - with_items: - - vm - - host - - datastore - - network - check_mode: yes - -- debug: - msg: "{{ all_folder_results }}" - -- name: ensure everything for {{ dc1 }} - assert: - that: - - all_folder_results.changed - -- name: Create all types of sub folder - vcenter_folder: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ dc1 }}" - folder_name: "sub_{{ item }}_folder" - parent_folder: 'vm_folder' - state: present - register: all_folder_results - with_items: - - vm - - host - - datastore - - network - -- name: Recreate all types of sub folder - vcenter_folder: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ dc1 }}" - folder_name: "sub_{{ item }}_folder" - parent_folder: 'vm_folder' - state: present - register: recreate_folders - with_items: - - vm - - host - - datastore - - network - -- name: Create a 3rd level of directory - vcenter_folder: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ dc1 }}" - folder_name: yet_another_level - parent_folder: vm_folder/sub_vm_folder - state: present - register: yet_another_level -- debug: var=yet_another_level - -- name: Recreate a 3rd level of directory - vcenter_folder: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ dc1 }}" - folder_name: yet_another_level - parent_folder: vm_folder/sub_vm_folder - state: present - register: recreate_yet_another_level -- debug: var=recreate_yet_another_level - -- debug: - msg: "{{ all_folder_results }}" - -- name: ensure everything for {{ dc1 }} - assert: - that: - - all_folder_results.changed - - not recreate_folders.changed - - not recreate_yet_another_level.changed - -## Testcase: Delete all types of folder -# -# Doesn't work with vcsim. Looks like UnregisterAndDestroy isn't supported. -- when: vcsim is not defined - block: - - name: Remove a 3rd level of directory - vcenter_folder: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ dc1 }}" - folder_name: yet_another_level - parent_folder: vm_folder/sub_vm_folder - state: absent - register: remove_yet_another_level - - debug: var=remove_yet_another_level - - - name: Delete all types of folder - vcenter_folder: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ dc1 }}" - folder_name: "{{ item }}_folder" - folder_type: "{{ item }}" - state: absent - register: all_folder_results - with_items: - - vm - - host - - datastore - - network - - - debug: msg="{{ all_folder_results }}" - - - name: ensure everything for {{ dc1 }} - assert: - that: - - all_folder_results.changed - - - name: Delete all types of folder again - vcenter_folder: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ dc1 }}" - folder_name: "{{ item }}_folder" - folder_type: "{{ item }}" - state: absent - register: all_folder_results - with_items: - - vm - - host - - datastore - - network - - - debug: msg="{{ all_folder_results }}" - - - name: ensure everything for {{ dc1 }} - assert: - that: - - not all_folder_results.changed diff --git a/test/integration/targets/vcenter_license/aliases b/test/integration/targets/vcenter_license/aliases deleted file mode 100644 index be8c5b72ff..0000000000 --- a/test/integration/targets/vcenter_license/aliases +++ /dev/null @@ -1,3 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vcenter_license/meta/main.yml b/test/integration/targets/vcenter_license/meta/main.yml deleted file mode 100644 index 828342c2da..0000000000 --- a/test/integration/targets/vcenter_license/meta/main.yml +++ /dev/null @@ -1,2 +0,0 @@ -dependencies: - - prepare_vmware_tests diff --git a/test/integration/targets/vcenter_license/tasks/main.yml b/test/integration/targets/vcenter_license/tasks/main.yml deleted file mode 100644 index f57d3a5c16..0000000000 --- a/test/integration/targets/vcenter_license/tasks/main.yml +++ /dev/null @@ -1,27 +0,0 @@ -# Test code for the vcenter license module. -# Copyright: (c) 2017, Dag Wieers <dag@wieers.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - name: Add a vCenter evaluation license - vcenter_license: &vcenter_lic_data - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - license: 00000-00000-00000-00000-00000 - state: present - - - name: Remove an (unused) vCenter evaluation license - vcenter_license: - <<: *vcenter_lic_data - state: absent - - - name: Add an invalid vCenter license - vcenter_license: - <<: *vcenter_lic_data - license: 00000-00000-00000-00000-00001 - state: present - register: vcenter_license_output - failed_when: '"is not existing or can not be added" not in vcenter_license_output.msg' diff --git a/test/integration/targets/vmware_about_facts/aliases b/test/integration/targets/vmware_about_facts/aliases deleted file mode 100644 index b6fc00bfec..0000000000 --- a/test/integration/targets/vmware_about_facts/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_about_facts/tasks/main.yml b/test/integration/targets/vmware_about_facts/tasks/main.yml deleted file mode 100644 index 49499421c9..0000000000 --- a/test/integration/targets/vmware_about_facts/tasks/main.yml +++ /dev/null @@ -1,58 +0,0 @@ -# Test code for the vmware_about_facts module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - -- name: Get Details about VMware vCenter Server - vmware_about_facts: &vmware_about_data - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - register: about - -- assert: - that: - - about.about_facts["{{ item }}"] is defined - with_items: - - api_type - - api_version - - build - - instance_uuid - - license_product_name - - license_product_version - - locale_build - - locale_version - - os_type - - product_full_name - - product_line_id - - product_name - - vendor - - version - -- name: Get Details about VMware vCenter Server in check mode - vmware_about_facts: - <<: *vmware_about_data - register: about - check_mode: yes - -- assert: - that: - - about.about_facts["{{ item }}"] is defined - with_items: - - api_type - - api_version - - build - - instance_uuid - - license_product_name - - license_product_version - - locale_build - - locale_version - - os_type - - product_full_name - - product_line_id - - product_name - - vendor - - version diff --git a/test/integration/targets/vmware_about_info/aliases b/test/integration/targets/vmware_about_info/aliases deleted file mode 100644 index b6fc00bfec..0000000000 --- a/test/integration/targets/vmware_about_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_about_info/tasks/main.yml b/test/integration/targets/vmware_about_info/tasks/main.yml deleted file mode 100644 index a46c55edb4..0000000000 --- a/test/integration/targets/vmware_about_info/tasks/main.yml +++ /dev/null @@ -1,58 +0,0 @@ -# Test code for the vmware_about_info module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - -- name: Get Details about VMware vCenter Server - vmware_about_info: &vmware_about_data - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - register: about - -- assert: - that: - - about.about_info["{{ item }}"] is defined - with_items: - - api_type - - api_version - - build - - instance_uuid - - license_product_name - - license_product_version - - locale_build - - locale_version - - os_type - - product_full_name - - product_line_id - - product_name - - vendor - - version - -- name: Get Details about VMware vCenter Server in check mode - vmware_about_info: - <<: *vmware_about_data - register: about - check_mode: yes - -- assert: - that: - - about.about_info["{{ item }}"] is defined - with_items: - - api_type - - api_version - - build - - instance_uuid - - license_product_name - - license_product_version - - locale_build - - locale_version - - os_type - - product_full_name - - product_line_id - - product_name - - vendor - - version diff --git a/test/integration/targets/vmware_category/aliases b/test/integration/targets/vmware_category/aliases deleted file mode 100644 index b6fc00bfec..0000000000 --- a/test/integration/targets/vmware_category/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_category/tasks/associable_obj_types.yml b/test/integration/targets/vmware_category/tasks/associable_obj_types.yml deleted file mode 100644 index a9d1749cd7..0000000000 --- a/test/integration/targets/vmware_category/tasks/associable_obj_types.yml +++ /dev/null @@ -1,90 +0,0 @@ -# Test code for the vmware_category Operations. -# Copyright: (c) 2019, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: Create different types of category with associable object types - vmware_category: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: False - category_name: '{{ item }} name' - category_description: '{{ item }} description' - associable_object_types: - - "{{ item }}" - state: present - with_items: - - All objects - - Folder - - Cluster - - Datacenter - - Datastore - - Datastore Cluster - - Distributed Port Group - - Distributed Switch - - Host - - Content Library - - Library item - - Network - - Resource Pool - - vApp - - Virtual Machine - -- name: Delete different types of category with associable object types - vmware_category: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: False - category_name: '{{ item }} name' - state: absent - with_items: - - All objects - - Folder - - Cluster - - Datacenter - - Datastore - - Datastore Cluster - - Distributed Port Group - - Distributed Switch - - Host - - Content Library - - Library item - - Network - - Resource Pool - - vApp - - Virtual Machine - -- name: Create category with 2 associable object types - vmware_category: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: False - category_name: 'Sample_cate_0001' - category_description: 'sample description' - associable_object_types: - - Datastore - - Cluster - state: present - register: category_change - -- name: Assert change is made - assert: - that: - - category_change.changed - -- name: Delete category with 2 associable object types - vmware_category: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: False - category_name: 'Sample_cate_0001' - state: absent - register: category_change - -- name: Assert change is made - assert: - that: - - category_change.changed diff --git a/test/integration/targets/vmware_category/tasks/main.yml b/test/integration/targets/vmware_category/tasks/main.yml deleted file mode 100644 index 96a490f8c3..0000000000 --- a/test/integration/targets/vmware_category/tasks/main.yml +++ /dev/null @@ -1,9 +0,0 @@ -# Test code for the vmware_category Operations. -# Copyright: (c) 2019, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - - include: associable_obj_types.yml diff --git a/test/integration/targets/vmware_cluster/aliases b/test/integration/targets/vmware_cluster/aliases deleted file mode 100644 index b6fc00bfec..0000000000 --- a/test/integration/targets/vmware_cluster/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_cluster/tasks/main.yml b/test/integration/targets/vmware_cluster/tasks/main.yml deleted file mode 100644 index 5652902e0a..0000000000 --- a/test/integration/targets/vmware_cluster/tasks/main.yml +++ /dev/null @@ -1,62 +0,0 @@ -# Test code for the vmware_cluster module. -# Copyright: (c) 2017, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - vars: - setup_datacenter: true - -# Testcase 0001: Add Cluster -- &add_cluster - name: add cluster - vmware_cluster: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: "{{ dc1 }}" - cluster_name: test_cluster_0001 - state: present - register: cluster_result_0001 - -- &ensure_changed - name: ensure cluster is present - assert: - that: - - "{{ cluster_result_0001.changed == true }}" - -# # Broken by: https://github.com/ansible/ansible/issues/54857 -# - <<: *add_cluster -# name: add cluster (again) - -# - &ensure_unchanged -# name: ensure cluster is unchanged -# assert: -# that: -# - "{{ cluster_result_0001.changed == false }}" - -- when: vcsim is not defined - block: - - &del_cluster - name: delete cluster - vmware_cluster: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: "{{ dc1 }}" - cluster_name: test_cluster_0001 - state: absent - register: cluster_result_0001 - - - <<: *ensure_changed - - - <<: *del_cluster - name: delete cluster (again) - - #- <<: *ensure_unchanged - - name: ensure cluster is unchanged - assert: - that: - - "{{ cluster_result_0001.changed == false }}" diff --git a/test/integration/targets/vmware_cluster_drs/aliases b/test/integration/targets/vmware_cluster_drs/aliases deleted file mode 100644 index b6fc00bfec..0000000000 --- a/test/integration/targets/vmware_cluster_drs/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_cluster_drs/tasks/main.yml b/test/integration/targets/vmware_cluster_drs/tasks/main.yml deleted file mode 100644 index 5662769e74..0000000000 --- a/test/integration/targets/vmware_cluster_drs/tasks/main.yml +++ /dev/null @@ -1,97 +0,0 @@ -# Test code for the vmware_cluster module. -# Copyright: (c) 2017, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - -# Setup: Create test cluster -- name: Create test cluster - vmware_cluster: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: "{{ dc1 }}" - cluster_name: test_cluster_drs - state: present - -# Testcase 0001: Enable DRS -- name: Enable DRS - vmware_cluster_drs: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: "{{ dc1 }}" - cluster_name: test_cluster_drs - enable_drs: yes - register: cluster_drs_result_0001 - -- name: Ensure DRS is enabled - assert: - that: - - "{{ cluster_drs_result_0001.changed == true }}" - -# Testcase 0002: Disable DRS -- name: Disable DRS - vmware_cluster_drs: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: "{{ dc1 }}" - cluster_name: test_cluster_drs - enable_drs: no - register: cluster_drs_result_0002 - -- name: Ensure DRS is disabled - assert: - that: - - "{{ cluster_drs_result_0002.changed == true }}" - -- when: vcsim is not defined - block: - - name: Change advanced setting "TryBalanceVmsPerHost" (check-mode) - vmware_cluster_drs: &change_balance_vms - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: "{{ dc1 }}" - cluster_name: test_cluster_drs - advanced_settings: - 'TryBalanceVmsPerHost': '1' - check_mode: yes - register: change_balance_vms_check - - - assert: - that: - - change_balance_vms_check.changed - - - name: Change advanced setting "TryBalanceVmsPerHost" - vmware_cluster_drs: *change_balance_vms - register: change_balance_vms - - - assert: - that: - - change_balance_vms.changed - - - name: Change advanced setting "TryBalanceVmsPerHost" again - vmware_cluster_drs: *change_balance_vms - register: change_balance_vms_again - - - assert: - that: - - not change_balance_vms_again.changed - - # Delete test cluster - - name: Delete test cluster - vmware_cluster: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: "{{ dc1 }}" - cluster_name: test_cluster_drs - state: absent diff --git a/test/integration/targets/vmware_cluster_facts/aliases b/test/integration/targets/vmware_cluster_facts/aliases deleted file mode 100644 index dea29ccd8b..0000000000 --- a/test/integration/targets/vmware_cluster_facts/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_cluster_facts/tasks/main.yml b/test/integration/targets/vmware_cluster_facts/tasks/main.yml deleted file mode 100644 index df7b34c555..0000000000 --- a/test/integration/targets/vmware_cluster_facts/tasks/main.yml +++ /dev/null @@ -1,92 +0,0 @@ -# Test code for the vmware_cluster_facts module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - -- &vc_all_data - name: gather facts about all clusters in the given datacenter - vmware_cluster_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: False - datacenter: "{{ dc1 }}" - register: all_cluster_result - -- &ensure_vc_all_data - name: ensure facts are gathered for all clusters - assert: - that: - - all_cluster_result.clusters - - not all_cluster_result.changed - -- <<: *vc_all_data - name: Gather facts about all clusters in the given datacenter in check mode - check_mode: yes - -- debug: msg=all_cluster_result - -- <<: *ensure_vc_all_data - name: Ensure facts are gathered for all clusters in check mode - -- &vc_cluster_data - name: Gather facts about the given cluster - vmware_cluster_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: False - cluster_name: "{{ ccr1 }}" - register: cluster_result - -- &ensure_vc_cluster_data - name: Ensure facts are gathered for the given cluster - assert: - that: - - cluster_result.clusters - - not cluster_result.changed - -- <<: *vc_cluster_data - name: Gather facts about the given cluster in check mode - check_mode: yes - -- <<: *ensure_vc_cluster_data - name: Ensure facts are gathered for the given cluster in check mode - - -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_category: true - setup_tag: true - - - name: Apply tag to cluster - vmware_tag_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - tag_names: - - '{{ cluster_category }}:{{ cluster_tag }}' - state: present - object_name: '{{ ccr1 }}' - object_type: ClusterComputeResource - - - name: Get facts about cluster - vmware_cluster_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - show_tag: True - cluster_name: "{{ ccr1 }}" - register: cluster_info - - - assert: - that: - - cluster_info is defined - - cluster_info.clusters[ccr1].tags is defined diff --git a/test/integration/targets/vmware_cluster_ha/aliases b/test/integration/targets/vmware_cluster_ha/aliases deleted file mode 100644 index b6fc00bfec..0000000000 --- a/test/integration/targets/vmware_cluster_ha/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_cluster_ha/tasks/main.yml b/test/integration/targets/vmware_cluster_ha/tasks/main.yml deleted file mode 100644 index bda03fd94c..0000000000 --- a/test/integration/targets/vmware_cluster_ha/tasks/main.yml +++ /dev/null @@ -1,174 +0,0 @@ -# Test code for the vmware_cluster module. -# Copyright: (c) 2017, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - -# Setup: Create test cluster -- name: Create test cluster - vmware_cluster: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: "{{ dc1 }}" - cluster_name: test_cluster_ha - state: present - -# Testcase 0001: Enable HA -- name: Enable HA - vmware_cluster_ha: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: "{{ dc1 }}" - cluster_name: test_cluster_ha - enable_ha: yes - register: cluster_ha_result_0001 - -- name: Ensure HA is enabled - assert: - that: - - "{{ cluster_ha_result_0001.changed == true }}" - -# Testcase 0002: Enable Slot based Admission Control -- name: Enable Slot based Admission Control - vmware_cluster_ha: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: "{{ dc1 }}" - cluster_name: test_cluster_ha - enable_ha: yes - slot_based_admission_control: - failover_level: 1 - register: cluster_ha_result_0002 - -- name: Ensure Admission Cotrol is enabled - assert: - that: - - "{{ cluster_ha_result_0002.changed == true }}" - -# Testcase 0003: Enable Cluster resource Percentage based Admission Control -- name: Enable Cluster resource Percentage based Admission Control - vmware_cluster_ha: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: "{{ dc1 }}" - cluster_name: test_cluster_ha - enable_ha: yes - reservation_based_admission_control: - auto_compute_percentages: false - failover_level: 1 - cpu_failover_resources_percent: 33 - memory_failover_resources_percent: 33 - register: cluster_ha_result_0003 - -- name: Ensure Admission Cotrol is enabled - assert: - that: - - "{{ cluster_ha_result_0003.changed == true }}" - -# Testcase 0004: Set Isolation Response to powerOff -- name: Set Isolation Response to powerOff - vmware_cluster_ha: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: "{{ dc1 }}" - cluster_name: test_cluster_ha - enable_ha: yes - host_isolation_response: 'powerOff' - register: cluster_ha_result_0004 - -- name: Ensure Isolation Response is enabled - assert: - that: - - "{{ cluster_ha_result_0004.changed == true }}" - -# Testcase 0005: Set Isolation Response to shutdown -- name: Set Isolation Response to shutdown - vmware_cluster_ha: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: "{{ dc1 }}" - cluster_name: test_cluster_ha - enable_ha: yes - host_isolation_response: 'shutdown' - register: cluster_ha_result_0005 - -- name: Ensure Isolation Response is enabled - assert: - that: - - "{{ cluster_ha_result_0005.changed == true }}" - -# Testcase 0006: Disable HA -- name: Disable HA - vmware_cluster_ha: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: "{{ dc1 }}" - cluster_name: test_cluster_ha - enable_ha: no - register: cluster_ha_result_0006 - -- name: Ensure HA is disabled - assert: - that: - - "{{ cluster_ha_result_0006.changed == true }}" - -- when: vcsim is not defined - block: - - name: Change advanced setting "number of heartbeat datastores" (check-mode) - vmware_cluster_ha: &change_num_heartbeat_ds - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: "{{ dc1 }}" - cluster_name: test_cluster_ha - advanced_settings: - 'das.heartbeatDsPerHost': '4' - check_mode: yes - register: change_num_heartbeat_ds_check - - - assert: - that: - - change_num_heartbeat_ds_check.changed - - - name: Change advanced setting "number of heartbeat datastores" - vmware_cluster_ha: *change_num_heartbeat_ds - register: change_num_heartbeat_ds - - - assert: - that: - - change_num_heartbeat_ds.changed - - - name: Change advanced setting "number of heartbeat datastores" again - vmware_cluster_ha: *change_num_heartbeat_ds - register: change_num_heartbeat_ds_again - - - assert: - that: - - not change_num_heartbeat_ds_again.changed - - # Delete test cluster - - name: Delete test cluster - vmware_cluster: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: "{{ dc1 }}" - cluster_name: test_cluster_ha - state: absent diff --git a/test/integration/targets/vmware_cluster_info/aliases b/test/integration/targets/vmware_cluster_info/aliases deleted file mode 100644 index dea29ccd8b..0000000000 --- a/test/integration/targets/vmware_cluster_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_cluster_info/tasks/main.yml b/test/integration/targets/vmware_cluster_info/tasks/main.yml deleted file mode 100644 index 0d0ba4e947..0000000000 --- a/test/integration/targets/vmware_cluster_info/tasks/main.yml +++ /dev/null @@ -1,91 +0,0 @@ -# Test code for the vmware_cluster_info module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - -- &vc_all_data - name: gather info about all clusters in the given datacenter - vmware_cluster_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: False - datacenter: "{{ dc1 }}" - register: all_cluster_result - -- &ensure_vc_all_data - name: ensure info are gathered for all clusters - assert: - that: - - all_cluster_result.clusters - - not all_cluster_result.changed - -- <<: *vc_all_data - name: Gather info about all clusters in the given datacenter in check mode - check_mode: yes - -- debug: msg=all_cluster_result - -- <<: *ensure_vc_all_data - name: Ensure info is gathered for all clusters in check mode - -- &vc_cluster_data - name: Gather info about the given cluster - vmware_cluster_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: False - cluster_name: "{{ ccr1 }}" - register: cluster_result - -- &ensure_vc_cluster_data - name: Ensure info are gathered for the given cluster - assert: - that: - - cluster_result.clusters - - not cluster_result.changed - -- <<: *vc_cluster_data - name: Gather info about the given cluster in check mode - check_mode: yes - -- <<: *ensure_vc_cluster_data - name: Ensure info is gathered for the given cluster in check mode - -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_category: true - setup_tag: true - - - name: Apply tag to cluster - vmware_tag_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - tag_names: - - '{{ cluster_category }}:{{ cluster_tag }}' - state: present - object_name: '{{ ccr1 }}' - object_type: ClusterComputeResource - - - name: Get info about cluster - vmware_cluster_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - show_tag: True - cluster_name: "{{ ccr1 }}" - register: cluster_info - - - assert: - that: - - cluster_info is defined - - cluster_info.clusters[ccr1].tags is defined diff --git a/test/integration/targets/vmware_cluster_vsan/aliases b/test/integration/targets/vmware_cluster_vsan/aliases deleted file mode 100644 index b6fc00bfec..0000000000 --- a/test/integration/targets/vmware_cluster_vsan/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_cluster_vsan/tasks/main.yml b/test/integration/targets/vmware_cluster_vsan/tasks/main.yml deleted file mode 100644 index 23657bb146..0000000000 --- a/test/integration/targets/vmware_cluster_vsan/tasks/main.yml +++ /dev/null @@ -1,64 +0,0 @@ -# Test code for the vmware_cluster module. -# Copyright: (c) 2017, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - -- when: vcsim is not defined - block: - # Setup: Create test cluster - - name: Create test cluster - vmware_cluster: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: "{{ dc1 }}" - cluster_name: test_cluster_vsan - state: present - - # Testcase 0001: Enable vSAN - - name: Enable vSAN - vmware_cluster_vsan: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: "{{ dc1 }}" - cluster_name: test_cluster_vsan - enable_vsan: yes - register: cluster_vsan_result_0001 - - - name: Ensure vSAN is enabled - assert: - that: - - "{{ cluster_vsan_result_0001.changed == true }}" - - # Testcase 0002: Disable vSAN - - name: Disable vSAN - vmware_cluster_vsan: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: "{{ dc1 }}" - cluster_name: test_cluster_vsan - enable_vsan: no - register: cluster_vsan_result_0002 - - - name: Ensure vSAN is disabled - assert: - that: - - "{{ cluster_vsan_result_0002.changed == true }}" - - # Delete test cluster - - name: Delete test cluster - vmware_cluster: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: "{{ dc1 }}" - cluster_name: test_cluster_vsan - state: absent diff --git a/test/integration/targets/vmware_content_deploy_template/aliases b/test/integration/targets/vmware_content_deploy_template/aliases deleted file mode 100644 index a6a5f023b4..0000000000 --- a/test/integration/targets/vmware_content_deploy_template/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -unsupported -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_content_deploy_template/tasks/main.yml b/test/integration/targets/vmware_content_deploy_template/tasks/main.yml deleted file mode 100644 index 38b511a716..0000000000 --- a/test/integration/targets/vmware_content_deploy_template/tasks/main.yml +++ /dev/null @@ -1,37 +0,0 @@ -# Test code for the deploy VM from content library template. -# 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) -- import_role: - name: prepare_vmware_tests - vars: - setup_datacenter: true - -- when: vcsim is not defined - block: - - &deploy_vm_from_content_library_template - vmware_content_deploy_template: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - template: '{{ test_vm_temp }}' - datastore: '{{ rw_datastore }}' - datacenter: '{{ dc1 }}' - folder: '{{ f0 }}' - host: '{{ esx1 }}' - name: 'test_content_deploy_vm' - state: poweredon - validate_certs: false - register: template_deploy - - - name: Check VM deployed successfully - assert: - that: - - template_deploy.changed - - - <<: *deploy_vm_from_content_library_template - name: Deploy VM from template again - - - name: Check VM with same name is deployed - assert: - that: - - not template_deploy.changed
\ No newline at end of file diff --git a/test/integration/targets/vmware_content_library_info/aliases b/test/integration/targets/vmware_content_library_info/aliases deleted file mode 100644 index 62871ab8f0..0000000000 --- a/test/integration/targets/vmware_content_library_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_content_library_info/tasks/main.yml b/test/integration/targets/vmware_content_library_info/tasks/main.yml deleted file mode 100644 index d9d22b9812..0000000000 --- a/test/integration/targets/vmware_content_library_info/tasks/main.yml +++ /dev/null @@ -1,40 +0,0 @@ -# Test code for the vmware_content_library_info. -# 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) - -- when: vcsim is not defined - block: - - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_content_library: true - - # Get List of Content Libraries - - name: Get List of Content Libraries - vmware_content_library_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: false - register: content_library_info - - - debug: var=content_library_info - - set_fact: content_library="{{ content_library_info['content_libs'][0] }}" - - # Get Details of content library - - name: Get facts about Content Library - vmware_content_library_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - library_id: '{{ content_library }}' - validate_certs: false - register: content_lib_info - - - name: Check Content Library details - assert: - that: - - '{{ content_lib_info.content_lib_details[0].library_id == content_library }}' diff --git a/test/integration/targets/vmware_content_library_manager/aliases b/test/integration/targets/vmware_content_library_manager/aliases deleted file mode 100644 index 62871ab8f0..0000000000 --- a/test/integration/targets/vmware_content_library_manager/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_content_library_manager/tasks/main.yml b/test/integration/targets/vmware_content_library_manager/tasks/main.yml deleted file mode 100644 index 94134e3e71..0000000000 --- a/test/integration/targets/vmware_content_library_manager/tasks/main.yml +++ /dev/null @@ -1,91 +0,0 @@ -# Test code for the vmware_content_library CRUD Operations. -# 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) -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - -- when: vcsim is not defined - block: - - &content_lib_delete - name: Delete content library if exists - vmware_content_library_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - library_name: Sample_Library - state: absent - - - &content_lib_create - name: Create content library - vmware_content_library_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: False - library_name: Sample_Library - library_description: Sample Description - datastore_name: '{{ rw_datastore }}' - state: present - register: content_lib_create_result - - - name: Check content library is created - assert: - that: - - content_lib_create_result.changed - - - <<: *content_lib_create - name: Create content library again - - - name: Check if no changes are made - assert: - that: - - not content_lib_create_result.changed - - # Testcase Update Content Library - - &update_content_lib - name: Update a content library - vmware_content_library_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - library_name: Sample_Library - library_description: Update Sample Description - state: present - register: content_lib_update_result - - - name: Check content library is updated - assert: - that: - - content_lib_update_result.changed - - - <<: *update_content_lib - name: Update a content library again - - - name: Check content library is not updated - assert: - that: - - not content_lib_update_result.changed - - # Testcase Delete the content library - - <<: *content_lib_delete - name: Delete content library - register: content_lib_delete_result - - - name: Check content library is deleted - assert: - that: - - content_lib_delete_result.changed - - - <<: *content_lib_delete - name: Delete content library again - register: content_lib_delete_result - - - name: Check if no changes are made - assert: - that: - - not content_lib_delete_result.changed diff --git a/test/integration/targets/vmware_datacenter/aliases b/test/integration/targets/vmware_datacenter/aliases deleted file mode 100644 index b6fc00bfec..0000000000 --- a/test/integration/targets/vmware_datacenter/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_datacenter/tasks/main.yml b/test/integration/targets/vmware_datacenter/tasks/main.yml deleted file mode 100644 index 4a590b138d..0000000000 --- a/test/integration/targets/vmware_datacenter/tasks/main.yml +++ /dev/null @@ -1,50 +0,0 @@ -# Test code for the vmware_datacenter module. -# Copyright: (c) 2017, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - -- &add_dc - name: Add datacenter - vmware_datacenter: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: datacenter_0001 - state: present - register: dc_result - -- debug: - var: dc_result - -- name: Ensure datacenter is present - assert: - that: - - dc_result.changed - -- <<: *add_dc - name: add datacenter again to check idempotent behavior - -- name: Ensure datacenter status is not changed - assert: - that: - - not dc_result.changed - -- when: vcsim is not defined - block: - - name: Delete datacenter - vmware_datacenter: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: datacenter_0001 - state: absent - register: dc_result_delete - - - name: Ensure datacenter is absent - assert: - that: - - dc_result_delete.changed diff --git a/test/integration/targets/vmware_datastore_cluster/aliases b/test/integration/targets/vmware_datastore_cluster/aliases deleted file mode 100644 index b6fc00bfec..0000000000 --- a/test/integration/targets/vmware_datastore_cluster/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_datastore_cluster/tasks/main.yml b/test/integration/targets/vmware_datastore_cluster/tasks/main.yml deleted file mode 100644 index f679172feb..0000000000 --- a/test/integration/targets/vmware_datastore_cluster/tasks/main.yml +++ /dev/null @@ -1,125 +0,0 @@ -# Test code for the vmware_datastore_cluster module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - - - name: Add a datastore cluster to datacenter (check-mode) - vmware_datastore_cluster: &add_datastore_cluster - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - datacenter_name: "{{ dc1 }}" - datastore_cluster_name: DSC1 - enable_sdrs: False - state: present - check_mode: yes - register: add_dsc_check - - - assert: - that: - - add_dsc_check.changed - - - name: Add a datastore cluster to datacenter - vmware_datastore_cluster: *add_datastore_cluster - register: add_dsc - - - assert: - that: - - add_dsc.changed - - - name: Add a datastore cluster to datacenter again - vmware_datastore_cluster: *add_datastore_cluster - register: add_dsc - - - assert: - that: - - not add_dsc.changed - - - name: Enable SDRS on a datastore cluster (check-mode) - vmware_datastore_cluster: &enable_sdrs - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - datacenter_name: "{{ dc1 }}" - datastore_cluster_name: DSC1 - enable_sdrs: True - state: present - check_mode: yes - register: enable_sdrs_check - - - assert: - that: - - enable_sdrs_check.changed - - - name: Enable SDRS on a datastore cluster - vmware_datastore_cluster: *enable_sdrs - register: enable_sdrs - - - assert: - that: - - enable_sdrs.changed - - - name: Enable SDRS on a datastore cluster again - vmware_datastore_cluster: *enable_sdrs - register: enable_sdrs_again - - - assert: - that: - - not enable_sdrs_again.changed - - - name: Create a datastore folder on given Datacenter - vcenter_folder: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: '{{ dc1 }}' - folder_name: 'my_datastore_folder' - folder_type: datastore - state: present - validate_certs: no - register: my_datastore_folder - - - name: Add a datastore cluster using folder - vmware_datastore_cluster: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - folder: "{{ my_datastore_folder.result.path }}" - datastore_cluster_name: DSC2 - state: present - register: add_dsc_folder_check - - - assert: - that: - - add_dsc_folder_check.changed - - - name: Delete a datastore cluster to datacenter (check-mode) - vmware_datastore_cluster: &delete_datastore_cluster - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - datacenter_name: "{{ dc1 }}" - datastore_cluster_name: DSC1 - state: absent - check_mode: yes - register: delete_dsc_check - - - assert: - that: - - delete_dsc_check.changed - - - name: Delete a datastore cluster to datacenter - vmware_datastore_cluster: *delete_datastore_cluster - register: delete_dsc_check - - - assert: - that: - - delete_dsc_check.changed diff --git a/test/integration/targets/vmware_datastore_facts/aliases b/test/integration/targets/vmware_datastore_facts/aliases deleted file mode 100644 index dea29ccd8b..0000000000 --- a/test/integration/targets/vmware_datastore_facts/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_datastore_facts/tasks/main.yml b/test/integration/targets/vmware_datastore_facts/tasks/main.yml deleted file mode 100644 index a78d70fe1f..0000000000 --- a/test/integration/targets/vmware_datastore_facts/tasks/main.yml +++ /dev/null @@ -1,126 +0,0 @@ -# Test code for the vmware_datastore_facts module. -# Copyright (c) 2017, Tim Rightnour <thegarbledone@gmail.com> -# Copyright (c) 2018, Ansible Project -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - - -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - -- when: vcsim is not defined - block: - - name: get list of facts about datastores from the ESXi - vmware_datastore_facts: - validate_certs: False - hostname: '{{ item }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - register: facts_from_esxi - with_items: "{{ esxi_hosts }}" - - assert: - that: - - "facts_from_esxi.results[0].datastores|selectattr('type', 'equalto', 'NFS')|list|length == 2" - -- name: get list of facts about datastores - vmware_datastore_facts: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - gather_nfs_mount_info: true - register: facts_from_vcenter_with_dc_filter - -- when: vcsim is not defined - block: - - name: get list of facts about datastores - vmware_datastore_facts: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - gather_nfs_mount_info: true - register: facts_from_vcenter_with_no_filter - - - assert: - that: - - "facts_from_vcenter_with_dc_filter.datastores|selectattr('type', 'equalto', 'NFS')|list|length == 2" - - "facts_from_vcenter_with_no_filter.datastores|selectattr('type', 'equalto', 'NFS')|list|length == 2" - - "facts_from_vcenter_with_no_filter.datastores[0]['capacity'] is defined" - -# Testcase 0002: Get a full list of datastores in a cluster -- name: get list of facts about datastores - no dc - vmware_datastore_facts: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster: "{{ ccr1 }}" - register: datastore_facts_0002 - -- debug: - msg: "{{ datastore_facts_0002 }}" - -- assert: - that: - - "datastore_facts_0002['datastores'][0]['capacity'] is defined" - -# Testcase 0003: Find a specific datastore -- name: get list of facts about one datastore - vmware_datastore_facts: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - name: "{{ ro_datastore }}" - register: datastore_facts_0003 - -- debug: - msg: "{{ datastore_facts_0003 }}" - -- assert: - that: - - "datastore_facts_0003['datastores'][0]['name'] == ro_datastore" - - "datastore_facts_0003['datastores'][0]['capacity'] is defined" - -- name: get list of extended facts about one datastore - vmware_datastore_facts: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - name: "{{ ro_datastore }}" - gather_nfs_mount_info: True - gather_vmfs_mount_info: True - register: datastore_facts_0004 - -- debug: - msg: "{{ datastore_facts_0004 }}" - -- assert: - that: - - "datastore_facts_0004['datastores'][0]['name'] == ro_datastore" - - "datastore_facts_0004['datastores'][0]['capacity'] is defined" - -- name: get list of facts about one datastore in check mode - vmware_datastore_facts: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - name: "{{ ro_datastore }}" - register: datastore_facts_0005 - -- debug: - msg: "{{ datastore_facts_0005 }}" - -- assert: - that: - - "datastore_facts_0005['datastores'][0]['name'] == ro_datastore" - - "datastore_facts_0005['datastores'][0]['capacity'] is defined" diff --git a/test/integration/targets/vmware_datastore_info/aliases b/test/integration/targets/vmware_datastore_info/aliases deleted file mode 100644 index dea29ccd8b..0000000000 --- a/test/integration/targets/vmware_datastore_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_datastore_info/tasks/main.yml b/test/integration/targets/vmware_datastore_info/tasks/main.yml deleted file mode 100644 index eff3f73fc0..0000000000 --- a/test/integration/targets/vmware_datastore_info/tasks/main.yml +++ /dev/null @@ -1,192 +0,0 @@ -# Test code for the vmware_datastore_info module. -# Copyright (c) 2017, Tim Rightnour <thegarbledone@gmail.com> -# Copyright (c) 2018, Ansible Project -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - - -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - -- when: vcsim is not defined - block: - - name: get list of info about datastores from the ESXi - vmware_datastore_info: - validate_certs: False - hostname: '{{ item }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - register: info_from_esxi - with_items: "{{ esxi_hosts }}" - - assert: - that: - - "info_from_esxi.results[0].datastores|selectattr('type', 'equalto', 'NFS')|list|length == 2" - -- name: get list of info about datastores - vmware_datastore_info: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - gather_nfs_mount_info: true - register: info_from_vcenter_with_dc_filter - -- when: vcsim is not defined - block: - - name: get list of info about datastores - vmware_datastore_info: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - gather_nfs_mount_info: true - register: info_from_vcenter_with_no_filter - - - assert: - that: - - "info_from_vcenter_with_dc_filter.datastores|selectattr('type', 'equalto', 'NFS')|list|length == 2" - - "info_from_vcenter_with_no_filter.datastores|selectattr('type', 'equalto', 'NFS')|list|length == 2" - - "info_from_vcenter_with_no_filter.datastores[0]['capacity'] is defined" - -# Testcase 0002: Get a full list of datastores in a cluster -- name: get list of info about datastores - no dc - vmware_datastore_info: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster: "{{ ccr1 }}" - register: datastore_info_0002 - -- debug: - msg: "{{ datastore_info_0002 }}" - -- assert: - that: - - "datastore_info_0002['datastores'][0]['capacity'] is defined" - -# Testcase 0003: Find a specific datastore -- name: get list of info about one datastore - vmware_datastore_info: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - name: "{{ ro_datastore }}" - register: datastore_info_0003 - -- debug: - msg: "{{ datastore_info_0003 }}" - -- assert: - that: - - "datastore_info_0003['datastores'][0]['name'] == ro_datastore" - - "datastore_info_0003['datastores'][0]['capacity'] is defined" - -- name: get list of extended info about one datastore - vmware_datastore_info: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - name: "{{ ro_datastore }}" - gather_nfs_mount_info: True - gather_vmfs_mount_info: True - register: datastore_info_0004 - -- debug: - msg: "{{ datastore_info_0004 }}" - -- assert: - that: - - "datastore_info_0004['datastores'][0]['name'] == ro_datastore" - - "datastore_info_0004['datastores'][0]['capacity'] is defined" - -- name: get list of info about one datastore in check mode - vmware_datastore_info: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - name: "{{ ro_datastore }}" - register: datastore_info_0005 - -- debug: - msg: "{{ datastore_info_0005 }}" - -- assert: - that: - - "datastore_info_0005['datastores'][0]['name'] == ro_datastore" - - "datastore_info_0005['datastores'][0]['capacity'] is defined" - -# Testcase with property specify -- name: get list of info about datastores with properties specify - no dc - vmware_datastore_info: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster: "{{ ccr1 }}" - schema: vsphere - properties: - - name - register: datastore_info_0006 - -- debug: - msg: "{{ datastore_info_0006 }}" - -- assert: - that: - - "datastore_info_0006['datastores'][0]['name'] is defined" - -- name: get list of info about one datastore with properties specify - vmware_datastore_info: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - name: "{{ ro_datastore }}" - schema: vsphere - properties: - - name - register: datastore_info_0007 - -- debug: - msg: "{{ datastore_info_0007 }}" - -- assert: - that: - - "datastore_info_0007['datastores'][0]['name'] is defined" - - "datastore_info_0007['datastores'][0]['name'] == ro_datastore" - - "datastore_info_0007['datastores'] | length == 1" - -- name: get list of info about datastores with multiple properties specify - vmware_datastore_info: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - name: "{{ ro_datastore }}" - schema: vsphere - properties: - - name - - capability.vsanSparseSupported - - overallStatus - register: datastore_info_0008 - -- debug: - msg: "{{ datastore_info_0008 }}" - -- assert: - that: - - "datastore_info_0008['datastores'][0]['name'] is defined" - - "datastore_info_0008['datastores'][0]['capability']['vsanSparseSupported'] is defined" - - "datastore_info_0008['datastores'][0]['overallStatus'] is defined" diff --git a/test/integration/targets/vmware_datastore_maintenancemode/aliases b/test/integration/targets/vmware_datastore_maintenancemode/aliases deleted file mode 100644 index 62871ab8f0..0000000000 --- a/test/integration/targets/vmware_datastore_maintenancemode/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_datastore_maintenancemode/tasks/main.yml b/test/integration/targets/vmware_datastore_maintenancemode/tasks/main.yml deleted file mode 100644 index 62632a047c..0000000000 --- a/test/integration/targets/vmware_datastore_maintenancemode/tasks/main.yml +++ /dev/null @@ -1,84 +0,0 @@ -# Test code for the vmware_datastore_maintenancemode module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# TODO: vcsim does not support datastore maintenance mode properties -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - - - name: Enter datastore in maintenance mode - vmware_datastore_maintenancemode: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - state: present - datastore: "{{ ro_datastore }}" - validate_certs: no - register: test_result_0001 - - - debug: - var: test_result_0001 - - - name: assert that changes were made - assert: - that: - - test_result_0001 is changed - - - name: Enter datastore in maintenance mode again - vmware_datastore_maintenancemode: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - state: present - datastore: "{{ ro_datastore }}" - validate_certs: no - register: test_result_0002 - - - debug: - var: test_result_0002 - - - name: assert that no changes were made - assert: - that: - - not (test_result_0002 is changed) - - - name: Exit datastores from maintenance mode - vmware_datastore_maintenancemode: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - state: absent - datastore: "{{ ro_datastore }}" - validate_certs: no - register: test_result_0003 - - - debug: - var: test_result_0003 - - - name: assert that changes were made - assert: - that: - - test_result_0003 is changed - - - name: Exit datastores from maintenance mode again - vmware_datastore_maintenancemode: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - state: absent - datastore: "{{ ro_datastore }}" - validate_certs: no - register: test_result_0004 - - - debug: - var: test_result_0004 - - - name: assert that no changes were made - assert: - that: - - not (test_result_0004 is changed) diff --git a/test/integration/targets/vmware_drs_group/aliases b/test/integration/targets/vmware_drs_group/aliases deleted file mode 100644 index dea29ccd8b..0000000000 --- a/test/integration/targets/vmware_drs_group/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_drs_group/tasks/main.yml b/test/integration/targets/vmware_drs_group/tasks/main.yml deleted file mode 100644 index 071f9c0719..0000000000 --- a/test/integration/targets/vmware_drs_group/tasks/main.yml +++ /dev/null @@ -1,75 +0,0 @@ -# Test code for the vmware_drs_group module -# Copyright: (c) 2018, Karsten Kaj Jakobsen <kj@patientsky.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_virtualmachines: true - -- name: Create DRS VM group - vmware_drs_group: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: False - # Options - cluster_name: '{{ ccr1 }}' - datacenter_name: '{{ dc1 }}' - group_name: TEST_VM_01 - vms: "{{ virtual_machines_in_cluster | map(attribute='name') | list }}" - state: present - register: drs_vm_group_01_results - -- debug: - var: drs_vm_group_01_results - -- assert: - that: - - "drs_vm_group_01_results.changed" - -- when: vcsim is defined or esxi_hosts | length >= 3 - block: - - name: Create DRS Host group - vmware_drs_group: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: False - cluster_name: '{{ ccr1 }}' - datacenter_name: '{{ dc1 }}' - group_name: TEST_HOST_01 - hosts: "{{ esxi_hosts[0:3] }}" - state: present - register: drs_host_group_01_results - - - debug: - var: drs_host_group_01_results - - - assert: - that: - - "drs_host_group_01_results.changed" - - - name: Delete DRS Host group - vmware_drs_group: - # Login creds - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: False - # Options - cluster_name: DC0_C0 - datacenter_name: DC0 - group_name: TEST_HOST_01 - hosts: [] - state: absent - register: drs_host_group_01_delete_results - - - debug: - var: drs_host_group_01_delete_results - - - assert: - that: - - "drs_host_group_01_delete_results.changed" diff --git a/test/integration/targets/vmware_drs_group_facts/aliases b/test/integration/targets/vmware_drs_group_facts/aliases deleted file mode 100644 index b6fc00bfec..0000000000 --- a/test/integration/targets/vmware_drs_group_facts/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_drs_group_facts/tasks/main.yml b/test/integration/targets/vmware_drs_group_facts/tasks/main.yml deleted file mode 100644 index d941a2a5be..0000000000 --- a/test/integration/targets/vmware_drs_group_facts/tasks/main.yml +++ /dev/null @@ -1,44 +0,0 @@ -# Test code for the vmware_drs_group_facts module -# Copyright: (c) 2018, Karsten Kaj Jakobsen <kj@patientsky.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - -- when: vcsim is defined or esxi_hosts | length >= 3 - block: - - name: Gather DRS group facts from given cluster - vmware_drs_group_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: '{{ ccr1 }}' - validate_certs: False - register: drs_group_0001_results - - - debug: - var: drs_group_0001_results - - - assert: - that: - - "drs_group_0001_results.drs_group_facts.DC0_C0 is defined" - - "not drs_group_0001_results.drs_group_facts.DC0_C1 is defined" - - "not drs_group_0001_results.changed" - - - name: Gather DRS group facts from given datacenter - vmware_drs_group_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: '{{ dc1 }}' - validate_certs: False - register: drs_group_0002_results - - - debug: - var: drs_group_0002_results - - - assert: - that: - - "drs_group_0002_results.drs_group_facts.DC0_C0 is defined" - - "not drs_group_0002_results.drs_group_facts.DC0_C1 is defined" - - "not drs_group_0002_results.changed" diff --git a/test/integration/targets/vmware_drs_group_info/aliases b/test/integration/targets/vmware_drs_group_info/aliases deleted file mode 100644 index b6fc00bfec..0000000000 --- a/test/integration/targets/vmware_drs_group_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_drs_group_info/tasks/main.yml b/test/integration/targets/vmware_drs_group_info/tasks/main.yml deleted file mode 100644 index 8b7e20be64..0000000000 --- a/test/integration/targets/vmware_drs_group_info/tasks/main.yml +++ /dev/null @@ -1,44 +0,0 @@ -# Test code for the vmware_drs_group_info module -# Copyright: (c) 2018, Karsten Kaj Jakobsen <kj@patientsky.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - -- when: vcsim is defined or esxi_hosts | length >= 3 - block: - - name: Gather DRS group info from given cluster - vmware_drs_group_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: '{{ ccr1 }}' - validate_certs: False - register: drs_group_0001_results - - - debug: - var: drs_group_0001_results - - - assert: - that: - - "drs_group_0001_results.drs_group_info.DC0_C0 is defined" - - "not drs_group_0001_results.drs_group_info.DC0_C1 is defined" - - "not drs_group_0001_results.changed" - - - name: Gather DRS group info from given datacenter - vmware_drs_group_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: '{{ dc1 }}' - validate_certs: False - register: drs_group_0002_results - - - debug: - var: drs_group_0002_results - - - assert: - that: - - "drs_group_0002_results.drs_group_info.DC0_C0 is defined" - - "not drs_group_0002_results.drs_group_info.DC0_C1 is defined" - - "not drs_group_0002_results.changed" diff --git a/test/integration/targets/vmware_drs_rule_facts/aliases b/test/integration/targets/vmware_drs_rule_facts/aliases deleted file mode 100644 index dea29ccd8b..0000000000 --- a/test/integration/targets/vmware_drs_rule_facts/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_drs_rule_facts/tasks/main.yml b/test/integration/targets/vmware_drs_rule_facts/tasks/main.yml deleted file mode 100644 index 825fc6ea4d..0000000000 --- a/test/integration/targets/vmware_drs_rule_facts/tasks/main.yml +++ /dev/null @@ -1,47 +0,0 @@ -# Test code for the vmware_drs_rule_facts module -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - -- when: vcsim is defined or esxi_hosts | length >= 3 - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - - name: Gather facts about DRS rule from given cluster - vmware_drs_rule_facts: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: DC0_C0 - register: drs_rule_0001_results - - - debug: - var: drs_rule_0001_results - - - assert: - that: - - "drs_rule_0001_results.drs_rule_facts is defined" - - "not drs_rule_0001_results.changed" - - - name: Gather facts about DRS rule from given datacenter - vmware_drs_rule_facts: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: DC0 - register: drs_rule_0001_results - - - debug: - var: drs_rule_0001_results - - - assert: - that: - - "drs_rule_0001_results.drs_rule_facts is defined" - - "not drs_rule_0001_results.changed" diff --git a/test/integration/targets/vmware_drs_rule_info/aliases b/test/integration/targets/vmware_drs_rule_info/aliases deleted file mode 100644 index dea29ccd8b..0000000000 --- a/test/integration/targets/vmware_drs_rule_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_drs_rule_info/tasks/main.yml b/test/integration/targets/vmware_drs_rule_info/tasks/main.yml deleted file mode 100644 index 1b4f428d69..0000000000 --- a/test/integration/targets/vmware_drs_rule_info/tasks/main.yml +++ /dev/null @@ -1,47 +0,0 @@ -# Test code for the vmware_drs_rule_info module -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - -- when: vcsim is defined or esxi_hosts | length >= 3 - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - - name: Gather info about DRS rule from given cluster - vmware_drs_rule_info: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: DC0_C0 - register: drs_rule_0001_results - - - debug: - var: drs_rule_0001_results - - - assert: - that: - - "drs_rule_0001_results.drs_rule_info is defined" - - "not drs_rule_0001_results.changed" - - - name: Gather info about DRS rule from given datacenter - vmware_drs_rule_info: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: DC0 - register: drs_rule_0001_results - - - debug: - var: drs_rule_0001_results - - - assert: - that: - - "drs_rule_0001_results.drs_rule_info is defined" - - "not drs_rule_0001_results.changed" diff --git a/test/integration/targets/vmware_dvs_portgroup/aliases b/test/integration/targets/vmware_dvs_portgroup/aliases deleted file mode 100644 index b6fc00bfec..0000000000 --- a/test/integration/targets/vmware_dvs_portgroup/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_dvs_portgroup/tasks/main.yml b/test/integration/targets/vmware_dvs_portgroup/tasks/main.yml deleted file mode 100644 index 00dbefd304..0000000000 --- a/test/integration/targets/vmware_dvs_portgroup/tasks/main.yml +++ /dev/null @@ -1,387 +0,0 @@ -# Test code for the vmware_dvs_portgroup module. -# Copyright: (c) 2017, Philippe Dellaert <philippe@dellaert.org> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - vars: - setup_dvswitch: true - -- name: create basic portgroup - vmware_dvs_portgroup: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - switch_name: "{{ dvswitch1 }}" - portgroup_name: "basic" - vlan_id: 0 - num_ports: 32 - portgroup_type: earlyBinding - state: present - register: dvs_pg_result_0001 - -- debug: - var: dvs_pg_result_0001 - -- name: ensure dvs portgroup is present - assert: - that: - - dvs_pg_result_0001.changed - -- name: create basic VLAN portgroup - vmware_dvs_portgroup: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - switch_name: "{{ dvswitch1 }}" - portgroup_name: "basic-vlan10" - vlan_id: 10 - num_ports: 32 - portgroup_type: earlyBinding - state: present - register: dvs_pg_result_0002 - -- name: ensure dvs portgroup is present - assert: - that: - - dvs_pg_result_0002.changed - -- name: create basic trunk portgroup - vmware_dvs_portgroup: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - switch_name: "{{ dvswitch1 }}" - portgroup_name: "basic-trunk" - vlan_id: 1-4094 - vlan_trunk: True - num_ports: 32 - portgroup_type: earlyBinding - state: present - register: dvs_pg_result_0003 - -- name: ensure dvs portgroup is present - assert: - that: - - dvs_pg_result_0003.changed - -- name: create basic portgroup again - vmware_dvs_portgroup: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - switch_name: "{{ dvswitch1 }}" - portgroup_name: "basic" - vlan_id: 0 - num_ports: 32 - portgroup_type: earlyBinding - state: present - register: dvs_pg_result_0004 - -- name: ensure dvs portgroup is present - assert: - that: - - not dvs_pg_result_0004.changed - -- name: create basic portgroup with all security and policy settings enabled - vmware_dvs_portgroup: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - switch_name: "{{ dvswitch1 }}" - portgroup_name: "basic-all-enabled" - vlan_id: 0 - num_ports: 32 - portgroup_type: earlyBinding - state: present - network_policy: - promiscuous: yes - forged_transmits: yes - mac_changes: yes - port_policy: - block_override: yes - ipfix_override: yes - live_port_move: yes - network_rp_override: yes - port_config_reset_at_disconnect: yes - security_override: yes - shaping_override: yes - traffic_filter_override: yes - uplink_teaming_override: yes - vendor_config_override: yes - vlan_override: yes - register: dvs_pg_result_0005 - -- name: ensure dvs portgroup is present - assert: - that: - - dvs_pg_result_0005.changed - -- name: create basic portgroup with some security and policy settings enabled - vmware_dvs_portgroup: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - switch_name: "{{ dvswitch1 }}" - portgroup_name: "basic-some-enabled" - vlan_id: 0 - num_ports: 32 - portgroup_type: earlyBinding - state: present - network_policy: - promiscuous: yes - forged_transmits: yes - mac_changes: no - port_policy: - vlan_override: yes - register: dvs_pg_result_0006 - -- name: ensure dvs portgroup is present - assert: - that: - - dvs_pg_result_0006.changed - -- name: Change forged_transmits to no - vmware_dvs_portgroup: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - switch_name: "{{ dvswitch1 }}" - portgroup_name: "basic-some-enabled" - vlan_id: 0 - num_ports: 32 - portgroup_type: earlyBinding - state: present - network_policy: - promiscuous: yes - forged_transmits: no - mac_changes: no - port_policy: - vlan_override: yes - register: dvs_pg_result_0007 - -- name: ensure forged_transmits is changed - assert: - that: - - dvs_pg_result_0007.changed - -- name: Change vlan_override to no - vmware_dvs_portgroup: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - switch_name: "{{ dvswitch1 }}" - portgroup_name: "basic-some-enabled" - vlan_id: 0 - num_ports: 32 - portgroup_type: earlyBinding - state: present - network_policy: - promiscuous: yes - forged_transmits: no - mac_changes: no - port_policy: - vlan_override: no - register: dvs_pg_result_0008 - -- name: ensure vlan_override is changed - assert: - that: - - dvs_pg_result_0008.changed - -- name: Change num_ports to 16 - vmware_dvs_portgroup: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - switch_name: "{{ dvswitch1 }}" - portgroup_name: "basic-some-enabled" - vlan_id: 0 - num_ports: 16 - portgroup_type: earlyBinding - state: present - network_policy: - promiscuous: yes - forged_transmits: no - mac_changes: no - port_policy: - vlan_override: no - register: dvs_pg_result_0009 - -- name: ensure vlan_override is changed - assert: - that: - - dvs_pg_result_0009.changed - -- name: Change portgroup_type to ephemeral - vmware_dvs_portgroup: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - switch_name: "{{ dvswitch1 }}" - portgroup_name: "basic-some-enabled" - vlan_id: 0 - num_ports: 16 - portgroup_type: ephemeral - state: present - network_policy: - promiscuous: yes - forged_transmits: no - mac_changes: no - port_policy: - vlan_override: no - register: dvs_pg_result_0010 - -- name: ensure vlan_override is changed - assert: - that: - - dvs_pg_result_0010.changed - -- name: delete basic portgroup - vmware_dvs_portgroup: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - switch_name: "{{ dvswitch1 }}" - portgroup_name: "basic" - vlan_id: 0 - num_ports: 32 - portgroup_type: earlyBinding - state: absent - register: dvs_pg_result_0011 - -- name: ensure dvs portgroup is removed - assert: - that: - - dvs_pg_result_0011.changed - -- name: delete basic portgroup again - vmware_dvs_portgroup: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - switch_name: "{{ dvswitch1 }}" - portgroup_name: "basic" - vlan_id: 0 - num_ports: 32 - portgroup_type: earlyBinding - state: absent - register: dvs_pg_result_0012 - -- name: ensure dvs portgroup is removed - assert: - that: - - not dvs_pg_result_0012.changed - -- name: Check valid VLAN id range in DVS Portgroup - vmware_dvs_portgroup: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - switch_name: "{{ dvswitch1 }}" - portgroup_name: "basic_trunk_0001" - vlan_id: 1-4096 - vlan_trunk: True - num_ports: 32 - portgroup_type: earlyBinding - state: present - register: dvs_pg_result_0013 - ignore_errors: True - -- name: Ensure module fails for invalid VLAN id - assert: - that: - - not dvs_pg_result_0013.changed - - "'vlan_id range 1-4096 specified is incorrect. The valid vlan_id range is from 0 to 4094.' == '{{ dvs_pg_result_0013.msg }}'" - -- name: Change VLAN on basic VLAN portgroup - vmware_dvs_portgroup: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - switch_name: "{{ dvswitch1 }}" - portgroup_name: "basic-vlan10" - vlan_id: 20 - num_ports: 32 - portgroup_type: earlyBinding - state: present - register: dvs_pg_result_0014 - -- name: ensure dvs portgroup is changed - assert: - that: - - dvs_pg_result_0014.changed - -- name: Change VLAN range on basic trunk portgroup - vmware_dvs_portgroup: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - switch_name: "{{ dvswitch1 }}" - portgroup_name: "basic-trunk" - vlan_id: 1000-2000 - vlan_trunk: True - num_ports: 32 - portgroup_type: earlyBinding - state: present - register: dvs_pg_result_0015 - -- name: ensure dvs portgroup is changed - assert: - that: - - dvs_pg_result_0015.changed - -- name: create complex trunk portgroup - vmware_dvs_portgroup: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - switch_name: "{{ dvswitch1 }}" - portgroup_name: "complex-trunk" - vlan_id: 1-1000, 1005, 1100-1200 - vlan_trunk: True - num_ports: 32 - portgroup_type: earlyBinding - state: present - register: dvs_pg_result_0016 - -- name: ensure dvs portgroup is present - assert: - that: - - dvs_pg_result_0016.changed - -- name: change complex trunk portgroup - vmware_dvs_portgroup: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - switch_name: "{{ dvswitch1 }}" - portgroup_name: "complex-trunk" - vlan_id: 1-1000, 1006, 1100-1200 - vlan_trunk: True - num_ports: 32 - portgroup_type: earlyBinding - state: present - register: dvs_pg_result_0017 - -- name: ensure dvs portgroup is changed - assert: - that: - - dvs_pg_result_0017.changed diff --git a/test/integration/targets/vmware_dvs_portgroup_facts/aliases b/test/integration/targets/vmware_dvs_portgroup_facts/aliases deleted file mode 100644 index b1212da1b7..0000000000 --- a/test/integration/targets/vmware_dvs_portgroup_facts/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_dvs_portgroup_facts/tasks/main.yml b/test/integration/targets/vmware_dvs_portgroup_facts/tasks/main.yml deleted file mode 100644 index 38a5b63b36..0000000000 --- a/test/integration/targets/vmware_dvs_portgroup_facts/tasks/main.yml +++ /dev/null @@ -1,56 +0,0 @@ -# Test code for the vmware_dvs_portgroup_facts module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - vars: - setup_dvswitch: true - -- when: vcsim is not defined - block: - - &dvs_facts - name: Gather facts about DVS portgroup - vmware_dvs_portgroup_facts: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - register: dvs_results - - - debug: - var: dvs_results - - - assert: - that: - - dvs_results.dvs_portgroup_facts is defined - - - <<: *dvs_facts - name: Gather facts about DVS portgroup in check mode - check_mode: yes - - - debug: - var: dvs_results - - - assert: - that: - - dvs_results.dvs_portgroup_facts is defined - -# Testcase 0002: Get portgroup facts for a given dvswitch -- name: get facts for a given dvswitch - vmware_dvs_portgroup_facts: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - dvswitch: "{{ dvswitch1 }}" - register: dvs_results_0002 - -- debug: - msg: "{{ dvs_results_0002 }}" - -- assert: - that: - - "dvs_results_0002['dvs_portgroup_facts']['DVS0'] is defined" diff --git a/test/integration/targets/vmware_dvs_portgroup_find/aliases b/test/integration/targets/vmware_dvs_portgroup_find/aliases deleted file mode 100644 index b1212da1b7..0000000000 --- a/test/integration/targets/vmware_dvs_portgroup_find/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_dvs_portgroup_find/tasks/main.yml b/test/integration/targets/vmware_dvs_portgroup_find/tasks/main.yml deleted file mode 100644 index 2eb372a018..0000000000 --- a/test/integration/targets/vmware_dvs_portgroup_find/tasks/main.yml +++ /dev/null @@ -1,23 +0,0 @@ -# Test code for the vmware_dvs_portgroup_find module. -# Copyright: (c) 2019, David Martinez (@dx0xm) -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - vars: - setup_dvswitch: true - -- name: get list of portgroups - vmware_dvs_portgroup_find: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - register: dvspg_0001 - -- debug: - var: dvspg_0001 - -- assert: - that: - - dvspg_0001.dvs_portgroups is defined diff --git a/test/integration/targets/vmware_dvs_portgroup_info/aliases b/test/integration/targets/vmware_dvs_portgroup_info/aliases deleted file mode 100644 index b1212da1b7..0000000000 --- a/test/integration/targets/vmware_dvs_portgroup_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_dvs_portgroup_info/tasks/main.yml b/test/integration/targets/vmware_dvs_portgroup_info/tasks/main.yml deleted file mode 100644 index 52babceeca..0000000000 --- a/test/integration/targets/vmware_dvs_portgroup_info/tasks/main.yml +++ /dev/null @@ -1,56 +0,0 @@ -# Test code for the vmware_dvs_portgroup_info module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - vars: - setup_dvswitch: true - -- when: vcsim is not defined - block: - - &dvs_info - name: Gather info about DVS portgroup - vmware_dvs_portgroup_info: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - register: dvs_results - - - debug: - var: dvs_results - - - assert: - that: - - dvs_results.dvs_portgroup_info is defined - - - <<: *dvs_info - name: Gather info about DVS portgroup in check mode - check_mode: yes - - - debug: - var: dvs_results - - - assert: - that: - - dvs_results.dvs_portgroup_info is defined - -# Testcase 0002: Get portgroup info for a given dvswitch -- name: get info for a given dvswitch - vmware_dvs_portgroup_info: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - dvswitch: "{{ dvswitch1 }}" - register: dvs_results_0002 - -- debug: - msg: "{{ dvs_results_0002 }}" - -- assert: - that: - - "dvs_results_0002['dvs_portgroup_info']['DVS0'] is defined" diff --git a/test/integration/targets/vmware_dvswitch/aliases b/test/integration/targets/vmware_dvswitch/aliases deleted file mode 100644 index b6fc00bfec..0000000000 --- a/test/integration/targets/vmware_dvswitch/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_dvswitch/tasks/main.yml b/test/integration/targets/vmware_dvswitch/tasks/main.yml deleted file mode 100644 index b1aa86675b..0000000000 --- a/test/integration/targets/vmware_dvswitch/tasks/main.yml +++ /dev/null @@ -1,100 +0,0 @@ -# Test code for the vmware_dvswitch module. -# Copyright: (c) 2017, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - vars: - setup_datacenter: true - -- &dvs_data - name: Add distributed vSwitch - vmware_dvswitch: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: "{{ dc1 }}" - state: present - switch_name: dvswitch_0001 - mtu: 9000 - uplink_quantity: 2 - discovery_proto: lldp - discovery_operation: both - register: dvs_result_0001 - -- name: Ensure distributed vswitch is present - assert: - that: - - dvs_result_0001.changed - -- name: Create a VM folder on given Datacenter - vcenter_folder: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: '{{ dc1 }}' - folder_name: network_folder - folder_type: network - state: present - validate_certs: no - register: - network_folder_result - -- name: Add distributed vSwitch using folder - vmware_dvswitch: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - folder: "{{ network_folder_result.result.path }}" - state: present - switch_name: dvswitch_0002 - mtu: 9000 - uplink_quantity: 2 - discovery_proto: lldp - discovery_operation: both - register: dvs_result_0002 - -- name: Ensure distributed vswitch is present - assert: - that: - - dvs_result_0002.changed - -# vcsim doesn't support ldp check (self.dvs.config.linkDiscoveryProtocolConfig.protocol) -- when: vcsim is not defined - block: - - <<: *dvs_data - name: add distributed vSwitch again - register: dvs_result_0002 - - - name: ensure distributed vswitch is present - assert: - that: - - not dvs_result_0002.changed - -# FIXME: Remove this testcase from block once vcsim supports distributed vswitch delete method -# Currently, vcsim does not support distributed vswitch delete option, -# Once this feature is available we can move this out of this block - -# Testcase 0003: Add Distributed vSwitch - - name: delete the distributed vSwitch - vmware_dvswitch: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: "{{ dc1 }}" - state: absent - switch_name: '{{ item }}' - loop: - - dvswitch_0001 - - dvswitch_0002 - register: dvswitch_delete - - debug: var=dvswitch_delete - - - name: Ensure the state has changed - assert: - that: - - dvswitch_delete.results[0] is changed - - dvswitch_delete.results[1] is changed diff --git a/test/integration/targets/vmware_dvswitch_nioc/aliases b/test/integration/targets/vmware_dvswitch_nioc/aliases deleted file mode 100644 index b1212da1b7..0000000000 --- a/test/integration/targets/vmware_dvswitch_nioc/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_dvswitch_nioc/tasks/main.yml b/test/integration/targets/vmware_dvswitch_nioc/tasks/main.yml deleted file mode 100644 index 1aa4da06cd..0000000000 --- a/test/integration/targets/vmware_dvswitch_nioc/tasks/main.yml +++ /dev/null @@ -1,103 +0,0 @@ -# Test code for the vmware_dvswitch_nioc module. -# Copyright: (c) 2018, VMware, Inc. -# Copyright: (c) 2019, Abhijeet Kasurde <akasurde@redhat.com> -# SPDX-License-Identifier: GPL-3.0-or-later -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - - - name: Add distributed vSwitch - vmware_dvswitch: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: "{{ dc1 }}" - state: present - switch_name: dvswitch_0001 - mtu: 9000 - uplink_quantity: 2 - discovery_proto: lldp - discovery_operation: both - register: dvs_result_0001 - - - debug: - var: dvs_result_0001 - - - name: ensure distributed vswitch is present - assert: - that: - - dvs_result_0001 is changed - - - &enable_nioc - name: Enable NIOC - vmware_dvswitch_nioc: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - switch: dvswitch_0001 - version: version3 - validate_certs: no - resources: - - name: vmotion - limit: -1 - reservation: 128 - shares_level: normal - - name: vsan - limit: -1 - shares_level: custom - shares: 99 - reservation: 256 - state: present - register: enable_nioc_result - - - debug: - var: enable_nioc_result - - - name: Check if nioc is enabled - assert: - that: - - enable_nioc_result.changed - - - <<: *enable_nioc - name: Change nioc settings again and make sure it does not change - register: enable_nioc_result_2 - - - name: Check if nioc changes are not made - assert: - that: - - not enable_nioc_result_2.changed - - - &disable_nioc - name: Disable NIOC - vmware_dvswitch_nioc: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - switch: dvswitch_0001 - validate_certs: no - state: absent - register: disable_nioc_result - - - debug: - var: disable_nioc_result - - - name: Check if nioc is disabled - assert: - that: - - disable_nioc_result.changed - - - <<: *disable_nioc - name: Disable NIOC again - register: disable_nioc_result_2 - - - debug: - var: disable_nioc_result_2 - - - name: Check if nioc is not disabled since it is already disabled - assert: - that: - - not disable_nioc_result_2.changed diff --git a/test/integration/targets/vmware_dvswitch_pvlans/aliases b/test/integration/targets/vmware_dvswitch_pvlans/aliases deleted file mode 100644 index b1212da1b7..0000000000 --- a/test/integration/targets/vmware_dvswitch_pvlans/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_dvswitch_pvlans/tasks/main.yml b/test/integration/targets/vmware_dvswitch_pvlans/tasks/main.yml deleted file mode 100644 index 093598e451..0000000000 --- a/test/integration/targets/vmware_dvswitch_pvlans/tasks/main.yml +++ /dev/null @@ -1,74 +0,0 @@ -# Test code for the vmware_dvswitch_pvlans module. -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - -# Testcase 0001: Add Distributed vSwitch -- name: add distributed vSwitch - vmware_dvswitch: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: "{{ dc1 }}" - state: present - switch_name: dvswitch_0001 - mtu: 9000 - uplink_quantity: 2 - discovery_proto: lldp - discovery_operation: both - register: dvs_result_0001 - -- debug: - var: dvs_result_0001 - -- name: ensure distributed vswitch is present - assert: - that: - - dvs_result_0001 is changed - -- &pv_data - name: Configure PVLANs - vmware_dvswitch_pvlans: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - switch: dvswitch_0001 - primary_pvlans: - - primary_pvlan_id: 1 - - primary_pvlan_id: 4 - secondary_pvlans: - - primary_pvlan_id: 1 - secondary_pvlan_id: 2 - pvlan_type: isolated - - primary_pvlan_id: 1 - secondary_pvlan_id: 3 - pvlan_type: community - - primary_pvlan_id: 4 - secondary_pvlan_id: 5 - pvlan_type: community - validate_certs: no - register: pvlans_result - -- debug: - var: pvlans_result - -- name: ensure pvlans were configured - assert: - that: - - pvlans_result is changed - -- when: vcsim is not defined - block: - - <<: *pv_data - name: Configure PVLANs in check mode - register: pvlans_result_check_mode - check_mode: yes - - debug: - var: pvlans_result_check_mode - - name: ensure pvlans were not changed - assert: - that: - - not (pvlans_result_check_mode is changed) diff --git a/test/integration/targets/vmware_dvswitch_uplink_pg/aliases b/test/integration/targets/vmware_dvswitch_uplink_pg/aliases deleted file mode 100644 index b1212da1b7..0000000000 --- a/test/integration/targets/vmware_dvswitch_uplink_pg/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_dvswitch_uplink_pg/tasks/main.yml b/test/integration/targets/vmware_dvswitch_uplink_pg/tasks/main.yml deleted file mode 100644 index 4ca85fdd11..0000000000 --- a/test/integration/targets/vmware_dvswitch_uplink_pg/tasks/main.yml +++ /dev/null @@ -1,75 +0,0 @@ -# Test code for the vmware_dvswitch_uplink_pg module. -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - -# Testcase 0001: Add Distributed vSwitch -- name: add distributed vSwitch - vmware_dvswitch: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: "{{ dc1 }}" - state: present - switch_name: dvswitch_0001 - mtu: 9000 - uplink_quantity: 2 - discovery_proto: lldp - discovery_operation: both - register: dvs_result_0001 - -- debug: - var: dvs_result_0001 - -- name: ensure distributed vswitch is present - assert: - that: - - dvs_result_0001 is changed - -- when: vcsim is not defined - block: - - &uplink_data - name: Configure Uplink portgroup in check mode - vmware_dvswitch_uplink_pg: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - switch: dvswitch_0001 - name: dvswitch_0001-DVUplinks - advanced: - port_config_reset_at_disconnect: False - block_override: False - vendor_config_override: False - vlan_override: False - netflow_override: False - traffic_filter_override: False - vlan_trunk_range: [ 2-3967, 4049-4092 ] - netflow_enabled: True - block_all_ports: False - validate_certs: no - register: uplink_pg_result_check_mode - check_mode: yes - - - debug: - var: uplink_pg_result_check_mode - - - name: ensure uplink portgroup was changed - assert: - that: - - uplink_pg_result_check_mode is changed - - - <<: *uplink_data - name: Configure Uplink portgroup - register: uplink_pg_result - check_mode: no - - - debug: - var: uplink_pg_result - - - name: ensure uplink portgroup was changed - assert: - that: - - uplink_pg_result is changed diff --git a/test/integration/targets/vmware_evc_mode/aliases b/test/integration/targets/vmware_evc_mode/aliases deleted file mode 100644 index be8c5b72ff..0000000000 --- a/test/integration/targets/vmware_evc_mode/aliases +++ /dev/null @@ -1,3 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_evc_mode/meta/main.yml b/test/integration/targets/vmware_evc_mode/meta/main.yml deleted file mode 100644 index 828342c2da..0000000000 --- a/test/integration/targets/vmware_evc_mode/meta/main.yml +++ /dev/null @@ -1,2 +0,0 @@ -dependencies: - - prepare_vmware_tests diff --git a/test/integration/targets/vmware_evc_mode/tasks/main.yml b/test/integration/targets/vmware_evc_mode/tasks/main.yml deleted file mode 100644 index 111e61ec8d..0000000000 --- a/test/integration/targets/vmware_evc_mode/tasks/main.yml +++ /dev/null @@ -1,52 +0,0 @@ -# Test code for the vmware evc mode module. -# Copyright: (c) 2019, Michael Tipton <mike () ibeta.org> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_datacenter: true - - - name: add cluster - vmware_cluster: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: "{{ dc1 }}" - cluster_name: test_cluster_0001 - state: present - - - &evc_enable_data - name: Enable EVC mode on vCenter Cluster - vmware_evc_mode: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter_name: "{{ dc1 }}" - cluster_name: test_cluster_0001 - evc_mode: intel-broadwell - state: present - - - <<: *evc_enable_data - name: Enable EVC mode on vCenter cluster in check mode - check_mode: yes - - - &evc_disable_data - name: Disable EVC mode on vCenter Cluster - vmware_evc_mode: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter_name: "{{ dc1 }}" - cluster_name: test_cluster_0001 - evc_mode: intel-broadwell - state: absent - - - <<: *evc_disable_data - name: Disable EVC mode on vCenter Cluster in check mode - check_mode: yes diff --git a/test/integration/targets/vmware_export_ovf/aliases b/test/integration/targets/vmware_export_ovf/aliases deleted file mode 100644 index 62871ab8f0..0000000000 --- a/test/integration/targets/vmware_export_ovf/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_export_ovf/tasks/main.yml b/test/integration/targets/vmware_export_ovf/tasks/main.yml deleted file mode 100644 index 1f2a822fe3..0000000000 --- a/test/integration/targets/vmware_export_ovf/tasks/main.yml +++ /dev/null @@ -1,69 +0,0 @@ -# Test code for the vmware_export_ovf module -# Copyright: (c) 2019, Diane Wang (Tomorrow9) <dianew@vmware.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - name: create temporary build directory - tempfile: - state: directory - suffix: build - register: temp_dir - - debug: var=temp_dir - - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_virtualmachines: true - - - name: set state to poweroff on the tested VM - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "{{ virtual_machines_in_cluster[0].name }}" - state: poweredoff - - - name: export VM to ovf template - vmware_export_ovf: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "{{ virtual_machines_in_cluster[0].name }}" - datacenter: "{{ dc1 }}" - export_dir: "{{ temp_dir.path }}" - register: ovf_template - - debug: var=ovf_template - - name: assert the ovf template exported - assert: - that: - - "ovf_template.changed == true" - - "ovf_template.instance.device_files | length >= 1" - - - name: export VM to ovf template with timeout set - vmware_export_ovf: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "{{ virtual_machines_in_cluster[0].name }}" - datacenter: "{{ dc1 }}" - export_dir: "{{ temp_dir.path }}" - download_timeout: 30 - register: ovf_template - - debug: var=ovf_template - - name: assert the ovf template exported - assert: - that: - - "ovf_template.changed == true" - - "ovf_template.instance.device_files | length >= 1" - always: - - name: Clean up the temporary dir - file: - path: "{{ temp_dir.path }}" - state: absent - when: temp_dir.path is defined diff --git a/test/integration/targets/vmware_folder_info/aliases b/test/integration/targets/vmware_folder_info/aliases deleted file mode 100644 index b6fc00bfec..0000000000 --- a/test/integration/targets/vmware_folder_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_folder_info/tasks/main.yml b/test/integration/targets/vmware_folder_info/tasks/main.yml deleted file mode 100644 index 8022b6b5ab..0000000000 --- a/test/integration/targets/vmware_folder_info/tasks/main.yml +++ /dev/null @@ -1,51 +0,0 @@ -# Test code for the vmware_folder_info module. -# Copyright: (c) 2019, David Hewitt (@davidmhewitt) <davidmhewitt@gmail.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - -- name: create example toplevel folder - vcenter_folder: - <<: &vcenter_folder_data - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 | basename }}" - validate_certs: no - folder_name: "toplevel" - -- name: create an example child folder - vcenter_folder: - <<: *vcenter_folder_data - folder_name: "child_folder" - parent_folder: "toplevel" - -# Testcase 0001: Get details about folders -- name: get info about folders - vmware_folder_info: - <<: *vcenter_folder_data - register: folder_info_0001 - -- debug: var=folder_info_0001 - -- assert: - that: - - "{{ item }} is defined" - with_items: - - folder_info_0001['folder_info'] - - folder_info_0001['folder_info']['datastoreFolders'] - - folder_info_0001['folder_info']['hostFolders'] - - folder_info_0001['folder_info']['vmFolders'] - - folder_info_0001['folder_info']['networkFolders'] - - folder_info_0001['folder_info']['vmFolders']['subfolders']['toplevel'] - - folder_info_0001['folder_info']['vmFolders']['subfolders']['toplevel']['subfolders']['child_folder'] - -- assert: - that: - - "folder_info_0001['folder_info']['datastoreFolders']['path'] == \"/{{ dc1 | basename }}/datastore\"" - - "folder_info_0001['folder_info']['hostFolders']['path'] == \"/{{ dc1 | basename }}/host\"" - - "folder_info_0001['folder_info']['vmFolders']['path'] == \"/{{ dc1 | basename }}/vm\"" - - "folder_info_0001['folder_info']['networkFolders']['path'] == \"/{{ dc1 | basename }}/network\"" - - "folder_info_0001['folder_info']['vmFolders']['subfolders']['toplevel']['path'] == \"/{{ dc1 | basename }}/vm/toplevel\"" - - "folder_info_0001['folder_info']['vmFolders']['subfolders']['toplevel']['subfolders']['child_folder']['path'] == \"/{{ dc1 | basename }}/vm/toplevel/child_folder\"" diff --git a/test/integration/targets/vmware_guest/aliases b/test/integration/targets/vmware_guest/aliases deleted file mode 100644 index dea29ccd8b..0000000000 --- a/test/integration/targets/vmware_guest/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_guest/defaults/main.yml b/test/integration/targets/vmware_guest/defaults/main.yml deleted file mode 100644 index dfb0fd65dc..0000000000 --- a/test/integration/targets/vmware_guest/defaults/main.yml +++ /dev/null @@ -1,33 +0,0 @@ -vmware_guest_test_playbooks: - - boot_firmware_d1_c1_f0.yml - - boot_firmware_d1_c1_f0.yml - - cdrom_d1_c1_f0.yml - - check_mode.yml - - clone_customize_guest_test.yml - - clone_d1_c1_f0.yml - - clone_resize_disks.yml - - clone_with_convert.yml - - create_d1_c1_f0.yml - - create_guest_invalid_d1_c1_f0.yml - - create_nw_d1_c1_f0.yml - - create_rp_d1_c1_f0.yml - - delete_vm.yml - - disk_mode_d1_c1_f0.yml - - disk_size_d1_c1_f0.yml - - disk_type_d1_c1_f0.yml - - linked_clone_d1_c1_f0.yml - - mac_address_d1_c1_f0.yml - - max_connections.yml - - mem_reservation.yml - - network_negative_test.yml - - network_with_device.yml -# Currently, VCSIM doesn't support DVPG (as portkeys are not available) so commenting this test -# - network_with_dvpg.yml -# - network_with_portgroup.yml - - non_existent_vm_ops.yml - - poweroff_d1_c1_f0.yml - - poweroff_d1_c1_f1.yml -# - template_d1_c1_f0.yml - - vapp_d1_c1_f0.yml - - reconfig_vm_to_latest_version.yml - - remove_vm_from_inventory.yml diff --git a/test/integration/targets/vmware_guest/tasks/boot_firmware_d1_c1_f0.yml b/test/integration/targets/vmware_guest/tasks/boot_firmware_d1_c1_f0.yml deleted file mode 100644 index aade1494e3..0000000000 --- a/test/integration/targets/vmware_guest/tasks/boot_firmware_d1_c1_f0.yml +++ /dev/null @@ -1,117 +0,0 @@ -# Test code for the vmware_guest module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: create new VMs with boot_firmware as 'bios' - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - hardware: - num_cpus: 1 - boot_firmware: "bios" - memory_mb: 128 - disk: - - size: 1gb - type: thin - datastore: "{{ rw_datastore }}" - state: poweredoff - folder: "{{ f0 }}" - register: clone_d1_c1_f0 - -- debug: var=clone_d1_c1_f0 - -- name: assert that changes were made - assert: - that: - - clone_d1_c1_f0 is changed - -# VCSIM does not recognizes existing VMs boot firmware -- when: vcsim is not defined - block: - - name: create new VMs again with boot_firmware as 'bios' - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm2 - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - hardware: - num_cpus: 1 - boot_firmware: "bios" - memory_mb: 128 - disk: - - size: 1gb - type: thin - datastore: "{{ rw_datastore }}" - state: poweredoff - folder: "{{ f0 }}" - register: clone_d1_c1_f0 - - debug: var=clone_d1_c1_f0 - - name: assert that changes were not made - assert: - that: - - clone_d1_c1_f0 is changed - -- name: create new VMs with boot_firmware as 'efi' - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm3 - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - hardware: - num_cpus: 1 - boot_firmware: "efi" - memory_mb: 128 - disk: - - size: 1gb - type: thin - datastore: "{{ rw_datastore }}" - state: poweredoff - folder: "{{ f0 }}" - register: clone_d1_c1_f0 - -- debug: var=clone_d1_c1_f0 - -- name: assert that changes were made - assert: - that: - - clone_d1_c1_f0 is changed - -# VCSIM does not recognizes existing VMs boot firmware -- when: vcsim is not defined - block: - - name: create new VMs again with boot_firmware as 'efi' - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm3 - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - hardware: - num_cpus: 1 - boot_firmware: "efi" - memory_mb: 128 - disk: - - size: 1gb - type: thin - datastore: "{{ rw_datastore }}" - state: poweredoff - folder: "{{ f0 }}" - register: clone_d1_c1_f0 - - debug: var=clone_d1_c1_f0 - - name: assert that changes were not made - assert: - that: - - not (clone_d1_c1_f0 is changed) diff --git a/test/integration/targets/vmware_guest/tasks/cdrom_d1_c1_f0.yml b/test/integration/targets/vmware_guest/tasks/cdrom_d1_c1_f0.yml deleted file mode 100644 index 467cf25d1a..0000000000 --- a/test/integration/targets/vmware_guest/tasks/cdrom_d1_c1_f0.yml +++ /dev/null @@ -1,269 +0,0 @@ -- name: Create VM with CDROM - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - folder: vm - name: test_vm1 - datacenter: "{{ dc1 }}" - cluster: "{{ ccr1 }}" - resource_pool: Resources - guest_id: centos64Guest - hardware: - memory_mb: 128 - num_cpus: 1 - scsi: paravirtual - disk: - - size_mb: 128 - type: thin - datastore: "{{ rw_datastore }}" - cdrom: - type: iso - iso_path: "[{{ ro_datastore }}] centos.iso" - register: cdrom_vm - -- debug: var=cdrom_vm - -- name: assert the VM was created - assert: - that: - - "cdrom_vm.changed == true" - -- name: Update CDROM to iso for the new VM - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - folder: "vm" - name: test_vm1 - datastore: "{{ rw_datastore }}" - datacenter: "{{ dc1 }}" - cdrom: - type: iso - iso_path: "[{{ ro_datastore }}] fedora.iso" - state: present - register: cdrom_vm - -- debug: var=cdrom_vm - -- name: assert the VM was changed - assert: - that: - - "cdrom_vm.changed == true" - -- name: Update CDROM to client for the new VM - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - folder: vm - name: test_vm1 - datacenter: "{{ dc1 }}" - cdrom: - type: client - state: present - register: cdrom_vm - -- debug: var=cdrom_vm - -- name: assert the VM was changed - assert: - that: - - "cdrom_vm.changed == true" - -- name: clone vm - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm2 - template: test_vm1 - datacenter: "{{ dc1 }}" - state: poweredoff - folder: vm - convert: thin - -- name: Update CDROM to none for the new VM - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - folder: vm - name: test_vm2 - datacenter: "{{ dc1 }}" - cdrom: - type: none - state: present - register: cdrom_vm - -- debug: var=cdrom_vm - -- name: assert the VM was changed - assert: - that: - - "cdrom_vm.changed == true" - -- name: Create VM with multiple disks and a CDROM - GitHub issue 38679 - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - folder: "{{ f0 }}" - name: test_vm3 - datacenter: "{{ dc1 }}" - cluster: "{{ ccr1 }}" - resource_pool: Resources - guest_id: centos64Guest - hardware: - memory_mb: 128 - num_cpus: 1 - scsi: paravirtual - disk: - - size_mb: 128 - type: thin - datastore: "{{ rw_datastore }}" - - size_mb: 128 - type: thin - datastore: "{{ rw_datastore }}" - - size_mb: 128 - type: thin - datastore: "{{ rw_datastore }}" - cdrom: - type: iso - iso_path: "[{{ ro_datastore }}] fedora.iso" - register: cdrom_vm - -- debug: var=cdrom_vm - -- name: assert the VM was created - assert: - that: - - "cdrom_vm.changed == true" - -- name: Create VM with multiple CDROMs - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - folder: vm - name: test_vm1 - datacenter: "{{ dc1 }}" - cluster: "{{ ccr1 }}" - resource_pool: Resources - guest_id: centos64Guest - hardware: - memory_mb: 128 - num_cpus: 1 - scsi: paravirtual - disk: - - size_mb: 128 - type: thin - datastore: "{{ rw_datastore }}" - cdrom: - - controller_type: ide - controller_number: 0 - unit_number: 0 - type: iso - iso_path: "[{{ ro_datastore }}] centos.iso" - - controller_type: ide - controller_number: 0 - unit_number: 1 - type: client - - controller_number: 1 - unit_number: 0 - type: none - - controller_number: 1 - unit_number: 1 - type: client - register: cdrom_vm - -- debug: var=cdrom_vm - -- name: assert the VM was created - assert: - that: - - "cdrom_vm.changed == true" - -- name: Remove the last 2 CDROMs and update the first 2 for the new VM - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - folder: vm - name: test_vm1 - datacenter: "{{ dc1 }}" - cdrom: - - controller_type: ide - controller_number: 0 - unit_number: 0 - type: client - - controller_type: ide - controller_number: 0 - unit_number: 1 - type: iso - iso_path: "[{{ ro_datastore }}] fedora.iso" - - controller_type: ide - controller_number: 1 - unit_number: 0 - state: absent - - controller_type: ide - controller_number: 1 - unit_number: 1 - state: absent - state: present - register: cdrom_vm - -- debug: var=cdrom_vm - -- name: assert the VM was changed - assert: - that: - - "cdrom_vm.changed == true" - -# VCSIM fails with invalidspec exception but real vCenter PASS testcase -# Commenting this testcase till the time -- when: vcsim is not defined - block: - - name: Again create VM with multiple disks and a CDROM - GitHub issue 38679 - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - folder: "{{ f0 }}" - name: test_vm3 - datacenter: "{{ dc1 }}" - cluster: "{{ ccr1 }}" - resource_pool: Resources - guest_id: centos64Guest - hardware: - memory_mb: 128 - num_cpus: 1 - scsi: paravirtual - disk: - - size_mb: 128 - type: thin - datastore: "{{ rw_datastore }}" - - size_mb: 128 - type: thin - datastore: "{{ rw_datastore }}" - - size_mb: 128 - type: thin - datastore: "{{ rw_datastore }}" - cdrom: - type: iso - iso_path: "[{{ ro_datastore }}] base.iso" - register: cdrom_vm - - debug: var=cdrom_vm - - name: assert the VM was created - assert: - that: - - cdrom_vm is changed diff --git a/test/integration/targets/vmware_guest/tasks/check_mode.yml b/test/integration/targets/vmware_guest/tasks/check_mode.yml deleted file mode 100644 index d3f6f22634..0000000000 --- a/test/integration/targets/vmware_guest/tasks/check_mode.yml +++ /dev/null @@ -1,60 +0,0 @@ -# Test code for the vmware_guest module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: Perform all operation in check mode - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "{{ virtual_machines[0].name }}" - datacenter: "{{ dc1 }}" - state: "{{ item }}" - with_items: - - absent - - present - - poweredoff - - poweredon - - restarted - - suspended - - shutdownguest - - rebootguest - register: check_mode_state - check_mode: yes - -- debug: - var: check_mode_state - -- name: assert that changes were made - assert: - that: - - "check_mode_state.results|map(attribute='changed')|unique|list == [true]" - - "check_mode_state.results|map(attribute='vm_name')|unique|list == [ virtual_machines[0].name ]" - -- name: Perform all operation on non-existent VM in check mode - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: non_existent_vm - datacenter: "{{ dc1 }}" - state: "{{ item }}" - with_items: - - present - - poweredoff - - poweredon - - restarted - - suspended - register: check_mode_state - check_mode: yes - -- debug: - var: check_mode_state - -- name: assert that changes were made - assert: - that: - - "check_mode_state.results|map(attribute='changed')|unique|list == [true]" - - "check_mode_state.results|map(attribute='desired_operation')|unique|list == ['deploy_vm']" diff --git a/test/integration/targets/vmware_guest/tasks/clone_customize_guest_test.yml b/test/integration/targets/vmware_guest/tasks/clone_customize_guest_test.yml deleted file mode 100644 index f40848298c..0000000000 --- a/test/integration/targets/vmware_guest/tasks/clone_customize_guest_test.yml +++ /dev/null @@ -1,47 +0,0 @@ -# Test code for the vmware_guest module. -# 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) - -- name: clone vm from template and customize GOS - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - template: "{{ virtual_machines[0].name }}" - datacenter: "{{ dc1 }}" - state: poweredoff - folder: "{{ virtual_machines[0].folder }}" - convert: thin - register: clone_customize - -- debug: - var: clone_customize - -- name: assert that changes were made - assert: - that: - - clone_customize is changed - -- name: clone vm from template and customize GOS again - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - template: "{{ virtual_machines[0].name }}" - datacenter: "{{ dc1 }}" - state: poweredoff - folder: "{{ virtual_machines[0].folder }}" - convert: thin - register: clone_customize_again - -- debug: - var: clone_customize_again - -- name: assert that changes were not made - assert: - that: - - not (clone_customize_again is changed) diff --git a/test/integration/targets/vmware_guest/tasks/clone_d1_c1_f0.yml b/test/integration/targets/vmware_guest/tasks/clone_d1_c1_f0.yml deleted file mode 100644 index 3b3d2ad543..0000000000 --- a/test/integration/targets/vmware_guest/tasks/clone_d1_c1_f0.yml +++ /dev/null @@ -1,101 +0,0 @@ -# Test code for the vmware_guest module. -# Copyright: (c) 2017, James Tanner <tanner.jc@gmail.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: create new linked clone without specifying snapshot_src - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - template: "{{ virtual_machines[0].name }}" - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - folder: "{{ f0 }}" - linked_clone: True - register: linked_clone_d1_c1_f0 - ignore_errors: True - -- debug: - var: linked_clone_d1_c1_f0 - -- name: assert that changes were not made - assert: - that: - - not (linked_clone_d1_c1_f0 is changed) - -- name: create new linked clone without specifying linked_clone - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm2 - template: "{{ virtual_machines[0].name }}" - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - folder: "{{ f0 }}" - snapshot_src: "snap_shot1" - register: linked_clone_d1_c1_f0 - ignore_errors: True - -- debug: - var: linked_clone_d1_c1_f0 - -- name: assert that changes were not made - assert: - that: - - not (linked_clone_d1_c1_f0 is changed) - -# TODO: VCSIM: snapshot is not supported in current vcsim -# -#- name: create new linked clone with linked_clone and snapshot_src -# vmware_guest: -# validate_certs: False -# hostname: "{{ vcenter_hostname }}" -# username: "{{ vcenter_username }}" -# password: "{{ vcenter_password }}" -# name: "{{ 'new_vm_' + item|basename }}" -# template: "{{ item|basename }}" -# guest_id: centos64Guest -# datacenter: "{{ (item|basename).split('_')[0] }}" -# folder: "{{ item|dirname }}" -# snapshot_src: "snap_shot1" -# linked_clone: True -# with_items: "{{ vmlist['json'] }}" -# register: linked_clone_d1_c1_f0 -# ignore_errors: True - -#- debug: var=linked_clone_d1_c1_f0 - -#- name: assert that changes were made -# assert: -# that: -# - "linked_clone_d1_c1_f0.results|map(attribute='changed')|unique|list == [true]" - -# TODO: VCSIM: snapshot is not supported in current vcsim -# -#- name: create new linked clone with linked_clone and snapshot_src again -# vmware_guest: -# validate_certs: False -# hostname: "{{ vcenter_hostname }}" -# username: "{{ vcenter_username }}" -# password: "{{ vcenter_password }}" -# name: "{{ 'new_vm_' + item|basename }}" -# template: "{{ item|basename }}" -# guest_id: centos64Guest -# datacenter: "{{ (item|basename).split('_')[0] }}" -# folder: "{{ item|dirname }}" -# snapshot_src: "snap_shot1" -# linked_clone: True -# with_items: "{{ vmlist['json'] }}" -# register: linked_clone_d1_c1_f0 -# ignore_errors: True - -#- debug: var=linked_clone_d1_c1_f0 - -#- name: assert that changes were not made -# assert: -# that: -# - "linked_clone_d1_c1_f0.results|map(attribute='changed')|unique|list == [false]" diff --git a/test/integration/targets/vmware_guest/tasks/clone_resize_disks.yml b/test/integration/targets/vmware_guest/tasks/clone_resize_disks.yml deleted file mode 100644 index 70004d161b..0000000000 --- a/test/integration/targets/vmware_guest/tasks/clone_resize_disks.yml +++ /dev/null @@ -1,77 +0,0 @@ -# Test code for the vmware_guest module. -# Copyright: (c) 2019, Noe Gonzalez <noe.a.gonzalez@gmail.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - name: create new VM - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: clone_resize_disks_original - datacenter: "{{ dc1 }}" - cluster: "{{ ccr1 }}" - folder: "{{ f0 }}" - hardware: - num_cpus: 1 - memory_mb: 128 - guest_id: centos7_64Guest - disk: - - size_gb: 1 - type: thin - datastore: "{{ rw_datastore }}" - state: poweredoff - - - name: convert to VM template - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: clone_resize_disks_original - datacenter: "{{ dc1 }}" - cluster: "{{ ccr1 }}" - folder: "{{ f0 }}" - is_template: True - - - name: clone template and modify disks - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: clone_resize_disks_clone - datacenter: "{{ dc1 }}" - cluster: "{{ ccr1 }}" - folder: "{{ f0 }}" - disk: - - size_gb: 2 - type: thin - datastore: "{{ rw_datastore }}" - - size_gb: 3 - type: thin - datastore: "{{ rw_datastore }}" - template: clone_resize_disks_original - state: poweredoff - register: l_clone_template_modify_disks - - - assert: - that: - - l_clone_template_modify_disks.changed | bool - - - name: delete VM clone & original template - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "{{ item }}" - datacenter: "{{ dc1 }}" - cluster: "{{ ccr1 }}" - folder: "{{ f0 }}" - state: absent - with_items: - - clone_resize_disks_original - - clone_resize_disks_clone diff --git a/test/integration/targets/vmware_guest/tasks/clone_with_convert.yml b/test/integration/targets/vmware_guest/tasks/clone_with_convert.yml deleted file mode 100644 index bf3abfae36..0000000000 --- a/test/integration/targets/vmware_guest/tasks/clone_with_convert.yml +++ /dev/null @@ -1,66 +0,0 @@ -# Test code for the vmware_guest module. -# Copyright: (c) 2018, Christophe FERREIRA <christophe.ferreira@cnaf.fr> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: clone vm from template and convert to thin - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - template: "{{ virtual_machines[0].name }}" - datacenter: "{{ dc1 }}" - state: poweredoff - folder: "{{ virtual_machines[0].folder }}" - convert: thin - register: clone_thin - -- debug: var=clone_thin - -- name: assert that changes were made - assert: - that: - - clone_thin is changed - -- name: clone vm from template and convert to thick - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm2 - template: "{{ virtual_machines[0].name }}" - datacenter: "{{ dc1 }}" - state: poweredoff - folder: "{{ virtual_machines[0].folder }}" - convert: thick - register: clone_thick - -- debug: var=clone_thick - -- name: assert that changes were made - assert: - that: - - clone_thick is changed - -- name: clone vm from template and convert to eagerzeroedthick - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm3 - template: "{{ virtual_machines[0].name }}" - datacenter: "{{ dc1 }}" - state: poweredoff - folder: "{{ virtual_machines[0].folder }}" - convert: eagerzeroedthick - register: clone_eagerzeroedthick - -- debug: var=clone_eagerzeroedthick - -- name: assert that changes were made - assert: - that: - - clone_eagerzeroedthick is changed diff --git a/test/integration/targets/vmware_guest/tasks/create_d1_c1_f0.yml b/test/integration/targets/vmware_guest/tasks/create_d1_c1_f0.yml deleted file mode 100644 index b4ee85002d..0000000000 --- a/test/integration/targets/vmware_guest/tasks/create_d1_c1_f0.yml +++ /dev/null @@ -1,164 +0,0 @@ -# Test code for the vmware_guest module. -# Copyright: (c) 2017, James Tanner <tanner.jc@gmail.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: create new VMs - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - #template: "{{ item|basename }}" - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - hardware: - num_cpus: 1 - num_cpu_cores_per_socket: 1 - memory_mb: 128 - hotadd_memory: true - hotadd_cpu: false - # vcsim does not support these settings, so commenting - # till the time. - # memory_reservation: 128 - # memory_reservation_lock: False - # nested_virt: True - # hotremove_cpu: True - # mem_limit: 8096 - # mem_reservation: 4096 - # cpu_limit: 8096 - # cpu_reservation: 4096 - max_connections: 10 - disk: - - size: 1gb - type: thin - datastore: "{{ rw_datastore }}" - state: poweredoff - folder: '{{ f0 }}' - register: clone_d1_c1_f0 - -- debug: var=clone_d1_c1_f0 - -- name: assert that changes were made - assert: - that: - - clone_d1_c1_f0 is changed - -- name: create the VM again - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - #template: "{{ item|basename }}" - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - hardware: - num_cpus: 1 - num_cpu_cores_per_socket: 1 - memory_mb: 128 - disk: - - size: 1gb - type: thin - datastore: "{{ rw_datastore }}" - state: poweredoff - folder: '{{ f0 }}' - register: clone_d1_c1_f0_recreate - -- debug: var=clone_d1_c1_f0_recreate - -- name: assert that no changes were made after re-creating - assert: - that: - - not (clone_d1_c1_f0_recreate is changed) - -- name: modify the new VMs - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - #template: "{{ item|basename }}" - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - hardware: - num_cpus: 2 - memory_mb: 128 - state: present - folder: '{{ f0 }}' - register: clone_d1_c1_f0_modify - -- debug: var=clone_d1_c1_f0_modify - -- name: assert that changes were made with modification - assert: - that: - - clone_d1_c1_f0_modify is changed - -- name: re-modify the new VMs - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - #template: "{{ item|basename }}" - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - hardware: - num_cpus: 2 - memory_mb: 128 - state: present - folder: '{{ f0 }}' - register: clone_d1_c1_f0_remodify - -- debug: var=clone_d1_c1_f0_remodify - -- name: assert that no changes were made when re-modified - assert: - that: - - not (clone_d1_c1_f0_remodify is changed) - -- name: delete the new VMs - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - #template: "{{ item|basename }}" - #guest_id: centos64Guest - datacenter: "{{ dc1 }}" - state: absent - folder: '{{ f0 }}' - register: clone_d1_c1_f0_delete - -- debug: var=clone_d1_c1_f0_delete - -- name: assert that changes were made with deletion - assert: - that: - - clone_d1_c1_f0_delete is changed - -- name: re-delete the new VMs - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - #template: "{{ item|basename }}" - #guest_id: centos64Guest - datacenter: "{{ dc1 }}" - state: absent - folder: '{{ f0 }}' - register: clone_d1_c1_f0_redelete - -- debug: var=clone_d1_c1_f0_redelete - -- name: assert that no changes were made with redeletion - assert: - that: - - not (clone_d1_c1_f0_redelete is changed) diff --git a/test/integration/targets/vmware_guest/tasks/create_guest_invalid_d1_c1_f0.yml b/test/integration/targets/vmware_guest/tasks/create_guest_invalid_d1_c1_f0.yml deleted file mode 100644 index 8a0b6468b6..0000000000 --- a/test/integration/targets/vmware_guest/tasks/create_guest_invalid_d1_c1_f0.yml +++ /dev/null @@ -1,32 +0,0 @@ -# Test code for the vmware_guest module. -# Copyright: (c) 2017, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - name: create new virtual machine with invalid guest id - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: invalid_vm - guest_id: "invalid_guest_id" - datacenter: "{{ dc1 }}" - hardware: - num_cpus: 1 - memory_mb: 128 - disk: - - size: 1gb - type: thin - datastore: "{{ rw_datastore }}" - state: present - folder: "{{ f0 }}" - register: invalid_guest_0001_d1_c1_f0 - ignore_errors: yes - - debug: var=invalid_guest_0001_d1_c1_f0 - - name: assert that changes were made - assert: - that: - - "not (invalid_guest_0001_d1_c1_f0 is changed)" - - "'configSpec.guestId' in invalid_guest_0001_d1_c1_f0['msg']" diff --git a/test/integration/targets/vmware_guest/tasks/create_nw_d1_c1_f0.yml b/test/integration/targets/vmware_guest/tasks/create_nw_d1_c1_f0.yml deleted file mode 100644 index 2a22dce2f6..0000000000 --- a/test/integration/targets/vmware_guest/tasks/create_nw_d1_c1_f0.yml +++ /dev/null @@ -1,38 +0,0 @@ -# Test code for the vmware_guest module. -# Copyright: (c) 2017, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: create new VMs - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - hardware: - num_cpus: 1 - memory_mb: 128 - disk: - - size: 1gb - type: thin - datastore: "{{ rw_datastore }}" - networks: - - name: 'VM Network' - device_type: vmxnet3 - ip: 192.168.10.1 - netmask: 255.255.255.0 - wake_on_lan: True - start_connected: True - allow_guest_control: True - state: poweredoff - folder: F0 - register: clone_d1_c1_f0 - -- debug: var=clone_d1_c1_f0 - -- name: assert that changes were made - assert: - that: - - clone_d1_c1_f0 is changed diff --git a/test/integration/targets/vmware_guest/tasks/create_rp_d1_c1_f0.yml b/test/integration/targets/vmware_guest/tasks/create_rp_d1_c1_f0.yml deleted file mode 100644 index 30319b78d7..0000000000 --- a/test/integration/targets/vmware_guest/tasks/create_rp_d1_c1_f0.yml +++ /dev/null @@ -1,205 +0,0 @@ -# Create one with the defaults -- name: create new VM with default resource pool - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - #template: "{{ item|basename }}" - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - hardware: - num_cpus: 1 - memory_mb: 128 - disk: - - size: 1gb - type: thin - datastore: "{{ rw_datastore }}" - state: poweredoff - folder: F0 - register: clone_rp_d1_c1_f0 - -- debug: var=clone_rp_d1_c1_f0 - -- name: assert that changes were made - assert: - that: - - clone_rp_d1_c1_f0 is changed - -- name: delete the new VMs - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - #template: "{{ item|basename }}" - #guest_id: centos64Guest - datacenter: "{{ dc1 }}" - state: absent - folder: F0 - register: clone_rp_d1_c1_f0_delete - -- debug: var=clone_rp_d1_c1_f0_delete - -- name: assert that changes were made with deletion - assert: - that: - - clone_rp_d1_c1_f0_delete is changed - -# now create with just a cluster -- name: create new VM with default resource pool in cluster - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - #template: "{{ item|basename }}" - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - cluster: "{{ ccr1 }}" - hardware: - num_cpus: 1 - memory_mb: 128 - disk: - - size: 1gb - type: thin - datastore: "{{ rw_datastore }}" - state: poweredoff - folder: F0 - register: clone_rpc_d1_c1_f0 - -- debug: var=clone_rpc_d1_c1_f0 - -- name: assert that changes were made - assert: - that: - - clone_rpc_d1_c1_f0 is changed - -- name: delete the new VMs - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - #template: "{{ item|basename }}" - #guest_id: centos64Guest - datacenter: "{{ dc1 }}" - cluster: "{{ ccr1 }}" - state: absent - folder: F0 - register: clone_rpc_d1_c1_f0_delete - -- debug: var=clone_rpc_d1_c1_f0_delete - -- name: assert that changes were made with deletion - assert: - that: - - clone_rpc_d1_c1_f0_delete is changed - -# now create with a specific resource pool -- name: create new VM with specific resource pool in cluster - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - #template: "{{ item|basename }}" - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - cluster: "{{ ccr1 }}" - resource_pool: DC0_C0_RP1 - hardware: - num_cpus: 1 - memory_mb: 128 - disk: - - size: 1gb - type: thin - datastore: "{{ rw_datastore }}" - state: poweredoff - folder: F0 - register: clone_rpcp_d1_c1_f0 - -- debug: var=clone_rpcp_d1_c1_f0 - -- name: assert that changes were made - assert: - that: - - clone_rpcp_d1_c1_f0 is changed - -- name: delete the new VMs - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - #template: "{{ item|basename }}" - #guest_id: centos64Guest - datacenter: "{{ dc1 }}" - cluster: "{{ ccr1 }}" - state: absent - folder: F0 - register: clone_rpcp_d1_c1_f0_delete - -- debug: var=clone_rpcp_d1_c1_f0_delete - -- name: assert that changes were made with deletion - assert: - that: - - clone_rpcp_d1_c1_f0_delete is changed - -# now create with a specific host -- name: create new VM with specific host - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - #template: "{{ item|basename }}" - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - esxi_hostname: '{{ esxi1 }}' - hardware: - num_cpus: 1 - memory_mb: 128 - disk: - - size: 1gb - type: thin - datastore: "{{ rw_datastore }}" - state: poweredoff - folder: F0 - register: clone_rph_d1_c1_f0 - -- debug: var=clone_rph_d1_c1_f0 - -- name: assert that changes were made - assert: - that: - - clone_rph_d1_c1_f0 is changed - -- name: delete the new VMs - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - #template: "{{ item|basename }}" - #guest_id: centos64Guest - datacenter: "{{ dc1 }}" - state: absent - folder: F0 - register: clone_rph_d1_c1_f0_delete - -- debug: var=clone_rph_d1_c1_f0_delete - -- name: assert that changes were made with deletion - assert: - that: - - clone_rph_d1_c1_f0_delete is changed diff --git a/test/integration/targets/vmware_guest/tasks/delete_vm.yml b/test/integration/targets/vmware_guest/tasks/delete_vm.yml deleted file mode 100644 index 600df0fc50..0000000000 --- a/test/integration/targets/vmware_guest/tasks/delete_vm.yml +++ /dev/null @@ -1,22 +0,0 @@ -# Test code for the vmware_guest module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: Delete VM - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: nothinghere - datacenter: "{{ dc1 }}" - state: absent - register: delete_vm - ignore_errors: yes - -- debug: var=delete_vm - -- name: assert that changes were made - assert: - that: - - "not delete_vm.changed" diff --git a/test/integration/targets/vmware_guest/tasks/disk_mode_d1_c1_f0.yml b/test/integration/targets/vmware_guest/tasks/disk_mode_d1_c1_f0.yml deleted file mode 100644 index 7a14d11981..0000000000 --- a/test/integration/targets/vmware_guest/tasks/disk_mode_d1_c1_f0.yml +++ /dev/null @@ -1,89 +0,0 @@ -# Test code for the vmware_guest module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: create new VMs with invalid disk mode - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - hardware: - num_cpus: 1 - memory_mb: 128 - disk: - - size: 1gb - type: eagerzeroedthick - datastore: "{{ rw_datastore }}" - disk_mode: 'invalid_disk_mode' - state: poweredoff - folder: "{{ f0 }}" - register: test_vm1 - ignore_errors: True - -- debug: var=test_vm1 - -- name: assert that changes were not made - assert: - that: - - not(test_vm1 is changed) - -- name: create new VMs with valid disk mode - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - hardware: - num_cpus: 1 - memory_mb: 128 - disk: - - size: 1gb - type: eagerzeroedthick - datastore: "{{ rw_datastore }}" - disk_mode: 'independent_persistent' - state: poweredoff - folder: "{{ f0 }}" - register: test_vm1_2 - -- debug: var=test_vm1_2 - -- name: assert that changes were made - assert: - that: - - test_vm1_2 is changed - -#TODO: vcsim does not support reconfiguration of disk mode, fails with types.InvalidDeviceSpec -- when: vcsim is not defined - block: - - name: create new VMs with valid disk mode again - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - hardware: - num_cpus: 1 - memory_mb: 128 - disk: - - size: 1gb - type: eagerzeroedthick - datastore: "{{ rw_datastore }}" - disk_mode: 'independent_persistent' - state: poweredoff - folder: "{{ f0 }}" - register: test_vm1_2 - - debug: var=test_vm1_2 - - name: assert that changes were not made - assert: - that: - - not (test_vm1_2 is changed) diff --git a/test/integration/targets/vmware_guest/tasks/disk_size_d1_c1_f0.yml b/test/integration/targets/vmware_guest/tasks/disk_size_d1_c1_f0.yml deleted file mode 100644 index c40f19e624..0000000000 --- a/test/integration/targets/vmware_guest/tasks/disk_size_d1_c1_f0.yml +++ /dev/null @@ -1,31 +0,0 @@ -# Test code for the vmware_guest module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: create new VMs with invalid disk size - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - hardware: - num_cpus: 1 - memory_mb: 128 - disk: - - size: 0gb - type: eagerzeroedthick - datastore: "{{ rw_datastore }}" - state: poweredoff - folder: "{{ f0 }}" - register: disk_size_d1_c1_f0 - ignore_errors: True - -- debug: var=disk_size_d1_c1_f0 - -- name: assert that changes were made - assert: - that: - - not (disk_size_d1_c1_f0 is changed) diff --git a/test/integration/targets/vmware_guest/tasks/disk_type_d1_c1_f0.yml b/test/integration/targets/vmware_guest/tasks/disk_type_d1_c1_f0.yml deleted file mode 100644 index 3bd4089597..0000000000 --- a/test/integration/targets/vmware_guest/tasks/disk_type_d1_c1_f0.yml +++ /dev/null @@ -1,33 +0,0 @@ -# Test code for the vmware_guest module. -# Copyright: (c) 2017, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: create new VMs - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - hardware: - num_cpus: 1 - memory_mb: 128 - disk: - - size: 1gb - type: eagerzeroedthick - datastore: "{{ rw_datastore }}" - - size: 1gb - type: thin - datastore: "{{ rw_datastore }}" - state: poweredoff - folder: F0 - register: disk_type_d1_c1_f0 - -- debug: var=disk_type_d1_c1_f0 - -- name: assert that changes were made - assert: - that: - - disk_type_d1_c1_f0 is changed diff --git a/test/integration/targets/vmware_guest/tasks/linked_clone_d1_c1_f0.yml b/test/integration/targets/vmware_guest/tasks/linked_clone_d1_c1_f0.yml deleted file mode 100644 index 702ca59da7..0000000000 --- a/test/integration/targets/vmware_guest/tasks/linked_clone_d1_c1_f0.yml +++ /dev/null @@ -1,100 +0,0 @@ -# Test code for the vmware_guest module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: create new linked clone without specifying snapshot_src - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "{{ 'new_vm_' + item.name }}" - template: "{{ item.name }}" - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - folder: "{{ f0 }}" - linked_clone: True - with_items: "{{ virtual_machines }}" - register: linked_clone_d1_c1_f0 - ignore_errors: True - -- debug: var=linked_clone_d1_c1_f0 - -- name: assert that changes were not made - assert: - that: - - "linked_clone_d1_c1_f0.results|map(attribute='changed')|unique|list == [false]" - -- name: create new linked clone without specifying linked_clone - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "{{ 'new_vm_' + item.name }}" - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - folder: "{{ f0 }}" - snapshot_src: "snap_shot1" - with_items: "{{ virtual_machines }}" - register: linked_clone_d1_c1_f0 - ignore_errors: True - -- debug: var=linked_clone_d1_c1_f0 - -- name: assert that changes were not made - assert: - that: - - "linked_clone_d1_c1_f0.results|map(attribute='changed')|unique|list == [false]" - -# TODO: VCSIM: snapshot is not supported in current vcsim -# -#- name: create new linked clone with linked_clone and snapshot_src -# vmware_guest: -# validate_certs: False -# hostname: "{{ vcsim }}" -# username: "{{ vcsim_instance['json']['username'] }}" -# password: "{{ vcsim_instance['json']['password'] }}" -# name: "{{ 'new_vm_' + item|basename }}" -# template: "{{ item|basename }}" -# guest_id: centos64Guest -# datacenter: "{{ (item|basename).split('_')[0] }}" -# folder: "{{ item|dirname }}" -# snapshot_src: "snap_shot1" -# linked_clone: True -# with_items: "{{ vmlist['json'] }}" -# register: linked_clone_d1_c1_f0 -# ignore_errors: True - -#- debug: var=linked_clone_d1_c1_f0 - -#- name: assert that changes were made -# assert: -# that: -# - "linked_clone_d1_c1_f0.results|map(attribute='changed')|unique|list == [true]" - -# TODO: VCSIM: snapshot is not supported in current vcsim -# -#- name: create new linked clone with linked_clone and snapshot_src again -# vmware_guest: -# validate_certs: False -# hostname: "{{ vcsim }}" -# username: "{{ vcsim_instance['json']['username'] }}" -# password: "{{ vcsim_instance['json']['password'] }}" -# name: "{{ 'new_vm_' + item|basename }}" -# template: "{{ item|basename }}" -# guest_id: centos64Guest -# datacenter: "{{ (item|basename).split('_')[0] }}" -# folder: "{{ item|dirname }}" -# snapshot_src: "snap_shot1" -# linked_clone: True -# with_items: "{{ vmlist['json'] }}" -# register: linked_clone_d1_c1_f0 -# ignore_errors: True - -#- debug: var=linked_clone_d1_c1_f0 - -#- name: assert that changes were not made -# assert: -# that: -# - "linked_clone_d1_c1_f0.results|map(attribute='changed')|unique|list == [false]" diff --git a/test/integration/targets/vmware_guest/tasks/mac_address_d1_c1_f0.yml b/test/integration/targets/vmware_guest/tasks/mac_address_d1_c1_f0.yml deleted file mode 100644 index 6e5a8d9217..0000000000 --- a/test/integration/targets/vmware_guest/tasks/mac_address_d1_c1_f0.yml +++ /dev/null @@ -1,37 +0,0 @@ -# Test code for the vmware_guest module. -# Copyright: (c) 2017, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: create new VMs with manual MAC address - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - hardware: - num_cpus: 1 - memory_mb: 128 - disk: - - size: 1gb - type: thin - datastore: "{{ rw_datastore }}" - networks: - - name: VM Network - ip: 192.168.10.12 - netmask: 255.255.255.0 - gateway: 192.168.10.254 - mac: aa:bb:cc:dd:aa:42 - state: poweredoff - folder: vm - register: clone_d1_c1_f0 - -- debug: var=clone_d1_c1_f0 - -- name: assert that changes were made - assert: - that: - - "clone_d1_c1_f0['instance']['hw_eth0']['addresstype'] == 'manual'" - - "clone_d1_c1_f0['instance']['hw_eth0']['macaddress'] == 'aa:bb:cc:dd:aa:42'" diff --git a/test/integration/targets/vmware_guest/tasks/main.yml b/test/integration/targets/vmware_guest/tasks/main.yml deleted file mode 100644 index d61f8ea1f3..0000000000 --- a/test/integration/targets/vmware_guest/tasks/main.yml +++ /dev/null @@ -1,19 +0,0 @@ -# Test code for the vmware_guest module. -# Copyright: (c) 2017, James Tanner <tanner.jc@gmail.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datacenter: true - setup_datastore: true - setup_dvswitch: true - setup_resource_pool: true - setup_virtualmachines: true - setup_dvs_portgroup: true - -- include_tasks: run_test_playbook.yml - with_items: '{{ vmware_guest_test_playbooks }}' - loop_control: - loop_var: test_playbook diff --git a/test/integration/targets/vmware_guest/tasks/max_connections.yml b/test/integration/targets/vmware_guest/tasks/max_connections.yml deleted file mode 100644 index d9ab6b6621..0000000000 --- a/test/integration/targets/vmware_guest/tasks/max_connections.yml +++ /dev/null @@ -1,45 +0,0 @@ -# Test code for the vmware_guest module. -# Copyright: (c) 2019, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - &add_mk_conn - name: Create new VM with max_connections as 4 - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - hardware: - num_cpus: 1 - memory_mb: 128 - max_connections: 4 - disk: - - size: 1gb - type: thin - datastore: "{{ rw_datastore }}" - state: present - folder: "{{ f0 }}" - register: mk_conn_result_0001 - - - debug: var=mk_conn_result_0001 - - - name: Assert that changes were made - assert: - that: - - mk_conn_result_0001 is changed - - - <<: *add_mk_conn - name: Again create new VMs again with max_connections as 4 - register: mk_conn_result_0002 - - - debug: var=mk_conn_result_0002 - - - name: Assert that changes were not made - assert: - that: - - not (mk_conn_result_0002 is changed) diff --git a/test/integration/targets/vmware_guest/tasks/mem_reservation.yml b/test/integration/targets/vmware_guest/tasks/mem_reservation.yml deleted file mode 100644 index a5a9762f62..0000000000 --- a/test/integration/targets/vmware_guest/tasks/mem_reservation.yml +++ /dev/null @@ -1,125 +0,0 @@ -# Test code for the vmware_guest module. -# Copyright: (c) 2019, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - &add_mem_reserve - name: Create new VMs with mem_reservation as 0 - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - hardware: - num_cpus: 1 - memory_mb: 128 - mem_reservation: 0 - disk: - - size: 1gb - type: thin - datastore: "{{ rw_datastore }}" - state: present - folder: "{{ virtual_machines[0].folder }}" - register: mem_reserve_result_0001 - - - debug: var=mem_reserve_result_0001 - - - name: Assert that changes were made - assert: - that: - - mem_reserve_result_0001 is changed - - - <<: *add_mem_reserve - name: Again create new VMs with mem_reservation as 0 - register: mem_reserve_result_0002 - - - debug: var=mem_reserve_result_0002 - - - name: Assert that changes were not made - assert: - that: - - not (mem_reserve_result_0002 is changed) - - - &add_memory_reserve - name: Create new VM with memory_reservation as 0 - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm2 - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - hardware: - num_cpus: 1 - memory_mb: 128 - memory_reservation: 0 - disk: - - size: 1gb - type: thin - datastore: "{{ rw_datastore }}" - state: present - folder: "{{ virtual_machines[0].folder }}" - register: memory_reserve_result_0003 - - - debug: var=memory_reserve_result_0003 - - - name: Assert that changes were made - assert: - that: - - memory_reserve_result_0003 is changed - - - <<: *add_memory_reserve - name: Again create new VMs with memory_reservation as 0 - register: memory_reserve_result_0004 - - - debug: var=memory_reserve_result_0004 - - - name: Assert that changes were not made - assert: - that: - - not (memory_reserve_result_0004 is changed) - - - &no_memory_reserve - name: Create new VMs without memory_reservation or mem_reservation - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm3 - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - hardware: - num_cpus: 1 - memory_mb: 128 - memory_reservation: 0 - disk: - - size: 1gb - type: thin - datastore: "{{ rw_datastore }}" - state: present - folder: "{{ virtual_machines[0].folder }}" - register: no_memory_reserve_result_0005 - - - debug: var=no_memory_reserve_result_0005 - - - name: Assert that changes were made - assert: - that: - - no_memory_reserve_result_0005 is changed - - - <<: *no_memory_reserve - name: Again create new VMs without memory_reservation or mem_reservation - register: no_memory_reserve_result_0006 - - - debug: var=no_memory_reserve_result_0006 - - - name: Assert that changes were not made - assert: - that: - - not (no_memory_reserve_result_0006 is changed) diff --git a/test/integration/targets/vmware_guest/tasks/network_negative_test.yml b/test/integration/targets/vmware_guest/tasks/network_negative_test.yml deleted file mode 100644 index 768e06b042..0000000000 --- a/test/integration/targets/vmware_guest/tasks/network_negative_test.yml +++ /dev/null @@ -1,339 +0,0 @@ -# Test code for the vmware_guest module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- debug: var=f0 - -- name: create new VMs with non-existent network - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: new_vm - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - disk: - - size: 3mb - type: thin - datastore: "{{ rw_datastore }}" - networks: - - name: "Non existent VM" - hardware: - num_cpus: 1 - memory_mb: 128 - state: poweredoff - folder: "{{ f0 }}" - register: non_existent_network - ignore_errors: yes - -- debug: var=non_existent_network - -- name: assert that no changes were not made - assert: - that: - - not (non_existent_network is changed) - - "'does not exist' in non_existent_network.msg" - -- name: create new VMs with network and with only IP - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: new_vm - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - disk: - - size: 3mb - type: thin - datastore: "{{ rw_datastore }}" - networks: - - name: "VM Network" - type: static - ip: 10.10.10.10 - hardware: - num_cpus: 1 - memory_mb: 128 - state: poweredoff - folder: "{{ f0 }}" - register: no_netmask - ignore_errors: yes - -- debug: var=no_netmask - -- name: assert that no changes were not made - assert: - that: - - "not no_netmask.changed" - - "\"'netmask' is required if 'ip' is specified under VM network list.\" in no_netmask.msg" - -- name: create new VMs with network and with only netmask - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: new_vm - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - disk: - - size: 3mb - type: thin - datastore: "{{ rw_datastore }}" - networks: - - name: "VM Network" - type: static - netmask: 255.255.255.0 - hardware: - num_cpus: 1 - memory_mb: 128 - state: poweredoff - folder: "{{ f0 }}" - register: no_ip - ignore_errors: yes - -- debug: var=no_ip - -- name: assert that changes were not made - assert: - that: - - "not no_ip.changed" - - "\"'ip' is required if 'netmask' is specified under VM network list.\" in no_ip.msg" - -- name: create new VMs with network and without network name - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: new_vm - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - disk: - - size: 3mb - type: thin - datastore: "{{ rw_datastore }}" - networks: - - ip: 10.10.10.10 - netmask: 255.255.255 - type: static - hardware: - num_cpus: 1 - memory_mb: 128 - state: poweredoff - folder: "{{ f0 }}" - register: no_network_name - ignore_errors: yes - -- debug: var=no_network_name - -- name: assert that no changes were not made - assert: - that: - - "not no_network_name.changed" - - "\"Please specify at least a network name or a VLAN name under VM network list.\" in no_network_name.msg" - -- name: create new VMs with network and without network name - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: new_vm - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - disk: - - size: 3mb - type: thin - datastore: "{{ rw_datastore }}" - networks: - - vlan: non_existing_vlan - ip: 10.10.10.10 - netmask: 255.255.255 - hardware: - num_cpus: 1 - memory_mb: 128 - state: poweredoff - folder: "{{ f0 }}" - register: no_network - ignore_errors: yes - -- debug: var=no_network - -- name: assert that changes were not made - assert: - that: - - "not no_network.changed" - - "\"VLAN 'non_existing_vlan' does not exist.\" in no_network.msg" - -- name: create new VMs with invalid device type - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: new_vm - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - disk: - - size: 3mb - type: thin - datastore: "{{ rw_datastore }}" - networks: - - name: "VM Network" - ip: 10.10.10.10 - netmask: 255.255.255 - device_type: abc - hardware: - num_cpus: 1 - memory_mb: 128 - state: poweredoff - folder: "{{ f0 }}" - register: invalid_device_type - ignore_errors: yes - -- debug: var=invalid_device_type - -- name: assert that changes were not made - assert: - that: - - "not invalid_device_type.changed" - - "\"Device type specified 'abc' is not valid.\" in invalid_device_type.msg" - -- name: create new VMs with invalid device MAC address - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: new_vm - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - disk: - - size: 3mb - type: thin - datastore: "{{ rw_datastore }}" - networks: - - name: "VM Network" - ip: 10.10.10.10 - netmask: 255.255.255 - device_type: e1000 - mac: abcdef - hardware: - num_cpus: 1 - memory_mb: 128 - state: poweredoff - folder: "{{ f0 }}" - register: invalid_mac - ignore_errors: yes - -- debug: var=invalid_mac - -- name: assert that changes were not made - assert: - that: - - "not invalid_mac.changed" - - "\"Device MAC address 'abcdef' is invalid.\" in invalid_mac.msg" - -- name: create new VMs with invalid network type - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: new_vm - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - disk: - - size: 3mb - type: thin - datastore: "{{ rw_datastore }}" - networks: - - name: "VM Network" - ip: 10.10.10.10 - netmask: 255.255.255 - device_type: e1000 - mac: 01:23:45:67:89:ab - type: aaaaa - hardware: - num_cpus: 1 - memory_mb: 128 - state: poweredoff - folder: "{{ f0 }}" - register: invalid_network_type - ignore_errors: yes - -- debug: var=invalid_network_type - -- name: assert that changes were not made - assert: - that: - - "not invalid_network_type.changed" - - "\"Network type 'aaaaa' is not a valid parameter.\" in invalid_network_type.msg" - -- name: create new VMs with IP, netmask and network type as "DHCP" - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: new_vm - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - disk: - - size: 3mb - type: thin - datastore: "{{ rw_datastore }}" - networks: - - name: "VM Network" - ip: 10.10.10.10 - netmask: 255.255.255 - device_type: e1000 - mac: 01:23:45:67:89:ab - type: dhcp - hardware: - num_cpus: 1 - memory_mb: 128 - state: poweredoff - folder: "{{ f0 }}" - register: invalid_dhcp_network_type - ignore_errors: yes - -- debug: var=invalid_dhcp_network_type - -- name: assert that changes were not made - assert: - that: - - "not invalid_dhcp_network_type.changed" - - "\"Static IP information provided for network\" in invalid_dhcp_network_type.msg" - -- name: create new VMs with no network type which set network type as "DHCP" - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - disk: - - size: 3mb - type: thin - datastore: "{{ rw_datastore }}" - networks: - - name: "VM Network" - hardware: - num_cpus: 1 - memory_mb: 128 - state: poweredoff - folder: "{{ f0 }}" - register: no_network_type - ignore_errors: yes - -- debug: var=no_network_type - -- name: assert that changes were made - assert: - that: - - "no_network_type.changed" diff --git a/test/integration/targets/vmware_guest/tasks/network_with_device.yml b/test/integration/targets/vmware_guest/tasks/network_with_device.yml deleted file mode 100644 index 64b591adb7..0000000000 --- a/test/integration/targets/vmware_guest/tasks/network_with_device.yml +++ /dev/null @@ -1,60 +0,0 @@ -# Test code for the vmware_guest module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# Testcase to check #38605 -- name: Deploy VM first VM - vmware_guest: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: False - datacenter: "{{ dc1 }}" - state: poweredon - folder: "{{ f0 }}" - name: test_vm1 - disk: - - size: 10mb - datastore: "{{ rw_datastore }}" - guest_id: rhel7_64guest - hardware: - memory_mb: 128 - num_cpus: 1 - networks: - - name: 'VM Network' - device_type: "vmxnet3" - register: vm_result - -- debug: var=vm_result - -- assert: - that: - - "vm_result.changed" - -- name: Deploy VM again - vmware_guest: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: False - datacenter: "{{ dc1 }}" - state: poweredon - folder: "{{ f0 }}" - name: test_vm1 - disk: - - size: 10mb - datastore: "{{ rw_datastore }}" - guest_id: rhel7_64guest - hardware: - memory_mb: 128 - num_cpus: 1 - networks: - - name: 'VM Network' - device_type: "vmxnet3" - register: vm_result_again - -- debug: var=vm_result_again - -- assert: - that: - - not (vm_result_again is changed) diff --git a/test/integration/targets/vmware_guest/tasks/network_with_dvpg.yml b/test/integration/targets/vmware_guest/tasks/network_with_dvpg.yml deleted file mode 100644 index fba25aeee5..0000000000 --- a/test/integration/targets/vmware_guest/tasks/network_with_dvpg.yml +++ /dev/null @@ -1,152 +0,0 @@ -# Test code for the vmware_guest module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# Clone from existing VM with DVPG -- when: vcsim is not defined - block: - - name: Deploy VM from template - vmware_guest: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ dc1 }}" - state: poweredon - folder: "{{ f0 }}" - template: "{{ virtual_machines[0].name }}" - name: test_vm1 - disk: - - size: 1gb - datastore: "{{ rw_datastore }}" - guest_id: rhel7_64guest - hardware: - memory_mb: 128 - num_cpus: 1 - networks: - - name: '{{ dvpg1 }}' - register: no_vm_result - - debug: var=no_vm_result - - assert: - that: - - no_vm_result is changed - - # New clone with DVPG - - name: Deploy new VM with DVPG - vmware_guest: - esxi_hostname: "{{ esxi_hosts[0] }}" - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ dc1 }}" - state: poweredon - folder: "{{ f0 }}" - name: test_vm2 - disk: - - size: 1gb - datastore: "{{ rw_datastore }}" - guest_id: rhel7_64guest - hardware: - memory_mb: 128 - num_cpus: 1 - networks: - - name: '{{ dvpg1 }}' - dvswitch_name: "{{ dvswitch1 }}" - register: no_vm_result - - debug: var=no_vm_result - - assert: - that: - - no_vm_result is changed - - - name: Deploy same VM again - vmware_guest: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ dc1 }}" - state: poweredon - folder: "{{ f0 }}" - name: test_vm2 - disk: - - size: 1gb - datastore: "{{ rw_datastore }}" - guest_id: rhel7_64guest - hardware: - memory_mb: 128 - num_cpus: 1 - networks: - - name: '{{ dvpg1 }}' - register: no_vm_result - - debug: var=no_vm_result - - assert: - that: - - not (no_vm_result is changed) - - - name: Deploy new VM with DVPG with slash in name - vmware_guest: - esxi_hostname: "{{ esxi_hosts[0] }}" - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ dc1 }}" - state: poweredon - folder: "{{ f0 }}" - name: test_vm3 - disk: - - size: 1gb - datastore: "{{ rw_datastore }}" - guest_id: rhel7_64guest - hardware: - memory_mb: 128 - num_cpus: 1 - networks: - - name: '{{ dvpg_with_slash }}' - dvswitch_name: "{{ dvswitch1 }}" - register: no_vm_result - - debug: var=no_vm_result - - assert: - that: - - no_vm_result is changed - - - name: Deploy same VM again - vmware_guest: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ dc1 }}" - state: poweredon - folder: "{{ f0 }}" - name: test_vm3 - disk: - - size: 1gb - datastore: "{{ rw_datastore }}" - guest_id: rhel7_64guest - hardware: - memory_mb: 128 - num_cpus: 1 - networks: - - name: '{{ dvpg_with_slash }}' - register: no_vm_result - - debug: var=no_vm_result - - assert: - that: - - not (no_vm_result is changed) - always: - - when: vcsim is not defined - name: Remove VM to free the portgroup - vmware_guest: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - name: '{{ item }}' - force: yes - state: absent - with_items: - - test_vm1 - - test_vm2 - - test_vm3 diff --git a/test/integration/targets/vmware_guest/tasks/network_with_portgroup.yml b/test/integration/targets/vmware_guest/tasks/network_with_portgroup.yml deleted file mode 100644 index c9eb80186a..0000000000 --- a/test/integration/targets/vmware_guest/tasks/network_with_portgroup.yml +++ /dev/null @@ -1,47 +0,0 @@ -# Test code for the vmware_guest module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com>, Tim Steinbach <tim@nequissimus.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: Add portgroup - vmware_dvs_portgroup: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - portgroup_name: "portgroup_network" - switch_name: "{{ dvswitch1 }}" - vlan_id: "1" - num_ports: 2 - portgroup_type: earlyBinding - state: present - register: dvsportgroup -- debug: var=dvsportgroup -- name: create new VMs with portgroup - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - disk: - - size: 3mb - type: thin - datastore: "{{ rw_datastore }}" - networks: - - name: portgroup_network - switch_name: "{{ dvswitch1 }}" - hardware: - num_cpus: 1 - memory_mb: 128 - state: poweredoff - folder: "{{ f0 }}" - register: vm_with_portgroup - ignore_errors: no - -- debug: var=vm_with_portgroup - -- assert: - that: - - vm_with_portgroup is changed diff --git a/test/integration/targets/vmware_guest/tasks/non_existent_vm_ops.yml b/test/integration/targets/vmware_guest/tasks/non_existent_vm_ops.yml deleted file mode 100644 index 0815fdf9c6..0000000000 --- a/test/integration/targets/vmware_guest/tasks/non_existent_vm_ops.yml +++ /dev/null @@ -1,23 +0,0 @@ -# Test code for the vmware_guest module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: Perform operation on non-existent VM - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "non_existent_vm" - datacenter: "{{ dc1 }}" - folder: "{{ f0 }}" - state: poweredoff - register: non_existent_vm_ops - ignore_errors: yes -- debug: var=non_existent_vm_ops -- name: assert that changes were not made - assert: - that: - - not (non_existent_vm_ops is changed) - - "'msg' in non_existent_vm_ops" - - "'Unable to find the datastore with given parameters.' in non_existent_vm_ops.msg" diff --git a/test/integration/targets/vmware_guest/tasks/poweroff_d1_c1_f0.yml b/test/integration/targets/vmware_guest/tasks/poweroff_d1_c1_f0.yml deleted file mode 100644 index 6bddf568f7..0000000000 --- a/test/integration/targets/vmware_guest/tasks/poweroff_d1_c1_f0.yml +++ /dev/null @@ -1,27 +0,0 @@ -# Test code for the vmware_guest module. -# Copyright: (c) 2017, James Tanner <tanner.jc@gmail.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: create a VM with the poweroff status - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "{{ item.name }}" - state: poweredoff - with_items: "{{ virtual_machines }}" - register: poweroff_d1_c1_f0 - -- debug: - var: poweroff_d1_c1_f0 - -- name: make sure changes were made - assert: - that: - - poweroff_d1_c1_f0.results[0].instance.hw_power_status == "poweredOff" - -- name: make sure no changes were made (the VMs are already off) - assert: - that: - - poweroff_d1_c1_f0.results[0].changed|bool == false diff --git a/test/integration/targets/vmware_guest/tasks/poweroff_d1_c1_f1.yml b/test/integration/targets/vmware_guest/tasks/poweroff_d1_c1_f1.yml deleted file mode 100644 index cb5ada078f..0000000000 --- a/test/integration/targets/vmware_guest/tasks/poweroff_d1_c1_f1.yml +++ /dev/null @@ -1,22 +0,0 @@ -# Test code for the vmware_guest module. -# Copyright: (c) 2017, James Tanner <tanner.jc@gmail.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# https://github.com/ansible/ansible/issues/25011 -# Sending "-folders 1" to vcsim nests the datacenter under -# the folder so that the path prefix is no longer /vm -# -# /F0/DC0/vm/F0/DC0_H0_VM0 - -- name: set state to poweredoff on all VMs - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "{{ item.name }}" - state: poweredoff - folder: "{{ item.folder }}" - with_items: "{{ virtual_machines }}" - register: poweroff_d1_c1_f1 -- debug: var=poweroff_d1_c1_f1 diff --git a/test/integration/targets/vmware_guest/tasks/reconfig_vm_to_latest_version.yml b/test/integration/targets/vmware_guest/tasks/reconfig_vm_to_latest_version.yml deleted file mode 100644 index 619090dc0b..0000000000 --- a/test/integration/targets/vmware_guest/tasks/reconfig_vm_to_latest_version.yml +++ /dev/null @@ -1,73 +0,0 @@ -# Test code for the vmware_guest module. -# 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) -# Skipping out idepotency test untill issue fixed in reconfigure_vm() become_method - -- name: Create VM with hardware version 12 - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - guest_id: centos7_64Guest - datacenter: "{{ dc1 }}" - folder: "{{ f0 }}" - datastore: '{{ rw_datastore }}' - hardware: - num_cpus: 4 - memory_mb: 1028 - version: 12 - state: present - register: create_vm_with_version_12 - -- name: assert that changes were made - assert: - that: - - create_vm_with_version_12 is changed - -- name: Deploy New VM with latest hardware version - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm2 - guest_id: centos7_64Guest - datacenter: "{{ dc1 }}" - folder: "{{ f0 }}" - datastore: '{{ rw_datastore }}' - hardware: - num_cpus: 4 - memory_mb: 1028 - version: latest - state: present - register: deploy_vm_to_latest - -- name: assert that changes were made - assert: - that: - - deploy_vm_to_latest is changed - -- name: Upgrade VM to latest version - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - guest_id: centos7_64Guest - datacenter: "{{ dc1 }}" - folder: "{{ f0 }}" - datastore: '{{ rw_datastore }}' - hardware: - num_cpus: 4 - memory_mb: 1028 - version: latest - state: present - register: upgrade_vm - -- name: assert that changes were made - assert: - that: - - upgrade_vm is changed diff --git a/test/integration/targets/vmware_guest/tasks/remove_vm_from_inventory.yml b/test/integration/targets/vmware_guest/tasks/remove_vm_from_inventory.yml deleted file mode 100644 index 74da57d4b0..0000000000 --- a/test/integration/targets/vmware_guest/tasks/remove_vm_from_inventory.yml +++ /dev/null @@ -1,61 +0,0 @@ -# Test code for the vmware_guest module. -# 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) - -- name: Create VM to unregister - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - folder: F0 - hardware: - num_cpus: 1 - num_cpu_cores_per_socket: 1 - memory_mb: 128 - disk: - - size: 1gb - type: thin - datastore: "{{ rw_datastore }}" - state: present - register: create_vm_for_test - -- name: assert that changes were made - assert: - that: - - create_vm_for_test is changed - -- name: Remove VM from Inventory - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - delete_from_inventory: True - state: absent - register: remove_vm_from_inventory - -- name: assert that changes were made - assert: - that: - - remove_vm_from_inventory is changed - -- name: Remove VM again from Inventory - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - delete_from_inventory: True - state: absent - register: remove_again_vm_from_inventory - -- name: assert that changes were made - assert: - that: - - not (remove_again_vm_from_inventory is changed) diff --git a/test/integration/targets/vmware_guest/tasks/run_test_playbook.yml b/test/integration/targets/vmware_guest/tasks/run_test_playbook.yml deleted file mode 100644 index d60dc394e1..0000000000 --- a/test/integration/targets/vmware_guest/tasks/run_test_playbook.yml +++ /dev/null @@ -1,17 +0,0 @@ -- block: - - include_tasks: '{{ test_playbook }}' - always: - - name: Remove VM - vmware_guest: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no -# cluster: "{{ ccr1 }}" - name: '{{ item }}' - force: yes - state: absent - with_items: - - test_vm1 - - test_vm2 - - test_vm3 diff --git a/test/integration/targets/vmware_guest/tasks/template_d1_c1_f0.yml b/test/integration/targets/vmware_guest/tasks/template_d1_c1_f0.yml deleted file mode 100644 index 55e27c9ded..0000000000 --- a/test/integration/targets/vmware_guest/tasks/template_d1_c1_f0.yml +++ /dev/null @@ -1,105 +0,0 @@ -- name: Create VMs with the poweredoff state - vmware_guest: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - validate_certs: no - folder: '{{ f0 }}' - name: 'test_vm1' - state: poweredoff - guest_id: debian8_64Guest - disk: - - size_gb: 1 - type: thin - datastore: '{{ rw_datastore }}' - hardware: - memory_mb: 128 - num_cpus: 1 - scsi: paravirtual - cdrom: - type: iso - iso_path: "[{{ ro_datastore }}] fedora.iso" - networks: - - name: VM Network - -- name: ensure that VM1 are not flagged as templates - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - folder: "{{ virtual_machines[1].folder }}" - name: "{{ virtual_machines[1].name }}" - state: present - is_template: False - register: no_template_initial - -- debug: var=no_template_initial - -- name: ensure no changes were made - assert: - that: - - not (no_template_initial is changed) - -- name: convert VM1 to template - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - folder: "{{ virtual_machines[1].folder }}" - name: "{{ virtual_machines[1].name }}" - state: present - is_template: True - register: convert_to_template - -- debug: var=convert_to_template - -- name: ensure that changes were made - assert: - that: - - convert_to_template is changed - -- name: make double sure that VM1 is template - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - folder: "{{ virtual_machines[1].folder }}" - name: "{{ virtual_machines[1].name }}" - state: present - is_template: True - register: still_templates - -- debug: var=still_templates - -- name: ensure that no changes were made - assert: - that: - - not (still_templates is changed) - -# To avoid the follow error of vcsim: VirtualMachine:vm-67 does not implement: MarkAsVirtualMachine -- when: vcsim is not defined - block: - - name: convert template back to VMs - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - folder: "{{ virtual_machines[1].folder }}" - name: "{{ virtual_machines[1].name }}" - state: present - is_template: False - register: revert_to_vm - - debug: var=revert_to_vm - - name: ensure that changes were made - assert: - that: - - revert_to_vm is changed diff --git a/test/integration/targets/vmware_guest/tasks/vapp_d1_c1_f0.yml b/test/integration/targets/vmware_guest/tasks/vapp_d1_c1_f0.yml deleted file mode 100644 index bd83f97db6..0000000000 --- a/test/integration/targets/vmware_guest/tasks/vapp_d1_c1_f0.yml +++ /dev/null @@ -1,100 +0,0 @@ -# Test code for the vmware_guest module. -# Copyright: (c) 2018, goshkis -# Copyright: (c) 2019, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- &vapp_new_vm - name: Create test VM with vAPP settings - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - folder: "vm" - name: test_vm1 - datacenter: "{{ dc1 }}" - cluster: "{{ ccr1 }}" - resource_pool: Resources - guest_id: centos64Guest - hardware: - memory_mb: 128 - num_cpus: 1 - scsi: paravirtual - disk: - - size_mb: 128 - type: thin - datastore: "{{ rw_datastore }}" - vapp_properties: - - id: prop_id1 - category: category - label: prop_label1 - type: string - value: prop_value1 - - id: prop_id2 - category: category - label: prop_label2 - type: string - value: prop_value2 - register: vapp_vm - -- debug: var=vapp_vm - -- name: assert the vApp propeties were created - assert: - that: - - "vapp_vm.failed == false" - - "vapp_vm.changed == true" - -- when: vcsim is not defined - block: - - <<: *vapp_new_vm - name: Try to create same VM with same vAPP settings - register: vapp_vm_no_change - - - debug: var=vapp_vm_no_change - - - name: Assert that vApp properties were not changed - assert: - that: - - "vapp_vm_no_change.failed == false" - - "not vapp_vm_no_change.changed" - -- &vapp_edit_vm - name: Edit one vApp property and removing another - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - folder: "vm" - name: test_vm1 - datacenter: "{{ dc1 }}" - vapp_properties: - - id: prop_id1 - operation: remove - - id: prop_id2 - value: prop_value3 - state: present - register: vapp_vm - -- debug: var=vapp_vm - -- name: assert the VM was changed - assert: - that: - - "vapp_vm.failed == false" - - "vapp_vm.changed == true" - -- when: vcsim is not defined - block: - - <<: *vapp_edit_vm - name: Try to edit VM with vApp settings - register: vapp_vm_no_change_edit - - - debug: var=vapp_vm_no_change_edit - - - name: assert the VM was changed - assert: - that: - - "vapp_vm_no_change_edit.failed == false" - - "vapp_vm_no_change_edit.changed == false" diff --git a/test/integration/targets/vmware_guest/tasks/windows_vbs_d1_c1_f0.yml b/test/integration/targets/vmware_guest/tasks/windows_vbs_d1_c1_f0.yml deleted file mode 100644 index 88a5757bf1..0000000000 --- a/test/integration/targets/vmware_guest/tasks/windows_vbs_d1_c1_f0.yml +++ /dev/null @@ -1,93 +0,0 @@ -- name: Create Windows 10 VM with VBS enabled - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - folder: "{{ f0 }}" - name: vbs-Test - datacenter: "{{ dc1 }}" - cluster: "{{ ccr1 }}" - resource_pool: Resources - guest_id: windows9_64Guest - hardware: - memory_mb: 128 - num_cpus: 1 - virt_based_security: True - version: 14 - boot_firmware: efi - scsi: paravirtual - disk: - - size_mb: 128 - type: thin - datastore: '{{ rw_datastore }}' - cdrom: - type: client - register: vbs_vm - -- debug: var=vbs_vm - -- name: assert the VM was created - assert: - that: - - "vbs_vm.failed == false" - - "vbs_vm.changed == true" - -- name: Create Windows Server 2016 VM without VBS enabled - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - folder: "{{ f0 }}" - name: vbs-Test2 - datacenter: "{{ dc1 }}" - cluster: "{{ ccr1 }}" - resource_pool: Resources - guest_id: windows9Server64Guest - hardware: - memory_mb: 128 - num_cpus: 1 - version: 14 - boot_firmware: efi - scsi: paravirtual - disk: - - size_mb: 128 - type: thin - datastore: '{{ rw_datastore }}' - cdrom: - type: client - register: vbs_vm - -- debug: var=vbs_vm - -- name: assert the VM was created - assert: - that: - - "vbs_vm.failed == false" - - "vbs_vm.changed == true" - -- name: Enable VBS for Windows Server 2016 VM - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - folder: "{{ f0 }}" - name: vbs-Test2 - datacenter: "{{ f0 }}" - disk: - - size_mb: 256 - type: thin - datastore: '{{ rw_datastore }}' - hardware: - virt_based_security: True - state: present - register: vbs_vm - -- debug: var=vbs_vm - -- name: assert the VM was changed - assert: - that: - - vbs_vm is changed diff --git a/test/integration/targets/vmware_guest_boot_facts/aliases b/test/integration/targets/vmware_guest_boot_facts/aliases deleted file mode 100644 index 62871ab8f0..0000000000 --- a/test/integration/targets/vmware_guest_boot_facts/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_guest_boot_facts/tasks/main.yml b/test/integration/targets/vmware_guest_boot_facts/tasks/main.yml deleted file mode 100644 index a5d5cfc645..0000000000 --- a/test/integration/targets/vmware_guest_boot_facts/tasks/main.yml +++ /dev/null @@ -1,51 +0,0 @@ -# Test code for the vmware_guest_boot_facts module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_virtualmachines: true - - - name: Gather facts about VM boot order - vmware_guest_boot_facts: - validate_certs: no - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - name: "{{ virtual_machines[0].name }}" - register: vm1_facts - - debug: var=vm1_facts - - name: assert that values are set - assert: - that: - - vm1_facts.vm_boot_facts.current_boot_delay is defined - - vm1_facts.vm_boot_facts.current_boot_firmware is defined - - vm1_facts.vm_boot_facts.current_boot_order is defined - - vm1_facts.vm_boot_facts.current_boot_retry_delay is defined - - vm1_facts.vm_boot_facts.current_boot_retry_enabled is defined - - vm1_facts.vm_boot_facts.current_enter_bios_setup is defined - - - name: Gather facts about VM boot order in check mode - vmware_guest_boot_facts: - validate_certs: no - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - name: "{{ virtual_machines[0].name }}" - check_mode: yes - register: vm1_facts - - debug: var=vm1_facts - - name: assert that values are set - assert: - that: - - vm1_facts.vm_boot_facts.current_boot_delay is defined - - vm1_facts.vm_boot_facts.current_boot_firmware is defined - - vm1_facts.vm_boot_facts.current_boot_order is defined - - vm1_facts.vm_boot_facts.current_boot_retry_delay is defined - - vm1_facts.vm_boot_facts.current_boot_retry_enabled is defined - - vm1_facts.vm_boot_facts.current_enter_bios_setup is defined diff --git a/test/integration/targets/vmware_guest_boot_info/aliases b/test/integration/targets/vmware_guest_boot_info/aliases deleted file mode 100644 index 62871ab8f0..0000000000 --- a/test/integration/targets/vmware_guest_boot_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_guest_boot_info/tasks/main.yml b/test/integration/targets/vmware_guest_boot_info/tasks/main.yml deleted file mode 100644 index f40f397181..0000000000 --- a/test/integration/targets/vmware_guest_boot_info/tasks/main.yml +++ /dev/null @@ -1,51 +0,0 @@ -# Test code for the vmware_guest_boot_info module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_virtualmachines: true - - - name: Gather info about VM boot order - vmware_guest_boot_info: - validate_certs: no - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - name: "{{ virtual_machines[0].name }}" - register: vm1_info - - debug: var=vm1_info - - name: assert that values are set - assert: - that: - - vm1_info.vm_boot_info.current_boot_delay is defined - - vm1_info.vm_boot_info.current_boot_firmware is defined - - vm1_info.vm_boot_info.current_boot_order is defined - - vm1_info.vm_boot_info.current_boot_retry_delay is defined - - vm1_info.vm_boot_info.current_boot_retry_enabled is defined - - vm1_info.vm_boot_info.current_enter_bios_setup is defined - - - name: Gather info about VM boot order in check mode - vmware_guest_boot_info: - validate_certs: no - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - name: "{{ virtual_machines[0].name }}" - check_mode: yes - register: vm1_info - - debug: var=vm1_info - - name: assert that values are set - assert: - that: - - vm1_info.vm_boot_info.current_boot_delay is defined - - vm1_info.vm_boot_info.current_boot_firmware is defined - - vm1_info.vm_boot_info.current_boot_order is defined - - vm1_info.vm_boot_info.current_boot_retry_delay is defined - - vm1_info.vm_boot_info.current_boot_retry_enabled is defined - - vm1_info.vm_boot_info.current_enter_bios_setup is defined diff --git a/test/integration/targets/vmware_guest_controller/aliases b/test/integration/targets/vmware_guest_controller/aliases deleted file mode 100644 index 62871ab8f0..0000000000 --- a/test/integration/targets/vmware_guest_controller/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_guest_controller/tasks/main.yml b/test/integration/targets/vmware_guest_controller/tasks/main.yml deleted file mode 100644 index 117ee1e2bd..0000000000 --- a/test/integration/targets/vmware_guest_controller/tasks/main.yml +++ /dev/null @@ -1,82 +0,0 @@ -# Test code for the vmware_guest_controller module -# Copyright: (c) 2019, Diane Wang (Tomorrow9) <dianew@vmware.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_virtualmachines: true - - - name: gather disk controllers facts of the virtual machine - vmware_guest_controller: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "{{ virtual_machines[0].name }}" - gather_disk_controller_facts: true - register: disk_controller_facts - - - debug: var=disk_controller_facts - - - name: get the number of existing disk controllers - set_fact: - scsi_num: "{{ disk_controller_facts.disk_controller_data.scsi | length }}" - - set_fact: - sata_num: "{{ disk_controller_facts.disk_controller_data.sata | length }}" - - set_fact: - nvme_num: "{{ disk_controller_facts.disk_controller_data.nvme | length }}" - - - name: add new disk controllers to virtual machine - vmware_guest_controller: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "{{ virtual_machines[0].name }}" - sleep_time: 30 - controllers: - - type: sata - state: present - - type: paravirtual - state: present - register: add_disk_controller - - - debug: var=add_disk_controller - - - name: assert the new disk controllers were added to VM - assert: - that: - - "add_disk_controller.changed == true" - - "{{ add_disk_controller.disk_controller_data.scsi | length | int }} == {{ scsi_num | int + 1 }}" - - "{{ add_disk_controller.disk_controller_data.sata | length | int }} == {{ sata_num | int + 1 }}" - - - name: delete specified disk controllers - vmware_guest_controller: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "{{ virtual_machines[0].name }}" - sleep_time: 30 - controllers: - - state: absent - type: sata - controller_number: "{{ sata_num }}" - - state: absent - type: paravirtual - controller_number: "{{ scsi_num }}" - register: del_disk_controller - - - debug: var=del_disk_controller - - - name: assert the disk controllers were removed - assert: - that: - - "del_disk_controller.changed == true" - - "{{ del_disk_controller.disk_controller_data.sata | length | int }} == {{ sata_num | int }}" - - "{{ del_disk_controller.disk_controller_data.scsi | length | int }} == {{ scsi_num | int }}" diff --git a/test/integration/targets/vmware_guest_cross_vc_clone/aliases b/test/integration/targets/vmware_guest_cross_vc_clone/aliases deleted file mode 100644 index cf30c57ca1..0000000000 --- a/test/integration/targets/vmware_guest_cross_vc_clone/aliases +++ /dev/null @@ -1,3 +0,0 @@ -cloud/vcenter -unsupported -needs/target/prepare_vmware_tests
\ No newline at end of file diff --git a/test/integration/targets/vmware_guest_cross_vc_clone/tasks/main.yml b/test/integration/targets/vmware_guest_cross_vc_clone/tasks/main.yml deleted file mode 100644 index 9b9faceb60..0000000000 --- a/test/integration/targets/vmware_guest_cross_vc_clone/tasks/main.yml +++ /dev/null @@ -1,160 +0,0 @@ -# Test code for the vmware_guest_cross_vc_clone Operations. -# Copyright: (c) 2020, Anusha Hegde <anushah@vmware.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - vars: - setup_datacenter: true - -- name: Create VM - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - folder: "{{ f0 }}" - hardware: - num_cpus: 1 - memory_mb: 512 - disk: - - size: 1gb - type: thin - autoselect_datastore: True - state: present - register: create_vm_for_test - -- name: Create VM template - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm2 - is_template: True - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - folder: "{{ f0 }}" - hardware: - num_cpus: 1 - memory_mb: 512 - disk: - - size: 1gb - type: thin - autoselect_datastore: True - state: present - register: create_vm_template_for_test - -- name: clone a template across VC - vmware_guest_cross_vc_clone: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: "{{ vcenter_password }}" - validate_certs: no - name: "test_vm2" - destination_vm_name: "cloned_vm_from_template" - destination_vcenter: '{{ destination_vcenter_hostname }}' - destination_vcenter_username: '{{ destination_vcenter_username }}' - destination_vcenter_password: '{{ destination_vcenter_password }}' - destination_host: '{{ destination_esxi }}' - destination_datastore: '{{ destination_datastore }}' - destination_vm_folder: '{{ destination_vm_folder }}' - power_on: no - register: cross_vc_clone_from_template - -- name: assert that changes were made - assert: - that: - - cross_vc_clone_from_template is changed - -- name: clone a VM across VC - vmware_guest_cross_vc_clone: - hostname: '{{ destination_vcenter_hostname }}' - username: '{{ destination_vcenter_username }}' - password: "{{ destination_vcenter_password }}" - validate_certs: no - name: "test_vm1" - destination_vm_name: "cloned_vm_from_vm" - destination_vcenter: '{{ destination_vcenter_hostname }}' - destination_vcenter_username: '{{ destination_vcenter_username }}' - destination_vcenter_password: '{{ destination_vcenter_password }}' - destination_vcenter_port: '{{ destination_vcenter_port }}' - destination_vcenter_validate_certs: '{{ destination_vcenter_validate_certs }}' - destination_host: '{{ destination_esxi1 }}' - destination_datastore: '{{ destination_datastore }}' - destination_vm_folder: '{{ destination_vm_folder }}' - power_on: yes - register: cross_vc_clone_from_vm - -- name: assert that changes were made - assert: - that: - - cross_vc_clone_from_vm is changed - -- name: clone a VM across VC when datastore cluster is specified - vmware_guest_cross_vc_clone: - hostname: '{{ destination_vcenter_hostname }}' - username: '{{ destination_vcenter_username }}' - password: "{{ destination_vcenter_password }}" - validate_certs: no - name: "test_vm1" - destination_vm_name: "cloned_vm_from_vm" - destination_vcenter: '{{ destination_vcenter_hostname }}' - destination_vcenter_username: '{{ destination_vcenter_username }}' - destination_vcenter_password: '{{ destination_vcenter_password }}' - destination_host: '{{ destination_esxi1 }}' - destination_datastore: '{{ destination_datastore_cluster }}' - destination_vm_folder: '{{ destination_vm_folder }}' - power_on: yes - register: cross_vc_clone_from_vm_with_datastore_cluster - -- name: assert that changes were made - assert: - that: - - cross_vc_clone_from_vm_with_datastore_cluster is changed - -- name: clone in check mode - vmware_guest_cross_vc_clone: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: "{{ vcenter_password }}" - validate_certs: no - name: "test_vm2" - destination_vm_name: "cloned_vm_from_template_in_check_mode" - destination_vcenter: '{{ destination_vcenter_hostname }}' - destination_vcenter_username: '{{ destination_vcenter_username }}' - destination_vcenter_password: '{{ destination_vcenter_password }}' - destination_host: '{{ destination_esxi }}' - destination_datastore: '{{ destination_datastore }}' - destination_vm_folder: '{{ destination_vm_folder }}' - power_on: no - check_mode: yes - register: check_mode_clone - -- debug: - var: check_mode_clone - -- name: idempotency check - VM name already exists - vmware_guest_cross_vc_clone: - hostname: '{{ destination_vcenter_hostname }}' - username: '{{ destination_vcenter_username }}' - password: "{{ destination_vcenter_password }}" - validate_certs: no - name: "test_vm1" - destination_vm_name: "cloned_vm_from_vm" - destination_vcenter: '{{ destination_vcenter_hostname }}' - destination_vcenter_username: '{{ destination_vcenter_username }}' - destination_vcenter_password: '{{ destination_vcenter_password }}' - destination_host: '{{ destination_esxi1 }}' - destination_datastore: '{{ destination_datastore }}' - destination_vm_folder: '{{ destination_vm_folder }}' - power_on: yes - register: idempotency_check - -- name: assert that no changes were made - assert: - that: - - idempotency_check is unchanged
\ No newline at end of file diff --git a/test/integration/targets/vmware_guest_custom_attribute_defs/aliases b/test/integration/targets/vmware_guest_custom_attribute_defs/aliases deleted file mode 100644 index 62871ab8f0..0000000000 --- a/test/integration/targets/vmware_guest_custom_attribute_defs/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_guest_custom_attribute_defs/tasks/main.yml b/test/integration/targets/vmware_guest_custom_attribute_defs/tasks/main.yml deleted file mode 100644 index 684eb9ddcc..0000000000 --- a/test/integration/targets/vmware_guest_custom_attribute_defs/tasks/main.yml +++ /dev/null @@ -1,85 +0,0 @@ -# Test code for the vmware_guest_custom_attribute_defs module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_virtualmachines: true -- name: remove attribute definition - vmware_guest_custom_attribute_defs: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - state: absent - attribute_key: sample_5 - -- name: add custom attribute definition - vmware_guest_custom_attribute_defs: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - state: present - attribute_key: sample_5 - register: add_attrib_def - -- debug: var=add_attrib_def - -- assert: - that: - - add_attrib_def is changed - - "'sample_5' in add_attrib_def.custom_attribute_defs" - -- name: add attribute definition again - vmware_guest_custom_attribute_defs: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - state: present - attribute_key: sample_5 - register: add_attrib_def - -- debug: var=add_attrib_def - -- assert: - that: - - not (add_attrib_def is changed) - -- name: remove attribute definition - vmware_guest_custom_attribute_defs: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - state: absent - attribute_key: sample_5 - register: remove_attrib_def - -- debug: var=remove_attrib_def - -- assert: - that: - - "remove_attrib_def.changed" - - "'sample_5' not in remove_attrib_def.custom_attribute_defs" - -- name: remove attribute definition - vmware_guest_custom_attribute_defs: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - state: absent - attribute_key: sample_5 - register: remove_attrib_def - -- debug: var=remove_attrib_def - -- assert: - that: - - "not remove_attrib_def.changed" - - "'sample_5' not in remove_attrib_def.custom_attribute_defs" diff --git a/test/integration/targets/vmware_guest_custom_attributes/aliases b/test/integration/targets/vmware_guest_custom_attributes/aliases deleted file mode 100644 index 62871ab8f0..0000000000 --- a/test/integration/targets/vmware_guest_custom_attributes/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_guest_custom_attributes/tasks/main.yml b/test/integration/targets/vmware_guest_custom_attributes/tasks/main.yml deleted file mode 100644 index 64b9f8963c..0000000000 --- a/test/integration/targets/vmware_guest_custom_attributes/tasks/main.yml +++ /dev/null @@ -1,110 +0,0 @@ -# Test code for the vmware_guest_custom_attributes module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# TODO: Current pinned version of vcsim does not support custom fields -# commenting testcase below -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_virtualmachines: true -- name: Add custom attribute to the given virtual machine - vmware_guest_custom_attributes: - validate_certs: False - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: "{{ dc1 }}" - name: "{{ virtual_machines[0].name }}" - folder: "{{ virtual_machines[0].folder }}" - state: present - attributes: - - name: 'sample_1' - value: 'sample_1_value' - - name: 'sample_2' - value: 'sample_2_value' - - name: 'sample_3' - value: 'sample_3_value' - register: guest_info_0001 - -- debug: var=guest_info_0001 - -- assert: - that: - - guest_info_0001 is changed - -- name: Add custom attribute to the given virtual machine again - vmware_guest_custom_attributes: - validate_certs: False - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: "{{ dc1 }}" - name: "{{ virtual_machines[0].name }}" - folder: "{{ virtual_machines[0].folder }}" - state: present - attributes: - - name: 'sample_1' - value: 'sample_1_value' - - name: 'sample_2' - value: 'sample_2_value' - - name: 'sample_3' - value: 'sample_3_value' - register: guest_info_0002 - -- debug: var=guest_info_0002 - -- assert: - that: - - not (guest_info_0002 is changed) - -- name: Remove custom attribute to the given virtual machine - vmware_guest_custom_attributes: - validate_certs: False - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: "{{ dc1 }}" - name: "{{ virtual_machines[0].name }}" - folder: "{{ virtual_machines[0].folder }}" - state: absent - attributes: - - name: 'sample_1' - - name: 'sample_2' - - name: 'sample_3' - register: guest_info_0004 - -- debug: msg="{{ guest_info_0004 }}" - -- assert: - that: - - "guest_info_0004.changed" - -# TODO: vcsim returns duplicate values so removing custom attributes -# results in change. vCenter show correct behavior. Commenting this -# till this is supported by vcsim. -- when: vcsim is not defined - block: - - name: Remove custom attribute to the given virtual machine again - vmware_guest_custom_attributes: - validate_certs: False - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: "{{ dc1 }}" - name: "{{ virtual_machines[0].name }}" - folder: "{{ virtual_machines[0].folder }}" - state: absent - attributes: - - name: 'sample_1' - - name: 'sample_2' - - name: 'sample_3' - register: guest_info_0005 - - - debug: var=guest_info_0005 - - - assert: - that: - - not (guest_info_0005 is changed) diff --git a/test/integration/targets/vmware_guest_customization_facts/aliases b/test/integration/targets/vmware_guest_customization_facts/aliases deleted file mode 100644 index 62871ab8f0..0000000000 --- a/test/integration/targets/vmware_guest_customization_facts/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_guest_customization_facts/tasks/main.yml b/test/integration/targets/vmware_guest_customization_facts/tasks/main.yml deleted file mode 100644 index e515707fb6..0000000000 --- a/test/integration/targets/vmware_guest_customization_facts/tasks/main.yml +++ /dev/null @@ -1,40 +0,0 @@ -# Test code for the vmware_guest_customization_facts module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# TODO: vcsim does not support customizationspecmanager related functionalities - -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_virtualmachines: true - - - &vm_guest_facts - name: Gather facts about given customization spec - vmware_guest_customization_facts: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - register: vm_custom_spec_facts - - - debug: - var: vm_custom_spec_facts - - - assert: - that: - - "not vm_custom_spec_facts.changed" - - - <<: *vm_guest_facts - name: Gather facts about given customization spec in check module - - - debug: - var: vm_custom_spec_facts - - - assert: - that: - - "not vm_custom_spec_facts.changed" diff --git a/test/integration/targets/vmware_guest_customization_info/aliases b/test/integration/targets/vmware_guest_customization_info/aliases deleted file mode 100644 index 62871ab8f0..0000000000 --- a/test/integration/targets/vmware_guest_customization_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_guest_customization_info/tasks/main.yml b/test/integration/targets/vmware_guest_customization_info/tasks/main.yml deleted file mode 100644 index a371d8a3d3..0000000000 --- a/test/integration/targets/vmware_guest_customization_info/tasks/main.yml +++ /dev/null @@ -1,40 +0,0 @@ -# Test code for the vmware_guest_customization_info module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# TODO: vcsim does not support customizationspecmanager related functionalities - -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_virtualmachines: true - - - &vm_guest_info - name: Gather info about given customization spec - vmware_guest_customization_info: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - register: vm_custom_spec_info - - - debug: - var: vm_custom_spec_info - - - assert: - that: - - "not vm_custom_spec_info.changed" - - - <<: *vm_guest_info - name: Gather info about given customization spec in check module - - - debug: - var: vm_custom_spec_info - - - assert: - that: - - "not vm_custom_spec_info.changed" diff --git a/test/integration/targets/vmware_guest_disk/aliases b/test/integration/targets/vmware_guest_disk/aliases deleted file mode 100644 index 62871ab8f0..0000000000 --- a/test/integration/targets/vmware_guest_disk/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_guest_disk/tasks/main.yml b/test/integration/targets/vmware_guest_disk/tasks/main.yml deleted file mode 100644 index 6c2d1c2cbb..0000000000 --- a/test/integration/targets/vmware_guest_disk/tasks/main.yml +++ /dev/null @@ -1,232 +0,0 @@ -# Test code for the vmware_guest_disk_disk module. - -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_virtualmachines: true - -- name: create new disk with invalid disk mode - vmware_guest_disk: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - validate_certs: no - name: "{{ virtual_machines[0].name }}" - disk: - - datastore: "{{ rw_datastore }}" - disk_mode: "invalid_disk_mode" - scsi_controller: 0 - scsi_type: 'paravirtual' - size_gb: 10 - state: present - type: eagerzeroedthick - unit_number: 2 - register: test_create_disk1 - ignore_errors: True - -- debug: - msg: "{{ test_create_disk1 }}" - -- name: assert that changes were not made - assert: - that: - - not(test_create_disk1 is changed) - -- name: create new disk(s) with valid disk mode - vmware_guest_disk: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - validate_certs: no - name: "{{ virtual_machines[0].name }}" - disk: - - datastore: "{{ rw_datastore }}" - disk_mode: "independent_persistent" - scsi_controller: 0 - scsi_type: 'paravirtual' - size_gb: 1 - state: present - type: eagerzeroedthick - unit_number: 2 - - datastore: "{{ rw_datastore }}" - disk_mode: "independent_nonpersistent" - scsi_controller: 0 - scsi_type: 'paravirtual' - size_gb: 1 - state: present - type: eagerzeroedthick - unit_number: 3 - - datastore: "{{ rw_datastore }}" - disk_mode: "persistent" - scsi_controller: 0 - scsi_type: 'paravirtual' - size_gb: 1 - state: present - type: eagerzeroedthick - unit_number: 4 - register: test_create_disk2 - -- debug: - msg: "{{ test_create_disk2 }}" - -- name: assert that changes were made - assert: - that: - - test_create_disk2 is changed - -- name: create new disk with custom shares - vmware_guest_disk: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - validate_certs: no - name: "{{ virtual_machines[0].name }}" - disk: - - size_gb: 1 - type: eagerzeroedthick - datastore: "{{ rw_datastore }}" - disk_mode: "independent_nonpersistent" - scsi_controller: 1 - state: present - unit_number: 4 - shares: - level: custom - level_value: 1300 - register: test_custom_shares - -- debug: - msg: "{{ test_custom_shares }}" - -- name: assert that changes were made - assert: - that: - - test_custom_shares is changed - -- name: create new disk with custom IO limits and shares in IO Limits - vmware_guest_disk: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - validate_certs: no - name: "{{ virtual_machines[0].name }}" - disk: - - size_gb: 1 - type: eagerzeroedthick - datastore: "{{ rw_datastore }}" - disk_mode: "independent_nonpersistent" - scsi_controller: 2 - state: present - unit_number: 4 - iolimit: - limit: 1506 - shares: - level: custom - level_value: 1305 - register: test_custom_IoLimit_shares - -- debug: - msg: "{{ test_custom_IoLimit_shares }}" - -- name: assert that changes were made - assert: - that: - - test_custom_IoLimit_shares is changed - -- name: Update disk for custom IO limits in IO Limits - vmware_guest_disk: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - validate_certs: no - name: "{{ virtual_machines[0].name }}" - disk: - - size_gb: 2 - type: eagerzeroedthick - datastore: "{{ rw_datastore }}" - disk_mode: "independent_nonpersistent" - scsi_controller: 2 - state: present - unit_number: 4 - iolimit: - limit: 1500 - shares: - level: custom - level_value: 1305 - register: test_custom_IoLimit - -- debug: - msg: "{{ test_custom_IoLimit }}" - -- name: assert that changes were made - assert: - that: - - test_custom_IoLimit is changed - -- name: Update disk for shares of IO limits - vmware_guest_disk: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - validate_certs: no - name: "{{ virtual_machines[0].name }}" - disk: - - size_gb: 3 - type: eagerzeroedthick - datastore: "{{ rw_datastore }}" - disk_mode: "independent_nonpersistent" - scsi_controller: 2 - state: present - unit_number: 4 - iolimit: - limit: 1500 - shares: - level: low - level_value: 650 - register: test_shares_IoLimit - -- debug: - msg: "{{ test_shares_IoLimit }}" - -- name: assert that changes were made - assert: - that: - - test_shares_IoLimit is changed - -- name: Update disk for shares and IoLimits of IO limits - vmware_guest_disk: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - validate_certs: no - name: "{{ virtual_machines[0].name }}" - disk: - - size_gb: 4 - type: eagerzeroedthick - datastore: "{{ rw_datastore }}" - disk_mode: "independent_nonpersistent" - scsi_controller: 2 - state: present - unit_number: 4 - iolimit: - limit: 1507 - shares: - level: high - level_value: 1200 - register: test_shares_IoLimits - -- debug: - msg: "{{ test_shares_IoLimits }}" - -- name: assert that changes were made - assert: - that: - - test_shares_IoLimits is changed diff --git a/test/integration/targets/vmware_guest_disk_facts/aliases b/test/integration/targets/vmware_guest_disk_facts/aliases deleted file mode 100644 index 62871ab8f0..0000000000 --- a/test/integration/targets/vmware_guest_disk_facts/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_guest_disk_facts/tasks/main.yml b/test/integration/targets/vmware_guest_disk_facts/tasks/main.yml deleted file mode 100644 index eb5367c677..0000000000 --- a/test/integration/targets/vmware_guest_disk_facts/tasks/main.yml +++ /dev/null @@ -1,52 +0,0 @@ -# Test code for the vmware_guest_disk_facts module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_virtualmachines: true - -- name: set state to poweron the first VM - vmware_guest_powerstate: - validate_certs: no - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "{{ virtual_machines[0].name }}" - folder: '{{ f0 }}' - state: powered-on - -- name: Gather facts about virtual machine disks - vmware_guest_disk_facts: &get_facts - validate_certs: no - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - name: "{{ virtual_machines[0].name }}" - datacenter: '{{ dc1 }}' - register: disk_facts - -- debug: - msg: '{{ disk_facts }}' - -- name: assert that no changes were made - assert: - that: - - "not disk_facts.changed" - -- name: Gather facts about virtual machine disks in check mode - vmware_guest_disk_facts: - <<: *get_facts - register: disk_facts - check_mode: yes - -- debug: - msg: '{{ disk_facts }}' - -- name: assert that no changes were made - assert: - that: - - "not disk_facts.changed" diff --git a/test/integration/targets/vmware_guest_disk_info/aliases b/test/integration/targets/vmware_guest_disk_info/aliases deleted file mode 100644 index 62871ab8f0..0000000000 --- a/test/integration/targets/vmware_guest_disk_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_guest_disk_info/tasks/main.yml b/test/integration/targets/vmware_guest_disk_info/tasks/main.yml deleted file mode 100644 index 3c6b6c5336..0000000000 --- a/test/integration/targets/vmware_guest_disk_info/tasks/main.yml +++ /dev/null @@ -1,52 +0,0 @@ -# Test code for the vmware_guest_disk_info module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_virtualmachines: true - -- name: set state to poweron the first VM - vmware_guest_powerstate: - validate_certs: no - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "{{ virtual_machines[0].name }}" - folder: '{{ f0 }}' - state: powered-on - -- name: Gather info about virtual machine disks - vmware_guest_disk_info: &get_info - validate_certs: no - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - name: "{{ virtual_machines[0].name }}" - datacenter: '{{ dc1 }}' - register: disk_info - -- debug: - msg: '{{ disk_info }}' - -- name: assert that no changes were made - assert: - that: - - "not disk_info.changed" - -- name: Gather info about virtual machine disks in check mode - vmware_guest_disk_info: - <<: *get_info - register: disk_info - check_mode: yes - -- debug: - msg: '{{ disk_info }}' - -- name: assert that no changes were made - assert: - that: - - "not disk_info.changed" diff --git a/test/integration/targets/vmware_guest_facts/aliases b/test/integration/targets/vmware_guest_facts/aliases deleted file mode 100644 index dea29ccd8b..0000000000 --- a/test/integration/targets/vmware_guest_facts/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_guest_facts/tasks/main.yml b/test/integration/targets/vmware_guest_facts/tasks/main.yml deleted file mode 100644 index 187e7c7f48..0000000000 --- a/test/integration/targets/vmware_guest_facts/tasks/main.yml +++ /dev/null @@ -1,226 +0,0 @@ -# Test code for the vmware_guest_facts module. -# Copyright: (c) 2017, Abhijeet Kasurde <akasurde@redhat.com> -# Copyright: (c) 2018, James E. King III (@jeking3) <jking@apache.org> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_virtualmachines: true - -# Testcase 0001: Get details about virtual machines -- name: get list of facts about virtual machines - vmware_guest_facts: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - name: "{{ virtual_machines[0].name }}" - folder: "{{ virtual_machines[0].folder }}" - register: guest_facts_0001 - -- debug: - var: guest_facts_0001 - -- assert: - that: - - "guest_facts_0001['instance']['hw_name'] == virtual_machines[0].name" - - "guest_facts_0001['instance']['hw_product_uuid'] is defined" - - "guest_facts_0001['instance']['hw_cores_per_socket'] is defined" - - "guest_facts_0001['instance']['hw_datastores'] is defined" - - "guest_facts_0001['instance']['hw_esxi_host'] is defined" - - "guest_facts_0001['instance']['hw_files'] is defined" - - "guest_facts_0001['instance']['hw_guest_ha_state'] is defined" - - "guest_facts_0001['instance']['hw_is_template'] is defined" - - "guest_facts_0001['instance']['hw_folder'] is defined" - - "guest_facts_0001['instance']['guest_question'] is defined" - - "guest_facts_0001['instance']['guest_consolidation_needed'] is defined" - - "guest_facts_0001['instance']['moid'] is defined" - - "guest_facts_0001['instance']['vimref'] is defined" - - "'portgroup_portkey' in guest_facts_0001['instance']['hw_eth0']" - - "'portgroup_key' in guest_facts_0001['instance']['hw_eth0']" - - "guest_facts_0001['instance']['instance_uuid'] is defined" - -- set_fact: vm1_uuid="{{ guest_facts_0001['instance']['hw_product_uuid'] }}" - -- set_fact: vm1_instance_uuid="{{ guest_facts_0001['instance']['instance_uuid'] }}" - -- set_fact: vm1_moid="{{ guest_facts_0001['instance']['moid'] }}" - -- debug: - var: vm1_uuid - -# Testcase 0002: Get details about virtual machines using UUID -- name: get list of facts about virtual machines using UUID - vmware_guest_facts: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - uuid: "{{ vm1_uuid }}" - register: guest_facts_0002 - -- debug: - var: guest_facts_0002 - -- name: Get specific details about virtual machines using the vsphere output schema - vmware_guest_facts: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - uuid: "{{ vm1_uuid }}" - schema: vsphere - properties: - - config.hardware.memoryMB - - guest - - name - - summary.runtime.connectionState - register: guest_facts_0002b - -- debug: - var: guest_facts_0002b - -- assert: - that: - - "guest_facts_0002['instance']['hw_name'] == virtual_machines[0].name" - - "guest_facts_0002['instance']['hw_product_uuid'] is defined" - - "guest_facts_0002['instance']['hw_product_uuid'] == vm1_uuid" - - "guest_facts_0002['instance']['hw_cores_per_socket'] is defined" - - "guest_facts_0002b['instance']['config']['hardware']['memoryMB'] is defined" - - "guest_facts_0002b['instance']['config']['hardware']['numCoresPerSocket'] is not defined" - - "guest_facts_0002b['instance']['guest']['toolsVersion'] is defined" - - "guest_facts_0001['instance']['moid'] is defined" - - "guest_facts_0001['instance']['vimref'] is defined" - - "guest_facts_0002b['instance']['overallStatus'] is not defined" - -# Testcase 0003: Get details about virtual machines without snapshots using UUID -- name: get empty list of snapshots from virtual machine using UUID - vmware_guest_facts: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - uuid: "{{ vm1_uuid }}" - register: guest_facts_0003 - -- debug: - var: guest_facts_0003 - -- assert: - that: - - "guest_facts_0003['instance']['snapshots']|length == 0" - - "guest_facts_0003['instance']['current_snapshot'] is none" - -# Testcase 0004: Get details about virtual machines with two snapshots using UUID -- name: Create first snapshot - vmware_guest_snapshot: &vm_snap - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - name: "{{ virtual_machines[0].name }}" - folder: "{{ virtual_machines[0].folder }}" - state: present - snapshot_name: snap1 - -- name: Create second snapshot - vmware_guest_snapshot: - <<: *vm_snap - snapshot_name: snap2 - -- name: get list of snapshots from virtual machine using UUID - vmware_guest_facts: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - uuid: "{{ vm1_uuid }}" - register: guest_facts_0004 - -- debug: - var: guest_facts_0004 - -- assert: - that: - - "guest_facts_0004['instance']['snapshots'] is defined" - - "guest_facts_0004['instance']['snapshots'][0]['name'] == 'snap1'" - - "guest_facts_0004['instance']['snapshots'][1]['name'] == 'snap2'" - - "guest_facts_0004['instance']['current_snapshot']['name'] == 'snap2'" - - "guest_facts_0004['instance']['hw_folder'] is defined" - -# Testcase 0005: Get details about virtual machines using UUID -- name: get list of facts about virtual machines using instance UUID - vmware_guest_facts: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - uuid: "{{ vm1_instance_uuid }}" - use_instance_uuid: True - register: guest_facts_0005 - -- debug: - msg: "{{ guest_facts_0005 }}" - -- assert: - that: - - "guest_facts_0005['instance']['hw_name'] == virtual_machines[0].name" - - "guest_facts_0005['instance']['hw_product_uuid'] is defined" - - "guest_facts_0005['instance']['hw_product_uuid'] == vm1_uuid" - - "guest_facts_0005['instance']['hw_cores_per_socket'] is defined" - - "guest_facts_0005['instance']['hw_datastores'] is defined" - - "guest_facts_0005['instance']['hw_esxi_host'] is defined" - - "guest_facts_0005['instance']['hw_files'] is defined" - - "guest_facts_0005['instance']['hw_guest_ha_state'] is defined" - - "guest_facts_0005['instance']['hw_is_template'] is defined" - - "guest_facts_0005['instance']['hw_folder'] is defined" - - "guest_facts_0005['instance']['guest_question'] is defined" - - "guest_facts_0005['instance']['guest_consolidation_needed'] is defined" - - "guest_facts_0005['instance']['instance_uuid'] is defined" - - "guest_facts_0005['instance']['instance_uuid'] == vm1_instance_uuid" - - "guest_facts_0005['instance']['moid'] is defined" - - "guest_facts_0005['instance']['vimref'] is defined" - -# Testcase 0006: Get details about virtual machines using MoID -- name: get list of facts about virtual machines using instance MoID - vmware_guest_facts: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - moid: "{{ vm1_moid }}" - use_instance_uuid: True - register: guest_facts_0006 - -- debug: - msg: "{{ guest_facts_0006 }}" - -- assert: - that: - - "guest_facts_0006['instance']['hw_name'] == virtual_machines[0].name" - - "guest_facts_0006['instance']['hw_product_uuid'] is defined" - - "guest_facts_0006['instance']['hw_product_uuid'] == vm1_uuid" - - "guest_facts_0006['instance']['hw_cores_per_socket'] is defined" - - "guest_facts_0006['instance']['hw_datastores'] is defined" - - "guest_facts_0006['instance']['hw_esxi_host'] is defined" - - "guest_facts_0006['instance']['hw_files'] is defined" - - "guest_facts_0006['instance']['hw_guest_ha_state'] is defined" - - "guest_facts_0006['instance']['hw_is_template'] is defined" - - "guest_facts_0006['instance']['hw_folder'] is defined" - - "guest_facts_0006['instance']['guest_question'] is defined" - - "guest_facts_0006['instance']['guest_consolidation_needed'] is defined" - - "guest_facts_0006['instance']['instance_uuid'] is defined" - - "guest_facts_0006['instance']['instance_uuid'] == vm1_instance_uuid" - - "guest_facts_0006['instance']['moid'] is defined" - - "guest_facts_0006['instance']['vimref'] is defined" diff --git a/test/integration/targets/vmware_guest_find/aliases b/test/integration/targets/vmware_guest_find/aliases deleted file mode 100644 index dea29ccd8b..0000000000 --- a/test/integration/targets/vmware_guest_find/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_guest_find/tasks/main.yml b/test/integration/targets/vmware_guest_find/tasks/main.yml deleted file mode 100644 index f8b7832249..0000000000 --- a/test/integration/targets/vmware_guest_find/tasks/main.yml +++ /dev/null @@ -1,60 +0,0 @@ -# Test code for the vmware_guest_find module. -# Copyright: (c) 2017, James Tanner <tanner.jc@gmail.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_virtualmachines: true -- name: find folders for each vm - vmware_guest_find: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "{{ item.name }}" - with_items: "{{ virtual_machines }}" - register: folders - -- debug: var=item - with_items: "{{ folders.results }}" - -# We only care that each VM was found, not that the folder path -# is completely accurate. Eventually the test should be extended -# to validate the full path for each VM. -- assert: - that: - - "{{ 'folders' in item }}" - - "{{ item['folders']|length == 1 }}" - with_items: "{{ folders.results }}" - -- name: get fact of the first VM - vmware_guest_info: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - name: "{{ virtual_machines[0].name }}" - folder: "{{ virtual_machines[0].folder }}" - register: guest_info_0001 - -- debug: var=guest_info_0001 - -- name: find folders for each vm using UUID - vmware_guest_find: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - uuid: "{{ guest_info_0001['instance']['hw_product_uuid'] }}" - register: folder_uuid - -- debug: var=folder_uuid - -- assert: - that: - - "{{ 'folders' in folder_uuid }}" - - "{{ folder_uuid['folders']|length == 1 }}" diff --git a/test/integration/targets/vmware_guest_info/aliases b/test/integration/targets/vmware_guest_info/aliases deleted file mode 100644 index dea29ccd8b..0000000000 --- a/test/integration/targets/vmware_guest_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_guest_info/tasks/main.yml b/test/integration/targets/vmware_guest_info/tasks/main.yml deleted file mode 100644 index cebfed0ad3..0000000000 --- a/test/integration/targets/vmware_guest_info/tasks/main.yml +++ /dev/null @@ -1,226 +0,0 @@ -# Test code for the vmware_guest_info module. -# Copyright: (c) 2017, Abhijeet Kasurde <akasurde@redhat.com> -# Copyright: (c) 2018, James E. King III (@jeking3) <jking@apache.org> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_virtualmachines: true - -# Testcase 0001: Get details about virtual machines -- name: get list of info about virtual machines - vmware_guest_info: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - name: "{{ virtual_machines[0].name }}" - folder: "{{ virtual_machines[0].folder }}" - register: guest_info_0001 - -- debug: - var: guest_info_0001 - -- assert: - that: - - "guest_info_0001['instance']['hw_name'] == virtual_machines[0].name" - - "guest_info_0001['instance']['hw_product_uuid'] is defined" - - "guest_info_0001['instance']['hw_cores_per_socket'] is defined" - - "guest_info_0001['instance']['hw_datastores'] is defined" - - "guest_info_0001['instance']['hw_esxi_host'] is defined" - - "guest_info_0001['instance']['hw_files'] is defined" - - "guest_info_0001['instance']['hw_guest_ha_state'] is defined" - - "guest_info_0001['instance']['hw_is_template'] is defined" - - "guest_info_0001['instance']['hw_folder'] is defined" - - "guest_info_0001['instance']['guest_question'] is defined" - - "guest_info_0001['instance']['guest_consolidation_needed'] is defined" - - "guest_info_0001['instance']['moid'] is defined" - - "guest_info_0001['instance']['vimref'] is defined" - - "'portgroup_portkey' in guest_info_0001['instance']['hw_eth0']" - - "'portgroup_key' in guest_info_0001['instance']['hw_eth0']" - - "guest_info_0001['instance']['instance_uuid'] is defined" - -- set_fact: vm1_uuid="{{ guest_info_0001['instance']['hw_product_uuid'] }}" - -- set_fact: vm1_instance_uuid="{{ guest_info_0001['instance']['instance_uuid'] }}" - -- set_fact: vm1_moid="{{ guest_info_0001['instance']['moid'] }}" - -- debug: - var: vm1_uuid - -# Testcase 0002: Get details about virtual machines using UUID -- name: get list of info about virtual machines using UUID - vmware_guest_info: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - uuid: "{{ vm1_uuid }}" - register: guest_info_0002 - -- debug: - var: guest_info_0002 - -- name: Get specific details about virtual machines using the vsphere output schema - vmware_guest_info: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - uuid: "{{ vm1_uuid }}" - schema: vsphere - properties: - - config.hardware.memoryMB - - guest - - name - - summary.runtime.connectionState - register: guest_info_0002b - -- debug: - var: guest_info_0002b - -- assert: - that: - - "guest_info_0002['instance']['hw_name'] == virtual_machines[0].name" - - "guest_info_0002['instance']['hw_product_uuid'] is defined" - - "guest_info_0002['instance']['hw_product_uuid'] == vm1_uuid" - - "guest_info_0002['instance']['hw_cores_per_socket'] is defined" - - "guest_info_0002b['instance']['config']['hardware']['memoryMB'] is defined" - - "guest_info_0002b['instance']['config']['hardware']['numCoresPerSocket'] is not defined" - - "guest_info_0002b['instance']['guest']['toolsVersion'] is defined" - - "guest_info_0001['instance']['moid'] is defined" - - "guest_info_0001['instance']['vimref'] is defined" - - "guest_info_0002b['instance']['overallStatus'] is not defined" - -# Testcase 0003: Get details about virtual machines without snapshots using UUID -- name: get empty list of snapshots from virtual machine using UUID - vmware_guest_info: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - uuid: "{{ vm1_uuid }}" - register: guest_info_0003 - -- debug: - var: guest_info_0003 - -- assert: - that: - - "guest_info_0003['instance']['snapshots']|length == 0" - - "guest_info_0003['instance']['current_snapshot'] is none" - -# Testcase 0004: Get details about virtual machines with two snapshots using UUID -- name: Create first snapshot - vmware_guest_snapshot: &vm_snap - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - name: "{{ virtual_machines[0].name }}" - folder: "{{ virtual_machines[0].folder }}" - state: present - snapshot_name: snap1 - -- name: Create second snapshot - vmware_guest_snapshot: - <<: *vm_snap - snapshot_name: snap2 - -- name: get list of snapshots from virtual machine using UUID - vmware_guest_info: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - uuid: "{{ vm1_uuid }}" - register: guest_info_0004 - -- debug: - var: guest_info_0004 - -- assert: - that: - - "guest_info_0004['instance']['snapshots'] is defined" - - "guest_info_0004['instance']['snapshots'][0]['name'] == 'snap1'" - - "guest_info_0004['instance']['snapshots'][1]['name'] == 'snap2'" - - "guest_info_0004['instance']['current_snapshot']['name'] == 'snap2'" - - "guest_info_0004['instance']['hw_folder'] is defined" - -# Testcase 0005: Get details about virtual machines using UUID -- name: get list of info about virtual machines using instance UUID - vmware_guest_info: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - uuid: "{{ vm1_instance_uuid }}" - use_instance_uuid: True - register: guest_info_0005 - -- debug: - msg: "{{ guest_info_0005 }}" - -- assert: - that: - - "guest_info_0005['instance']['hw_name'] == virtual_machines[0].name" - - "guest_info_0005['instance']['hw_product_uuid'] is defined" - - "guest_info_0005['instance']['hw_product_uuid'] == vm1_uuid" - - "guest_info_0005['instance']['hw_cores_per_socket'] is defined" - - "guest_info_0005['instance']['hw_datastores'] is defined" - - "guest_info_0005['instance']['hw_esxi_host'] is defined" - - "guest_info_0005['instance']['hw_files'] is defined" - - "guest_info_0005['instance']['hw_guest_ha_state'] is defined" - - "guest_info_0005['instance']['hw_is_template'] is defined" - - "guest_info_0005['instance']['hw_folder'] is defined" - - "guest_info_0005['instance']['guest_question'] is defined" - - "guest_info_0005['instance']['guest_consolidation_needed'] is defined" - - "guest_info_0005['instance']['instance_uuid'] is defined" - - "guest_info_0005['instance']['instance_uuid'] == vm1_instance_uuid" - - "guest_info_0005['instance']['moid'] is defined" - - "guest_info_0005['instance']['vimref'] is defined" - -# Testcase 0006: Get details about virtual machines using MoID -- name: get list of information about virtual machines using instance MoID - vmware_guest_info: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - moid: "{{ vm1_moid }}" - use_instance_uuid: True - register: guest_info_0006 - -- debug: - msg: "{{ guest_info_0006 }}" - -- assert: - that: - - "guest_info_0006['instance']['hw_name'] == virtual_machines[0].name" - - "guest_info_0006['instance']['hw_product_uuid'] is defined" - - "guest_info_0006['instance']['hw_product_uuid'] == vm1_uuid" - - "guest_info_0006['instance']['hw_cores_per_socket'] is defined" - - "guest_info_0006['instance']['hw_datastores'] is defined" - - "guest_info_0006['instance']['hw_esxi_host'] is defined" - - "guest_info_0006['instance']['hw_files'] is defined" - - "guest_info_0006['instance']['hw_guest_ha_state'] is defined" - - "guest_info_0006['instance']['hw_is_template'] is defined" - - "guest_info_0006['instance']['hw_folder'] is defined" - - "guest_info_0006['instance']['guest_question'] is defined" - - "guest_info_0006['instance']['guest_consolidation_needed'] is defined" - - "guest_info_0006['instance']['instance_uuid'] is defined" - - "guest_info_0006['instance']['instance_uuid'] == vm1_instance_uuid" - - "guest_info_0006['instance']['moid'] is defined" - - "guest_info_0006['instance']['vimref'] is defined" diff --git a/test/integration/targets/vmware_guest_move/aliases b/test/integration/targets/vmware_guest_move/aliases deleted file mode 100644 index dea29ccd8b..0000000000 --- a/test/integration/targets/vmware_guest_move/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_guest_move/tasks/main.yml b/test/integration/targets/vmware_guest_move/tasks/main.yml deleted file mode 100644 index e540bf884a..0000000000 --- a/test/integration/targets/vmware_guest_move/tasks/main.yml +++ /dev/null @@ -1,70 +0,0 @@ -# Test code for the vmware_guest_move module -# Copyright: (c) 2018, Jose Angel Munoz <josea.munoz@gmail.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_virtualmachines: true - -- name: Create a VM folder on given Datacenter - vcenter_folder: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: '{{ dc1 }}' - folder_name: 'f1' - folder_type: vm - state: present - validate_certs: no - register: dest_folder - -# Testcase 0001: Move vm and get changed status -- name: Move VM (Changed) - vmware_guest_move: - validate_certs: false - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: '{{ dc1 }}' - name: '{{ virtual_machines[0].name }}' - # Depends-On: https://github.com/ansible/ansible/pull/55237 - dest_folder: '{{ dest_folder.result.path }}' - register: vm_info_0001 - - -# Testcase 0002: Move vm and get OK status (Already Moved) -- &vm_move - name: Move VM (OK) - vmware_guest_move: - validate_certs: false - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: '{{ dc1 }}' - name: '{{ virtual_machines[0].name }}' - dest_folder: '{{ dest_folder.result.path }}' - register: vm_info_0002 - -- debug: - msg: "{{ vm_info_0001 }}" - -- debug: - msg: "{{ vm_info_0002 }}" - -- name: Make sure changes are done - assert: - that: - - vm_info_0001.changed - - not vm_info_0002.changed - -- <<: *vm_move - name: Move VM in check mode - check_mode: yes - register: vm_move_0003 - -- name: Make sure changes are not made in check mode - assert: - that: - - vm_move_0003.changed diff --git a/test/integration/targets/vmware_guest_network/aliases b/test/integration/targets/vmware_guest_network/aliases deleted file mode 100644 index 832eed362a..0000000000 --- a/test/integration/targets/vmware_guest_network/aliases +++ /dev/null @@ -1,6 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi -# until we figure out why vmware_guest_tools_wait fails in the CI -disabled diff --git a/test/integration/targets/vmware_guest_network/tasks/main.yml b/test/integration/targets/vmware_guest_network/tasks/main.yml deleted file mode 100644 index 7266f4c574..0000000000 --- a/test/integration/targets/vmware_guest_network/tasks/main.yml +++ /dev/null @@ -1,353 +0,0 @@ -# Test code for the vmware_guest_network module -# Copyright: (c) 2019, Diane Wang (Tomorrow9) <dianew@vmware.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_dvs_portgroup: true - setup_dvswitch: true - - - name: Create VMs - vmware_guest: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - validate_certs: no - folder: '/DC0/vm/F0' - name: test_vm1 - state: poweredon - guest_id: centos7_64Guest - disk: - - size_gb: 1 - type: thin - datastore: '{{ rw_datastore }}' - hardware: - version: latest - memory_mb: 1024 - num_cpus: 1 - scsi: paravirtual - cdrom: - type: iso - iso_path: "[{{ ro_datastore }}] fedora.iso" - networks: - - name: VM Network - - - vmware_guest_tools_wait: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - timeout: 600 - validate_certs: no - name: test_vm1 - - - name: gather network adapters' facts of the virtual machine - vmware_guest_network: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - gather_network_info: true - register: netadapter_info - - - debug: var=netadapter_info - - - name: get number of existing netowrk adapters - set_fact: - netadapter_num: "{{ netadapter_info.network_data | length }}" - - - name: add new network adapters to virtual machine - vmware_guest_network: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - networks: - - name: "VM Network" - state: new - device_type: e1000e - manual_mac: "aa:50:56:58:59:60" - connected: True - - name: "VM Network" - state: new - connected: True - device_type: vmxnet3 - manual_mac: "aa:50:56:58:59:61" - register: add_netadapter - - - debug: var=add_netadapter - - - name: assert the new netowrk adapters were added to VM - assert: - that: - - add_netadapter is changed - - "{{ add_netadapter.network_data | length | int }} == {{ netadapter_num | int + 2 }}" - - - name: delete one specified network adapter - vmware_guest_network: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - networks: - - state: absent - mac: "aa:50:56:58:59:60" - register: del_netadapter - - - debug: var=del_netadapter - - - name: assert the network adapter was removed - assert: - that: - - del_netadapter is changed - - "{{ del_netadapter.network_data | length | int }} == {{ netadapter_num | int + 1 }}" - - - name: get instance uuid of virtual machines - vmware_guest_info: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - datacenter: '{{ dc1 }}' - register: guest_info - - - set_fact: vm1_instance_uuid="{{ guest_info['instance']['instance_uuid'] }}" - - - name: add new network adapters to virtual machine with instance uuid - vmware_guest_network: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - uuid: '{{ vm1_instance_uuid }}' - use_instance_uuid: True - networks: - - name: "VM Network" - state: new - connected: True - device_type: e1000e - manual_mac: "bb:50:56:58:59:60" - register: add_netadapter_instanceuuid - - - debug: var=add_netadapter_instanceuuid - - - name: assert the new netowrk adapters were added to VM - assert: - that: - - add_netadapter_instanceuuid is changed - - "{{ add_netadapter_instanceuuid.network_data | length | int }} == {{ netadapter_num | int + 2 }}" - - - name: delete again one specified network adapter - vmware_guest_network: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - networks: - - state: absent - mac: "bb:50:56:58:59:60" - register: del_again_netadapter - - - debug: var=del_again_netadapter - - - name: assert the network adapter was removed - assert: - that: - - del_again_netadapter is changed - - "{{ del_again_netadapter.network_data | length | int }} == {{ netadapter_num | int + 1 }}" - - - name: disable DirectPath I/O on a Vmxnet3 adapter - vmware_guest_network: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "test_vm1" - networks: - - state: present - mac: "aa:50:56:58:59:61" - directpath_io: False - register: disable_directpath_io - - - debug: var=disable_directpath_io - - - name: enable DirectPath I/O on a Vmxnet3 adapter - vmware_guest_network: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "test_vm1" - networks: - - state: present - mac: "aa:50:56:58:59:61" - directpath_io: True - register: enable_directpath_io - - - debug: var=enable_directpath_io - - - name: disconnect one specified network adapter - vmware_guest_network: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - networks: - - state: present - mac: "aa:50:56:58:59:61" - connected: false - register: disc_netadapter - - - debug: var=disc_netadapter - - - name: assert the network adapter was disconnected - assert: - that: - - disc_netadapter is changed - - "{{ disc_netadapter.network_data[netadapter_num]['connected'] }} == false" - - - name: Check if network does not exists - vmware_guest_network: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - networks: - - name: non-existing-nw - manual_mac: "aa:50:56:11:22:33" - state: new - register: no_nw_details - ignore_errors: yes - - - debug: var=no_nw_details - - - name: Check if network does not exists - assert: - that: - - not (no_nw_details is changed) - - no_nw_details.failed - - - name: Change portgroup to dvPortgroup - vmware_guest_network: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - networks: - - name: "{{ dvpg1 }}" - label: "Network adapter 1" - connected: false - start_connected: true - state: present - register: change_netaddr_dvp - - - debug: var=change_netaddr_dvp - - - name: Check changed to dvPortgroup from PortGroup - assert: - that: - - change_netaddr_dvp.changed is sameas true - - - name: Change portgroup to dvPortgroup - vmware_guest_network: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - networks: - - name: "{{ dvpg1 }}" - label: "Network adapter 1" - connected: false - start_connected: true - state: present - register: change_netaddr_dvp - - - debug: var=change_netaddr_dvp - - - name: Check not changed of dvPortgroup - assert: - that: - - change_netaddr_dvp.changed is sameas false - - - name: Change dvPortgroup to PortGroup - vmware_guest_network: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - networks: - - name: "VM Network" - label: "Network adapter 1" - connected: false - start_connected: true - state: present - register: change_netaddr_pg - - - debug: var=change_netaddr_pg - - - name: Check changed to dvPortgroup from PortGroup - assert: - that: - - change_netaddr_pg.changed is sameas true - - change_netaddr_pg.network_data['0'].name == "VM Network" - - - name: Change dvPortgroup to PortGroup - vmware_guest_network: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - networks: - - name: "VM Network" - label: "Network adapter 1" - connected: false - start_connected: true - state: present - register: change_netaddr_pg - - - debug: var=change_netaddr_pg - - - name: Check not changed of PortGroup - assert: - that: - - change_netaddr_pg.changed is sameas false - - change_netaddr_pg.network_data['0'].name == "VM Network" - - # https://github.com/ansible/ansible/issues/65968 - - name: Create a network with dvPortgroup - vmware_guest_network: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - networks: - - name: "{{ dvpg1 }}" - label: "Network adapter 2" - connected: true - start_connected: true - state: new - register: create_netaddr_pg - - - debug: var=create_netaddr_pg - - - name: Check if network is created with dvpg - assert: - that: - - create_netaddr_pg.changed is sameas true diff --git a/test/integration/targets/vmware_guest_powerstate/aliases b/test/integration/targets/vmware_guest_powerstate/aliases deleted file mode 100644 index dea29ccd8b..0000000000 --- a/test/integration/targets/vmware_guest_powerstate/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_guest_powerstate/tasks/main.yml b/test/integration/targets/vmware_guest_powerstate/tasks/main.yml deleted file mode 100644 index 9460e25731..0000000000 --- a/test/integration/targets/vmware_guest_powerstate/tasks/main.yml +++ /dev/null @@ -1,72 +0,0 @@ -# Test code for the vmware_guest_powerstate module. -# Copyright: (c) 2017, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - -- name: Create a VM with the state poweredoff - vmware_guest: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - validate_certs: no - folder: '{{ f0 }}' - name: test_vm1 - state: poweredoff - guest_id: debian8_64Guest - disk: - - size_gb: 1 - type: thin - datastore: '{{ rw_datastore }}' - hardware: - memory_mb: 128 - num_cpus: 1 - scsi: paravirtual - cdrom: - type: iso - iso_path: "[{{ ro_datastore }}] fedora.iso" - networks: - - name: VM Network - -- name: set state to poweroff the first VM - vmware_guest_powerstate: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - folder: '{{ f0 }}' - state: powered-off - register: poweroff_d1_c1_f0 - -- debug: - var: poweroff_d1_c1_f0 - -- name: make sure change was made - assert: - that: - - not (poweroff_d1_c1_f0 is changed) - -- when: vcsim is not defined - block: - - name: Set a schedule task for first VM - vmware_guest_powerstate: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - folder: '{{ f0 }}' - scheduled_at: "10/10/2030 10:10" - state: powered-on - register: poweron_d1_c1_f0 - - - name: Check that task is schedule - assert: - that: - - poweron_d1_c1_f0 is changed diff --git a/test/integration/targets/vmware_guest_register_operation/aliases b/test/integration/targets/vmware_guest_register_operation/aliases deleted file mode 100644 index dea29ccd8b..0000000000 --- a/test/integration/targets/vmware_guest_register_operation/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_guest_register_operation/tasks/main.yml b/test/integration/targets/vmware_guest_register_operation/tasks/main.yml deleted file mode 100644 index 8e9cafe5ad..0000000000 --- a/test/integration/targets/vmware_guest_register_operation/tasks/main.yml +++ /dev/null @@ -1,261 +0,0 @@ -# Test code for the vmware_guest_register_operation module -# Copyright: (c) 2019, sky-joker <sky.jokerxx@gmail.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_cluster: true - setup_virtualmachines: true - setup_resource_pool: true - -- block: - - name: gather facts of vm - vmware_guest_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: False - datacenter: "{{ dc1 }}" - folder: "{{ f0 }}" - name: "{{ virtual_machines[0].name }}" - register: vm_facts - - - name: get a vm vmx file path - set_fact: vm_vmx_file_path="{{ vm_facts.instance.hw_files[0] }}" - -- name: Powered off the vm - vmware_guest_powerstate: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: False - folder: /vm - name: "{{ virtual_machines[0].name }}" - state: powered-off - -- name: Unregister VM from inventory - vmware_guest_register_operation: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ dc1 }}" - folder: "/vm" - name: "{{ virtual_machines[0].name }}" - state: absent - -- name: Gather all registered virtual machines - vmware_vm_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - register: vms - -- assert: - that: - - >- - vms.virtual_machines - | selectattr('guest_name', 'equalto', virtual_machines[0].name) - | map(attribute='guest_name') - | list - | length == 0 - -- assert: - that: - - item.guest_name != virtual_machines[0].name - loop: "{{ vms.virtual_machines }}" - -- name: Register VM to inventory - vmware_guest_register_operation: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ dc1 }}" - folder: "/vm" - esxi_hostname: "{{ esxi1 }}" - name: "{{ virtual_machines[0].name }}" - path: "{{ vm_vmx_file_path }}" - state: present - -- name: Gather all registered virtual machines - vmware_vm_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - register: vms - -- assert: - that: - - >- - vms.virtual_machines - | selectattr('guest_name', 'equalto', virtual_machines[0].name) - | selectattr('esxi_hostname', 'equalto', esxi1) - | map(attribute='guest_name') - | list - | length == 1 - -- name: Unregister VM from inventory - vmware_guest_register_operation: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ dc1 }}" - folder: "/vm" - name: "{{ virtual_machines[0].name }}" - state: absent - -- name: Gather all registered virtual machines - vmware_vm_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - register: vms - -- assert: - that: - - >- - vms.virtual_machines - | selectattr('guest_name', 'equalto', virtual_machines[0].name) - | map(attribute='guest_name') - | list - | length == 0 - -- name: Register VM in Cluster - vmware_guest_register_operation: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ dc1 }}" - folder: "/vm" - cluster: "{{ ccr1 }}" - name: "{{ virtual_machines[0].name }}" - path: "{{ vm_vmx_file_path }}" - state: present - -- name: Gather all registered virtual machines - vmware_vm_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - register: vms - -- assert: - that: - - >- - vms.virtual_machines - | selectattr('guest_name', 'equalto', virtual_machines[0].name) - | selectattr('cluster', 'equalto', ccr1) - | map(attribute='guest_name') - | list - | length == 1 - -- name: Unregister VM from inventory - vmware_guest_register_operation: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ dc1 }}" - folder: "/vm" - name: "{{ virtual_machines[0].name }}" - state: absent - -- name: Gather all registered virtual machines - vmware_vm_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - register: vms - -- assert: - that: - - >- - vms.virtual_machines - | selectattr('guest_name', 'equalto', virtual_machines[0].name) - | map(attribute='guest_name') - | list - | length == 0 - -- name: Register VM in Resource pool - vmware_guest_register_operation: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ dc1 }}" - folder: "/vm" - resource_pool: DC0_C0_RP1 - name: "{{ virtual_machines[0].name }}" - path: "{{ vm_vmx_file_path }}" - state: present - -- name: Gather all registered virtual machines - vmware_vm_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - register: vms - -- assert: - that: - - >- - vms.virtual_machines - | selectattr('guest_name', 'equalto', virtual_machines[0].name) - | map(attribute='guest_name') - | list - | length == 1 - -- name: Gather facts of vm - vmware_guest_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ dc1 }}" - folder: "/vm" - name: "{{ virtual_machines[0].name }}" - register: vm_facts - -- name: Get a vm uuid - set_fact: vm_uuid="{{ vm_facts.instance.hw_product_uuid }}" - -- name: Unregister VM from inventory with uuid parameter - vmware_guest_register_operation: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ dc1 }}" - folder: "/vm" - name: "{{ virtual_machines[0].name }}" - uuid: "{{ vm_uuid }}" - state: absent - -- name: Gather all registered virtual machines - vmware_vm_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - register: vms - -- assert: - that: - - >- - vms.virtual_machines - | selectattr('guest_name', 'equalto', virtual_machines[0].name) - | map(attribute='guest_name') - | list - | length == 0 diff --git a/test/integration/targets/vmware_guest_screenshot/aliases b/test/integration/targets/vmware_guest_screenshot/aliases deleted file mode 100644 index 62871ab8f0..0000000000 --- a/test/integration/targets/vmware_guest_screenshot/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_guest_screenshot/tasks/main.yml b/test/integration/targets/vmware_guest_screenshot/tasks/main.yml deleted file mode 100644 index 30ccf6bfde..0000000000 --- a/test/integration/targets/vmware_guest_screenshot/tasks/main.yml +++ /dev/null @@ -1,54 +0,0 @@ -# Test code for the vmware_guest_screenshot module -# Copyright: (c) 2019, Diane Wang (Tomorrow9) <dianew@vmware.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_virtualmachines: true - - - name: set VM state to powered on - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - folder: "{{ virtual_machines[0].folder }}" - name: "{{ virtual_machines[0].name }}" - state: poweredon - - - name: take screenshot of virtual machine's console - vmware_guest_screenshot: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "{{ virtual_machines[0].name }}" - register: take_screenshot - - debug: var=take_screenshot - - name: assert the screenshot captured - assert: - that: - - "take_screenshot.changed == true" - - - name: take screenshot of virtual machine's console and download to local - vmware_guest_screenshot: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "{{ virtual_machines[0].name }}" - local_path: "/tmp/screenshot_test.png" - datacenter: "{{ dc1 }}" - folder: "{{ virtual_machines[0].folder }}" - register: take_screenshot - - debug: var=take_screenshot - - name: assert the screenshot captured - assert: - that: - - "take_screenshot.changed == true" diff --git a/test/integration/targets/vmware_guest_sendkey/aliases b/test/integration/targets/vmware_guest_sendkey/aliases deleted file mode 100644 index 62871ab8f0..0000000000 --- a/test/integration/targets/vmware_guest_sendkey/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_guest_sendkey/tasks/main.yml b/test/integration/targets/vmware_guest_sendkey/tasks/main.yml deleted file mode 100644 index b23299223e..0000000000 --- a/test/integration/targets/vmware_guest_sendkey/tasks/main.yml +++ /dev/null @@ -1,55 +0,0 @@ -# Test code for the vmware_guest_sendkey module -# Copyright: (c) 2017, Diane Wang (Tomorrow9) <dianew@vmware.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_virtualmachines: true - - - name: set state to poweron the first VM - vmware_guest_powerstate: - validate_certs: no - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "{{ virtual_machines[0].name }}" - folder: '{{ f0 }}' - state: powered-on - - - name: send keys to virtual machine - vmware_guest_sendkey: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "{{ virtual_machines[0].name }}" - keys_send: - - DOWNARROW - - DOWNARROW - - ENTER - register: send_key - - debug: var=send_key - - name: assert the keys were sent to VM - assert: - that: - - "send_key.changed == true" - - - name: send string to virtual machine - vmware_guest_sendkey: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "{{ virtual_machines[0].name }}" - string_send: "test-user" - register: send_string - - debug: var=send_string - - name: assert the string was sent to VM - assert: - that: - - "send_string.changed == true" diff --git a/test/integration/targets/vmware_guest_serial_port/aliases b/test/integration/targets/vmware_guest_serial_port/aliases deleted file mode 100644 index 62871ab8f0..0000000000 --- a/test/integration/targets/vmware_guest_serial_port/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_guest_serial_port/tasks/main.yml b/test/integration/targets/vmware_guest_serial_port/tasks/main.yml deleted file mode 100644 index 236176b3cb..0000000000 --- a/test/integration/targets/vmware_guest_serial_port/tasks/main.yml +++ /dev/null @@ -1,103 +0,0 @@ -# Test code for the vmware_guest_serial_port Operations. -# Copyright: (c) 2019, Anusha Hegde <anushah@vmware.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - -- name: Create VM - vmware_guest: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: test_vm1 - guest_id: centos64Guest - datacenter: "{{ dc1 }}" - folder: "{{ f0 }}" - hardware: - num_cpus: 1 - memory_mb: 512 - disk: - - size: 1gb - type: thin - datastore: "{{ rw_datastore }}" - state: present - register: create_vm_for_test - -- name: assert that changes were made - assert: - that: - - create_vm_for_test is changed - -- name: Create multiple serial ports with Backing type - network, pipe, device and file - vmware_guest_serial_port: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - name: "test_vm1" - backings: - - type: 'network' - direction: 'client' - service_uri: 'tcp://6000' - yield_on_poll: True - - type: 'pipe' - pipe_name: 'serial_pipe' - endpoint: 'client' - - type: 'device' - device_name: '/dev/char/serial/uart0' - - type: 'file' - file_path: '[{{ rw_datastore }}]/file1' - yield_on_poll: True - register: create_multiple_ports - -- debug: var=create_multiple_ports - -- name: assert that changes were made - assert: - that: - - create_multiple_ports is changed - -- name: Modify existing serial port with Backing type - network - vmware_guest_serial_port: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - name: 'test_vm1' - backings: - - type: 'network' - state: 'present' - direction: 'server' - service_uri: 'tcp://6000' - register: modify_network_port - -- debug: var=modify_network_port - -- name: assert that changes were made - assert: - that: - - modify_network_port is changed - -- name: Remove serial port with Backing type - pipe - vmware_guest_serial_port: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - name: 'test_vm1' - backings: - - type: 'pipe' - state: 'absent' - register: remove_pipe_port - -- debug: var=remove_pipe_port - -- name: assert that changes were made - assert: - that: - - remove_pipe_port is changed diff --git a/test/integration/targets/vmware_guest_snapshot/aliases b/test/integration/targets/vmware_guest_snapshot/aliases deleted file mode 100644 index 62871ab8f0..0000000000 --- a/test/integration/targets/vmware_guest_snapshot/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_guest_snapshot/tasks/main.yml b/test/integration/targets/vmware_guest_snapshot/tasks/main.yml deleted file mode 100644 index 758a91da04..0000000000 --- a/test/integration/targets/vmware_guest_snapshot/tasks/main.yml +++ /dev/null @@ -1,178 +0,0 @@ -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_virtualmachines: true - -# Test0001: Try to delete the non-existent snapshot -- name: 0001 - Delete non-existent snapshot - vmware_guest_snapshot: - validate_certs: False - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: "{{ dc1 }}" - name: "{{ virtual_machines[0].name }}" - folder: "{{ virtual_machines[0].folder }}" - state: absent - snapshot_name: snap_a - -# Test0002: Create two snapshots -- name: 0002 - Create snapshot - vmware_guest_snapshot: - validate_certs: False - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: "{{ dc1 }}" - name: "{{ virtual_machines[0].name }}" - folder: "{{ virtual_machines[0].folder }}" - state: present - snapshot_name: "snap_{{item}}" - description: "snap named {{item}}" - with_items: - - a - - b - -- when: vcsim is not defined - block: -# Test0003: Reanme a to c - - name: 0003 - Rename snapshot - vmware_guest_snapshot: - validate_certs: False - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: "{{ dc1 }}" - name: "{{ virtual_machines[0].name }}" - folder: "{{ virtual_machines[0].folder }}" - state: present - snapshot_name: snap_a - new_snapshot_name: snap_c - -# Test0004: Create snap_a again -- name: 0004 - Re-create snapshot a - vmware_guest_snapshot: - validate_certs: False - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: "{{ dc1 }}" - name: "{{ virtual_machines[0].name }}" - folder: "{{ virtual_machines[0].folder }}" - state: present - snapshot_name: snap_a - description: "snap named a" - -# Test0005: Change description of snap_c -- name: 0005 - Change description of snap_c - vmware_guest_snapshot: - validate_certs: False - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: "{{ dc1 }}" - name: "{{ virtual_machines[0].name }}" - folder: "{{ virtual_machines[0].folder }}" - state: present - snapshot_name: snap_c - new_description: "renamed to snap_c from snap_a" - -- when: vcsim is not defined - block: -# Test0006: Delete snap_b with child remove - - name: 0006 - Delete snap_b with child remove - vmware_guest_snapshot: - validate_certs: False - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: "{{ dc1 }}" - name: "{{ virtual_machines[0].name }}" - folder: "{{ virtual_machines[0].folder }}" - state: absent - snapshot_name: snap_b - remove_children: True - - # Test0007: Delete all snapshots - - name: 0007 - Delete all snapshots - vmware_guest_snapshot: - validate_certs: False - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: "{{ dc1 }}" - name: "{{ virtual_machines[0].name }}" - folder: "{{ virtual_machines[0].folder }}" - state: remove_all - -# Test0008: Create snap_a again and revert to it -- name: 0008 - Re-create snapshot a - vmware_guest_snapshot: - validate_certs: False - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: "{{ dc1 }}" - name: "{{ virtual_machines[0].name }}" - folder: "{{ virtual_machines[0].folder }}" - state: present - snapshot_name: snap_a - description: "snap named a" - -- when: vcsim is not defined - block: - - name: 0008 - Revert to snap_a - vmware_guest_snapshot: - validate_certs: False - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: "{{ dc1 }}" - name: "{{ virtual_machines[0].name }}" - folder: "{{ virtual_machines[0].folder }}" - state: revert - snapshot_name: snap_a - -# Test0009: Create snap_a and check in result -- name: 0009 - create snapshot a - vmware_guest_snapshot: - validate_certs: False - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: "{{ dc1 }}" - name: "{{ virtual_machines[0].name }}" - folder: "{{ virtual_machines[0].folder }}" - state: present - snapshot_name: snap_a - description: "snap named a" - register: snapshot_details - -- debug: var=snapshot_details - -- name: Check if snapshot details available or not - assert: - that: - - "snapshot_details['msg'] == 'Snapshot named [snap_a] already exists and is current.'" - -# Test0011: Failure sceanrios - when name and UUID is not specified -- name: 0011 - name and UUID is missing - vmware_guest_snapshot: - validate_certs: False - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: "{{ dc1 }}" - state: present - snapshot_name: snap_a - description: "snap named a" - register: snapshot_failure_details - ignore_errors: yes - -- name: Check if error is shown - assert: - that: - - "'one of the following is required: name, uuid' in snapshot_failure_details['msg']" - - "snapshot_failure_details.changed == false" diff --git a/test/integration/targets/vmware_guest_snapshot_facts/aliases b/test/integration/targets/vmware_guest_snapshot_facts/aliases deleted file mode 100644 index 62871ab8f0..0000000000 --- a/test/integration/targets/vmware_guest_snapshot_facts/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_guest_snapshot_facts/tasks/main.yml b/test/integration/targets/vmware_guest_snapshot_facts/tasks/main.yml deleted file mode 100644 index f8908675cf..0000000000 --- a/test/integration/targets/vmware_guest_snapshot_facts/tasks/main.yml +++ /dev/null @@ -1,28 +0,0 @@ -# Test code for the vmware_host_dns_facts module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# TODO: vcsim does not support snapshot related functionalities -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_virtualmachines: true - -- name: Gather snapshot facts about given virtual machine - vmware_guest_snapshot_facts: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - name: "{{ virtual_machines[0].name }}" - folder: "{{ virtual_machines[0].folder }}" - register: vm_snapshot_facts - -- debug: var=vm_snapshot_facts - -- assert: - that: - - '"guest_snapshots" in vm_snapshot_facts' diff --git a/test/integration/targets/vmware_guest_snapshot_info/aliases b/test/integration/targets/vmware_guest_snapshot_info/aliases deleted file mode 100644 index 62871ab8f0..0000000000 --- a/test/integration/targets/vmware_guest_snapshot_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_guest_snapshot_info/tasks/main.yml b/test/integration/targets/vmware_guest_snapshot_info/tasks/main.yml deleted file mode 100644 index 81bc1fa10b..0000000000 --- a/test/integration/targets/vmware_guest_snapshot_info/tasks/main.yml +++ /dev/null @@ -1,28 +0,0 @@ -# Test code for the vmware_host_dns_info module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# TODO: vcsim does not support snapshot related functionalities -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_virtualmachines: true - -- name: Gather snapshot info about given virtual machine - vmware_guest_snapshot_info: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - name: "{{ virtual_machines[0].name }}" - folder: "{{ virtual_machines[0].folder }}" - register: vm_snapshot_info - -- debug: var=vm_snapshot_info - -- assert: - that: - - '"guest_snapshots" in vm_snapshot_info' diff --git a/test/integration/targets/vmware_guest_tools_info/aliases b/test/integration/targets/vmware_guest_tools_info/aliases deleted file mode 100644 index 62871ab8f0..0000000000 --- a/test/integration/targets/vmware_guest_tools_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_guest_tools_info/tasks/main.yml b/test/integration/targets/vmware_guest_tools_info/tasks/main.yml deleted file mode 100644 index 2302f13d99..0000000000 --- a/test/integration/targets/vmware_guest_tools_info/tasks/main.yml +++ /dev/null @@ -1,53 +0,0 @@ -# Test code for the vmware_guest_tools_info module -# Copyright: (c) 2019, Diane Wang (Tomorrow9) <dianew@vmware.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_virtualmachines: true - - - name: get instance uuid of virtual machine - vmware_guest_info: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "{{ virtual_machines[0].name }}" - datacenter: "{{ dc1 }}" - register: guest_info - - debug: var=guest_info - - - name: get VMware tools info of virtual machine by instance uuid - vmware_guest_tools_info: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - uuid: "{{ guest_info['instance']['instance_uuid'] }}" - use_instance_uuid: True - register: vmtools_info - - debug: var=vmtools_info - - name: assert VMware tools info returned - assert: - that: - - "vmtools_info.vmtools_info.vm_tools_install_status != ''" - - - name: get VMware tools info of virtual machine by name - vmware_guest_tools_info: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "{{ virtual_machines[0].name }}" - datacenter: "{{ dc1 }}" - register: vmtools_info - - debug: var=vmtools_info - - name: assert VMware tools info returned - assert: - that: - - "vmtools_info.vmtools_info.vm_tools_install_status != ''"
\ No newline at end of file diff --git a/test/integration/targets/vmware_guest_tools_wait/aliases b/test/integration/targets/vmware_guest_tools_wait/aliases deleted file mode 100644 index 316ccc9e4e..0000000000 --- a/test/integration/targets/vmware_guest_tools_wait/aliases +++ /dev/null @@ -1,6 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi -# the test fails randomly in the CI -disabled diff --git a/test/integration/targets/vmware_guest_tools_wait/tasks/main.yml b/test/integration/targets/vmware_guest_tools_wait/tasks/main.yml deleted file mode 100644 index 1c8e3ffc53..0000000000 --- a/test/integration/targets/vmware_guest_tools_wait/tasks/main.yml +++ /dev/null @@ -1,47 +0,0 @@ -# Test code for the vmware_guest_tools_wait module. -# Copyright: (c) 2017 Philippe Dellaert <philippe@dellaert.org> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_dvs_portgroup: true - setup_dvswitch: true - - - name: Create VMs - vmware_guest: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - validate_certs: no - folder: '/DC0/vm/F0' - name: test_vm1 - state: poweredon - guest_id: centos7_64Guest - disk: - - size_gb: 1 - type: thin - datastore: '{{ rw_datastore }}' - hardware: - version: latest - memory_mb: 1024 - num_cpus: 1 - scsi: paravirtual - cdrom: - type: iso - iso_path: "[{{ ro_datastore }}] fedora.iso" - networks: - - name: VM Network - - - vmware_guest_tools_wait: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - timeout: 800 - validate_certs: no - name: test_vm1 diff --git a/test/integration/targets/vmware_host/aliases b/test/integration/targets/vmware_host/aliases deleted file mode 100644 index 7f95a0d344..0000000000 --- a/test/integration/targets/vmware_host/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_2esxi diff --git a/test/integration/targets/vmware_host/tasks/main.yml b/test/integration/targets/vmware_host/tasks/main.yml deleted file mode 100644 index ad9755d916..0000000000 --- a/test/integration/targets/vmware_host/tasks/main.yml +++ /dev/null @@ -1,179 +0,0 @@ -# Test code for the vmware_host module. -# Copyright: (c) 2017, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -# Testcase: Add Host -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - # NOTE: prepare_vmware_tests should have already done that - - name: Add first ESXi Host to vCenter - vmware_host: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter_name: '{{ dc1 }}' - cluster_name: '{{ ccr1 }}' - esxi_hostname: '{{ esxi1 }}' - esxi_username: '{{ esxi_user }}' - esxi_password: '{{ esxi_password }}' - state: present - validate_certs: no - register: readd_host_result - - - name: Add first ESXi Host to vCenter (again) - vmware_host: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter_name: '{{ dc1 }}' - cluster_name: '{{ ccr1 }}' - esxi_hostname: '{{ esxi1 }}' - esxi_username: '{{ esxi_user }}' - esxi_password: '{{ esxi_password }}' - state: present - validate_certs: no - register: readd_host_result - - - name: ensure precend task didn't changed anything - assert: - that: - - not ( readd_host_result is changed) - - - name: add second host via add_or_reconnect - vmware_host: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: '{{ esxi2 }}' - esxi_username: '{{ esxi_user }}' - esxi_password: '{{ esxi_password }}' - datacenter_name: "{{ dc1 }}" - cluster_name: "{{ ccr1 }}" - state: add_or_reconnect - register: add_or_reconnect_host_result - - name: ensure host system is present - assert: - that: - - add_or_reconnect_host_result is changed - -- when: vcsim is not defined - block: - - name: disconnect host 2 - vmware_host: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: '{{ esxi2 }}' - datacenter_name: "{{ dc1 }}" - cluster_name: "{{ ccr1 }}" - fetch_ssl_thumbprint: False - state: absent - - - name: remove host again - vmware_host: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: '{{ esxi2 }}' - datacenter_name: "{{ dc1 }}" - cluster_name: "{{ ccr1 }}" - state: absent - register: reremove_host_result - - name: ensure precend task didn't changed anything - assert: - that: - - not ( reremove_host_result is changed) - - -## Testcase: Add Host to folder -# -# It's not possible to connect an ESXi host via vcsim. -- when: vcsim is not defined - block: - - name: Create host folder - vcenter_folder: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ dc1 }}" - folder_name: "Staging" - folder_type: host - state: present - register: folder_results - - - debug: msg="{{ folder_results }}" - - - name: ensure folder is present - assert: - that: - - folder_results.changed - - - name: Add host to folder in check mode - vmware_host: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: '{{ esxi2 }}' - esxi_username: '{{ esxi_user }}' - esxi_password: '{{ esxi_password }}' - datacenter_name: "{{ dc1 }}" - folder_name: "/{{ dc1 }}/host/Staging" - state: present - register: add_host_to_folder_result - check_mode: yes - - - name: ensure host system is not present - assert: - that: - - add_host_to_folder_result is changed - - - name: Add host to folder - vmware_host: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: '{{ esxi2 }}' - esxi_username: '{{ esxi_user }}' - esxi_password: '{{ esxi_password }}' - datacenter_name: "{{ dc1 }}" - folder_name: "/{{ dc1 }}/host/Staging" - state: present - register: add_host_to_folder_result - - - name: ensure host system is present - assert: - that: - - add_host_to_folder_result is changed - - - name: reconnect host - vmware_host: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: '{{ esxi2 }}' - esxi_username: '{{ esxi_user }}' - esxi_password: '{{ esxi_password }}' - datacenter_name: "{{ dc1 }}" - cluster_name: "{{ ccr1 }}" - state: reconnect - register: reconnect_host_result - - - name: ensure host system has been reconnected - assert: - that: - - reconnect_host_result is changed - # it would be a good idea to check the events on the host to see the reconnect - # https://github.com/vmware/govmomi/blob/master/govc/USAGE.md#events - # "govc events ..." need to be callable from - # https://github.com/ansible/vcenter-test-container/flask_control.py diff --git a/test/integration/targets/vmware_host_acceptance/aliases b/test/integration/targets/vmware_host_acceptance/aliases deleted file mode 100644 index 62871ab8f0..0000000000 --- a/test/integration/targets/vmware_host_acceptance/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_acceptance/tasks/main.yml b/test/integration/targets/vmware_host_acceptance/tasks/main.yml deleted file mode 100644 index c4f96ee88c..0000000000 --- a/test/integration/targets/vmware_host_acceptance/tasks/main.yml +++ /dev/null @@ -1,42 +0,0 @@ -# Test code for the vmware_host_acceptance module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - - - name: Change acceptance level of given hosts - vmware_host_acceptance: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - acceptance_level: community - state: present - register: host_acceptance_info - - debug: var=host_acceptance_info - - assert: - that: - - host_acceptance_info.facts is defined - - - name: Change acceptance level of given hosts in check mode - vmware_host_acceptance: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - acceptance_level: community - state: present - register: host_acceptance_info_check_mode - check_mode: yes - - debug: var=host_acceptance_info_check_mode - - assert: - that: - - host_acceptance_info_check_mode.facts is defined diff --git a/test/integration/targets/vmware_host_active_directory/aliases b/test/integration/targets/vmware_host_active_directory/aliases deleted file mode 100644 index 3eede2cbf0..0000000000 --- a/test/integration/targets/vmware_host_active_directory/aliases +++ /dev/null @@ -1,3 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests diff --git a/test/integration/targets/vmware_host_active_directory/tasks/main.yml b/test/integration/targets/vmware_host_active_directory/tasks/main.yml deleted file mode 100644 index 75be9c6d36..0000000000 --- a/test/integration/targets/vmware_host_active_directory/tasks/main.yml +++ /dev/null @@ -1,87 +0,0 @@ -# Test code for the vmware_host_active_directory module. -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# Active Directory domain isn't available - -- when: - - vcsim is not defined - - active_directory_domain is defined - block: - - name: Join an AD domain in check mode - vmware_host_active_directory: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - ad_domain: '{{ active_directory_domain }}' - ad_user: '{{ active_directory_user }}' - ad_password: '{{ active_directory_password }}' - ad_state: present - validate_certs: no - register: host_active_directory_info_check_mode - check_mode: yes - - - debug: var=host_active_directory_info_check_mode - - - assert: - that: - - host_active_directory_info_check_mode is defined - - host_active_directory_info_check_mode.changed - - - name: Join an AD domain - vmware_host_active_directory: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - ad_domain: example.local - ad_user: adjoin - ad_password: Password123$ - ad_state: present - validate_certs: no - register: host_active_directory_info - ignore_errors: true - - - debug: var=host_active_directory_info - - - assert: - that: - - host_active_directory_info is defined - - host_active_directory_info.changed - - - name: Leave AD domain in check mode - vmware_host_active_directory: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - ad_state: absent - validate_certs: no - register: host_active_directory_info_2_check_mode - check_mode: yes - - - debug: var=host_active_directory_info_2_check_mode - - - assert: - that: - - host_active_directory_info_2_check_mode is defined - - host_active_directory_info_2_check_mode.changed - - - name: Leave AD domain - vmware_host_active_directory: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - ad_state: absent - validate_certs: no - register: host_active_directory_info_2 - ignore_errors: true - - - debug: var=host_active_directory_info_2 - - - assert: - that: - - host_active_directory_info_2 is defined - - host_active_directory_info_2.changed diff --git a/test/integration/targets/vmware_host_auto_start/aliases b/test/integration/targets/vmware_host_auto_start/aliases deleted file mode 100644 index 5b4d23c89c..0000000000 --- a/test/integration/targets/vmware_host_auto_start/aliases +++ /dev/null @@ -1,5 +0,0 @@ -cloud/vcenter -skip/python2.6 -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_auto_start/tasks/esxi_auto_start_ops.yml b/test/integration/targets/vmware_host_auto_start/tasks/esxi_auto_start_ops.yml deleted file mode 100644 index 409de97e67..0000000000 --- a/test/integration/targets/vmware_host_auto_start/tasks/esxi_auto_start_ops.yml +++ /dev/null @@ -1,368 +0,0 @@ -# Test code for the vmware_vmware_host_auto_start. -# Copyright: (c) 2019, sky-joker <sky.jokerxx@gmail.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - - -- name: Update enabled param of autoStart defaults parameters for ESXi. - vmware_host_auto_start: - hostname: "{{ esxi1 }}" - username: "{{ esxi_user }}" - password: "{{ esxi_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - system_defaults: - enabled: yes - register: changed_system_defaults_result - -- name: Check return parameters. - assert: - that: - - changed_system_defaults_result.system_defaults_config.enabled is sameas true - - changed_system_defaults_result.system_defaults_config.start_delay == 120 - - changed_system_defaults_result.system_defaults_config.stop_action == 'powerOff' - - changed_system_defaults_result.system_defaults_config.start_delay == 120 - - changed_system_defaults_result.system_defaults_config.wait_for_heartbeat is sameas false - -- name: Gather facts for autoStart defaults parameters from ESXi. - vmware_host_facts: - hostname: "{{ esxi1 }}" - username: "{{ esxi_user }}" - password: "{{ esxi_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - schema: vsphere - properties: - - config.autoStart - register: auto_start_defaults_result - -- name: After update parameters, check system default parameters. - assert: - that: - - auto_start_defaults_result.ansible_facts.config.autoStart.defaults.enabled is sameas true - - auto_start_defaults_result.ansible_facts.config.autoStart.defaults.startDelay == 120 - - auto_start_defaults_result.ansible_facts.config.autoStart.defaults.stopAction == 'powerOff' - - auto_start_defaults_result.ansible_facts.config.autoStart.defaults.stopDelay == 120 - - auto_start_defaults_result.ansible_facts.config.autoStart.defaults.waitForHeartbeat is sameas false - -- name: Update all param of autoStart defaults parameters for ESXi. - vmware_host_auto_start: - hostname: "{{ esxi1 }}" - username: "{{ esxi_user }}" - password: "{{ esxi_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - system_defaults: - enabled: yes - start_delay: 200 - stop_action: guestShutdown - stop_delay: 300 - wait_for_heartbeat: yes - -- name: Gather facts for autoStart defaults parameters from ESXi. - vmware_host_facts: - hostname: "{{ esxi1 }}" - username: "{{ esxi_user }}" - password: "{{ esxi_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - schema: vsphere - properties: - - config.autoStart - register: auto_start_defaults_result - -- name: After update parameters, check system default parameters. - assert: - that: - - auto_start_defaults_result.ansible_facts.config.autoStart.defaults.enabled is sameas true - - auto_start_defaults_result.ansible_facts.config.autoStart.defaults.startDelay == 200 - - auto_start_defaults_result.ansible_facts.config.autoStart.defaults.stopAction == 'guestShutdown' - - auto_start_defaults_result.ansible_facts.config.autoStart.defaults.stopDelay == 300 - - auto_start_defaults_result.ansible_facts.config.autoStart.defaults.waitForHeartbeat is sameas true - -- name: Gather facts summary propertie from VM. - vmware_guest_info: - hostname: "{{ esxi1 }}" - username: "{{ esxi_user }}" - password: "{{ esxi_password }}" - validate_certs: no - datacenter: ha-datacenter - name: test_vm1 - schema: vsphere - properties: - - summary.vm - register: vm_summary_result - -- name: Update start_action parameters of autoStart powerInfo parameters for VM. - vmware_host_auto_start: - hostname: "{{ esxi1 }}" - username: "{{ esxi_user }}" - password: "{{ esxi_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - name: test_vm1 - power_info: - start_action: powerOn - register: changed_vm_power_info_result - -- name: Check return parameters. - assert: - that: - - changed_vm_power_info_result.power_info_config.start_action == 'powerOn' - - changed_vm_power_info_result.power_info_config.start_delay == -1 - - changed_vm_power_info_result.power_info_config.start_order == -1 - - changed_vm_power_info_result.power_info_config.stop_action == 'systemDefault' - - changed_vm_power_info_result.power_info_config.stop_delay == -1 - - changed_vm_power_info_result.power_info_config.wait_for_heartbeat == 'systemDefault' - -- name: Gather facts for autoStart config of VM from ESXi. - vmware_host_facts: - hostname: "{{ esxi1 }}" - username: "{{ esxi_user }}" - password: "{{ esxi_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - schema: vsphere - properties: - - config.autoStart - register: auto_start_defaults_result - -- name: After update parameters, check VM powerInfo parameters. - assert: - that: - - item.startAction == 'powerOn' - - item.startDelay == -1 - - item.startOrder == -1 - - item.stopAction == 'systemDefault' - - item.stopDelay == -1 - - item.waitForHeartbeat == 'systemDefault' - when: item.key == vm_summary_result.instance.summary.vm - loop: "{{ auto_start_defaults_result.ansible_facts.config.autoStart.powerInfo }}" - -- name: Update all parameters of autoStart powerInfo parameters for VM. - vmware_host_auto_start: - hostname: "{{ esxi1 }}" - username: "{{ esxi_user }}" - password: "{{ esxi_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - name: test_vm1 - power_info: - start_action: powerOn - start_delay: 200 - start_order: 1 - stop_action: suspend - stop_delay: 250 - wait_for_heartbeat: "yes" - -- name: Gather facts for autoStart config of VM from ESXi. - vmware_host_facts: - hostname: "{{ esxi1 }}" - username: "{{ esxi_user }}" - password: "{{ esxi_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - schema: vsphere - properties: - - config.autoStart - register: auto_start_defaults_result - -- name: After update parameters, check VM all powerInfo parameters. - assert: - that: - - item.startAction == 'powerOn' - - item.startDelay == 200 - - item.startOrder == 1 - - item.stopAction == 'suspend' - - item.stopDelay == 250 - - item.waitForHeartbeat == 'yes' - when: item.key == vm_summary_result.instance.summary.vm - loop: "{{ auto_start_defaults_result.ansible_facts.config.autoStart.powerInfo }}" - -- name: Gather facts summary propertie from VM. - vmware_guest_info: - hostname: "{{ esxi1 }}" - username: "{{ esxi_user }}" - password: "{{ esxi_password }}" - validate_certs: no - datacenter: ha-datacenter - name: test_vm2 - schema: vsphere - properties: - - summary.vm - register: vm_summary_result - -- name: Update all parameters of autoStart powerInfo parameters for other VM. - vmware_host_auto_start: - hostname: "{{ esxi1 }}" - username: "{{ esxi_user }}" - password: "{{ esxi_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - name: test_vm2 - power_info: - start_action: powerOn - start_delay: 100 - start_order: 2 - stop_action: suspend - stop_delay: 20 - wait_for_heartbeat: "no" - -- name: Gather facts for autoStart config of other VM from ESXi. - vmware_host_facts: - hostname: "{{ esxi1 }}" - username: "{{ esxi_user }}" - password: "{{ esxi_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - schema: vsphere - properties: - - config.autoStart - register: auto_start_defaults_result - -- name: After update parameters, check other VM all powerInfo parameters. - assert: - that: - - item.startAction == 'powerOn' - - item.startDelay == 100 - - item.startOrder == 2 - - item.stopAction == 'suspend' - - item.stopDelay == 20 - - item.waitForHeartbeat == 'no' - when: item.key == vm_summary_result.instance.summary.vm - loop: "{{ auto_start_defaults_result.ansible_facts.config.autoStart.powerInfo }}" - -- name: Check the operation of check_mode and diff. - vmware_host_auto_start: - hostname: "{{ esxi1 }}" - username: "{{ esxi_user }}" - password: "{{ esxi_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - name: test_vm2 - power_info: - start_action: powerOn - start_delay: 100 - start_order: -1 - stop_action: suspend - stop_delay: 20 - check_mode: yes - diff: yes - -- name: Gather facts for autoStart config of other VM from ESXi. - vmware_host_facts: - hostname: "{{ esxi1 }}" - username: "{{ esxi_user }}" - password: "{{ esxi_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - schema: vsphere - properties: - - config.autoStart - register: auto_start_defaults_result - -- name: After update parameters, check other VM all powerInfo parameters. - assert: - that: - - item.startAction == 'powerOn' - - item.startDelay == 100 - - item.startOrder == 2 - - item.stopAction == 'suspend' - - item.stopDelay == 20 - - item.waitForHeartbeat == 'no' - when: item.key == vm_summary_result.instance.summary.vm - loop: "{{ auto_start_defaults_result.ansible_facts.config.autoStart.powerInfo }}" - -- name: Gather facts instanceUuid and moid propertie from VM. - vmware_guest_info: - hostname: "{{ esxi1 }}" - username: "{{ esxi_user }}" - password: "{{ esxi_password }}" - validate_certs: no - datacenter: "{{ dc1 }}" - name: test_vm2 - schema: vsphere - properties: - - config.instanceUuid - - _moId - register: vm_instanceUuid_and_moid_result - -- name: Update all parameters of autoStart powerInfo parameters for VM using instanceUuid via vCenter. - vmware_host_auto_start: - hostname: "{{ esxi1 }}" - username: "{{ esxi_user }}" - password: "{{ esxi_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - uuid: "{{ vm_instanceUuid_and_moid_result.instance.config.instanceUuid }}" - use_instance_uuid: yes - power_info: - start_action: powerOn - start_delay: 300 - start_order: 1 - stop_action: none - stop_delay: 20 - wait_for_heartbeat: "no" - -- name: Gather facts for autoStart config of other VM from ESXi. - vmware_host_facts: - hostname: "{{ esxi1 }}" - username: "{{ esxi_user }}" - password: "{{ esxi_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - schema: vsphere - properties: - - config.autoStart - register: auto_start_defaults_result - -- name: After update parameters, check other VM all powerInfo parameters. - assert: - that: - - item.startAction == 'powerOn' - - item.startDelay == 300 - - item.startOrder == 1 - - item.stopAction == 'none' - - item.stopDelay == 20 - - item.waitForHeartbeat == 'no' - when: item.key == vm_summary_result.instance.summary.vm - loop: "{{ auto_start_defaults_result.ansible_facts.config.autoStart.powerInfo }}" - -- name: Update all parameters of autoStart powerInfo parameters for VM using moid via vCenter. - vmware_host_auto_start: - hostname: "{{ esxi1 }}" - username: "{{ esxi_user }}" - password: "{{ esxi_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - moid: "{{ vm_instanceUuid_and_moid_result.instance._moId }}" - power_info: - start_action: powerOn - start_delay: 200 - start_order: 1 - stop_action: powerOff - stop_delay: 300 - wait_for_heartbeat: "yes" - -- name: Gather facts for autoStart config of other VM from ESXi. - vmware_host_facts: - hostname: "{{ esxi1 }}" - username: "{{ esxi_user }}" - password: "{{ esxi_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - schema: vsphere - properties: - - config.autoStart - register: auto_start_defaults_result - -- name: After update parameters, check other VM all powerInfo parameters. - assert: - that: - - item.startAction == 'powerOn' - - item.startDelay == 200 - - item.startOrder == 1 - - item.stopAction == 'powerOff' - - item.stopDelay == 300 - - item.waitForHeartbeat == 'yes' - when: item.key == vm_summary_result.instance.summary.vm - loop: "{{ auto_start_defaults_result.ansible_facts.config.autoStart.powerInfo }}" diff --git a/test/integration/targets/vmware_host_auto_start/tasks/main.yml b/test/integration/targets/vmware_host_auto_start/tasks/main.yml deleted file mode 100644 index 54b96e3c16..0000000000 --- a/test/integration/targets/vmware_host_auto_start/tasks/main.yml +++ /dev/null @@ -1,57 +0,0 @@ -# Test code for the vmware_host_auto_start Operations. -# Copyright: (c) 2019, sky-joker <sky.jokerxx@gmail.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - - - name: Move the ESXi hosts out of the cluster - vmware_host: - datacenter_name: '{{ dc1 }}' - esxi_hostname: '{{ item }}' - esxi_username: '{{ esxi_user }}' - esxi_password: '{{ esxi_password }}' - folder: '/DC0/host' - state: present - with_items: "{{ esxi_hosts }}" - - - name: Disable the Maintenance Mode - vmware_maintenancemode: - esxi_hostname: '{{ item }}' - state: absent - with_items: "{{ esxi_hosts }}" - - - name: Create VM on esxi1 - vmware_guest: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - validate_certs: no - name: '{{ item }}' - folder: vm - esxi_hostname: "{{ esxi1 }}" - state: present - guest_id: centos7_64Guest - disk: - - size_gb: 1 - type: thin - datastore: '{{ rw_datastore }}' - hardware: - version: latest - memory_mb: 1024 - num_cpus: 1 - scsi: paravirtual - with_items: ['test_vm1', 'test_vm2'] - - - include_tasks: reset_auto_start_config.yml - - include: vcenter_auto_start_ops.yml - - include_tasks: reset_auto_start_config.yml - - include: esxi_auto_start_ops.yml - always: - - include_tasks: reset_auto_start_config.yml diff --git a/test/integration/targets/vmware_host_auto_start/tasks/reset_auto_start_config.yml b/test/integration/targets/vmware_host_auto_start/tasks/reset_auto_start_config.yml deleted file mode 100644 index 7455408978..0000000000 --- a/test/integration/targets/vmware_host_auto_start/tasks/reset_auto_start_config.yml +++ /dev/null @@ -1,35 +0,0 @@ -# Test code for the vmware_host_auto_start Operations. -# Copyright: (c) 2019, sky-joker <sky.jokerxx@gmail.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: "Reset powerInfo for autoStart parameters of {{ test_vm1 }}." - vmware_host_auto_start: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - name: test_vm1 - power_info: - start_action: none - -- name: "Reset powerInfo for autoStart parameters of {{ test_vm2 }}" - vmware_host_auto_start: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - name: test_vm2 - power_info: - start_action: none - -- name: Reset autoStart defaults parameters. - vmware_host_auto_start: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - system_defaults: - enabled: no diff --git a/test/integration/targets/vmware_host_auto_start/tasks/vcenter_auto_start_ops.yml b/test/integration/targets/vmware_host_auto_start/tasks/vcenter_auto_start_ops.yml deleted file mode 100644 index 1936c11873..0000000000 --- a/test/integration/targets/vmware_host_auto_start/tasks/vcenter_auto_start_ops.yml +++ /dev/null @@ -1,367 +0,0 @@ -# Test code for the vmware_vmware_host_auto_start. -# Copyright: (c) 2019, sky-joker <sky.jokerxx@gmail.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- name: Update enabled param of autoStart defaults parameters for ESXi via vCenter. - vmware_host_auto_start: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - system_defaults: - enabled: yes - register: changed_system_defaults_result - -- name: Check return parameters. - assert: - that: - - changed_system_defaults_result.system_defaults_config.enabled is sameas true - - changed_system_defaults_result.system_defaults_config.start_delay == 120 - - changed_system_defaults_result.system_defaults_config.stop_action == 'powerOff' - - changed_system_defaults_result.system_defaults_config.start_delay == 120 - - changed_system_defaults_result.system_defaults_config.wait_for_heartbeat is sameas false - -- name: Gather facts for autoStart defaults parameters from ESXi. - vmware_host_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - schema: vsphere - properties: - - config.autoStart - register: auto_start_defaults_result - -- name: After update parameters, check system default parameters. - assert: - that: - - auto_start_defaults_result.ansible_facts.config.autoStart.defaults.enabled is sameas true - - auto_start_defaults_result.ansible_facts.config.autoStart.defaults.startDelay == 120 - - auto_start_defaults_result.ansible_facts.config.autoStart.defaults.stopAction == 'powerOff' - - auto_start_defaults_result.ansible_facts.config.autoStart.defaults.stopDelay == 120 - - auto_start_defaults_result.ansible_facts.config.autoStart.defaults.waitForHeartbeat is sameas false - -- name: Update all param of autoStart defaults parameters for ESXi via vCenter. - vmware_host_auto_start: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - system_defaults: - enabled: yes - start_delay: 200 - stop_action: guestShutdown - stop_delay: 300 - wait_for_heartbeat: yes - -- name: Gather facts for autoStart defaults parameters from ESXi. - vmware_host_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - schema: vsphere - properties: - - config.autoStart - register: auto_start_defaults_result - -- name: After update parameters, check system default parameters. - assert: - that: - - auto_start_defaults_result.ansible_facts.config.autoStart.defaults.enabled is sameas true - - auto_start_defaults_result.ansible_facts.config.autoStart.defaults.startDelay == 200 - - auto_start_defaults_result.ansible_facts.config.autoStart.defaults.stopAction == 'guestShutdown' - - auto_start_defaults_result.ansible_facts.config.autoStart.defaults.stopDelay == 300 - - auto_start_defaults_result.ansible_facts.config.autoStart.defaults.waitForHeartbeat is sameas true - -- name: Gather facts summary propertie from VM. - vmware_guest_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ dc1 }}" - name: test_vm1 - schema: vsphere - properties: - - summary.vm - register: vm_summary_result - -- name: Update start_action parameters of autoStart powerInfo parameters for VM via vCenter. - vmware_host_auto_start: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - name: test_vm1 - power_info: - start_action: powerOn - register: changed_vm_power_info_result - -- name: Check return parameters. - assert: - that: - - changed_vm_power_info_result.power_info_config.start_action == 'powerOn' - - changed_vm_power_info_result.power_info_config.start_delay == -1 - - changed_vm_power_info_result.power_info_config.start_order == -1 - - changed_vm_power_info_result.power_info_config.stop_action == 'systemDefault' - - changed_vm_power_info_result.power_info_config.stop_delay == -1 - - changed_vm_power_info_result.power_info_config.wait_for_heartbeat == 'systemDefault' - -- name: Gather facts for autoStart config of VM from ESXi. - vmware_host_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - schema: vsphere - properties: - - config.autoStart - register: auto_start_defaults_result - -- name: After update parameters, check VM powerInfo parameters. - assert: - that: - - item.startAction == 'powerOn' - - item.startDelay == -1 - - item.startOrder == -1 - - item.stopAction == 'systemDefault' - - item.stopDelay == -1 - - item.waitForHeartbeat == 'systemDefault' - when: item.key == vm_summary_result.instance.summary.vm - loop: "{{ auto_start_defaults_result.ansible_facts.config.autoStart.powerInfo }}" - -- name: Update all parameters of autoStart powerInfo parameters for VM via vCenter. - vmware_host_auto_start: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - name: test_vm1 - power_info: - start_action: powerOn - start_delay: 200 - start_order: 1 - stop_action: suspend - stop_delay: 250 - wait_for_heartbeat: "yes" - -- name: Gather facts for autoStart config of VM from ESXi. - vmware_host_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - schema: vsphere - properties: - - config.autoStart - register: auto_start_defaults_result - -- name: After update parameters, check VM all powerInfo parameters. - assert: - that: - - item.startAction == 'powerOn' - - item.startDelay == 200 - - item.startOrder == 1 - - item.stopAction == 'suspend' - - item.stopDelay == 250 - - item.waitForHeartbeat == 'yes' - when: item.key == vm_summary_result.instance.summary.vm - loop: "{{ auto_start_defaults_result.ansible_facts.config.autoStart.powerInfo }}" - -- name: Gather facts summary propertie from VM. - vmware_guest_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ dc1 }}" - name: test_vm2 - schema: vsphere - properties: - - summary.vm - register: vm_summary_result - -- name: Update all parameters of autoStart powerInfo parameters for other VM via vCenter. - vmware_host_auto_start: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - name: test_vm2 - power_info: - start_action: powerOn - start_delay: 100 - start_order: 2 - stop_action: suspend - stop_delay: 20 - wait_for_heartbeat: "no" - -- name: Gather facts for autoStart config of other VM from ESXi. - vmware_host_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - schema: vsphere - properties: - - config.autoStart - register: auto_start_defaults_result - -- name: After update parameters, check other VM all powerInfo parameters. - assert: - that: - - item.startAction == 'powerOn' - - item.startDelay == 100 - - item.startOrder == 2 - - item.stopAction == 'suspend' - - item.stopDelay == 20 - - item.waitForHeartbeat == 'no' - when: item.key == vm_summary_result.instance.summary.vm - loop: "{{ auto_start_defaults_result.ansible_facts.config.autoStart.powerInfo }}" - -- name: Check the operation of check_mode and diff. - vmware_host_auto_start: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - name: test_vm2 - power_info: - start_action: powerOn - start_delay: 100 - start_order: -1 - stop_action: suspend - stop_delay: 20 - check_mode: yes - diff: yes - -- name: Gather facts for autoStart config of other VM from ESXi. - vmware_host_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - schema: vsphere - properties: - - config.autoStart - register: auto_start_defaults_result - -- name: After update parameters, check other VM all powerInfo parameters. - assert: - that: - - item.startAction == 'powerOn' - - item.startDelay == 100 - - item.startOrder == 2 - - item.stopAction == 'suspend' - - item.stopDelay == 20 - - item.waitForHeartbeat == 'no' - when: item.key == vm_summary_result.instance.summary.vm - loop: "{{ auto_start_defaults_result.ansible_facts.config.autoStart.powerInfo }}" - -- name: Gather facts instanceUuid and moid propertie from VM. - vmware_guest_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - datacenter: "{{ dc1 }}" - name: test_vm2 - schema: vsphere - properties: - - config.instanceUuid - - _moId - register: vm_instanceUuid_and_moid_result - -- name: Update all parameters of autoStart powerInfo parameters for VM using instanceUuid via vCenter. - vmware_host_auto_start: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - uuid: "{{ vm_instanceUuid_and_moid_result.instance.config.instanceUuid }}" - use_instance_uuid: yes - power_info: - start_action: powerOn - start_delay: 300 - start_order: 1 - stop_action: none - stop_delay: 20 - wait_for_heartbeat: "no" - -- name: Gather facts for autoStart config of other VM from ESXi. - vmware_host_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - schema: vsphere - properties: - - config.autoStart - register: auto_start_defaults_result - -- name: After update parameters, check other VM all powerInfo parameters. - assert: - that: - - item.startAction == 'powerOn' - - item.startDelay == 300 - - item.startOrder == 1 - - item.stopAction == 'none' - - item.stopDelay == 20 - - item.waitForHeartbeat == 'no' - when: item.key == vm_summary_result.instance.summary.vm - loop: "{{ auto_start_defaults_result.ansible_facts.config.autoStart.powerInfo }}" - -- name: Update all parameters of autoStart powerInfo parameters for VM using moid via vCenter. - vmware_host_auto_start: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - moid: "{{ vm_instanceUuid_and_moid_result.instance._moId }}" - power_info: - start_action: powerOn - start_delay: 200 - start_order: 1 - stop_action: powerOff - stop_delay: 300 - wait_for_heartbeat: "yes" - -- name: Gather facts for autoStart config of other VM from ESXi. - vmware_host_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - schema: vsphere - properties: - - config.autoStart - register: auto_start_defaults_result - -- name: After update parameters, check other VM all powerInfo parameters. - assert: - that: - - item.startAction == 'powerOn' - - item.startDelay == 200 - - item.startOrder == 1 - - item.stopAction == 'powerOff' - - item.stopDelay == 300 - - item.waitForHeartbeat == 'yes' - when: item.key == vm_summary_result.instance.summary.vm - loop: "{{ auto_start_defaults_result.ansible_facts.config.autoStart.powerInfo }}" diff --git a/test/integration/targets/vmware_host_capability_facts/aliases b/test/integration/targets/vmware_host_capability_facts/aliases deleted file mode 100644 index 62871ab8f0..0000000000 --- a/test/integration/targets/vmware_host_capability_facts/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_capability_facts/tasks/main.yml b/test/integration/targets/vmware_host_capability_facts/tasks/main.yml deleted file mode 100644 index 3b13971ca0..0000000000 --- a/test/integration/targets/vmware_host_capability_facts/tasks/main.yml +++ /dev/null @@ -1,38 +0,0 @@ -# Test code for the vmware_host_capability_facts module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# TODO: vcsim does not support host system capabilities - -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - - name: Gather capability facts for all ESXi host from given cluster - vmware_host_capability_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: False - cluster_name: "{{ ccr1 }}" - register: capability_0001_results - - assert: - that: - - not (capability_0001_results is changed) - - capability_0001_results.hosts_capability_facts is defined - - - name: Gather capability facts for ESXi host - vmware_host_capability_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: False - esxi_hostname: '{{ esxi1 }}' - register: capability_0002_results - - assert: - that: - - not (capability_0002_results is changed) - - capability_0002_results.hosts_capability_facts is defined diff --git a/test/integration/targets/vmware_host_capability_info/aliases b/test/integration/targets/vmware_host_capability_info/aliases deleted file mode 100644 index 62871ab8f0..0000000000 --- a/test/integration/targets/vmware_host_capability_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group1 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_capability_info/tasks/main.yml b/test/integration/targets/vmware_host_capability_info/tasks/main.yml deleted file mode 100644 index 14a270156a..0000000000 --- a/test/integration/targets/vmware_host_capability_info/tasks/main.yml +++ /dev/null @@ -1,38 +0,0 @@ -# Test code for the vmware_host_capability_info module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# TODO: vcsim does not support host system capabilities - -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - - name: Gather capability info for all ESXi host from given cluster - vmware_host_capability_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: False - cluster_name: "{{ ccr1 }}" - register: capability_0001_results - - assert: - that: - - not (capability_0001_results is changed) - - capability_0001_results.hosts_capability_info is defined - - - name: Gather capability info for ESXi host - vmware_host_capability_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: False - esxi_hostname: '{{ esxi1 }}' - register: capability_0002_results - - assert: - that: - - not (capability_0002_results is changed) - - capability_0002_results.hosts_capability_info is defined diff --git a/test/integration/targets/vmware_host_config_facts/aliases b/test/integration/targets/vmware_host_config_facts/aliases deleted file mode 100644 index dea29ccd8b..0000000000 --- a/test/integration/targets/vmware_host_config_facts/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group1 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_config_facts/tasks/main.yml b/test/integration/targets/vmware_host_config_facts/tasks/main.yml deleted file mode 100644 index ce1e059995..0000000000 --- a/test/integration/targets/vmware_host_config_facts/tasks/main.yml +++ /dev/null @@ -1,68 +0,0 @@ -# Test code for the vmware_host_config_facts module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - -- name: gather facts about all hosts in given cluster - vmware_host_config_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - cluster_name: "{{ ccr1 }}" - register: all_hosts_result - -- debug: - var: all_hosts_result - -- name: ensure facts are gathered for all hosts - assert: - that: - - all_hosts_result.hosts_facts - -- name: gather facts about all hosts in given cluster in check mode - vmware_host_config_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - cluster_name: "{{ ccr1 }}" - register: all_hosts_result_check_mode - check_mode: yes - -- name: ensure facts are gathered for all hosts - assert: - that: - - all_hosts_result_check_mode.hosts_facts - -- when: vcsim is not defined - block: - - name: gather facts about a given host in check mode - vmware_host_config_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - register: single_hosts_result_check_mode - check_mode: yes - - name: ensure facts are gathered for all hosts - assert: - that: - - single_hosts_result_check_mode.hosts_facts - - - name: gather facts about a given host - vmware_host_config_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - register: single_hosts_result - - name: ensure facts are gathered for all hosts - assert: - that: - - single_hosts_result.hosts_facts diff --git a/test/integration/targets/vmware_host_config_info/aliases b/test/integration/targets/vmware_host_config_info/aliases deleted file mode 100644 index e96093f00c..0000000000 --- a/test/integration/targets/vmware_host_config_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group2 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_config_info/tasks/main.yml b/test/integration/targets/vmware_host_config_info/tasks/main.yml deleted file mode 100644 index 061ab8c5d5..0000000000 --- a/test/integration/targets/vmware_host_config_info/tasks/main.yml +++ /dev/null @@ -1,68 +0,0 @@ -# Test code for the vmware_host_config_info module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - -- name: gather info about all hosts in given cluster - vmware_host_config_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - cluster_name: "{{ ccr1 }}" - register: all_hosts_result - -- debug: - var: all_hosts_result - -- name: ensure info are gathered for all hosts - assert: - that: - - all_hosts_result.hosts_info - -- name: gather info about all hosts in given cluster in check mode - vmware_host_config_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - cluster_name: "{{ ccr1 }}" - register: all_hosts_result_check_mode - check_mode: yes - -- name: ensure info are gathered for all hosts - assert: - that: - - all_hosts_result_check_mode.hosts_info - -- when: vcsim is not defined - block: - - name: gather info about a given host in check mode - vmware_host_config_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - register: single_hosts_result_check_mode - check_mode: yes - - name: ensure info are gathered for all hosts - assert: - that: - - single_hosts_result_check_mode.hosts_info - - - name: gather info about a given host - vmware_host_config_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - register: single_hosts_result - - name: ensure info are gathered for all hosts - assert: - that: - - single_hosts_result.hosts_info diff --git a/test/integration/targets/vmware_host_config_manager/aliases b/test/integration/targets/vmware_host_config_manager/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_host_config_manager/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_config_manager/tasks/main.yml b/test/integration/targets/vmware_host_config_manager/tasks/main.yml deleted file mode 100644 index 2be119de92..0000000000 --- a/test/integration/targets/vmware_host_config_manager/tasks/main.yml +++ /dev/null @@ -1,90 +0,0 @@ -# Test code for the vmware_host_config_manager module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - -- name: Change an invalid key - vmware_host_config_manager: - validate_certs: no - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: "{{ ccr1 }}" - options: - 'This.Is.No.Where': 'verbose' - failed_when: False - register: invalid_key -- debug: var=invalid_key -- name: ensure we raise the correct error - assert: - that: - - '"Unsupported option This.Is.No.Where" in invalid_key.msg' - -# TODO: vcsim does not support update host configuartion -- when: vcsim is not defined - block: - - name: Change info about all hosts in given cluster - vmware_host_config_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: "{{ ccr1 }}" - options: - 'Config.HostAgent.log.level': 'verbose' - validate_certs: no - - - name: Change info about a given host - vmware_host_config_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - options: - 'Config.HostAgent.log.level': 'info' - validate_certs: no - register: host_result - - - debug: var=host_result - - - name: ensure change was applied - assert: - that: - - host_result is changed - - - name: Change info about all hosts in given cluster in check mode - vmware_host_config_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: "{{ ccr1 }}" - options: - 'Config.HostAgent.log.level': 'verbose' - validate_certs: no - register: all_hosts_result_check_mode - check_mode: yes - - - name: ensure changes are done to all hosts - assert: - that: - - all_hosts_result_check_mode.changed - - - name: Change info about a given host in check mode - vmware_host_config_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - options: - 'Config.HostAgent.log.level': 'info' - validate_certs: no - register: host_result_check_mode - check_mode: yes - - - name: ensure changes are done to given hosts - assert: - that: - - all_hosts_result_check_mode.changed diff --git a/test/integration/targets/vmware_host_datastore/aliases b/test/integration/targets/vmware_host_datastore/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_host_datastore/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_datastore/tasks/main.yml b/test/integration/targets/vmware_host_datastore/tasks/main.yml deleted file mode 100644 index b4eda3bdb3..0000000000 --- a/test/integration/targets/vmware_host_datastore/tasks/main.yml +++ /dev/null @@ -1,84 +0,0 @@ -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - - name: Mount NFS (ro_datastore) datastores without esxi_hostname - vmware_host_datastore: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datastore_name: '{{ ro_datastore }}' - datastore_type: '{{ infra.datastores[ro_datastore].type }}' - nfs_server: '{{ infra.datastores[ro_datastore].server }}' - nfs_path: '{{ infra.datastores[ro_datastore].path }}' - nfs_ro: '{{ infra.datastores[ro_datastore].ro }}' - state: present - validate_certs: no - ignore_errors: true - register: mount_vmware_host_datastore - - debug: var=mount_vmware_host_datastore - - assert: - that: - - mount_vmware_host_datastore is failed - - mount_vmware_host_datastore.msg == "esxi_hostname is mandatory with a vcenter" - - - name: Mount NFS (ro_datastore) datastores with non existing host in esxi_hostname - vmware_host_datastore: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: 'nohost' - datastore_name: '{{ ro_datastore }}' - datastore_type: '{{ infra.datastores[ro_datastore].type }}' - nfs_server: '{{ infra.datastores[ro_datastore].server }}' - nfs_path: '{{ infra.datastores[ro_datastore].path }}' - nfs_ro: '{{ infra.datastores[ro_datastore].ro }}' - state: present - validate_certs: no - ignore_errors: true - register: mount_vmware_host_datastore - - debug: var=mount_vmware_host_datastore - - assert: - that: - - mount_vmware_host_datastore is failed - - mount_vmware_host_datastore.msg == "Failed to find ESXi hostname nohost" - - - name: Mount NFS (ro_datastore) datastores on esxi1 using esxi_hostname - vmware_host_datastore: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - datastore_name: '{{ ro_datastore }}' - datastore_type: '{{ infra.datastores[ro_datastore].type }}' - nfs_server: '{{ infra.datastores[ro_datastore].server }}' - nfs_path: '{{ infra.datastores[ro_datastore].path }}' - nfs_ro: '{{ infra.datastores[ro_datastore].ro }}' - state: present - validate_certs: no - register: mount_vmware_host_datastore - - debug: var=mount_vmware_host_datastore - - assert: - that: - - mount_vmware_host_datastore is changed - - - name: Mount NFS (ro_datastore) datastores to ESXi directly - vmware_host_datastore: - hostname: '{{ esxi1 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - datastore_name: '{{ ro_datastore }}' - datastore_type: '{{ infra.datastores[ro_datastore].type }}' - nfs_server: '{{ infra.datastores[ro_datastore].server }}' - nfs_path: '{{ infra.datastores[ro_datastore].path }}' - nfs_ro: '{{ infra.datastores[ro_datastore].ro }}' - state: present - validate_certs: no - register: mount_vmware_host_datastore - - debug: var=mount_vmware_host_datastore - - assert: - that: - - not (mount_vmware_host_datastore is changed) diff --git a/test/integration/targets/vmware_host_dns/aliases b/test/integration/targets/vmware_host_dns/aliases deleted file mode 100644 index 0c2e2cb9bd..0000000000 --- a/test/integration/targets/vmware_host_dns/aliases +++ /dev/null @@ -1,3 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests diff --git a/test/integration/targets/vmware_host_dns/tasks/dhcp.yml b/test/integration/targets/vmware_host_dns/tasks/dhcp.yml deleted file mode 100644 index 627580fca9..0000000000 --- a/test/integration/targets/vmware_host_dns/tasks/dhcp.yml +++ /dev/null @@ -1,303 +0,0 @@ -- name: Tests when the hosts have a DHCP DNS config - block: - # Testcase 0001: Ensure DNS config directly on the host is idempotent for DHCP - - name: Ensure DHCP config is idempotent when done directly on the host - vmware_host_dns: - hostname: '{{ esxi1 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - validate_certs: False - type: 'dhcp' - device: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['virtual_nic_device'] }}" - register: vmware_host_dns_result_0001 - - - name: Ensure DNS config wasn't changed - assert: - that: - - vmware_host_dns_result_0001 is not changed - - # Testcase 0002: Change DNS config directly on the host from DHCP to static - - name: Change DNS config from DHCP to static directly on the host - vmware_host_dns: - hostname: '{{ esxi1 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - validate_certs: False - type: 'static' - host_name: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['host_name'] }}" - domain: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['domain_name'] }}" - dns_servers: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['ip_address'] }}" - search_domains: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['search_domain'] }}" - register: vmware_host_dns_result_0002 - - - name: Ensure DNS config was changed - assert: - that: - - vmware_host_dns_result_0002 is changed - - # Testcase 0003: Ensure DNS config directly on the host is idempotent for static - - name: Ensure static DNS config is idempotent when done directly on the host - vmware_host_dns: - hostname: '{{ esxi1 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - validate_certs: False - type: 'static' - host_name: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['host_name'] }}" - domain: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['domain_name'] }}" - dns_servers: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['ip_address'] }}" - search_domains: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['search_domain'] }}" - register: vmware_host_dns_result_0003 - - - name: Ensure DNS config wasn't changed - assert: - that: - - vmware_host_dns_result_0003 is not changed - - # Testcase 0004: Ensure changing the hostname directly on the host works - - name: Ensure changing the hostname directly on the host works - vmware_host_dns: - hostname: '{{ esxi1 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - validate_certs: False - type: 'static' - host_name: newname - domain: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['domain_name'] }}" - dns_servers: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['ip_address'] }}" - search_domains: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['search_domain'] }}" - register: vmware_host_dns_result_0004 - - - name: Ensure DNS config was changed - assert: - that: - - vmware_host_dns_result_0004 is changed - - # Testcase 0005: Ensure changing the domain directly on the host works - - name: Ensure changing the domain directly on the host works - vmware_host_dns: - hostname: '{{ esxi1 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - validate_certs: False - type: 'static' - host_name: newname - domain: new.domain - dns_servers: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['ip_address'] }}" - search_domains: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['search_domain'] }}" - register: vmware_host_dns_result_0005 - - - name: Ensure DNS config was changed - assert: - that: - - vmware_host_dns_result_0005 is changed - - # Testcase 0006: Ensure changing the DNS servers directly on the host works - - name: Ensure changing the domain directly on the host works - vmware_host_dns: - hostname: '{{ esxi1 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - validate_certs: False - type: 'static' - host_name: newname - domain: new.domain - dns_servers: - - 1.2.3.4 - - 5.6.7.8 - search_domains: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['search_domain'] }}" - register: vmware_host_dns_result_0006 - - - name: Ensure DNS config was changed - assert: - that: - - vmware_host_dns_result_0006 is changed - - # Testcase 0007: Ensure changing the search domain directly on the host works - - name: Ensure changing the domain directly on the host works - vmware_host_dns: - hostname: '{{ esxi1 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - validate_certs: False - type: 'static' - host_name: newname - domain: new.domain - dns_servers: - - 1.2.3.4 - - 5.6.7.8 - search_domains: - - subdomain.example.local - - example.local - register: vmware_host_dns_result_0007 - - - name: Ensure DNS config was changed - assert: - that: - - vmware_host_dns_result_0007 is changed - - # Testcase 0008: Change DNS config directly on the host from static to DHCP - - name: Change DNS config from static to DHCP directly on the host - vmware_host_dns: - hostname: '{{ esxi1 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - validate_certs: False - type: 'dhcp' - device: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['virtual_nic_device'] }}" - register: vmware_host_dns_result_0008 - - - name: Ensure DNS config was changed - assert: - that: - - vmware_host_dns_result_0008 is changed - - # Testcase 0009: Ensure DNS config on the cluster is idempotent for DHCP - - name: Ensure DHCP config is idempotent when done on the cluster - vmware_host_dns: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: "{{ ccr1 }}" - validate_certs: False - type: 'dhcp' - device: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['virtual_nic_device'] }}" - register: vmware_host_dns_result_0009 - - - name: Ensure DNS config wasn't changed - assert: - that: - - vmware_host_dns_result_0009 is not changed - - # Testcase 0010: Ensure changing DNS config on the cluster from DHCP to static works - - name: Ensure changing DNS config on the cluster from DHCP to static works - vmware_host_dns: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: "{{ ccr1 }}" - validate_certs: False - type: 'static' - domain: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['domain_name'] }}" - dns_servers: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['ip_address'] }}" - search_domains: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['search_domain'] }}" - register: vmware_host_dns_result_0010 - - - name: Ensure DNS config was changed - assert: - that: - - vmware_host_dns_result_0010 is changed - - # Testcase 0011: Ensure DNS config on the cluster is idempotent for static - - name: Ensure static DNS config is idempotent when done on the cluster - vmware_host_dns: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: "{{ ccr1 }}" - validate_certs: False - type: 'static' - domain: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['domain_name'] }}" - dns_servers: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['ip_address'] }}" - search_domains: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['search_domain'] }}" - register: vmware_host_dns_result_0011 - - - name: Ensure DNS config wasn't changed - assert: - that: - - vmware_host_dns_result_0011 is not changed - - # Testcase 0012: Ensure changing the domain on the cluster works - - name: Ensure changing the domain on the cluster works - vmware_host_dns: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: "{{ ccr1 }}" - validate_certs: False - type: 'static' - domain: new.domain - dns_servers: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['ip_address'] }}" - search_domains: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['search_domain'] }}" - register: vmware_host_dns_result_0012 - - - name: Ensure DNS config was changed - assert: - that: - - vmware_host_dns_result_0012 is changed - - # Testcase 0013: Ensure changing the DNS servers on the cluster works - - name: Ensure changing the DNS servers on the cluster works - vmware_host_dns: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: "{{ ccr1 }}" - validate_certs: False - type: 'static' - domain: new.domain - dns_servers: - - 1.2.3.4 - - 5.6.7.8 - search_domains: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['search_domain'] }}" - register: vmware_host_dns_result_0013 - - - name: Ensure DNS config was changed - assert: - that: - - vmware_host_dns_result_0013 is changed - - # Testcase 0014: Ensure changing the search domains on the cluster works - - name: Ensure changing the search domains on the cluster works - vmware_host_dns: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: "{{ ccr1 }}" - validate_certs: False - type: 'static' - domain: new.domain - dns_servers: - - 1.2.3.4 - - 5.6.7.8 - search_domains: - - subdomain.example.local - - example.local - register: vmware_host_dns_result_0014 - - - name: Ensure DNS config was changed - assert: - that: - - vmware_host_dns_result_0014 is changed - - # Testcase 0015: Ensure changing DNS config on the cluster from static to DHCP works - - name: Ensure changing DNS config on the cluster from static to DHCP works - vmware_host_dns: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: "{{ ccr1 }}" - validate_certs: False - type: 'dhcp' - device: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['virtual_nic_device'] }}" - register: vmware_host_dns_result_0015 - - - name: Ensure DNS config was changed - assert: - that: - - vmware_host_dns_result_0015 is changed - - always: - # Revert to original DNS configuration - - name: Revert to original DNS configuration - vmware_host_dns: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: "{{ item }}" - validate_certs: False - type: 'dhcp' - device: "{{ dns['results'][index]['hosts_dns_info'][esxi1]['virtual_nic_device'] }}" - loop: "{{ esxi_hosts }}" - loop_control: - index_var: index diff --git a/test/integration/targets/vmware_host_dns/tasks/main.yml b/test/integration/targets/vmware_host_dns/tasks/main.yml deleted file mode 100644 index 2c247c515d..0000000000 --- a/test/integration/targets/vmware_host_dns/tasks/main.yml +++ /dev/null @@ -1,28 +0,0 @@ -# Test code for the vmware_host_dns module. -# Copyright: (c) 2019, Mario Lenz <m@riolenz.de> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# This tests assume that all ESXi hosts either have a static or a dynamic DNS -# configuration. They probably will fail if on host is 'static' and the other -# is 'dhcp' configured. -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - - name: Gather DNS facts about ESXi Host - vmware_host_dns_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: "{{ item }}" - validate_certs: False - loop: "{{ esxi_hosts }}" - register: dns - - - include_tasks: dhcp.yml - when: dns['results'][0]['hosts_dns_info'][esxi1]['dhcp'] - - include_tasks: static.yml - when: not dns['results'][0]['hosts_dns_info'][esxi1]['dhcp'] diff --git a/test/integration/targets/vmware_host_dns/tasks/static.yml b/test/integration/targets/vmware_host_dns/tasks/static.yml deleted file mode 100644 index e69f50ac11..0000000000 --- a/test/integration/targets/vmware_host_dns/tasks/static.yml +++ /dev/null @@ -1,225 +0,0 @@ -- name: Tests when the hosts have a static DNS config - block: - # Testcase 0001: Ensure DNS config directly on the host is idempotent for static - - name: Ensure static DNS config is idempotent when done directly on the host - vmware_host_dns: - hostname: '{{ esxi1 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - validate_certs: False - type: 'static' - host_name: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['host_name'] }}" - domain: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['domain_name'] }}" - dns_servers: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['ip_address'] }}" - search_domains: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['search_domain'] }}" - register: vmware_host_dns_result_0001 - - - name: Ensure DNS config wasn't changed - assert: - that: - - vmware_host_dns_result_0001 is not changed - - # Testcase 0002: Ensure changing the hostname directly on the host works - - name: Ensure changing the hostname directly on the host works - vmware_host_dns: - hostname: '{{ esxi1 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - validate_certs: False - type: 'static' - host_name: newname - domain: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['domain_name'] }}" - dns_servers: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['ip_address'] }}" - search_domains: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['search_domain'] }}" - register: vmware_host_dns_result_0002 - - - name: Ensure DNS config was changed - assert: - that: - - vmware_host_dns_result_0002 is changed - - # Testcase 0003: Ensure changing the domain directly on the host works - - name: Ensure changing the domain directly on the host works - vmware_host_dns: - hostname: '{{ esxi1 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - validate_certs: False - type: 'static' - host_name: newname - domain: new.domain - dns_servers: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['ip_address'] }}" - search_domains: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['search_domain'] }}" - register: vmware_host_dns_result_0003 - - - name: Ensure DNS config was changed - assert: - that: - - vmware_host_dns_result_0003 is changed - - # Testcase 0004: Ensure changing the DNS servers directly on the host works - - name: Ensure changing the domain directly on the host works - vmware_host_dns: - hostname: '{{ esxi1 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - validate_certs: False - type: 'static' - host_name: newname - domain: new.domain - dns_servers: - - 1.2.3.4 - - 5.6.7.8 - search_domains: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['search_domain'] }}" - register: vmware_host_dns_result_0004 - - - name: Ensure DNS config was changed - assert: - that: - - vmware_host_dns_result_0004 is changed - - # Testcase 0005: Ensure changing the search domain directly on the host works - - name: Ensure changing the domain directly on the host works - vmware_host_dns: - hostname: '{{ esxi1 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - validate_certs: False - type: 'static' - host_name: newname - domain: new.domain - dns_servers: - - 1.2.3.4 - - 5.6.7.8 - search_domains: - - subdomain.example.local - - example.local - register: vmware_host_dns_result_0005 - - - name: Ensure DNS config was changed - assert: - that: - - vmware_host_dns_result_0005 is changed - - # Revert to original DNS configuration with a different search_domains - - name: Revert to original DNS configuration - vmware_host_dns: - hostname: '{{ esxi1 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - validate_certs: False - type: 'static' - host_name: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['host_name'] }}" - domain: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['domain_name'] }}" - dns_servers: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['ip_address'] }}" - search_domains: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['search_domain'] }}" - - # Testcase 0006: Ensure DNS config on the cluster is idempotent for static - - name: Apply configuration on a cluster - vmware_host_dns: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: "{{ ccr1 }}" - validate_certs: False - type: 'static' - search_domains: "different-search-domain" - register: vmware_host_dns_result_0006 - - - name: Ensure configuration has changed - assert: - that: - - vmware_host_dns_result_0006 is changed - - - name: Revert to original DNS configuration - vmware_host_dns: - hostname: '{{ esxi1 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - validate_certs: False - type: 'static' - host_name: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['host_name'] }}" - domain: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['domain_name'] }}" - dns_servers: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['ip_address'] }}" - search_domains: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['search_domain'] }}" - - # Testcase 0007: Ensure changing the domain on the cluster works - - name: Ensure changing the domain on the cluster works - vmware_host_dns: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: "{{ ccr1 }}" - validate_certs: False - type: 'static' - domain: new.domain - dns_servers: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['ip_address'] }}" - search_domains: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['search_domain'] }}" - register: vmware_host_dns_result_0007 - - - name: Ensure DNS config was changed - assert: - that: - - vmware_host_dns_result_0007 is changed - - # Testcase 0008: Ensure changing the DNS servers on the cluster works - - name: Ensure changing the DNS servers on the cluster works - vmware_host_dns: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: "{{ ccr1 }}" - validate_certs: False - type: 'static' - domain: new.domain - dns_servers: - - 1.2.3.4 - - 5.6.7.8 - search_domains: "{{ dns['results'][0]['hosts_dns_info'][esxi1]['search_domain'] }}" - register: vmware_host_dns_result_0008 - - - name: Ensure DNS config was changed - assert: - that: - - vmware_host_dns_result_0008 is changed - - # Testcase 0009: Ensure changing the search domains on the cluster works - - name: Ensure changing the search domains on the cluster works - vmware_host_dns: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - cluster_name: "{{ ccr1 }}" - validate_certs: False - type: 'static' - domain: new.domain - dns_servers: - - 1.2.3.4 - - 5.6.7.8 - search_domains: - - subdomain.example.local - - example.local - register: vmware_host_dns_result_0009 - - - name: Ensure DNS config was changed - assert: - that: - - vmware_host_dns_result_0009 is changed - - always: - # Revert to original DNS configuration - - name: Revert to original DNS configuration - vmware_host_dns: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - esxi_hostname: "{{ item }}" - validate_certs: False - type: 'static' - host_name: "{{ dns['results'][index]['hosts_dns_info'][item]['host_name'] }}" - domain: "{{ dns['results'][index]['hosts_dns_info'][item]['domain_name'] }}" - dns_servers: "{{ dns['results'][index]['hosts_dns_info'][item]['ip_address'] }}" - search_domains: "{{ dns['results'][index]['hosts_dns_info'][item]['search_domain'] }}" - loop: "{{ esxi_hosts }}" - loop_control: - index_var: index diff --git a/test/integration/targets/vmware_host_dns_facts/aliases b/test/integration/targets/vmware_host_dns_facts/aliases deleted file mode 100644 index 527c737768..0000000000 --- a/test/integration/targets/vmware_host_dns_facts/aliases +++ /dev/null @@ -1,5 +0,0 @@ -shippable/vcenter/group2 -cloud/vcenter - -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_dns_facts/tasks/main.yml b/test/integration/targets/vmware_host_dns_facts/tasks/main.yml deleted file mode 100644 index 09865d05db..0000000000 --- a/test/integration/targets/vmware_host_dns_facts/tasks/main.yml +++ /dev/null @@ -1,70 +0,0 @@ -# Test code for the vmware_host_dns_facts module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - -- name: gather DNS facts about all hosts in given cluster - vmware_host_dns_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: "{{ ccr1 }}" - validate_certs: no - register: all_hosts_dns_result - -- name: ensure DNS facts are gathered for all hosts in given cluster - assert: - that: - - all_hosts_dns_result.hosts_dns_facts - - not all_hosts_dns_result.changed - -- name: gather DNS facts about host system - vmware_host_dns_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - register: all_hosts_dns_result - -- name: ensure DNS facts are gathered about host system - assert: - that: - - all_hosts_dns_result.hosts_dns_facts - - not all_hosts_dns_result.changed - -- name: gather DNS facts about all hosts in given cluster in check mode - vmware_host_dns_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: "{{ ccr1 }}" - validate_certs: no - register: all_hosts_dns_result_check_mode - check_mode: yes - -- name: ensure DNS facts are gathered for all hosts in given cluster - assert: - that: - - all_hosts_dns_result_check_mode.hosts_dns_facts - - not all_hosts_dns_result_check_mode.changed - -- name: gather DNS facts about host system in check mode - vmware_host_dns_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - register: all_hosts_dns_result_check_mode - check_mode: yes - -- name: ensure DNS facts are gathered about host system - assert: - that: - - all_hosts_dns_result_check_mode.hosts_dns_facts - - not all_hosts_dns_result_check_mode.changed diff --git a/test/integration/targets/vmware_host_dns_info/aliases b/test/integration/targets/vmware_host_dns_info/aliases deleted file mode 100644 index 527c737768..0000000000 --- a/test/integration/targets/vmware_host_dns_info/aliases +++ /dev/null @@ -1,5 +0,0 @@ -shippable/vcenter/group2 -cloud/vcenter - -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_dns_info/tasks/main.yml b/test/integration/targets/vmware_host_dns_info/tasks/main.yml deleted file mode 100644 index cc732ff220..0000000000 --- a/test/integration/targets/vmware_host_dns_info/tasks/main.yml +++ /dev/null @@ -1,70 +0,0 @@ -# Test code for the vmware_host_dns_info module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - -- name: gather DNS info about all hosts in given cluster - vmware_host_dns_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: "{{ ccr1 }}" - validate_certs: no - register: all_hosts_dns_result - -- name: ensure DNS info are gathered for all hosts in given cluster - assert: - that: - - all_hosts_dns_result.hosts_dns_info - - not all_hosts_dns_result.changed - -- name: gather DNS info about host system - vmware_host_dns_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - register: all_hosts_dns_result - -- name: ensure DNS info are gathered about host system - assert: - that: - - all_hosts_dns_result.hosts_dns_info - - not all_hosts_dns_result.changed - -- name: gather DNS info about all hosts in given cluster in check mode - vmware_host_dns_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: "{{ ccr1 }}" - validate_certs: no - register: all_hosts_dns_result_check_mode - check_mode: yes - -- name: ensure DNS info are gathered for all hosts in given cluster - assert: - that: - - all_hosts_dns_result_check_mode.hosts_dns_info - - not all_hosts_dns_result_check_mode.changed - -- name: gather DNS info about host system in check mode - vmware_host_dns_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - register: all_hosts_dns_result_check_mode - check_mode: yes - -- name: ensure DNS info are gathered about host system - assert: - that: - - all_hosts_dns_result_check_mode.hosts_dns_info - - not all_hosts_dns_result_check_mode.changed diff --git a/test/integration/targets/vmware_host_facts/aliases b/test/integration/targets/vmware_host_facts/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_host_facts/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_facts/tasks/main.yml b/test/integration/targets/vmware_host_facts/tasks/main.yml deleted file mode 100644 index aba1bbccf1..0000000000 --- a/test/integration/targets/vmware_host_facts/tasks/main.yml +++ /dev/null @@ -1,93 +0,0 @@ -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - name: get host facts through a vcenter - vmware_host_facts: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - register: facts - - debug: var=facts - - name: verify some data,like ansible_processor - assert: - that: - - "'ansible_hostname' in facts['ansible_facts']" - - "'ansible_processor' in facts['ansible_facts']" - - "'ansible_in_maintenance_mode' in facts['ansible_facts']" - - "'ansible_uptime' in facts['ansible_facts']" - - "'ansible_uuid' in facts['ansible_facts']" - - - name: get host facts through from a host - vmware_host_facts: - validate_certs: False - hostname: '{{ esxi1 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - register: facts - - debug: var=facts - - name: verify some data,like ansible_processor - assert: - that: - - "'ansible_hostname' in facts['ansible_facts']" - - "'ansible_processor' in facts['ansible_facts']" - - "'ansible_in_maintenance_mode' in facts['ansible_facts']" - - "'ansible_uptime' in facts['ansible_facts']" - - "'ansible_uuid' in facts['ansible_facts']" - - - name: get host properties facts through a vcenter - vmware_host_facts: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - schema: vsphere - properties: - - hardware.memorySize - - hardware.cpuInfo.numCpuCores - - config.product.apiVersion - - overallStatus - register: facts - - debug: var=facts - - name: verify some data,like ansible_processor - assert: - that: - - "'hardware' in facts['ansible_facts']" - - "'config' in facts['ansible_facts']" - - "'overallStatus' in facts['ansible_facts']" - - "'memorySize' in facts['ansible_facts']['hardware']" - - "'cpuInfo' in facts['ansible_facts']['hardware']" - - "'numCpuCores' in facts['ansible_facts']['hardware']['cpuInfo']" - - "'product' in facts['ansible_facts']['config']" - - "'apiVersion' in facts['ansible_facts']['config']['product']" - - - name: get host properties facts through from a host - vmware_host_facts: - validate_certs: False - hostname: '{{ esxi1 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - schema: vsphere - properties: - - hardware.memorySize - - hardware.cpuInfo.numCpuCores - - config.product.apiVersion - - overallStatus - register: facts - - debug: var=facts - - name: verify some data,like ansible_processor - assert: - that: - - "'hardware' in facts['ansible_facts']" - - "'config' in facts['ansible_facts']" - - "'overallStatus' in facts['ansible_facts']" - - "'memorySize' in facts['ansible_facts']['hardware']" - - "'cpuInfo' in facts['ansible_facts']['hardware']" - - "'numCpuCores' in facts['ansible_facts']['hardware']['cpuInfo']" - - "'product' in facts['ansible_facts']['config']" - - "'apiVersion' in facts['ansible_facts']['config']['product']" diff --git a/test/integration/targets/vmware_host_feature_facts/aliases b/test/integration/targets/vmware_host_feature_facts/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_host_feature_facts/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_feature_facts/tasks/main.yml b/test/integration/targets/vmware_host_feature_facts/tasks/main.yml deleted file mode 100644 index cfc85db0b3..0000000000 --- a/test/integration/targets/vmware_host_feature_facts/tasks/main.yml +++ /dev/null @@ -1,77 +0,0 @@ -# Test code for the vmware_host_feature_facts module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# TODO: vcsim does not support host feature capabilities -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - -- name: Gather feature capability facts for all ESXi host from given cluster - vmware_host_feature_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - cluster_name: "{{ ccr1 }}" - register: capability_0001_results - -- debug: var=capability_0001_results - -- assert: - that: - - "not capability_0001_results.changed" - - "capability_0001_results.hosts_feature_facts is defined" - -- name: Gather feature capability facts for all ESXi host from given cluster in check mode - vmware_host_feature_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - cluster_name: "{{ ccr1 }}" - register: capability_0001_results - check_mode: yes - -- debug: var=capability_0001_results - -- assert: - that: - - "not capability_0001_results.changed" - - "capability_0001_results.hosts_feature_facts is defined" - -- name: Gather feature capability facts for ESXi host - vmware_host_feature_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: '{{ esxi1 }}' - register: capability_0002_results - -- debug: var=capability_0002_results - -- assert: - that: - - "not capability_0002_results.changed" - - "capability_0002_results.hosts_feature_facts is defined" - - -- name: Gather feature capability facts for ESXi host in check mode - vmware_host_feature_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: '{{ esxi1 }}' - register: capability_0002_results - check_mode: yes - -- debug: var=capability_0002_results - -- assert: - that: - - "not capability_0002_results.changed" - - "capability_0002_results.hosts_feature_facts is defined" diff --git a/test/integration/targets/vmware_host_feature_info/aliases b/test/integration/targets/vmware_host_feature_info/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_host_feature_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_feature_info/tasks/main.yml b/test/integration/targets/vmware_host_feature_info/tasks/main.yml deleted file mode 100644 index 3b57020815..0000000000 --- a/test/integration/targets/vmware_host_feature_info/tasks/main.yml +++ /dev/null @@ -1,77 +0,0 @@ -# Test code for the vmware_host_feature_info module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# TODO: vcsim does not support host feature capabilities -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - -- name: Gather feature capability info for all ESXi host from given cluster - vmware_host_feature_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - cluster_name: "{{ ccr1 }}" - register: capability_0001_results - -- debug: var=capability_0001_results - -- assert: - that: - - "not capability_0001_results.changed" - - "capability_0001_results.hosts_feature_info is defined" - -- name: Gather feature capability info for all ESXi host from given cluster in check mode - vmware_host_feature_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - cluster_name: "{{ ccr1 }}" - register: capability_0001_results - check_mode: yes - -- debug: var=capability_0001_results - -- assert: - that: - - "not capability_0001_results.changed" - - "capability_0001_results.hosts_feature_info is defined" - -- name: Gather feature capability info for ESXi host - vmware_host_feature_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: '{{ esxi1 }}' - register: capability_0002_results - -- debug: var=capability_0002_results - -- assert: - that: - - "not capability_0002_results.changed" - - "capability_0002_results.hosts_feature_info is defined" - - -- name: Gather feature capability info for ESXi host in check mode - vmware_host_feature_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: '{{ esxi1 }}' - register: capability_0002_results - check_mode: yes - -- debug: var=capability_0002_results - -- assert: - that: - - "not capability_0002_results.changed" - - "capability_0002_results.hosts_feature_info is defined" diff --git a/test/integration/targets/vmware_host_firewall_facts/aliases b/test/integration/targets/vmware_host_firewall_facts/aliases deleted file mode 100644 index 527c737768..0000000000 --- a/test/integration/targets/vmware_host_firewall_facts/aliases +++ /dev/null @@ -1,5 +0,0 @@ -shippable/vcenter/group2 -cloud/vcenter - -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_firewall_facts/tasks/main.yml b/test/integration/targets/vmware_host_firewall_facts/tasks/main.yml deleted file mode 100644 index e58e8f1fc9..0000000000 --- a/test/integration/targets/vmware_host_firewall_facts/tasks/main.yml +++ /dev/null @@ -1,73 +0,0 @@ -# Test code for the vmware_host_firewall_facts module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - -- name: Gather firewall facts for a given ESXi - vmware_host_firewall_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: '{{ esxi1 }}' - register: firewall_0004_results - check_mode: yes - -- assert: - that: - - "not firewall_0004_results.changed" - - "firewall_0004_results.hosts_firewall_facts is defined" - - -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - - name: Gather firewall facts for all ESXi host from given cluster - vmware_host_firewall_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - cluster_name: "{{ ccr1 }}" - register: firewall_0001_results - - - assert: - that: - - "not firewall_0001_results.changed" - - "firewall_0001_results.hosts_firewall_facts is defined" - - - name: Gather firewall facts for ESXi host - vmware_host_firewall_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: '{{ esxi1 }}' - register: firewall_0002_results - - - assert: - that: - - "not firewall_0002_results.changed" - - "firewall_0002_results.hosts_firewall_facts is defined" - - - name: Gather firewall facts for all ESXi host from given cluster in check mode - vmware_host_firewall_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - cluster_name: "{{ ccr1 }}" - register: firewall_0003_results - check_mode: yes - - - assert: - that: - - "not firewall_0003_results.changed" - - "firewall_0003_results.hosts_firewall_facts is defined" diff --git a/test/integration/targets/vmware_host_firewall_info/aliases b/test/integration/targets/vmware_host_firewall_info/aliases deleted file mode 100644 index 527c737768..0000000000 --- a/test/integration/targets/vmware_host_firewall_info/aliases +++ /dev/null @@ -1,5 +0,0 @@ -shippable/vcenter/group2 -cloud/vcenter - -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_firewall_info/tasks/main.yml b/test/integration/targets/vmware_host_firewall_info/tasks/main.yml deleted file mode 100644 index 29a8b610d0..0000000000 --- a/test/integration/targets/vmware_host_firewall_info/tasks/main.yml +++ /dev/null @@ -1,73 +0,0 @@ -# Test code for the vmware_host_firewall_info module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - -- name: Gather firewall info for a given ESXi - vmware_host_firewall_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: '{{ esxi1 }}' - register: firewall_0004_results - check_mode: yes - -- assert: - that: - - "not firewall_0004_results.changed" - - "firewall_0004_results.hosts_firewall_info is defined" - - -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - - name: Gather firewall info for all ESXi host from given cluster - vmware_host_firewall_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - cluster_name: "{{ ccr1 }}" - register: firewall_0001_results - - - assert: - that: - - "not firewall_0001_results.changed" - - "firewall_0001_results.hosts_firewall_info is defined" - - - name: Gather firewall info for ESXi host - vmware_host_firewall_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: '{{ esxi1 }}' - register: firewall_0002_results - - - assert: - that: - - "not firewall_0002_results.changed" - - "firewall_0002_results.hosts_firewall_info is defined" - - - name: Gather firewall info for all ESXi host from given cluster in check mode - vmware_host_firewall_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - cluster_name: "{{ ccr1 }}" - register: firewall_0003_results - check_mode: yes - - - assert: - that: - - "not firewall_0003_results.changed" - - "firewall_0003_results.hosts_firewall_info is defined" diff --git a/test/integration/targets/vmware_host_firewall_manager/aliases b/test/integration/targets/vmware_host_firewall_manager/aliases deleted file mode 100644 index 25f9cd8975..0000000000 --- a/test/integration/targets/vmware_host_firewall_manager/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group2 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_2esxi diff --git a/test/integration/targets/vmware_host_firewall_manager/tasks/main.yml b/test/integration/targets/vmware_host_firewall_manager/tasks/main.yml deleted file mode 100644 index f96acb9841..0000000000 --- a/test/integration/targets/vmware_host_firewall_manager/tasks/main.yml +++ /dev/null @@ -1,222 +0,0 @@ -# Test code for the vmware_host_firewall_manager module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - - name: Enable vvold rule set on all hosts of {{ ccr1 }} - vmware_host_firewall_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - cluster_name: "{{ ccr1 }}" - rules: - - name: vvold - enabled: True - register: all_hosts_result - - debug: msg="{{ all_hosts_result }}" - - name: ensure everything is changed for all hosts of {{ ccr1 }} - assert: - that: - - all_hosts_result.changed - - all_hosts_result.rule_set_state is defined - - - name: ensure info are gathered for all hosts of {{ ccr1 }} - assert: - that: - - all_hosts_result.rule_set_state[item]['vvold']['current_state'] == True - - all_hosts_result.rule_set_state[item]['vvold']['desired_state'] == True - - all_hosts_result.rule_set_state[item]['vvold']['previous_state'] == False - with_items: - - '{{ esxi1 }}' - - '{{ esxi2 }}' - - - name: Disable vvold for {{ host1 }} - vmware_host_firewall_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: '{{ esxi1 }}' - rules: - - name: vvold - enabled: False - register: host_result - - debug: msg="{{ host_result }}" - - name: ensure vvold is disabled for {{ host1 }} - assert: - that: - - host_result.changed - - host_result.rule_set_state is defined - - - name: ensure info are gathered for {{ host1 }} - assert: - that: - - host_result.rule_set_state[item]['vvold']['current_state'] == False - - host_result.rule_set_state[item]['vvold']['desired_state'] == False - - host_result.rule_set_state[item]['vvold']['previous_state'] == True - with_items: - - '{{ esxi1 }}' - - - name: Enable vvold rule set on all hosts of {{ ccr1 }} in check mode - vmware_host_firewall_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - cluster_name: "{{ ccr1 }}" - rules: - - name: vvold - enabled: True - register: all_hosts_result_check_mode - check_mode: yes - - debug: var=all_hosts_result_check_mode - - name: ensure everything is changed for all hosts of {{ ccr1 }} - assert: - that: - - all_hosts_result_check_mode.changed - - all_hosts_result_check_mode.rule_set_state is defined - - - name: ensure info are gathered for all hosts of {{ ccr1 }} - assert: - that: - - all_hosts_result_check_mode.rule_set_state[esxi1]['vvold']['current_state'] == True - - all_hosts_result_check_mode.rule_set_state[esxi2]['vvold']['current_state'] == True - - all_hosts_result_check_mode.rule_set_state[esxi2]['vvold']['desired_state'] == True - - - name: Disable vvold for {{ host1 }} in check mode - vmware_host_firewall_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: '{{ esxi1 }}' - rules: - - name: vvold - enabled: False - register: host_result_check_mode - check_mode: yes - - debug: msg="{{ host_result_check_mode }}" - - name: ensure vvold is disabled for {{ host1 }} - assert: - that: - - host_result_check_mode.changed == False - - host_result_check_mode.rule_set_state is defined - - - name: ensure info are gathered for {{ host1 }} - assert: - that: - - host_result_check_mode.rule_set_state[item]['vvold']['current_state'] == False - - host_result_check_mode.rule_set_state[item]['vvold']['desired_state'] == False - - host_result_check_mode.rule_set_state[item]['vvold']['previous_state'] == False - with_items: - - '{{ esxi1 }}' - - - name: Configure CIMHttpServer rule set on all hosts of {{ ccr1 }} - vmware_host_firewall_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - cluster_name: "{{ ccr1 }}" - rules: - - name: CIMHttpServer - enabled: True - allowed_hosts: - all_ip: False - ip_address: - - "192.168.100.11" - - "192.168.100.12" - ip_network: - - "192.168.200.0/24" - register: all_hosts_ip_specific - - debug: var=all_hosts_ip_specific - - name: ensure everything is changed for all hosts of {{ ccr1 }} - assert: - that: - - all_hosts_ip_specific.changed - - all_hosts_ip_specific.rule_set_state is defined - - - name: ensure CIMHttpServer is configured for all hosts in {{ ccr1 }} - assert: - that: - - all_hosts_ip_specific.rule_set_state[item]['CIMHttpServer']['current_state'] == True - - all_hosts_ip_specific.rule_set_state[item]['CIMHttpServer']['desired_state'] == True - - all_hosts_ip_specific.rule_set_state[item]['CIMHttpServer']['previous_state'] == True - - all_hosts_ip_specific.rule_set_state[item]['CIMHttpServer']['allowed_hosts']['current_allowed_all'] == False - - all_hosts_ip_specific.rule_set_state[item]['CIMHttpServer']['allowed_hosts']['previous_allowed_all'] == True - - all_hosts_ip_specific.rule_set_state[item]['CIMHttpServer']['allowed_hosts']['desired_allowed_all'] == False - - "'192.168.100.11' in all_hosts_ip_specific.rule_set_state[item]['CIMHttpServer']['allowed_hosts']['current_allowed_ip']" - - "'192.168.100.12' in all_hosts_ip_specific.rule_set_state[item]['CIMHttpServer']['allowed_hosts']['current_allowed_ip']" - - all_hosts_ip_specific.rule_set_state[item]['CIMHttpServer']['allowed_hosts']['previous_allowed_ip'] == [] - - "'192.168.100.11' in all_hosts_ip_specific.rule_set_state[item]['CIMHttpServer']['allowed_hosts']['desired_allowed_ip']" - - "'192.168.100.12' in all_hosts_ip_specific.rule_set_state[item]['CIMHttpServer']['allowed_hosts']['desired_allowed_ip']" - - all_hosts_ip_specific.rule_set_state[item]['CIMHttpServer']['allowed_hosts']['current_allowed_networks'] == ["192.168.200.0/24"] - - all_hosts_ip_specific.rule_set_state[item]['CIMHttpServer']['allowed_hosts']['previous_allowed_networks'] == [] - - all_hosts_ip_specific.rule_set_state[item]['CIMHttpServer']['allowed_hosts']['desired_allowed_networks'] == ["192.168.200.0/24"] - with_items: - - '{{ esxi1 }}' - - '{{ esxi2 }}' - - - name: Configure the NFC firewall rule to only allow traffic from one IP on one ESXi host - vmware_host_firewall_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - rules: - - name: NFC - enabled: True - allowed_hosts: - all_ip: False - ip_address: - - "192.168.100.11" - register: single_host_ip_specific - - set_fact: - nfc_state: "{{ single_host_ip_specific.rule_set_state[esxi1]['NFC'] }}" - - debug: var=single_host_ip_specific - - debug: var=nfc_state - - name: ensure NFC is configured on that host - assert: - that: - - nfc_state.current_state == true - - nfc_state.desired_state == true - - nfc_state.previous_state == true - - nfc_state.allowed_hosts.current_allowed_all == False - - nfc_state.allowed_hosts.previous_allowed_all == True - - nfc_state.allowed_hosts.desired_allowed_all == False - - nfc_state.allowed_hosts.current_allowed_ip == ["192.168.100.11"] - - nfc_state.allowed_hosts.previous_allowed_all == True - - nfc_state.allowed_hosts.desired_allowed_ip == ["192.168.100.11"] - - nfc_state.allowed_hosts.current_allowed_networks == [] - - nfc_state.allowed_hosts.previous_allowed_networks == [] - - nfc_state.allowed_hosts.desired_allowed_networks == [] - - - name: Ensure we can still pass the allowed_hosts configuration through a list for compat - vmware_host_firewall_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: "{{ esxi1 }}" - rules: - - name: NFC - enabled: True - allowed_hosts: - - all_ip: False - ip_address: - - "1.2.3.4" - register: using_list - - debug: var=using_list - - set_fact: - nfc_state: "{{ using_list.rule_set_state[esxi1]['NFC'] }}" - - name: ensure the correct host is set - assert: - that: - - nfc_state.allowed_hosts.current_allowed_ip == ["1.2.3.4"] diff --git a/test/integration/targets/vmware_host_hyperthreading/aliases b/test/integration/targets/vmware_host_hyperthreading/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_host_hyperthreading/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_hyperthreading/tasks/main.yml b/test/integration/targets/vmware_host_hyperthreading/tasks/main.yml deleted file mode 100644 index f3f4cd8edf..0000000000 --- a/test/integration/targets/vmware_host_hyperthreading/tasks/main.yml +++ /dev/null @@ -1,92 +0,0 @@ -# Test code for the vmware_host_hyperthreading module. -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# Hyperthreading optimization is not available for hosts in vcsim -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - -- name: Enable Hyperthreading everywhere - vmware_host_hyperthreading: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - state: disabled - register: enable_hyperthreading_everywhere - ignore_errors: true - -- when: enable_hyperthreading_everywhere is succeeded - block: - - - name: Disable Hyperthreading for a given host - vmware_host_hyperthreading: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - state: disabled - register: host_hyperthreading_info - - - debug: var=host_hyperthreading_info - - - assert: - that: - - host_hyperthreading_info is defined - - host_hyperthreading_info.changed - - - name: Disable Hyperthreading for a given host in check mode - vmware_host_hyperthreading: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - state: disabled - register: host_hyperthreading_info_check_mode - check_mode: yes - - - debug: var=host_hyperthreading_info_check_mode - - - assert: - that: - - host_hyperthreading_info_check_mode is defined - - - name: Disable Hyperthreading for all hosts in given cluster - vmware_host_hyperthreading: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: "{{ ccr1 }}" - validate_certs: no - state: disabled - register: host_hyperthreading_info - - - debug: var=host_hyperthreading_info - - - assert: - that: - - host_hyperthreading_info is defined - - host_hyperthreading_info is changed - - - name: Enable Hyperthreading for all hosts in given cluster in check mode - vmware_host_hyperthreading: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: "{{ ccr1 }}" - validate_certs: no - state: enabled - register: host_hyperthreading_info_check_mode - check_mode: yes - - - debug: var=host_hyperthreading_info_check_mode - - - assert: - that: - - host_hyperthreading_info_check_mode is defined - - host_hyperthreading_info_check_mode.changed diff --git a/test/integration/targets/vmware_host_ipv6/aliases b/test/integration/targets/vmware_host_ipv6/aliases deleted file mode 100644 index e96093f00c..0000000000 --- a/test/integration/targets/vmware_host_ipv6/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group2 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_ipv6/tasks/main.yml b/test/integration/targets/vmware_host_ipv6/tasks/main.yml deleted file mode 100644 index 95184b44c2..0000000000 --- a/test/integration/targets/vmware_host_ipv6/tasks/main.yml +++ /dev/null @@ -1,91 +0,0 @@ -# Test code for the vmware_host_ipv6 module. -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - - name: Ensure IPv6 is off - vmware_host_ipv6: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: "{{ ccr1 }}" - validate_certs: no - state: disabled - register: host_ipv6_info - - - name: Enable IPv6 support for a given host - vmware_host_ipv6: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - state: enabled - register: host_ipv6_info - - debug: var=host_ipv6_info - - assert: - that: - - host_ipv6_info is defined - - host_ipv6_info.changed - - - name: Enable IPv6 support for a given host in check mode - vmware_host_ipv6: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - state: enabled - register: host_ipv6_info_check_mode - check_mode: yes - - debug: var=host_ipv6_info_check_mode - - assert: - that: - - host_ipv6_info_check_mode is defined - - not (host_ipv6_info_check_mode is changed) - - - name: Reset the status again - vmware_host_ipv6: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: "{{ ccr1 }}" - validate_certs: no - state: disabled - register: host_ipv6_info - - - name: Enable IPv6 support for all hosts in given cluster - vmware_host_ipv6: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: "{{ ccr1 }}" - validate_certs: no - state: enabled - register: hosts_ipv6_info - - debug: var=hosts_ipv6_info - - assert: - that: - - hosts_ipv6_info is defined - - hosts_ipv6_info.changed - - - name: Enable IPv6 support for all hosts in given cluster in check mode - vmware_host_ipv6: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: "{{ ccr1 }}" - validate_certs: no - state: enabled - register: hosts_ipv6_info_check_mode - check_mode: yes - - debug: var=hosts_ipv6_info_check_mode - - assert: - that: - - hosts_ipv6_info_check_mode is defined - - not (hosts_ipv6_info_check_mode is changed) diff --git a/test/integration/targets/vmware_host_kernel_manager/aliases b/test/integration/targets/vmware_host_kernel_manager/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_host_kernel_manager/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_kernel_manager/tasks/main.yml b/test/integration/targets/vmware_host_kernel_manager/tasks/main.yml deleted file mode 100644 index 5204e0d061..0000000000 --- a/test/integration/targets/vmware_host_kernel_manager/tasks/main.yml +++ /dev/null @@ -1,52 +0,0 @@ -# test code for the vmware_host_kernel_manager module -# Copyright: (c) 2019, Aaron Longchamps <a.j.longchamps@gmail.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - - - name: First, set ipv6=0, for consistency - vmware_host_kernel_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: False - esxi_hostname: '{{ esxi1 }}' - kernel_module_name: "tcpip4" - kernel_module_option: "ipv6=0" - - - name: host connected, module exists, options exist, arguments different - vmware_host_kernel_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: False - esxi_hostname: '{{ esxi1 }}' - kernel_module_name: "tcpip4" - kernel_module_option: "ipv6=0" - register: my_results_01 - - debug: var=my_results_01 - - name: Check that the provided kernel_module_name has kernel_module_option set - assert: - that: - - "'original_options' in my_results_01['host_kernel_status']['{{ esxi1 }}']" - - "my_results_01['host_kernel_status']['{{ esxi1 }}'].original_options == 'ipv6=0'" - - - name: host connected, module exists, same options for idempotence test - vmware_host_kernel_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: False - esxi_hostname: '{{ esxi1 }}' - kernel_module_name: "tcpip4" - kernel_module_option: "ipv6=0" - register: my_results_02 - - name: Check that changed is false - assert: - that: - - not (my_results_02 is changed) diff --git a/test/integration/targets/vmware_host_ntp/aliases b/test/integration/targets/vmware_host_ntp/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_host_ntp/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_ntp/tasks/main.yml b/test/integration/targets/vmware_host_ntp/tasks/main.yml deleted file mode 100644 index 79a959b29f..0000000000 --- a/test/integration/targets/vmware_host_ntp/tasks/main.yml +++ /dev/null @@ -1,168 +0,0 @@ -# Test code for the vmware_host_ntp module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# TODO: vcsim does not support update host NTP configuration -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - - name: Add NTP server to a host - vmware_host_ntp: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - state: present - ntp_servers: - - 0.pool.ntp.org - validate_certs: no - register: present - - debug: var=present - - - name: Add another NTP server to a host - vmware_host_ntp: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - state: present - ntp_servers: - - 1.pool.ntp.org - validate_certs: no - register: present - - debug: var=present - - - name: Remove NTP server from a host - vmware_host_ntp: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - state: absent - ntp_servers: - - 1.pool.ntp.org - validate_certs: no - register: absent_one - - debug: var=absent_one - - - name: Remove NTP server from a host - vmware_host_ntp: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - state: present - ntp_servers: - - 1.pool.ntp.org - validate_certs: no - register: present - - debug: var=present - - - name: Add more NTP servers to a host - vmware_host_ntp: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - state: present - ntp_servers: - - 2.pool.ntp.org - - 3.pool.ntp.org - - 4.pool.ntp.org - validate_certs: no - register: present - - debug: var=present - - - name: Remove all NTP servers from a host - vmware_host_ntp: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - state: absent - ntp_servers: - - 0.pool.ntp.org - - 1.pool.ntp.org - - 2.pool.ntp.org - - 3.pool.ntp.org - - 4.pool.ntp.org - - 6.pool.ntp.org - validate_certs: no - register: absent_all - - debug: var=absent_all - - - name: Configure NTP servers for a host - vmware_host_ntp: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - ntp_servers: - - 0.pool.ntp.org - - 1.pool.ntp.org - - 2.pool.ntp.org - validate_certs: no - register: ntp_servers - - debug: var=ntp_servers - - - name: Configure NTP servers for a host - vmware_host_ntp: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - ntp_servers: - - 3.pool.ntp.org - - 4.pool.ntp.org - - 5.pool.ntp.org - verbose: true - validate_certs: no - register: ntp_servers - - debug: var=ntp_servers - - - name: Add NTP server to a host in check mode - vmware_host_ntp: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - state: present - ntp_servers: - - 0.pool.ntp.org - validate_certs: no - register: present - check_mode: yes - - debug: var=present - - - name: Remove NTP server to a host in check mode - vmware_host_ntp: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - state: absent - ntp_servers: - - 0.pool.ntp.org - validate_certs: no - register: present - check_mode: yes - - debug: var=present - - - name: Configure NTP servers for a host in check mode - vmware_host_ntp: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - ntp_servers: - - 0.pool.ntp.org - - 1.pool.ntp.org - - 2.pool.ntp.org - validate_certs: no - register: ntp_servers - check_mode: yes - - debug: var=ntp_servers diff --git a/test/integration/targets/vmware_host_ntp_facts/aliases b/test/integration/targets/vmware_host_ntp_facts/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_host_ntp_facts/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_ntp_facts/tasks/main.yml b/test/integration/targets/vmware_host_ntp_facts/tasks/main.yml deleted file mode 100644 index 9dc0309eaa..0000000000 --- a/test/integration/targets/vmware_host_ntp_facts/tasks/main.yml +++ /dev/null @@ -1,24 +0,0 @@ -# Test code for the vmware_host_ntp_facts module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# TODO: vcsim does not support NTP Manager related to operations -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - - name: Gather NTP facts about all hosts in given host - vmware_host_ntp_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - register: host_ntp - - debug: var=host_ntp - - assert: - that: - - host_ntp.hosts_ntp_facts is defined diff --git a/test/integration/targets/vmware_host_ntp_info/aliases b/test/integration/targets/vmware_host_ntp_info/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_host_ntp_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_ntp_info/tasks/main.yml b/test/integration/targets/vmware_host_ntp_info/tasks/main.yml deleted file mode 100644 index 16d240e9f7..0000000000 --- a/test/integration/targets/vmware_host_ntp_info/tasks/main.yml +++ /dev/null @@ -1,24 +0,0 @@ -# Test code for the vmware_host_ntp_info module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# TODO: vcsim does not support NTP Manager related to operations -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - - name: Gather NTP info about all hosts in given host - vmware_host_ntp_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - register: host_ntp - - debug: var=host_ntp - - assert: - that: - - host_ntp.hosts_ntp_info is defined diff --git a/test/integration/targets/vmware_host_package_facts/aliases b/test/integration/targets/vmware_host_package_facts/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_host_package_facts/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_package_facts/tasks/main.yml b/test/integration/targets/vmware_host_package_facts/tasks/main.yml deleted file mode 100644 index b5f8270f0d..0000000000 --- a/test/integration/targets/vmware_host_package_facts/tasks/main.yml +++ /dev/null @@ -1,24 +0,0 @@ -# Test code for the vmware_host_package_facts module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# TODO: vcsim does not support Package Manager related to operations -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - - name: Gather facts about all hosts in given cluster - vmware_host_package_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - register: host_packages - - debug: var=host_packages - - assert: - that: - - host_packages.hosts_package_facts is defined diff --git a/test/integration/targets/vmware_host_package_info/aliases b/test/integration/targets/vmware_host_package_info/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_host_package_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_package_info/tasks/main.yml b/test/integration/targets/vmware_host_package_info/tasks/main.yml deleted file mode 100644 index c4482efc6c..0000000000 --- a/test/integration/targets/vmware_host_package_info/tasks/main.yml +++ /dev/null @@ -1,24 +0,0 @@ -# Test code for the vmware_host_package_info module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# TODO: vcsim does not support Package Manager related to operations -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - - name: Gather info about all hosts in given cluster - vmware_host_package_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - register: host_packages - - debug: var=host_packages - - assert: - that: - - host_packages.hosts_package_info is defined diff --git a/test/integration/targets/vmware_host_powermgmt_policy/aliases b/test/integration/targets/vmware_host_powermgmt_policy/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_host_powermgmt_policy/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_powermgmt_policy/tasks/main.yml b/test/integration/targets/vmware_host_powermgmt_policy/tasks/main.yml deleted file mode 100644 index c899e7a668..0000000000 --- a/test/integration/targets/vmware_host_powermgmt_policy/tasks/main.yml +++ /dev/null @@ -1,103 +0,0 @@ -# Test code for the vmware_host_powermgmt_policy module. -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - - name: Reset all the hosts to balanced - vmware_host_powermgmt_policy: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: "{{ ccr1 }}" - policy: balanced - validate_certs: no - - # The following test cases aren't supported by vcsim - - name: Set the Power Management Policy for esxi1 - vmware_host_powermgmt_policy: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - policy: high-performance - validate_certs: no - register: host_result - - debug: var=host_result - - name: Ensure Power Management Policy for esxi1 - assert: - that: - - host_result.result['{{ esxi1 }}'].current_state == "high-performance" - - - name: Reset all the hosts to balanced - vmware_host_powermgmt_policy: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: "{{ ccr1 }}" - policy: balanced - validate_certs: no - register: all_hosts_result - - debug: var=all_hosts_result - - name: Ensure Power Management Policy is changed for all hosts of {{ ccr1 }} - assert: - that: - - all_hosts_result is changed - - all_hosts_result.result is defined - - - name: Reset all the hosts to balanced - vmware_host_powermgmt_policy: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: "{{ ccr1 }}" - policy: balanced - validate_certs: no - - - name: Set the Power Management Policy for esxi1 in check mode - vmware_host_powermgmt_policy: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - policy: high-performance - validate_certs: no - register: host_result - check_mode: yes - - debug: var=host_result - - name: Ensure Power Management Policy for esxi1 in check mode - assert: - that: - - host_result is changed - - host_result.result is defined - - - name: Set the Power Management Policy on all hosts of {{ ccr1 }} - vmware_host_powermgmt_policy: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: "{{ ccr1 }}" - policy: balanced - validate_certs: no - register: all_hosts_result - check_mode: yes - - debug: var=all_hosts_result - - name: Ensure we are still using the 'balanced' mode - assert: - that: - - not (all_hosts_result is changed) - - "all_hosts_result.result['{{ esxi1 }}'].current_state == 'balanced'" - always: - - name: Reset all the hosts to balanced - vmware_host_powermgmt_policy: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: "{{ ccr1 }}" - policy: balanced - validate_certs: no diff --git a/test/integration/targets/vmware_host_powerstate/aliases b/test/integration/targets/vmware_host_powerstate/aliases deleted file mode 100644 index 0c2e2cb9bd..0000000000 --- a/test/integration/targets/vmware_host_powerstate/aliases +++ /dev/null @@ -1,3 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests diff --git a/test/integration/targets/vmware_host_powerstate/tasks/main.yml b/test/integration/targets/vmware_host_powerstate/tasks/main.yml deleted file mode 100644 index ae89113412..0000000000 --- a/test/integration/targets/vmware_host_powerstate/tasks/main.yml +++ /dev/null @@ -1,34 +0,0 @@ -# Test code for the vmware_host_powerstate module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# TODO: vcsim does not support Powerstate related to operations -- when: False - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - - # https://kb.vmware.com/s/article/2001651?lang=en_US - # It seems like we need a Power managment interface to be able to run the - # module. - # I currently get: - # "Failed to power down '192.168.123.7' to standby as host system due to : ('The operation is not supported on the object.', None)" - - name: Restart Host - vmware_host_powerstate: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: False - state: power-down-to-standby - esxi_hostname: '{{ esxi1 }}' - force: True - register: host_powerstate - - - debug: var=host_powerstate - - - assert: - that: - - host_powerstate.results is changed diff --git a/test/integration/targets/vmware_host_scanhba/aliases b/test/integration/targets/vmware_host_scanhba/aliases deleted file mode 100644 index e96093f00c..0000000000 --- a/test/integration/targets/vmware_host_scanhba/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group2 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_scanhba/tasks/main.yml b/test/integration/targets/vmware_host_scanhba/tasks/main.yml deleted file mode 100644 index 2701b10473..0000000000 --- a/test/integration/targets/vmware_host_scanhba/tasks/main.yml +++ /dev/null @@ -1,25 +0,0 @@ -# Test code for the vmware_host_scanhba module. -# Copyright: (c) 2019, Michael Eaton <me@michaeleaton.me> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - - name: Recan HBA's for an entire cluster (there should be at least one host as above) - vmware_host_scanhba: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - cluster_name: '{{ ccr1 }}' - refresh_storage: false - register: host_scan_results - - debug: msg="{{ host_scan_results }}" - - name: ensure a change occured (as in the scan happened) and the task didnt fail - assert: - that: - - host_scan_results.changed - - not host_scan_results.failed diff --git a/test/integration/targets/vmware_host_service_facts/aliases b/test/integration/targets/vmware_host_service_facts/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_host_service_facts/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_service_facts/tasks/main.yml b/test/integration/targets/vmware_host_service_facts/tasks/main.yml deleted file mode 100644 index 1f3f9e854f..0000000000 --- a/test/integration/targets/vmware_host_service_facts/tasks/main.yml +++ /dev/null @@ -1,39 +0,0 @@ -# Test code for the vmware_host_service_facts module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# TODO: vcsim does not support service related to operations -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - - &host_srv_facts - name: Check facts about all hosts in given cluster - vmware_host_service_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - register: host_services - - - debug: - var: host_services - - - assert: - that: - - host_services.host_service_facts is defined - - - <<: *host_srv_facts - name: Check facts about all hosts in given cluster in check mode - check_mode: yes - - - debug: - var: host_services - - - assert: - that: - - host_services.host_service_facts is defined diff --git a/test/integration/targets/vmware_host_service_info/aliases b/test/integration/targets/vmware_host_service_info/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_host_service_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_service_info/tasks/main.yml b/test/integration/targets/vmware_host_service_info/tasks/main.yml deleted file mode 100644 index 60f8725075..0000000000 --- a/test/integration/targets/vmware_host_service_info/tasks/main.yml +++ /dev/null @@ -1,39 +0,0 @@ -# Test code for the vmware_host_service_info module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# TODO: vcsim does not support service related to operations -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - - &host_srv_info - name: Check info about all hosts in given cluster - vmware_host_service_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - register: host_services - - - debug: - var: host_services - - - assert: - that: - - host_services.host_service_info is defined - - - <<: *host_srv_info - name: Check info about all hosts in given cluster in check mode - check_mode: yes - - - debug: - var: host_services - - - assert: - that: - - host_services.host_service_info is defined diff --git a/test/integration/targets/vmware_host_service_manager/aliases b/test/integration/targets/vmware_host_service_manager/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_host_service_manager/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_service_manager/tasks/main.yml b/test/integration/targets/vmware_host_service_manager/tasks/main.yml deleted file mode 100644 index 7098675ef4..0000000000 --- a/test/integration/targets/vmware_host_service_manager/tasks/main.yml +++ /dev/null @@ -1,86 +0,0 @@ -# Test code for the vmware_host_service_manager module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# TODO: vcsim does not support service management -# commenting this testcase till the time. -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - - name: Start ntpd service on all hosts in given cluster - vmware_host_service_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - cluster_name: "{{ ccr1 }}" - service_name: ntpd - state: present - register: all_hosts_result - - debug: var=all_hosts_result - - - name: Stop ntpd service on a given host - vmware_host_service_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: '{{ esxi1 }}' - service_name: ntpd - state: absent - register: single_hosts_result - - name: ensure info are gathered - assert: - that: - - single_hosts_result is changed - - - name: Start ntpd service on all hosts in given cluster in check mode - vmware_host_service_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - cluster_name: "{{ ccr1 }}" - service_name: ntpd - state: present - register: all_hosts_result_check_mode - check_mode: yes - - name: ensure info are gathered for all hosts - assert: - that: - - all_hosts_result_check_mode is changed - - - name: Stop ntpd service on a given host in check mode - vmware_host_service_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: '{{ esxi1 }}' - service_name: ntpd - state: absent - register: single_hosts_result_check_mode - check_mode: yes - - name: ensure info are gathered - assert: - that: - - not (single_hosts_result_check_mode is changed) - - - name: Start ntpd service on all hosts in given cluster - vmware_host_service_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - cluster_name: "{{ ccr1 }}" - service_name: ntpd - state: present - register: all_hosts_result_check_mode - - name: finally, ensure ntp is running on the cluster - assert: - that: - - all_hosts_result_check_mode is changed diff --git a/test/integration/targets/vmware_host_snmp/aliases b/test/integration/targets/vmware_host_snmp/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_host_snmp/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_snmp/tasks/main.yml b/test/integration/targets/vmware_host_snmp/tasks/main.yml deleted file mode 100644 index 45f73e48b8..0000000000 --- a/test/integration/targets/vmware_host_snmp/tasks/main.yml +++ /dev/null @@ -1,56 +0,0 @@ -# Test code for the vmware_host_snmp. -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - # SNMP works only with standalone ESXi server - - name: Enable and configure SNMP community in check mode - vmware_host_snmp: - hostname: '{{ esxi1 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - community: [ test ] - state: enabled - validate_certs: no - register: snmp_enabled_check_mode - check_mode: yes - - debug: var=snmp_enabled_check_mode - - assert: - that: - - snmp_enabled_check_mode is defined - - snmp_enabled_check_mode.changed - - - name: Enable and configure SNMP community - vmware_host_snmp: - hostname: '{{ esxi1 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - community: [ test ] - state: enabled - validate_certs: no - register: snmp_enabled - - debug: var=snmp_enabled - - assert: - that: - - snmp_enabled is defined - - snmp_enabled.changed - - - name: Disable SNMP - vmware_host_snmp: - hostname: '{{ esxi1 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - state: disabled - validate_certs: no - register: snmp_disabled - - debug: var=snmp_enabled - - assert: - that: - - snmp_enabled is defined - - snmp_enabled.changed diff --git a/test/integration/targets/vmware_host_ssl_facts/aliases b/test/integration/targets/vmware_host_ssl_facts/aliases deleted file mode 100644 index e96093f00c..0000000000 --- a/test/integration/targets/vmware_host_ssl_facts/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group2 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_ssl_facts/tasks/main.yml b/test/integration/targets/vmware_host_ssl_facts/tasks/main.yml deleted file mode 100644 index b04b36f715..0000000000 --- a/test/integration/targets/vmware_host_ssl_facts/tasks/main.yml +++ /dev/null @@ -1,70 +0,0 @@ -# Test code for the vmware_host_ssl_facts module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - -- name: Gather SSL facts about ESXi machine - vmware_host_ssl_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - register: ssl_facts - -- debug: var=ssl_facts - -- assert: - that: - - ssl_facts.host_ssl_facts is defined - -- name: Gather facts about all hostsystem in given cluster - vmware_host_ssl_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: "{{ ccr1 }}" - validate_certs: no - register: ssl_facts - -- debug: var=ssl_facts - -- assert: - that: - - ssl_facts.host_ssl_facts is defined - -- name: Gather SSL facts about ESXi machine in check mode - vmware_host_ssl_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - check_mode: yes - register: ssl_facts - -- debug: var=ssl_facts - -- assert: - that: - - ssl_facts.host_ssl_facts is defined - -- name: Gather facts about all hostsystem in given cluster in check mode ee - vmware_host_ssl_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: "{{ ccr1 }}" - validate_certs: no - check_mode: yes - register: ssl_facts - -- debug: var=ssl_facts - -- assert: - that: - - ssl_facts.host_ssl_facts is defined diff --git a/test/integration/targets/vmware_host_ssl_info/aliases b/test/integration/targets/vmware_host_ssl_info/aliases deleted file mode 100644 index e96093f00c..0000000000 --- a/test/integration/targets/vmware_host_ssl_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group2 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_ssl_info/tasks/main.yml b/test/integration/targets/vmware_host_ssl_info/tasks/main.yml deleted file mode 100644 index f2eb77112b..0000000000 --- a/test/integration/targets/vmware_host_ssl_info/tasks/main.yml +++ /dev/null @@ -1,70 +0,0 @@ -# Test code for the vmware_host_ssl_info module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - -- name: Gather SSL info about ESXi machine - vmware_host_ssl_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - register: ssl_info - -- debug: var=ssl_info - -- assert: - that: - - ssl_info.host_ssl_info is defined - -- name: Gather info about all hostsystem in given cluster - vmware_host_ssl_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: "{{ ccr1 }}" - validate_certs: no - register: ssl_info - -- debug: var=ssl_info - -- assert: - that: - - ssl_info.host_ssl_info is defined - -- name: Gather SSL info about ESXi machine in check mode - vmware_host_ssl_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - check_mode: yes - register: ssl_info - -- debug: var=ssl_info - -- assert: - that: - - ssl_info.host_ssl_info is defined - -- name: Gather info about all hostsystem in given cluster in check mode ee - vmware_host_ssl_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: "{{ ccr1 }}" - validate_certs: no - check_mode: yes - register: ssl_info - -- debug: var=ssl_info - -- assert: - that: - - ssl_info.host_ssl_info is defined diff --git a/test/integration/targets/vmware_host_vmhba_facts/aliases b/test/integration/targets/vmware_host_vmhba_facts/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_host_vmhba_facts/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_vmhba_facts/tasks/main.yml b/test/integration/targets/vmware_host_vmhba_facts/tasks/main.yml deleted file mode 100644 index 0fcc5e3cc5..0000000000 --- a/test/integration/targets/vmware_host_vmhba_facts/tasks/main.yml +++ /dev/null @@ -1,39 +0,0 @@ -# Test code for the vmware_host_vmhba_facts module. -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# TODO: vcsim does not support networkConfig related to operations -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - - &vmhba_data - name: Gather vmhba facts - vmware_host_vmhba_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - register: host_vmhbas - - - debug: - var: host_vmhbas - - - assert: - that: - - host_vmhbas.hosts_vmhbas_facts is defined - - - <<: *vmhba_data - name: Gather vmhba facts in check mode - check_mode: yes - - - debug: - var: host_vmhbas - - - assert: - that: - - host_vmhbas.hosts_vmhbas_facts is defined diff --git a/test/integration/targets/vmware_host_vmhba_info/aliases b/test/integration/targets/vmware_host_vmhba_info/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_host_vmhba_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_vmhba_info/tasks/main.yml b/test/integration/targets/vmware_host_vmhba_info/tasks/main.yml deleted file mode 100644 index bfb014cfe3..0000000000 --- a/test/integration/targets/vmware_host_vmhba_info/tasks/main.yml +++ /dev/null @@ -1,39 +0,0 @@ -# Test code for the vmware_host_vmhba_info module. -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# TODO: vcsim does not support networkConfig related to operations -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - - &vmhba_data - name: Gather vmhba info - vmware_host_vmhba_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - register: host_vmhbas - - - debug: - var: host_vmhbas - - - assert: - that: - - host_vmhbas.hosts_vmhbas_info is defined - - - <<: *vmhba_data - name: Gather vmhba info in check mode - check_mode: yes - - - debug: - var: host_vmhbas - - - assert: - that: - - host_vmhbas.hosts_vmhbas_info is defined diff --git a/test/integration/targets/vmware_host_vmnic_facts/aliases b/test/integration/targets/vmware_host_vmnic_facts/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_host_vmnic_facts/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_vmnic_facts/tasks/main.yml b/test/integration/targets/vmware_host_vmnic_facts/tasks/main.yml deleted file mode 100644 index 865705d3b9..0000000000 --- a/test/integration/targets/vmware_host_vmnic_facts/tasks/main.yml +++ /dev/null @@ -1,40 +0,0 @@ -# Test code for the vmware_host_vmnic_facts module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# TODO: vcsim does not support networkConfig related to operations -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - - name: Gather vmnic facts about a host - vmware_host_vmnic_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - register: host_vmnics - - debug: var=host_vmnics - - assert: - that: - - host_vmnics.hosts_vmnics_facts is defined - - - name: Gather extended vmnic facts about a host - vmware_host_vmnic_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - capabilities: true - directpath_io: true - sriov: true - register: host_vmnics_extended - - debug: var=host_vmnics_extended - - assert: - that: - - host_vmnics_extended.hosts_vmnics_facts is defined diff --git a/test/integration/targets/vmware_host_vmnic_info/aliases b/test/integration/targets/vmware_host_vmnic_info/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_host_vmnic_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_host_vmnic_info/tasks/main.yml b/test/integration/targets/vmware_host_vmnic_info/tasks/main.yml deleted file mode 100644 index 722bd61701..0000000000 --- a/test/integration/targets/vmware_host_vmnic_info/tasks/main.yml +++ /dev/null @@ -1,40 +0,0 @@ -# Test code for the vmware_host_vmnic_info module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# TODO: vcsim does not support networkConfig related to operations -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - - name: Gather vmnic info about a host - vmware_host_vmnic_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - register: host_vmnics - - debug: var=host_vmnics - - assert: - that: - - host_vmnics.hosts_vmnics_info is defined - - - name: Gather extended vmnic info about a host - vmware_host_vmnic_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - capabilities: true - directpath_io: true - sriov: true - register: host_vmnics_extended - - debug: var=host_vmnics_extended - - assert: - that: - - host_vmnics_extended.hosts_vmnics_info is defined diff --git a/test/integration/targets/vmware_local_role_facts/aliases b/test/integration/targets/vmware_local_role_facts/aliases deleted file mode 100644 index e96093f00c..0000000000 --- a/test/integration/targets/vmware_local_role_facts/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group2 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_local_role_facts/tasks/main.yml b/test/integration/targets/vmware_local_role_facts/tasks/main.yml deleted file mode 100644 index 45db965647..0000000000 --- a/test/integration/targets/vmware_local_role_facts/tasks/main.yml +++ /dev/null @@ -1,46 +0,0 @@ -# Test code for the vmware_local_role_facts module -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - -- name: Set list of Roles in fact - set_fact: - role_list: - - Admin -# With govcsim, NoCryptoAdmin has no privilege. -# - NoCryptoAdmin - - Anonymous - - ReadOnly - -- &role_data - name: Gather Role facts - vmware_local_role_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - register: role_details - -- &list_to_dict - name: List to dict - set_fact: - role_dict: "{{ dict(role_details.local_role_facts|map(attribute='role_name')|zip(role_details.local_role_facts)) }}" - -- name: Test if NoAccess has no privilege - assert: - that: "{{ role_dict['NoAccess']['privileges'] | list | length == 0 }}" - -- &role_test - name: Test if role id is present for role - assert: - that: "{{ role_dict[item]['privileges'] | list | length > 0 }}" - with_items: "{{ role_list }}" - -- <<: *role_data - name: Gather Role facts in check mode - check_mode: yes - -- <<: *role_test - name: Test if role id is present for role in check mode diff --git a/test/integration/targets/vmware_local_role_info/aliases b/test/integration/targets/vmware_local_role_info/aliases deleted file mode 100644 index e96093f00c..0000000000 --- a/test/integration/targets/vmware_local_role_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group2 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_local_role_info/tasks/main.yml b/test/integration/targets/vmware_local_role_info/tasks/main.yml deleted file mode 100644 index cff8b57151..0000000000 --- a/test/integration/targets/vmware_local_role_info/tasks/main.yml +++ /dev/null @@ -1,46 +0,0 @@ -# Test code for the vmware_local_role_info module -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - -- name: Set list of Roles in fact - set_fact: - role_list: - - Admin - # NoCryptoAdmin has no privilege with govcsim - # - NoCryptoAdmin - - Anonymous - - ReadOnly - -- &role_data - name: Gather Role info - vmware_local_role_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - register: role_details - -- &list_to_dict - name: List to dict - set_fact: - role_dict: "{{ dict(role_details.local_role_info|map(attribute='role_name')|zip(role_details.local_role_info)) }}" - -- name: Test if NoAccess has no privilege - assert: - that: "{{ role_dict['NoAccess']['privileges'] | list | length == 0 }}" - -- &role_test - name: Test if role id is present for role - assert: - that: "{{ role_dict[item]['privileges'] | list | length > 0 }}" - with_items: "{{ role_list }}" - -- <<: *role_data - name: Gather Role info in check mode - check_mode: yes -- <<: *list_to_dict -- <<: *role_test - name: Test if role id is present for role in check mode diff --git a/test/integration/targets/vmware_local_role_manager/aliases b/test/integration/targets/vmware_local_role_manager/aliases deleted file mode 100644 index 900b4c2c3c..0000000000 --- a/test/integration/targets/vmware_local_role_manager/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group2 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_local_role_manager/tasks/main.yml b/test/integration/targets/vmware_local_role_manager/tasks/main.yml deleted file mode 100644 index 86daa5921b..0000000000 --- a/test/integration/targets/vmware_local_role_manager/tasks/main.yml +++ /dev/null @@ -1,162 +0,0 @@ -# Test code for the vmware_local_role_manager module -# Copyright: (c) 2017-2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - -- name: Create a role without privileges in check mode - vmware_local_role_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - local_role_name: SampleRole_0001 - validate_certs: no - state: present - register: role_creation - check_mode: yes - -- name: Verify if role was created - assert: - that: - - role_creation.changed - -- &create_role_data - name: Create a role without privileges - vmware_local_role_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - local_role_name: SampleRole_0001 - validate_certs: no - state: present - register: role_creation_0001 - -- name: Verify if role was created - assert: - that: - - role_creation_0001.changed - -- <<: *create_role_data - name: Again create a role without privileges - -- name: verify if role is not created again - assert: - that: - - not role_creation_0001.changed - -- &delete_role_data - name: Delete a role - vmware_local_role_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - local_role_name: SampleRole_0001 - validate_certs: no - state: absent - register: role_creation_0001 - -- name: Verify if role is not present - assert: - that: - - role_creation_0001.changed - -- <<: *delete_role_data - name: Delete role again - -- name: Verify if role is absent again - assert: - that: - - not role_creation_0001.changed - -- name: Create a role with privileges - vmware_local_role_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - local_role_name: SampleRole_0001 - validate_certs: no - local_privilege_ids: ['VirtualMachine.State.RenameSnapshot'] - state: present - register: role_creation_0001 - -- name: Verify if role is created with privileges - assert: - that: - - role_creation_0001.changed - -- &exist_role_data - name: Add a privilege to existing privileges - vmware_local_role_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - local_role_name: SampleRole_0001 - validate_certs: no - local_privilege_ids: ['Folder.Create'] - action: add - state: present - register: role_add - -- name: Verify if role is updated with updated privileges - assert: - that: - - role_add.changed - -- <<: *exist_role_data - name: Again add a privilege to existing privileges - -- name: Verify if role is not updated - assert: - that: - - not role_add.changed - -- &remove_role_data - name: Remove a privilege from existing privileges - vmware_local_role_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - local_role_name: SampleRole_0001 - validate_certs: no - local_privilege_ids: ['Folder.Create'] - action: remove - register: role_remove - -- name: verify if role is updated with privileges - assert: - that: - - role_remove.changed - -- <<: *remove_role_data - name: Again remove a privilege from existing privileges - -- name: Verify if role is not updated - assert: - that: - - not role_remove.changed - -- &set_priv_role_data - name: Set a privilege to an existing role - vmware_local_role_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - local_role_name: SampleRole_0001 - validate_certs: no - local_privilege_ids: ['Folder.Create'] - action: set - register: role_set - -- name: Verify if role is updated with privileges - assert: - that: - - role_set.changed - -- <<: *set_priv_role_data - name: Again set a privilege to an existing role - -- name: verify if role is not updated - assert: - that: - - not role_set.changed diff --git a/test/integration/targets/vmware_local_user_facts/aliases b/test/integration/targets/vmware_local_user_facts/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_local_user_facts/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_local_user_facts/tasks/main.yml b/test/integration/targets/vmware_local_user_facts/tasks/main.yml deleted file mode 100644 index f0f1b56018..0000000000 --- a/test/integration/targets/vmware_local_user_facts/tasks/main.yml +++ /dev/null @@ -1,38 +0,0 @@ -# Test code for the vmware_local_user_facts module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# Commenting local user testcases as older vcsim docker image -# does not support this. -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_esxi_instance: true - - # Local user manager works only with standalone ESXi server - - &user_fact_data - name: Gather facts about users - vmware_local_user_facts: - hostname: "{{ esxi1 }}" - username: "{{ esxi_user }}" - password: "{{ esxi_password }}" - validate_certs: False - register: all_user_facts - - - name: ensure user facts are gathered - assert: - that: - - not all_user_facts.changed - - all_user_facts.local_user_facts is defined - - - <<: *user_fact_data - name: Gather facts about users in check mode - check_mode: yes - - - name: ensure user facts are gathered - assert: - that: - - not all_user_facts.changed - - all_user_facts.local_user_facts is defined diff --git a/test/integration/targets/vmware_local_user_info/aliases b/test/integration/targets/vmware_local_user_info/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_local_user_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_local_user_info/tasks/main.yml b/test/integration/targets/vmware_local_user_info/tasks/main.yml deleted file mode 100644 index f1985cca89..0000000000 --- a/test/integration/targets/vmware_local_user_info/tasks/main.yml +++ /dev/null @@ -1,38 +0,0 @@ -# Test code for the vmware_local_user_info module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# Commenting local user testcases as older vcsim docker image -# does not support this. -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_esxi_instance: true - - # Local user manager works only with standalone ESXi server - - &user_info_data - name: Gather info about users - vmware_local_user_info: - hostname: "{{ esxi1 }}" - username: "{{ esxi_user }}" - password: "{{ esxi_password }}" - validate_certs: False - register: all_user_info - - - name: ensure user info are gathered - assert: - that: - - not all_user_info.changed - - all_user_info.local_user_info is defined - - - <<: *user_info_data - name: Gather info about users in check mode - check_mode: yes - - - name: ensure user info are gathered - assert: - that: - - not all_user_info.changed - - all_user_info.local_user_info is defined diff --git a/test/integration/targets/vmware_local_user_manager/aliases b/test/integration/targets/vmware_local_user_manager/aliases deleted file mode 100644 index 3431786750..0000000000 --- a/test/integration/targets/vmware_local_user_manager/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_local_user_manager/tasks/main.yml b/test/integration/targets/vmware_local_user_manager/tasks/main.yml deleted file mode 100644 index f918d4a32f..0000000000 --- a/test/integration/targets/vmware_local_user_manager/tasks/main.yml +++ /dev/null @@ -1,39 +0,0 @@ -- import_role: - name: prepare_vmware_tests - -# Testcase 0003: Add Local user in vCenter server -- name: add local user - vmware_local_user_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - local_user_name: testuser_0003 - local_user_password: "SamplePassword!" - state: present - register: user_add_0003 - ignore_errors: yes - -- name: ensure user is created - assert: - that: - - user_add_0003.changed == false - - "{{ 'Failed to get local account manager settings' in user_add_0003.msg }}" - -# Testcase 0003: Delete Local user in vCenter server -- name: Delete local user - vmware_local_user_manager: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - local_user_name: testuser_0003 - state: absent - register: user_delete_0004 - ignore_errors: yes - -- name: ensure user is deleted - assert: - that: - - user_delete_0004.changed == false - - "{{ 'Failed to get local account manager settings' in user_delete_0004.msg }}" diff --git a/test/integration/targets/vmware_maintenancemode/aliases b/test/integration/targets/vmware_maintenancemode/aliases deleted file mode 100644 index e96093f00c..0000000000 --- a/test/integration/targets/vmware_maintenancemode/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group2 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_maintenancemode/tasks/main.yml b/test/integration/targets/vmware_maintenancemode/tasks/main.yml deleted file mode 100644 index 2fa681927f..0000000000 --- a/test/integration/targets/vmware_maintenancemode/tasks/main.yml +++ /dev/null @@ -1,76 +0,0 @@ -# Test code for the vmware_guest_maintenancemode module. -# Copyright: (c) 2017, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - -- name: Enter maintenance mode - vmware_maintenancemode: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - state: present - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - register: test_result_0001 - -- debug: var=test_result_0001 - -- name: assert that changes were made - assert: - that: - - test_result_0001 is changed - -- name: Enter maintenance mode again - vmware_maintenancemode: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - state: present - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - register: test_result_0002 - -- debug: var=test_result_0002 - -- name: assert that no changes were made - assert: - that: - - not (test_result_0002 is changed) - -- name: Exit maintenance mode - vmware_maintenancemode: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - state: absent - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - register: test_result_0003 - -- debug: var=test_result_0003 - -- name: assert that changes were made - assert: - that: - - test_result_0003 is changed - -- name: Exit maintenance mode again - vmware_maintenancemode: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - state: absent - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - register: test_result_0004 - -- debug: var=test_result_0004 - -- name: assert that no changes were made - assert: - that: - - not (test_result_0004 is changed) diff --git a/test/integration/targets/vmware_portgroup/aliases b/test/integration/targets/vmware_portgroup/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_portgroup/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_portgroup/tasks/main.yml b/test/integration/targets/vmware_portgroup/tasks/main.yml deleted file mode 100644 index 081b9c792f..0000000000 --- a/test/integration/targets/vmware_portgroup/tasks/main.yml +++ /dev/null @@ -1,73 +0,0 @@ -# Test code for the vmware_portgroup module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - - import_role: - name: prepare_vmware_tests - vars: - setup_datacenter: true - setup_attach_host: true - setup_cluster: true - setup_switch: true - - - name: Create portgroup without Portgroup and vSwitch - vmware_portgroup: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - ignore_errors: yes - register: no_pg_vs - - - assert: - that: - - '"missing" in no_pg_vs.msg' - - - name: Create portgroup without Portgroup - vmware_portgroup: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - vswitch: '' - validate_certs: no - ignore_errors: yes - register: no_vs - - - assert: - that: - - '"missing" in no_vs.msg' - - - name: Create portgroup without cluster - vmware_portgroup: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - vswitch: '{{ switch1 }}' - portgroup: 'pg_03' - validate_certs: no - ignore_errors: yes - register: no_cluster - - - assert: - that: - - '"cluster_name" in no_cluster.msg' - - - name: Create portgroup - vmware_portgroup: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - vswitch: '{{ switch1 }}' - portgroup: 'pg_03' - cluster_name: "{{ ccr1 }}" - validate_certs: no - state: present - ignore_errors: yes - register: pg_info - - - assert: - that: - - pg_info.changed diff --git a/test/integration/targets/vmware_portgroup_facts/aliases b/test/integration/targets/vmware_portgroup_facts/aliases deleted file mode 100644 index e96093f00c..0000000000 --- a/test/integration/targets/vmware_portgroup_facts/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group2 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_portgroup_facts/tasks/main.yml b/test/integration/targets/vmware_portgroup_facts/tasks/main.yml deleted file mode 100644 index 83c96dfdae..0000000000 --- a/test/integration/targets/vmware_portgroup_facts/tasks/main.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Test code for the vmware_portgroup_facts module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - -- name: Gather portgroup facts for all ESXi host from given cluster - vmware_portgroup_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - cluster_name: "{{ ccr1 }}" - register: portgroup_0001_results - -- assert: - that: - - "not portgroup_0001_results.changed" - - "portgroup_0001_results.hosts_portgroup_facts is defined" - -- name: Gather portgroup facts for an ESXi host - vmware_portgroup_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: '{{ esxi1 }}' - register: portgroup_0002_results - -- assert: - that: - - "not portgroup_0002_results.changed" - - "portgroup_0002_results.hosts_portgroup_facts is defined" - -- name: Gather all portgroup facts for an ESXi host - vmware_portgroup_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: '{{ esxi1 }}' - policies: true - register: portgroup_0003_results - -- assert: - that: - - "not portgroup_0003_results.changed" - - "portgroup_0003_results.hosts_portgroup_facts is defined" - -- name: Gather all portgroup facts for an ESXi host in check mode - vmware_portgroup_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: '{{ esxi1 }}' - policies: true - register: portgroup_0004_results - check_mode: yes - -- assert: - that: - - "not portgroup_0004_results.changed" - - "portgroup_0004_results.hosts_portgroup_facts is defined" diff --git a/test/integration/targets/vmware_portgroup_info/aliases b/test/integration/targets/vmware_portgroup_info/aliases deleted file mode 100644 index 527c737768..0000000000 --- a/test/integration/targets/vmware_portgroup_info/aliases +++ /dev/null @@ -1,5 +0,0 @@ -shippable/vcenter/group2 -cloud/vcenter - -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_portgroup_info/tasks/main.yml b/test/integration/targets/vmware_portgroup_info/tasks/main.yml deleted file mode 100644 index f79ff9a673..0000000000 --- a/test/integration/targets/vmware_portgroup_info/tasks/main.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Test code for the vmware_portgroup_info module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - -- name: Gather portgroup info for all ESXi host from given cluster - vmware_portgroup_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - cluster_name: "{{ ccr1 }}" - register: portgroup_0001_results - -- assert: - that: - - "not portgroup_0001_results.changed" - - "portgroup_0001_results.hosts_portgroup_info is defined" - -- name: Gather portgroup info for an ESXi host - vmware_portgroup_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: '{{ esxi1 }}' - register: portgroup_0002_results - -- assert: - that: - - "not portgroup_0002_results.changed" - - "portgroup_0002_results.hosts_portgroup_info is defined" - -- name: Gather all portgroup info for an ESXi host - vmware_portgroup_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: '{{ esxi1 }}' - policies: true - register: portgroup_0003_results - -- assert: - that: - - "not portgroup_0003_results.changed" - - "portgroup_0003_results.hosts_portgroup_info is defined" - -- name: Gather all portgroup info for an ESXi host in check mode - vmware_portgroup_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - esxi_hostname: '{{ esxi1 }}' - policies: true - register: portgroup_0004_results - check_mode: yes - -- assert: - that: - - "not portgroup_0004_results.changed" - - "portgroup_0004_results.hosts_portgroup_info is defined" diff --git a/test/integration/targets/vmware_resource_pool/aliases b/test/integration/targets/vmware_resource_pool/aliases deleted file mode 100644 index e96093f00c..0000000000 --- a/test/integration/targets/vmware_resource_pool/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group2 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_resource_pool/tasks/main.yml b/test/integration/targets/vmware_resource_pool/tasks/main.yml deleted file mode 100644 index 91f21a13be..0000000000 --- a/test/integration/targets/vmware_resource_pool/tasks/main.yml +++ /dev/null @@ -1,99 +0,0 @@ -# Test code for the vmware_resource_pool module. -# Copyright: (c) 2017, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - -# Testcase 0001: Add Resource pool -- name: add resource pool - vmware_resource_pool: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - cluster: "{{ ccr1 }}" - resource_pool: test_resource_0001 - mem_shares: normal - mem_limit: -1 - mem_reservation: 0 - mem_expandable_reservations: True - cpu_shares: normal - cpu_limit: -1 - cpu_reservation: 0 - cpu_expandable_reservations: True - state: present - register: resource_result_0001 - -- name: ensure a resource pool is present - assert: - that: - - "{{ resource_result_0001.changed == true }}" - - -# Testcase 0002: Add Resource pool again -- name: add resource pool again - vmware_resource_pool: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - cluster: "{{ ccr1 }}" - resource_pool: test_resource_0001 - mem_shares: normal - mem_limit: -1 - mem_reservation: 0 - mem_expandable_reservations: True - cpu_shares: normal - cpu_limit: -1 - cpu_reservation: 0 - cpu_expandable_reservations: True - state: present - register: resource_result_0002 - -- name: check if nothing is changed - assert: - that: - - "{{ resource_result_0002.changed == false }}" - - -# Testcase 0003: Remove Resource pool -- name: add resource pool again - vmware_resource_pool: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - cluster: "{{ ccr1 }}" - resource_pool: test_resource_0001 - state: absent - register: resource_result_0003 - -- name: check if resource pool is removed - assert: - that: - - "{{ resource_result_0003.changed == true }}" - -# Testcase 0004: Remove Resource pool again -- name: add resource pool again - vmware_resource_pool: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - cluster: "{{ ccr1 }}" - resource_pool: test_resource_0001 - state: absent - register: resource_result_0004 - -- name: check if resource pool is already removed - assert: - that: - - "{{ resource_result_0004.changed == false }}" diff --git a/test/integration/targets/vmware_resource_pool_facts/aliases b/test/integration/targets/vmware_resource_pool_facts/aliases deleted file mode 100644 index 900b4c2c3c..0000000000 --- a/test/integration/targets/vmware_resource_pool_facts/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group2 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_resource_pool_facts/tasks/main.yml b/test/integration/targets/vmware_resource_pool_facts/tasks/main.yml deleted file mode 100644 index 44e419e136..0000000000 --- a/test/integration/targets/vmware_resource_pool_facts/tasks/main.yml +++ /dev/null @@ -1,20 +0,0 @@ -# Test code for the vmware_resource_pool_facts module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - -- name: Gather facts about resource pool - vmware_resource_pool_facts: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - register: resource_result_0001 - -- name: ensure a resource pool is present - assert: - that: - - "{{ resource_result_0001.changed == false }}" - - "{{ resource_result_0001.resource_pool_facts is defined }}" diff --git a/test/integration/targets/vmware_resource_pool_info/aliases b/test/integration/targets/vmware_resource_pool_info/aliases deleted file mode 100644 index 900b4c2c3c..0000000000 --- a/test/integration/targets/vmware_resource_pool_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group2 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_resource_pool_info/tasks/main.yml b/test/integration/targets/vmware_resource_pool_info/tasks/main.yml deleted file mode 100644 index 51efa23944..0000000000 --- a/test/integration/targets/vmware_resource_pool_info/tasks/main.yml +++ /dev/null @@ -1,20 +0,0 @@ -# Test code for the vmware_resource_pool_info module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - -- name: Gather info about resource pool - vmware_resource_pool_info: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - register: resource_result_0001 - -- name: ensure a resource pool is present - assert: - that: - - "{{ resource_result_0001.changed == false }}" - - "{{ resource_result_0001.resource_pool_info is defined }}" diff --git a/test/integration/targets/vmware_tag/aliases b/test/integration/targets/vmware_tag/aliases deleted file mode 100644 index 9cc67c4113..0000000000 --- a/test/integration/targets/vmware_tag/aliases +++ /dev/null @@ -1,3 +0,0 @@ -cloud/vcenter -unsupported -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_tag/tasks/main.yml b/test/integration/targets/vmware_tag/tasks/main.yml deleted file mode 100644 index 8961c6916a..0000000000 --- a/test/integration/targets/vmware_tag/tasks/main.yml +++ /dev/null @@ -1,7 +0,0 @@ -# Test code for the vmware_tag Operations. -# 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) - -- include: tag_crud_ops.yml -- include: tag_manager_ops.yml -- include: tag_manager_duplicate_tag_cat.yml diff --git a/test/integration/targets/vmware_tag/tasks/tag_crud_ops.yml b/test/integration/targets/vmware_tag/tasks/tag_crud_ops.yml deleted file mode 100644 index 189e8a9809..0000000000 --- a/test/integration/targets/vmware_tag/tasks/tag_crud_ops.yml +++ /dev/null @@ -1,112 +0,0 @@ -# Test code for the vmware_tag CRUD Operations. -# Copyright: (c) 2019, Pavan Bidkar <pbidkar@vmware.com> -# Copyright: (c) 2019, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - &cat_create - name: Create Category - vmware_category: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: False - category_name: Sample_Cat_0006 - category_description: Sample Description - category_cardinality: 'multiple' - state: present - register: category_create - - - name: Check Category is created - assert: - that: - - category_create.changed - - - <<: *cat_create - name: Create category again - - - name: Check if no changes are made - assert: - that: - - not category_create.changed - - - name: Set Cat_ID Paramter. Required for Tag creation - set_fact: Cat_ID={{ category_create['category_results']['category_id'] }} - - # Testcase Create Tag - - &tag_create - name: Create a tag - vmware_tag: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - tag_name: Sample_Tag_0001 - category_id: "{{ Cat_ID }}" - tag_description: Sample Description - state: present - register: tag_creation - - - name: Check tag is created - assert: - that: - - tag_creation.changed - - - <<: *tag_create - name: Create a tag again - - - name: Check if no changes are made - assert: - that: - - not tag_creation.changed - - # Testcase Update Tag Description (reconfig) - - &tag_update - name: Update Tag Description - vmware_tag: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - tag_name: Sample_Tag_0001 - tag_description: Some fancy description - state: present - register: update_tag_desc - - - name: Check tag description updated - assert: - that: - - update_tag_desc.changed - - - <<: *tag_update - name: Update tag description again - - - name: Check if no changes are made - assert: - that: - - not update_tag_desc.changed - - # Testcase Delete the Tag - - &tag_delete - name: Delete Tag - vmware_tag: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - tag_name: Sample_Tag_0001 - state: absent - register: delete_tag - - - name: Check Tag is Deleted - assert: - that: - - delete_tag.changed - - <<: *tag_delete - name: Delete tag again - - - name: Check if no changes are made - assert: - that: - - not delete_tag.changed diff --git a/test/integration/targets/vmware_tag/tasks/tag_manager_duplicate_tag_cat.yml b/test/integration/targets/vmware_tag/tasks/tag_manager_duplicate_tag_cat.yml deleted file mode 100644 index e6ccb044ab..0000000000 --- a/test/integration/targets/vmware_tag/tasks/tag_manager_duplicate_tag_cat.yml +++ /dev/null @@ -1,163 +0,0 @@ -# Test code for the vmware_tag_manager -# Copyright: (c) 2019, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - name: Create first category - vmware_category: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - category_name: "{{ cat_one }}" - category_cardinality: 'multiple' - state: present - register: category_one_create - - - name: Create second category - vmware_category: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - category_name: "{{ cat_two }}" - category_cardinality: 'multiple' - state: present - register: category_two_create - - - name: Check categories are created - assert: - that: - - category_two_create.changed - - category_one_create.changed - - - name: Set category one id - set_fact: cat_one_id={{ category_one_create['category_results']['category_id'] }} - - - name: Set category two id - set_fact: cat_two_id={{ category_two_create['category_results']['category_id'] }} - - - name: Create duplicate tags in two different categories - vmware_tag: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - tag_name: "{{ tag_one }}" - category_id: "{{ cat_one_id }}" - state: present - register: tag_one_create - - - name: Check tag is created - assert: - that: - - tag_one_create.changed - - - name: Create duplicate tags in two different categories - vmware_tag: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - tag_name: "{{ tag_one }}" - category_id: "{{ cat_two_id }}" - state: present - register: tag_two_create - - - name: Check tag is created - assert: - that: - - tag_two_create.changed - - - name: Create duplicate tags in two different categories - vmware_tag: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - tag_name: "{{ tag_two }}" - category_id: "{{ cat_one_id }}" - state: present - register: tag_one_create - - - name: Check tag is created - assert: - that: - - tag_one_create.changed - - - name: Create duplicate tags in two different categories - vmware_tag: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - tag_name: "{{ tag_two }}" - category_id: "{{ cat_two_id }}" - state: present - register: tag_two_create - - - name: Check tag is created - assert: - that: - - tag_two_create.changed - - - name: Get VM Facts - vmware_vm_facts: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - register: vm_facts - - - set_fact: vm_name="{{ vm_facts['virtual_machines'][0]['guest_name'] }}" - - - name: Assign tags to given virtual machine - vmware_tag_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - tag_names: - - "{{ cat_one }}:{{ tag_one }}" - object_name: "{{ vm_name }}" - object_type: VirtualMachine - state: add - delegate_to: localhost - register: vm_tag_info - - - name: Check if we assigned correct tags - assert: - that: - - vm_tag_info.changed - - - name: Delete Tags - vmware_tag: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - tag_name: "{{ item }}" - state: absent - register: delete_tag - with_items: - - "{{ tag_one }}" - - "{{ tag_two }}" - - - name: Delete Categories - vmware_category: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - category_name: "{{ item }}" - state: absent - register: delete_categories - with_items: - - "{{ cat_one }}" - - "{{ cat_two }}" - vars: - cat_one: category_1001 - cat_two: category_1002 - tag_one: tag_1001 - tag_two: tag_1002 diff --git a/test/integration/targets/vmware_tag/tasks/tag_manager_ops.yml b/test/integration/targets/vmware_tag/tasks/tag_manager_ops.yml deleted file mode 100644 index 14158cfca0..0000000000 --- a/test/integration/targets/vmware_tag/tasks/tag_manager_ops.yml +++ /dev/null @@ -1,62 +0,0 @@ -# Test code for the vmware_tag Manager Operations. -# Copyright: (c) 2019, Pavan Bidkar <pbidkar@vmware.com> -# Copyright: (c) 2019, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - name: Get VM Facts - vmware_vm_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: False - register: vm_info - - - set_fact: vm_name="{{ vm_info['virtual_machines'][0]['guest_name'] }}" - - # Get Tagname - - &tag_info - name: Get info about tag - vmware_tag_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: False - register: tag_info - - - <<: *tag_info - name: Get info about tag in check mode - check_mode: yes - - - set_fact: Tag_Name={{ tag_info['tag_facts'].keys() | list }} - - - debug: var=Tag_Name - - # Testcase Assign tag to virtual Machine - - &tag_assign - name: Add tags to a virtual machine - vmware_tag_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - tag_names: - - "{{ Tag_Name[0] }}" - object_name: "{{ vm_name }}" - object_type: VirtualMachine - state: add - register: tag_manager_ops - - - name: Check tag is assign to virtual machine - assert: - that: - - tag_manager_ops.changed - - - <<: *tag_assign - name: Add tags to a virtual machine again - - - name: Check tag is not assigned to virtual machine again - assert: - that: - - not tag_manager_ops.changed diff --git a/test/integration/targets/vmware_tag_info/aliases b/test/integration/targets/vmware_tag_info/aliases deleted file mode 100644 index 9cc67c4113..0000000000 --- a/test/integration/targets/vmware_tag_info/aliases +++ /dev/null @@ -1,3 +0,0 @@ -cloud/vcenter -unsupported -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_tag_info/tasks/main.yml b/test/integration/targets/vmware_tag_info/tasks/main.yml deleted file mode 100644 index c7b0209a92..0000000000 --- a/test/integration/targets/vmware_tag_info/tasks/main.yml +++ /dev/null @@ -1,5 +0,0 @@ -# Test code for the vmware_tag_info. -# Copyright: (c) 2020, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- include: tag_info.yml
\ No newline at end of file diff --git a/test/integration/targets/vmware_tag_info/tasks/tag_info.yml b/test/integration/targets/vmware_tag_info/tasks/tag_info.yml deleted file mode 100644 index 819faaad34..0000000000 --- a/test/integration/targets/vmware_tag_info/tasks/tag_info.yml +++ /dev/null @@ -1,24 +0,0 @@ -# Test code for the vmware_tag_info. -# Copyright: (c) 2020, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - &tag_info - name: Get info about tag - vmware_tag_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: False - register: tag_info - - - <<: *tag_info - name: Get info about tag in check mode - check_mode: yes - - - name: Check if facts exists - assert: - that: - - tag_info['tag_facts'] is defined - - tag_info['tag_info'] is defined diff --git a/test/integration/targets/vmware_tag_manager/aliases b/test/integration/targets/vmware_tag_manager/aliases deleted file mode 100644 index 9cc67c4113..0000000000 --- a/test/integration/targets/vmware_tag_manager/aliases +++ /dev/null @@ -1,3 +0,0 @@ -cloud/vcenter -unsupported -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_tag_manager/tasks/main.yml b/test/integration/targets/vmware_tag_manager/tasks/main.yml deleted file mode 100644 index 54d2fa665f..0000000000 --- a/test/integration/targets/vmware_tag_manager/tasks/main.yml +++ /dev/null @@ -1,5 +0,0 @@ -# Test code for the vmware_tag_manger Operations. -# Copyright: (c) 2020, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- include: tag_manager_dict.yml diff --git a/test/integration/targets/vmware_tag_manager/tasks/tag_manager_dict.yml b/test/integration/targets/vmware_tag_manager/tasks/tag_manager_dict.yml deleted file mode 100644 index 0b414552ae..0000000000 --- a/test/integration/targets/vmware_tag_manager/tasks/tag_manager_dict.yml +++ /dev/null @@ -1,113 +0,0 @@ -# Test code for the vmware_tag_manager Operations. -# Copyright: (c) 2020, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# Testcase for https://github.com/ansible/ansible/issues/65765 -- when: vcsim is not defined - block: - - name: Create first category - vmware_category: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - category_name: "{{ cat_one }}" - category_cardinality: 'multiple' - state: present - register: category_one_create - - - name: Set category one id - set_fact: cat_one_id={{ category_one_create['category_results']['category_id'] }} - - - name: Create tag with colon in name - vmware_tag: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - tag_name: "{{ tag_one }}" - category_id: "{{ cat_one_id }}" - state: present - register: tag_one_create - - - name: Check tag is created - assert: - that: - - tag_one_create.changed - - - name: Get VM Facts - vmware_vm_info: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: False - register: vm_info - - - set_fact: vm_name="{{ vm_info['virtual_machines'][0]['guest_name'] }}" - - - name: Assign tag to given virtual machine - vmware_tag_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - tag_names: - - category: "{{ cat_one }}" - tag: "{{ tag_one }}" - object_name: "{{ vm_name }}" - object_type: VirtualMachine - state: add - delegate_to: localhost - register: vm_tag_info - - - name: Check if we assigned correct tags - assert: - that: - - vm_tag_info.changed - - - name: Remove tag to given virtual machine - vmware_tag_manager: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - tag_names: - - category: "{{ cat_one }}" - tag: "{{ tag_one }}" - object_name: "{{ vm_name }}" - object_type: VirtualMachine - state: remove - delegate_to: localhost - register: vm_tag_info - - - name: Check if we removed correct tag - assert: - that: - - vm_tag_info.changed - - - name: Delete Tags - vmware_tag: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - tag_name: "{{ item }}" - state: absent - register: delete_tag - with_items: - - "{{ tag_one }}" - - - name: Delete Categories - vmware_category: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - category_name: "{{ item }}" - state: absent - register: delete_categories - with_items: - - "{{ cat_one }}" - vars: - cat_one: category_1003 - tag_one: tag:1003 diff --git a/test/integration/targets/vmware_target_canonical_facts/aliases b/test/integration/targets/vmware_target_canonical_facts/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_target_canonical_facts/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_target_canonical_facts/tasks/main.yml b/test/integration/targets/vmware_target_canonical_facts/tasks/main.yml deleted file mode 100644 index 45ac3bda84..0000000000 --- a/test/integration/targets/vmware_target_canonical_facts/tasks/main.yml +++ /dev/null @@ -1,38 +0,0 @@ -# Test code for the vmware_target_canonical_facts module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# TODO: vcsim does not support SCSI target releated operations -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - -- name: Gather target facts for all ESXi host from given cluster - vmware_target_canonical_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: False - cluster_name: "{{ ccr1 }}" - register: target_0001_results - -- assert: - that: - - "not target_0001_results.changed" - - "target_0001_results.scsi_tgt_facts is defined" - -- name: Gather target facts for ESXi host - vmware_target_canonical_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: False - esxi_hostname: '{{ esxi1 }}' - register: target_0002_results - -- assert: - that: - - "not target_0002_results.changed" - - "target_0002_results.scsi_tgt_facts is defined" diff --git a/test/integration/targets/vmware_target_canonical_info/aliases b/test/integration/targets/vmware_target_canonical_info/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_target_canonical_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_target_canonical_info/tasks/main.yml b/test/integration/targets/vmware_target_canonical_info/tasks/main.yml deleted file mode 100644 index a30abab45b..0000000000 --- a/test/integration/targets/vmware_target_canonical_info/tasks/main.yml +++ /dev/null @@ -1,38 +0,0 @@ -# Test code for the vmware_target_canonical_info module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# TODO: vcsim does not support SCSI target releated operations -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - -- name: Gather target info for all ESXi host from given cluster - vmware_target_canonical_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: False - cluster_name: "{{ ccr1 }}" - register: target_0001_results - -- assert: - that: - - "not target_0001_results.changed" - - "target_0001_results.scsi_tgt_info is defined" - -- name: Gather target info for ESXi host - vmware_target_canonical_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: False - esxi_hostname: '{{ esxi1 }}' - register: target_0002_results - -- assert: - that: - - "not target_0002_results.changed" - - "target_0002_results.scsi_tgt_info is defined" diff --git a/test/integration/targets/vmware_vcenter_settings/aliases b/test/integration/targets/vmware_vcenter_settings/aliases deleted file mode 100644 index 900b4c2c3c..0000000000 --- a/test/integration/targets/vmware_vcenter_settings/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group2 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_vcenter_settings/tasks/main.yml b/test/integration/targets/vmware_vcenter_settings/tasks/main.yml deleted file mode 100644 index e2930e6206..0000000000 --- a/test/integration/targets/vmware_vcenter_settings/tasks/main.yml +++ /dev/null @@ -1,83 +0,0 @@ -# Test code for the vmware_vcenter_settings module. -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - -- name: Configure general settings in check mode - vmware_vcenter_settings: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - database: - max_connections: 50 - task_cleanup: true - task_retention: 180 - event_cleanup: true - event_retention: 180 - runtime_settings: - unique_id: 7 - managed_address: 192.168.1.0 - vcenter_server_name: "{{ inventory_hostname }}" - user_directory: - timeout: 120 - query_limit: true - query_limit_size: 100000 - validation: true - validation_period: 1440 - mail: - server: mail.example.local - sender: vcenter@{{ inventory_hostname }} - snmp_receivers: - snmp_receiver_1_url: localhost - snmp_receiver_1_enabled: true - snmp_receiver_1_port: 162 - snmp_receiver_1_community: public - timeout_settings: - normal_operations: 30 - long_operations: 120 - logging_options: info - validate_certs: no - register: all_settings_results_check_mode - check_mode: yes - -- debug: var=all_settings_results_check_mode - -- name: Configure general settings - vmware_vcenter_settings: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - database: - max_connections: 50 - task_cleanup: true - task_retention: 180 - event_cleanup: true - event_retention: 180 - runtime_settings: - unique_id: 7 - managed_address: 192.168.1.0 - vcenter_server_name: "{{ inventory_hostname }}" - user_directory: - timeout: 120 - query_limit: true - query_limit_size: 100000 - validation: true - validation_period: 1440 - mail: - server: mail.example.local - sender: vcenter@{{ inventory_hostname }} - snmp_receivers: - snmp_receiver_1_url: localhost - snmp_receiver_1_enabled: true - snmp_receiver_1_port: 162 - snmp_receiver_1_community: public - timeout_settings: - normal_operations: 30 - long_operations: 120 - logging_options: info - validate_certs: no - register: all_settings_results - -- debug: var=all_settings_results diff --git a/test/integration/targets/vmware_vcenter_statistics/aliases b/test/integration/targets/vmware_vcenter_statistics/aliases deleted file mode 100644 index 900b4c2c3c..0000000000 --- a/test/integration/targets/vmware_vcenter_statistics/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group2 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_vcenter_statistics/tasks/main.yml b/test/integration/targets/vmware_vcenter_statistics/tasks/main.yml deleted file mode 100644 index 446f84a35d..0000000000 --- a/test/integration/targets/vmware_vcenter_statistics/tasks/main.yml +++ /dev/null @@ -1,133 +0,0 @@ -# Test code for the vmware_vcenter_statistics module. -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - -- name: Disable all the statistics - vmware_vcenter_statistics: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - interval_past_day: - enabled: false - interval_past_week: - enabled: false - interval_past_month: - enabled: false - interval_past_year: - enabled: false - validate_certs: no - register: statistics_results_check_mode - -- name: Configure statistics in check mode - vmware_vcenter_statistics: &stats - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - interval_past_day: - enabled: true - interval_minutes: 5 - save_for_days: 3 - level: 2 - interval_past_week: - enabled: true - interval_minutes: 30 - save_for_weeks: 1 - level: 2 - interval_past_month: - enabled: true - interval_hours: 2 - save_for_months: 1 - level: 1 - interval_past_year: - enabled: true - interval_days: 1 - save_for_years: 1 - level: 1 - validate_certs: no - register: statistics_results_check_mode - check_mode: yes - -- debug: var=statistics_results_check_mode - -- name: ensure statistics were configured - assert: - that: - # Doesn't really work with vcsim. No matter which settings are used; they are always shown as already configured!? - - statistics_results_check_mode is changed - when: vcsim is not defined - -- name: Configure statistics - vmware_vcenter_statistics: - <<: *stats - register: statistics_results - -- debug: var=statistics_results - -- name: ensure statistics were configured - assert: - that: - - statistics_results is changed - when: vcsim is not defined - -- name: Configure statistics (again) - vmware_vcenter_statistics: - <<: *stats - register: statistics_results - -- debug: var=statistics_results - -- name: ensure statistics were configured - assert: - that: - - not (statistics_results is changed) - when: vcsim is not defined - -- name: Configure statistics intervall to level 2 for later check - vmware_vcenter_statistics: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - interval_past_day: - enabled: true - level: 2 - interval_past_week: - enabled: true - level: 2 - interval_past_month: - enabled: true - level: 2 - interval_past_year: - enabled: true - level: 2 - validate_certs: no - when: vcsim is not defined - -- name: Increase daily and weekly while decrease monthly and yearly - vmware_vcenter_statistics: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - interval_past_day: - enabled: true - level: 3 - interval_past_week: - enabled: true - level: 3 - interval_past_month: - enabled: true - level: 1 - interval_past_year: - enabled: true - level: 1 - validate_certs: no - register: statistics_results_mixed_increase_decrease - when: vcsim is not defined - -- name: Ensure statistics were configured - assert: - that: - - statistics_results_mixed_increase_decrease is changed - when: vcsim is not defined diff --git a/test/integration/targets/vmware_vm_facts/aliases b/test/integration/targets/vmware_vm_facts/aliases deleted file mode 100644 index c2c1343eac..0000000000 --- a/test/integration/targets/vmware_vm_facts/aliases +++ /dev/null @@ -1,5 +0,0 @@ -shippable/vcenter/group2 -shippable/vcenter/smoketest -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_vm_facts/tasks/main.yml b/test/integration/targets/vmware_vm_facts/tasks/main.yml deleted file mode 100644 index 948c9005ad..0000000000 --- a/test/integration/targets/vmware_vm_facts/tasks/main.yml +++ /dev/null @@ -1,100 +0,0 @@ -# Test code for the vmware_vm_facts module -# Copyright: (c) 2017, Abhijeet Kasurde <akasurde@redhat.com> -# Copyright, (c) 2018, Fedor Vompe <f.vompe@comptek.ru> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - vars: - setup_datastore: true - setup_virtualmachines: true - -- when: vcsim is not defined - block: - - name: Get facts from a given ESXi - vmware_vm_facts: - validate_certs: false - hostname: '{{ esxi1 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_virtualmachines: true - -- &vm_data - name: Get facts about available vms - vmware_vm_facts: - validate_certs: false - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - register: vm_facts - -- &set_vm_by_name - set_fact: - vm_by_name: "{{ dict(vm_facts.virtual_machines|map(attribute='guest_name')|zip(vm_facts.virtual_machines)) }}" - -- set_fact: - my_vm1: "{{ vm_by_name['DC0_H0_VM1'] }}" -- &vm_fact_check - name: Verify if VM facts exist - assert: - that: - - "my_vm1.esxi_hostname is defined" - - "my_vm1.guest_fullname is defined" - - "my_vm1.ip_address is defined" - - "my_vm1.mac_address is defined" - - "my_vm1.power_state is defined" - - "my_vm1.uuid is defined" - - "my_vm1.vm_network is defined" - -- <<: *vm_data - name: Get facts about available vms in check mode - check_mode: yes - -- <<: *vm_fact_check - name: Verify if VM facts exist in check mode - -- name: Get folder name from VM - vmware_guest_find: - validate_certs: false - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "{{ virtual_machines[0].name }}" - register: folder_path_info - -- set_fact: - folder_path: "{{ folder_path_info.folders[0] }}" - when: folder_path_info.folders is defined - -- name: Gather facts about VM using folder - vmware_vm_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - folder: "{{ folder_path }}" - register: vm_facts - when: folder_path_info.folders is defined -- debug: var=vm_facts - -- <<: *set_vm_by_name - -- set_fact: - my_vm0: "{{ vm_by_name['DC0_H0_VM0'] }}" - -- name: Check if facts are returned for VM with folder specified - assert: - that: - - "my_vm0.esxi_hostname is defined" - - "my_vm0.guest_fullname is defined" - - "my_vm0.ip_address is defined" - - "my_vm0.mac_address is defined" - - "my_vm0.power_state is defined" - - "my_vm0.uuid is defined" - - "my_vm0.vm_network is defined" diff --git a/test/integration/targets/vmware_vm_host_drs_rule/aliases b/test/integration/targets/vmware_vm_host_drs_rule/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_vm_host_drs_rule/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_vm_host_drs_rule/tasks/main.yml b/test/integration/targets/vmware_vm_host_drs_rule/tasks/main.yml deleted file mode 100644 index 41ac2560a0..0000000000 --- a/test/integration/targets/vmware_vm_host_drs_rule/tasks/main.yml +++ /dev/null @@ -1,81 +0,0 @@ -# Test code for the vmware_vm_vm_drs_rule module. -# Copyright: (c) 2017, Karsten Kaj Jakobsen <kj@patientsky.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_virtualmachines: true - - - name: Create DRS VM group - vmware_drs_group: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: False - # Options - cluster_name: '{{ ccr1 }}' - datacenter_name: '{{ dc1 }}' - group_name: DC0_C0_VM_GR1 - vms: "{{ virtual_machines_in_cluster | map(attribute='name') | list }}" - state: present - register: drs_vm_group_01_results - - debug: var=drs_vm_group_01_results - - - name: Create DRS Host group - vmware_drs_group: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: False - # Options - cluster_name: '{{ ccr1 }}' - datacenter_name: '{{ dc1 }}' - group_name: DC0_C0_HOST_GR1 - hosts: '{{ esxi_hosts }}' - state: present - register: drs_host_group_01_results - - debug: var=drs_host_group_01_results - - - name: Create mandatory DRS Affinity rule for VM/Host - vmware_vm_host_drs_rule: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - drs_rule_name: drs_rule_host_aff_0001 - vm_group_name: DC0_C0_VM_GR1 - host_group_name: DC0_C0_HOST_GR1 - cluster_name: "{{ ccr1 }}" - enabled: True - affinity_rule: True - mandatory: True - register: drs_rule_host_0001_results - - debug: var=drs_rule_host_0001_results - - assert: - that: - - "{{ drs_rule_host_0001_results.changed }}" - - # TODO: create host/vm group when vcsim supports this - - name: Create non-mandatory DRS Anti-Affinity rule for VM/Host - vmware_vm_host_drs_rule: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - drs_rule_name: drs_rule_host_aff_0001 - vm_group_name: DC0_C0_VM_GR1 - host_group_name: DC0_C0_HOST_GR1 - cluster_name: "{{ ccr1 }}" - enabled: True - affinity_rule: False - mandatory: False - register: drs_rule_host_0002_results - - debug: var=drs_rule_host_0002_results - - assert: - that: - - "{{ drs_rule_host_0001_results.changed }}" diff --git a/test/integration/targets/vmware_vm_info/aliases b/test/integration/targets/vmware_vm_info/aliases deleted file mode 100644 index c2c1343eac..0000000000 --- a/test/integration/targets/vmware_vm_info/aliases +++ /dev/null @@ -1,5 +0,0 @@ -shippable/vcenter/group2 -shippable/vcenter/smoketest -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_vm_info/tasks/main.yml b/test/integration/targets/vmware_vm_info/tasks/main.yml deleted file mode 100644 index 93236581b4..0000000000 --- a/test/integration/targets/vmware_vm_info/tasks/main.yml +++ /dev/null @@ -1,100 +0,0 @@ -# Test code for the vmware_vm_info module -# Copyright: (c) 2017, Abhijeet Kasurde <akasurde@redhat.com> -# Copyright, (c) 2018, Fedor Vompe <f.vompe@comptek.ru> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - vars: - setup_datastore: true - setup_virtualmachines: true - -- when: vcsim is not defined - block: - - name: Get info from a given ESXi - vmware_vm_info: - validate_certs: false - hostname: '{{ esxi1 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_virtualmachines: true - -- &vm_data - name: Get info about available vms - vmware_vm_info: - validate_certs: false - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - register: vm_info - -- &set_vm_by_name - set_fact: - vm_by_name: "{{ dict(vm_info.virtual_machines|map(attribute='guest_name')|zip(vm_info.virtual_machines)) }}" - -- set_fact: - my_vm1: "{{ vm_by_name['DC0_H0_VM1'] }}" -- &vm_fact_check - name: Verify if VM info exist - assert: - that: - - "my_vm1.esxi_hostname is defined" - - "my_vm1.guest_fullname is defined" - - "my_vm1.ip_address is defined" - - "my_vm1.mac_address is defined" - - "my_vm1.power_state is defined" - - "my_vm1.uuid is defined" - - "my_vm1.vm_network is defined" - -- <<: *vm_data - name: Get info about available vms in check mode - check_mode: yes - -- <<: *vm_fact_check - name: Verify if VM info exist in check mode - -- name: Get folder name from VM - vmware_guest_find: - validate_certs: false - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - name: "{{ virtual_machines[0].name }}" - register: folder_path_info - -- set_fact: - folder_path: "{{ folder_path_info.folders[0] }}" - when: folder_path_info.folders is defined - -- name: Gather info about VM using folder - vmware_vm_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - folder: "{{ folder_path }}" - register: vm_info - when: folder_path_info.folders is defined -- debug: var=vm_info - -- <<: *set_vm_by_name - -- set_fact: - my_vm0: "{{ vm_by_name['DC0_H0_VM0'] }}" - -- name: Check if info are returned for VM with folder specified - assert: - that: - - "my_vm0.esxi_hostname is defined" - - "my_vm0.guest_fullname is defined" - - "my_vm0.ip_address is defined" - - "my_vm0.mac_address is defined" - - "my_vm0.power_state is defined" - - "my_vm0.uuid is defined" - - "my_vm0.vm_network is defined" diff --git a/test/integration/targets/vmware_vm_storage_policy_info/aliases b/test/integration/targets/vmware_vm_storage_policy_info/aliases deleted file mode 100644 index 900b4c2c3c..0000000000 --- a/test/integration/targets/vmware_vm_storage_policy_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -shippable/vcenter/group2 -cloud/vcenter -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_vm_storage_policy_info/tasks/main.yml b/test/integration/targets/vmware_vm_storage_policy_info/tasks/main.yml deleted file mode 100644 index 25bba2a857..0000000000 --- a/test/integration/targets/vmware_vm_storage_policy_info/tasks/main.yml +++ /dev/null @@ -1,25 +0,0 @@ -# Test code for the vmware_vm_storage_policy_info module. -# Copyright: (c) 2019, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - &spbm_data - name: Get information about vSphere SPBM info - vmware_vm_storage_policy_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: no - register: spbm_data - - - &spbm_check - assert: - that: - - spbm_data.spbm_profiles is defined - - - <<: *spbm_data - name: Get information about vSphere SPBM info in check mode - check_mode: yes - - - <<: *spbm_check
\ No newline at end of file diff --git a/test/integration/targets/vmware_vm_vm_drs_rule/aliases b/test/integration/targets/vmware_vm_vm_drs_rule/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_vm_vm_drs_rule/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_vm_vm_drs_rule/tasks/main.yml b/test/integration/targets/vmware_vm_vm_drs_rule/tasks/main.yml deleted file mode 100644 index 8f049f7002..0000000000 --- a/test/integration/targets/vmware_vm_vm_drs_rule/tasks/main.yml +++ /dev/null @@ -1,144 +0,0 @@ -# Test code for the vmware_vm_vm_drs_rule module. -# Copyright: (c) 2017, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# TODO: vcsim does not support manage DRS rule -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_virtualmachines: true - - - &create_drs_rule - name: Create a DRS Affinity rule for vms - vmware_vm_vm_drs_rule: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - drs_rule_name: drs_rule_0001 - cluster_name: "{{ ccr1 }}" - vms: "{{ virtual_machines_in_cluster | map(attribute='name') | list }}" - enabled: True - affinity_rule: True - mandatory: True - register: drs_rule_0001_results - - - debug: var=drs_rule_0001_results - - - name: Check if changes are made - assert: - that: - - drs_rule_0001_results.changed - - - <<: *create_drs_rule - name: Create a DRS Affinity rule for vms again - - - name: Check if no changes are made if drs rule is created again - assert: - that: - - not drs_rule_0001_results.changed - - - &update_drs_rule - name: Update a DRS Affinity rule for vms - vmware_vm_vm_drs_rule: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - drs_rule_name: drs_rule_0001 - cluster_name: "{{ ccr1 }}" - vms: "{{ virtual_machines_in_cluster | map(attribute='name') | list }}" - enabled: False - affinity_rule: True - mandatory: False - register: drs_rule_0001_results - - - name: Check if changes are made if drs rule is created - assert: - that: - - drs_rule_0001_results.changed - - - <<: *update_drs_rule - name: Update a DRS Affinity rule for vms again - - - name: Check if no changes are made if drs rule is created again - assert: - that: - - not drs_rule_0001_results.changed - - - &delete_drs_rule - name: Delete a DRS Affinity rule for vms - vmware_vm_vm_drs_rule: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - drs_rule_name: drs_rule_0001 - cluster_name: "{{ ccr1 }}" - state: absent - register: drs_rule_0001_results - - - name: Check if DRS rule is delete - assert: - that: - - drs_rule_0001_results.changed - - - <<: *delete_drs_rule - name: Delete a DRS Affinity rule for vms again - - - name: Check if DRS rule is not delete again - assert: - that: - - not drs_rule_0001_results.changed - - - &create_anti_drs_rule - name: Create a DRS Anti-Affinity rule for vms - vmware_vm_vm_drs_rule: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - drs_rule_name: drs_rule_0002 - cluster_name: "{{ ccr1 }}" - vms: "{{ virtual_machines_in_cluster | map(attribute='name') | list }}" - enabled: True - affinity_rule: False - mandatory: False - register: drs_rule_0002_results - - - debug: var=drs_rule_0002_results - - - name: Check if DRS Anti-Affinity rule is created - assert: - that: - - drs_rule_0002_results.changed - - - <<: *create_anti_drs_rule - name: Create a DRS Anti-Affinity rule for vms again - - - debug: var=drs_rule_0002_results - - - name: Check if no changes are made if DRS Anti-Affinity rule is created again - assert: - that: - - not drs_rule_0002_results.changed - - - name: Delete a DRS Anti-Affinity rule for vms - vmware_vm_vm_drs_rule: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - drs_rule_name: drs_rule_0002 - cluster_name: "{{ ccr1 }}" - state: absent - register: drs_rule_0002_results - - - name: Check if DRS rule is not delete - assert: - that: - - drs_rule_0002_results.changed diff --git a/test/integration/targets/vmware_vmkernel/aliases b/test/integration/targets/vmware_vmkernel/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_vmkernel/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_vmkernel/tasks/main.yml b/test/integration/targets/vmware_vmkernel/tasks/main.yml deleted file mode 100644 index 88f159e457..0000000000 --- a/test/integration/targets/vmware_vmkernel/tasks/main.yml +++ /dev/null @@ -1,65 +0,0 @@ -# Test code for the vmware_vmkernel module. -# Copyright: (c) 2018, Christian Kotte <christian.kotte@gmx.de> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -- when: vcsim is not defined - block: -# TODO: vcsim does not support HostVirtualNicManager-related operations - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_switch: true - - - name: create basic portgroup - vmware_portgroup: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - switch_name: "{{ switch1 }}" - cluster_name: "{{ ccr1 }}" - portgroup_name: vMotion - vlan_id: 0 - state: present - register: dvs_pg_result_0001 - - - debug: var=dvs_pg_result_0001 - - name: Create VMkernel adapter with vMotion TCP/IP stack - vmware_vmkernel: &new_vmkernel - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - vswitch: "{{ switch1 }}" - portgroup: vMotion - mtu: 9000 - network: - type: static - ip_address: 192.168.100.100 - subnet_mask: 255.255.255.0 - tcpip_stack: vmotion - state: present - validate_certs: no - register: host_vmkernel - - debug: var=host_vmkernel - - - name: Create VMkernel adapter in check mode - vmware_vmkernel: - <<: *new_vmkernel - register: host_vmkernel - check_mode: yes - - debug: var=host_vmkernel - - - name: Delete VMkernel adapter - vmware_vmkernel: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - vswitch: "{{ switch1 }}" - device: '{{ host_vmkernel.device }}' - portgroup: vMotion - state: absent - validate_certs: no - register: host_vmkernel - - debug: var=host_vmkernel diff --git a/test/integration/targets/vmware_vmkernel_facts/aliases b/test/integration/targets/vmware_vmkernel_facts/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_vmkernel_facts/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_vmkernel_facts/tasks/main.yml b/test/integration/targets/vmware_vmkernel_facts/tasks/main.yml deleted file mode 100644 index cf70a6e6f5..0000000000 --- a/test/integration/targets/vmware_vmkernel_facts/tasks/main.yml +++ /dev/null @@ -1,38 +0,0 @@ -# Test code for the vmware_vmkernel_facts module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# TODO: vcsim does not support HostVirtualNicManager related to operations -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - - name: Gather VMkernel facts for a given host - vmware_vmkernel_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - register: host_vmkernel - - debug: var=host_vmkernel - - assert: - that: - - host_vmkernel.host_vmk_facts is defined - - - name: Gather VMkernel facts for a given host in check mode - vmware_vmkernel_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - register: host_vmkernel_check_mode - check_mode: yes - - debug: var=host_vmkernel - - assert: - that: - - host_vmkernel_check_mode.host_vmk_facts is defined diff --git a/test/integration/targets/vmware_vmkernel_info/aliases b/test/integration/targets/vmware_vmkernel_info/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_vmkernel_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_vmkernel_info/tasks/main.yml b/test/integration/targets/vmware_vmkernel_info/tasks/main.yml deleted file mode 100644 index 8c11359f88..0000000000 --- a/test/integration/targets/vmware_vmkernel_info/tasks/main.yml +++ /dev/null @@ -1,38 +0,0 @@ -# Test code for the vmware_vmkernel_info module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -# TODO: vcsim does not support HostVirtualNicManager related to operations -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - - name: Gather VMkernel info for a given host - vmware_vmkernel_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - register: host_vmkernel - - debug: var=host_vmkernel - - assert: - that: - - host_vmkernel.host_vmk_info is defined - - - name: Gather VMkernel info for a given host in check mode - vmware_vmkernel_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - register: host_vmkernel_check_mode - check_mode: yes - - debug: var=host_vmkernel - - assert: - that: - - host_vmkernel_check_mode.host_vmk_info is defined diff --git a/test/integration/targets/vmware_vmotion/aliases b/test/integration/targets/vmware_vmotion/aliases deleted file mode 100644 index 1e26bda5d0..0000000000 --- a/test/integration/targets/vmware_vmotion/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_2esxi diff --git a/test/integration/targets/vmware_vmotion/tasks/main.yml b/test/integration/targets/vmware_vmotion/tasks/main.yml deleted file mode 100644 index 37617ab556..0000000000 --- a/test/integration/targets/vmware_vmotion/tasks/main.yml +++ /dev/null @@ -1,133 +0,0 @@ -# Test code for the vmware_vmotion module. -# 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) - -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - setup_datastore: true - setup_resource_pool: true - -- when: vcsim is not defined - block: - - name: Add ESXi Hosts to vCenter - vmware_host: - datacenter_name: '{{ dc1 }}' - esxi_hostname: '{{ item }}' - esxi_username: '{{ esxi_user }}' - esxi_password: '{{ esxi_password }}' - folder: '/DC0/host' - state: present - with_items: "{{ esxi_hosts }}" - - - name: Disable the Maintenance Mode - vmware_maintenancemode: - esxi_hostname: '{{ item }}' - state: absent - with_items: "{{ esxi_hosts }}" - -- name: Create VM - vmware_guest: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter: "{{ dc1 }}" - validate_certs: no - name: test_vm1 - folder: vm - esxi_hostname: "{{ esxi1 }}" - state: present - guest_id: centos7_64Guest - disk: - - size_gb: 1 - type: thin - datastore: '{{ rw_datastore }}' - hardware: - version: latest - memory_mb: 1024 - num_cpus: 1 - scsi: paravirtual - register: vm_create - -- name: Perform vMotion of non-existing VM - vmware_vmotion: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - vm_name: not_a_thing - destination_host: '{{ esxi2 }}' - destination_datastore: '{{ rw_datastore }}' - register: vm_vmotion - ignore_errors: true - -- assert: - that: - - vm_vmotion.msg == "Failed to find the virtual machine with not_a_thing" - - -- name: Perform vMotion of virtual machine - vmware_vmotion: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - vm_name: test_vm1 - destination_host: '{{ esxi2 }}' - destination_datastore: '{{ rw_datastore }}' - register: vm_vmotion - -- name: assert that changes were made - assert: - that: - - vm_vmotion is changed - - -- name: Add ESXi Hosts to a cluster - vmware_host: - datacenter_name: '{{ dc1 }}' - cluster_name: '{{ ccr1 }}' - esxi_hostname: '{{ item }}' - esxi_username: '{{ esxi_user }}' - esxi_password: '{{ esxi_password }}' - state: present - with_items: "{{ esxi_hosts }}" - -- name: Disable the Maintenance Mode - vmware_maintenancemode: - esxi_hostname: '{{ item }}' - state: absent - with_items: "{{ esxi_hosts }}" - -- name: Perform vMotion of virtual machine to resource_pool - vmware_vmotion: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - vm_name: test_vm1 - destination_host: '{{ esxi1 }}' - destination_resourcepool: DC0_C0_RP1 - register: vm_vmotion_to_rp - -- name: assert that changes were made - assert: - that: - - vm_vmotion_to_rp is changed - -- name: Perform storage vMotion of virtual machine - vmware_vmotion: - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - validate_certs: no - vm_name: test_vm1 - destination_host: '{{ esxi2 }}' - destination_datastore: '{{ rw_datastore }}' - register: vm_vmotion_to_datastore - -- name: assert that changes were made - assert: - that: - - vm_vmotion_to_datastore is changed diff --git a/test/integration/targets/vmware_vsan_health_info/aliases b/test/integration/targets/vmware_vsan_health_info/aliases deleted file mode 100644 index b3bf7b222c..0000000000 --- a/test/integration/targets/vmware_vsan_health_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -unsupported -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_only diff --git a/test/integration/targets/vmware_vsan_health_info/tasks/main.yml b/test/integration/targets/vmware_vsan_health_info/tasks/main.yml deleted file mode 100644 index e456f8bd56..0000000000 --- a/test/integration/targets/vmware_vsan_health_info/tasks/main.yml +++ /dev/null @@ -1,22 +0,0 @@ -# Test code for the vmware_vsan_health_info module. -# Copyright: (c) 2019, OVH SAS -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - -- when: vcsim is not defined - block: - - name: Gather health info from a vSAN's cluster - vmware_vsan_health_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - cluster_name: "{{ ccr1 }}" - validate_certs: False - fetch_from_cache: False - register: info - - debug: var=info - - assert: - that: - - info.vsan_health_info is defined diff --git a/test/integration/targets/vmware_vspan_session/aliases b/test/integration/targets/vmware_vspan_session/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_vspan_session/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_vspan_session/tasks/main.yml b/test/integration/targets/vmware_vspan_session/tasks/main.yml deleted file mode 100644 index 24566bd3c1..0000000000 --- a/test/integration/targets/vmware_vspan_session/tasks/main.yml +++ /dev/null @@ -1,102 +0,0 @@ -# Test code for the vmware_vspan_session module. -# Copyright: (c) 2018, Peter Gyorgy <gyorgy.peter@edu.bme.hu> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - -- name: add distributed vSwitch - vmware_dvswitch: - validate_certs: False - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - datacenter_name: "{{ dc1 }}" - state: present - switch_name: dvswitch_0001 - mtu: 9000 - uplink_quantity: 2 - discovery_proto: lldp - discovery_operation: both - register: dvs_result_0001 -- debug: var=dvs_result_0001 -- name: ensure distributed vswitch is present - assert: - that: - - "{{ dvs_result_0001.changed == true }}" - -- name: Create vlan portgroup with all security and port policies - vmware_dvs_portgroup: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: False - portgroup_name: vlan-123-portrgoup - switch_name: dvswitch_0001 - vlan_id: 123 - num_ports: 120 - portgroup_type: earlyBinding - state: present - network_policy: - promiscuous: yes - forged_transmits: yes - mac_changes: yes - port_policy: - block_override: yes - ipfix_override: yes - live_port_move: yes - network_rp_override: yes - port_config_reset_at_disconnect: yes - security_override: yes - shaping_override: yes - traffic_filter_override: yes - uplink_teaming_override: yes - vendor_config_override: yes - vlan_override: yes - register: portgroup_create_result - -- name: ensure portgroup was created - assert: - that: - - portgroup_create_result.changed - -- when: vcsim is not defined - block: - - name: create a session. - vmware_vspan_session: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: False - switch: dvswitch_0001 - name: "session_0001" - state: "present" - enabled: True - description: "basic_description" - source_port_transmitted: 13 - source_port_received: 13 - destination_port: 12 - register: vspan_session_create_result - - debug: var=vspan_session_create_result - - name: ensure session was created - assert: - that: - - vspan_session_create_result.changed - - - name: delete a session. - vmware_vspan_session: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - validate_certs: False - switch: dvswitch_0001 - name: "session_0001" - state: "absent" - register: vspan_session_delete_result - - name: ensure session was deleted - assert: - that: - - vspan_session_delete_result.changed diff --git a/test/integration/targets/vmware_vswitch/aliases b/test/integration/targets/vmware_vswitch/aliases deleted file mode 100644 index 1e26bda5d0..0000000000 --- a/test/integration/targets/vmware_vswitch/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_2esxi diff --git a/test/integration/targets/vmware_vswitch/tasks/main.yml b/test/integration/targets/vmware_vswitch/tasks/main.yml deleted file mode 100644 index be19e88cc7..0000000000 --- a/test/integration/targets/vmware_vswitch/tasks/main.yml +++ /dev/null @@ -1,86 +0,0 @@ -# Test code for the vmware_vswitch module. -# Copyright: (c) 2017, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- when: vcsim is not defined - block: - - import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - - # TODO: akasurde: VCSIM does not suport network manager system - - name: Ensure the vswitch is not already here - include_tasks: teardown.yml - - - name: Add a nic to a switch - vmware_vswitch: - hostname: '{{ esxi1 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - validate_certs: no - switch: vmswitch_0001 - nics: vmnic1 - state: present - register: add_nic_run - - debug: var=add_nic_run - - assert: - that: - - add_nic_run.changed == true - - - name: Add a nic to a switch again - vmware_vswitch: - hostname: '{{ esxi1 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - validate_certs: no - switch: vmswitch_0001 - nics: vmnic1 - state: present - register: add_nic_again_run - - assert: - that: - - add_nic_again_run.changed == false - - - name: Remove a switch - vmware_vswitch: - hostname: '{{ esxi1 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - validate_certs: no - switch: vmswitch_0001 - state: absent - register: remove_nic_run - - assert: - that: - - remove_nic_run is changed - - - name: Remove a switch again - vmware_vswitch: - hostname: '{{ esxi1 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - validate_certs: no - switch: vmswitch_0001 - state: absent - register: remove_nic_again_run - - assert: - that: - - not (remove_nic_again_run is changed) - - - name: Add vswitch to a specific host system - vmware_vswitch: - validate_certs: False - hostname: '{{ vcenter_hostname }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - switch: vmswitch_0002 - nics: vmnic1 - esxi_hostname: '{{ esxi2 }}' - register: add_vswitch_with_host_system - - debug: var=add_vswitch_with_host_system - - assert: - that: - - add_vswitch_with_host_system is changed - always: - - include_tasks: teardown.yml diff --git a/test/integration/targets/vmware_vswitch/tasks/teardown.yml b/test/integration/targets/vmware_vswitch/tasks/teardown.yml deleted file mode 100644 index fb590664fe..0000000000 --- a/test/integration/targets/vmware_vswitch/tasks/teardown.yml +++ /dev/null @@ -1,16 +0,0 @@ -- name: Remove the vSwitches (ESXi1) - vmware_vswitch: - hostname: '{{ esxi1 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - switch_name: vmswitch_0001 - state: absent - -- name: Remove the vSwitches (ESXi2) - vmware_vswitch: - hostname: '{{ esxi2 }}' - username: '{{ esxi_user }}' - password: '{{ esxi_password }}' - switch_name: vmswitch_0002 - state: absent - when: esxi2 is defined diff --git a/test/integration/targets/vmware_vswitch_facts/aliases b/test/integration/targets/vmware_vswitch_facts/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_vswitch_facts/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_vswitch_facts/tasks/main.yml b/test/integration/targets/vmware_vswitch_facts/tasks/main.yml deleted file mode 100644 index f0bc95ed6d..0000000000 --- a/test/integration/targets/vmware_vswitch_facts/tasks/main.yml +++ /dev/null @@ -1,41 +0,0 @@ -# Test code for the vmware_vswitch_facts module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - -# TODO: vcsim does not support networkConfig related to operations - -- name: Gather vswitch facts about all hosts in given cluster - vmware_vswitch_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - register: switch_facts - -- debug: var=switch_facts - -- assert: - that: - - switch_facts.hosts_vswitch_facts is defined - -- name: Gather vswitch facts about all hosts in given cluster in check mode - vmware_vswitch_facts: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - register: switch_facts_check_mode - check_mode: yes - -- debug: var=switch_facts_check_mode - -- assert: - that: - - switch_facts_check_mode.hosts_vswitch_facts is defined diff --git a/test/integration/targets/vmware_vswitch_info/aliases b/test/integration/targets/vmware_vswitch_info/aliases deleted file mode 100644 index fa0e18d454..0000000000 --- a/test/integration/targets/vmware_vswitch_info/aliases +++ /dev/null @@ -1,4 +0,0 @@ -cloud/vcenter -shippable/vcenter/group2 -needs/target/prepare_vmware_tests -zuul/vmware/vcenter_1esxi diff --git a/test/integration/targets/vmware_vswitch_info/tasks/main.yml b/test/integration/targets/vmware_vswitch_info/tasks/main.yml deleted file mode 100644 index 87658f0a9b..0000000000 --- a/test/integration/targets/vmware_vswitch_info/tasks/main.yml +++ /dev/null @@ -1,41 +0,0 @@ -# Test code for the vmware_vswitch_info module. -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.com> -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -- import_role: - name: prepare_vmware_tests - vars: - setup_attach_host: true - -# TODO: vcsim does not support networkConfig related to operations - -- name: Gather vswitch info about all hosts in given cluster - vmware_vswitch_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - register: switch_info - -- debug: var=switch_info - -- assert: - that: - - switch_info.hosts_vswitch_info is defined - -- name: Gather vswitch info about all hosts in given cluster in check mode - vmware_vswitch_info: - hostname: "{{ vcenter_hostname }}" - username: "{{ vcenter_username }}" - password: "{{ vcenter_password }}" - esxi_hostname: '{{ esxi1 }}' - validate_certs: no - register: switch_info_check_mode - check_mode: yes - -- debug: var=switch_info_check_mode - -- assert: - that: - - switch_info_check_mode.hosts_vswitch_info is defined diff --git a/test/integration/targets/vsphere_file/aliases b/test/integration/targets/vsphere_file/aliases deleted file mode 100644 index ad7ccf7ada..0000000000 --- a/test/integration/targets/vsphere_file/aliases +++ /dev/null @@ -1 +0,0 @@ -unsupported diff --git a/test/integration/targets/vsphere_file/tasks/main.yml b/test/integration/targets/vsphere_file/tasks/main.yml deleted file mode 100644 index d3b0284b32..0000000000 --- a/test/integration/targets/vsphere_file/tasks/main.yml +++ /dev/null @@ -1,369 +0,0 @@ -- set_fact: - file: '/ansible_test_file.txt' - directory: '/ansible_test_directory/' - vsphere_connection: &vsphere_conn - host: '{{ vcenter_ipaddress }}' - username: '{{ vcenter_username }}' - password: '{{ vcenter_password }}' - datacenter: '{{ vcenter_datacenter }}' - datastore: '{{ vcenter_datastore }}' - validate_certs: false - -- set_fact: - vsphere_conection_file: &vsphere_conn_file - <<: *vsphere_conn - path: '{{ file }}' - vsphere_conection_dir: &vsphere_conn_dir - <<: *vsphere_conn - path: '{{ directory }}' - -# Clean up environment -- name: Delete file - vsphere_file: - <<: *vsphere_conn_file - state: absent - ignore_errors: true - -- name: Delete directory - vsphere_file: - <<: *vsphere_conn_dir - state: absent - ignore_errors: true - -# Test file operations -- name: Test file at start (check_mode) - vsphere_file: - <<: *vsphere_conn_file - state: file - check_mode: true - ignore_errors: true - register: cm_test_file_start - -- name: Verify cm_test_file_start - assert: - that: - - cm_test_file_start is failed - - cm_test_file_start.state == 'absent' - - cm_test_file_start.status == 404 - -- name: Test file at start (normal mode) - vsphere_file: - <<: *vsphere_conn_file - state: file - register: nm_test_file_start - ignore_errors: true - -- name: Verify nm_test_file_start - assert: - that: - - nm_test_file_start is failed - - nm_test_file_start.state == 'absent' - - nm_test_file_start.status == 404 - -- name: Touch file (check_mode) - vsphere_file: - <<: *vsphere_conn_file - state: touch - check_mode: true - register: cm_touch_file - -- name: Verify cm_touch_file - assert: - that: - - cm_touch_file is success - - cm_touch_file is changed - - cm_touch_file.reason == 'Created' - - cm_touch_file.size == 0 - #- cm_touch_file.state == 'file' # FIXME - - cm_touch_file.status == 201 - -- name: Touch file (normal mode) - vsphere_file: - <<: *vsphere_conn_file - state: touch - register: nm_touch_file - -- name: Verify nm_touch_file - assert: - that: - - nm_touch_file is success - - nm_touch_file is changed - - nm_touch_file.reason == 'Created' - - nm_touch_file.size == 0 - #- nm_touch_file.state == 'file' # FIXME - - nm_touch_file.status == 201 - -- name: Test file after touch (check_mode) - vsphere_file: - <<: *vsphere_conn_file - state: file - check_mode: true - register: cm_test_file_touch - -- name: Verify cm_test_file_touch - assert: - that: - - cm_test_file_touch is success - - cm_test_file_touch is not changed - - cm_test_file_touch.size == 0 - #- cm_test_file_touch.state == 'file' # FIXME - - cm_test_file_touch.status == 200 - -- name: Test file after touch (normal mode) - vsphere_file: - <<: *vsphere_conn_file - state: file - register: nm_test_file_touch - -- name: Verify nm_test_file_touch - assert: - that: - - nm_test_file_touch is success - - nm_test_file_touch is not changed - - nm_test_file_touch.size == 0 - #- nm_test_file_touch.state == 'file' # FIXME - - nm_test_file_touch.status == 200 - -- name: Delete file (check_mode) - vsphere_file: - <<: *vsphere_conn_file - state: absent - check_mode: true - register: cm_delete_file - -- name: Verify cm_delete_file - assert: - that: - - cm_delete_file is success - - cm_delete_file is changed - - cm_delete_file.reason == 'No Content' - - cm_delete_file.size == None - - cm_delete_file.state == 'absent' - - cm_delete_file.status == 204 - -- name: Delete file (normal mode) - vsphere_file: - <<: *vsphere_conn_file - state: absent - register: nm_delete_file - -- name: Verify nm_delete_file - assert: - that: - - nm_delete_file is success - - nm_delete_file is changed - - nm_delete_file.reason == 'No Content' - - nm_delete_file.size == None - - nm_delete_file.state == 'absent' - - nm_delete_file.status == 204 - -- name: Test file after delete (check_mode) - vsphere_file: - <<: *vsphere_conn_file - state: file - check_mode: true - ignore_errors: true - register: cm_test_file_delete - -- name: Verify cm_test_file_delete - assert: - that: - - cm_test_file_delete is failed - - cm_test_file_delete.size == None - - cm_test_file_delete.state == 'absent' - - cm_test_file_delete.status == 404 - -- name: Test file after delete (normal mode) - vsphere_file: - <<: *vsphere_conn_file - state: file - ignore_errors: true - register: nm_test_file_delete - -- name: Verify nm_test_file_delete - assert: - that: - - nm_test_file_delete is failed - - nm_test_file_delete.size == None - - nm_test_file_delete.state == 'absent' - - nm_test_file_delete.status == 404 - -# Test directory operations -- name: Test directory at start (check_mode) - vsphere_file: - <<: *vsphere_conn_dir - state: file - check_mode: true - ignore_errors: true - register: cm_test_dir_start - -- name: Verify cm_test_dir_start - assert: - that: - - cm_test_dir_start is failed - - cm_test_dir_start.size == None - - cm_test_dir_start.state == 'absent' - - cm_test_dir_start.status == 404 - -- name: Test directory at start (normal mode) - vsphere_file: - <<: *vsphere_conn_dir - state: file - ignore_errors: true - register: nm_test_dir_start - -# NOTE: Deleting directories is not implemented. -- name: Verify nm_test_dir_start - assert: - that: - - nm_test_dir_start is failed - - nm_test_dir_start.size == None - - nm_test_dir_start.state == 'absent' - - nm_test_dir_start.status == 404 - -- name: Create directory (check_mode) - vsphere_file: - <<: *vsphere_conn_dir - path: '{{ directory }}' - state: directory - check_mode: true - register: cm_create_dir - -- name: Verify cm_create_dir - assert: - that: - - cm_create_dir is success - - cm_create_dir is changed - - cm_create_dir.reason == 'Created' - - cm_create_dir.size == None - #- cm_create_dir.state == 'directory' # FIXME - - cm_create_dir.status == 201 - -- name: Create directory (normal mode) - vsphere_file: - <<: *vsphere_conn_dir - path: '{{ directory }}' - state: directory - register: nm_create_dir - -- name: Verify nm_create_dir - assert: - that: - - nm_create_dir is success - - nm_create_dir is changed - - nm_create_dir.reason == 'Created' - - nm_create_dir.size == None - #- nm_create_dir.state == 'directory' # FIXME - - nm_create_dir.status == 201 - -- name: Test directory after create (check_mode) - vsphere_file: - <<: *vsphere_conn_dir - path: '{{ directory }}' - state: file - check_mode: true - register: cm_test_dir_create - -- name: Verify cm_test_dir_create - assert: - that: - - cm_test_dir_create is success - - cm_test_dir_create is not changed - #- cm_test_dir_create.size == 0 - #- cm_test_dir_create.state == 'file' # FIXME - - cm_test_dir_create.status == 200 - -- name: Test directory after create (normal mode) - vsphere_file: - <<: *vsphere_conn_dir - path: '{{ directory }}' - state: file - register: nm_test_dir_create - -- name: Verify nm_test_dir_create - assert: - that: - - nm_test_dir_create is success - - nm_test_dir_create is not changed - #- nm_test_dir_create.size == 0 - #- nm_test_dir_create.state == 'file' # FIXME - - nm_test_dir_create.status == 200 - -- name: Delete directory (check_mode) - vsphere_file: - <<: *vsphere_conn_dir - state: absent - check_mode: true - ignore_errors: true - register: cm_delete_dir - -- name: Verify cm_delete_dir - assert: - that: - - cm_delete_dir is success - - cm_delete_dir is changed - - cm_delete_dir.reason == 'No Content' - - cm_delete_dir.size == None - - cm_delete_dir.state == 'absent' - - cm_delete_dir.status == 204 - -- name: Delete directory (normal mode) - vsphere_file: - <<: *vsphere_conn_dir - path: '{{ directory }}' - state: absent - ignore_errors: true - register: nm_delete_dir - -# NOTE: Deleting directories is not implemented -- name: Verify nm_delete_dir - assert: - that: - - nm_delete_dir is failed # FIXME - #- nm_delete_dir is success - #- nm_delete_dir is changed - - nm_delete_dir.reason == 'Method Not Allowed' # FIXME - #- cm_delete_dir.reason == 'No Content' - #- nm_delete_dir.size == None - #- cm_delete_dir.state == 'absent' - - nm_delete_dir.status == 405 # FIXME - #- cm_delete_dir.status == 204 - -- name: Test directory after delete (check_mode) - vsphere_file: - <<: *vsphere_conn_dir - path: '{{ directory }}' - state: file - check_mode: true - ignore_errors: true - register: cm_test_dir_delete - -- name: Verify cm_test_dir_delete - assert: - that: - - cm_test_dir_delete is success # FIXME - - cm_test_dir_delete is not changed #FIXME - #- cm_test_dir_delete is failed - #- cm_test_dir_delete.size == None - #- cm_test_dir_delete.state == 'file' - - cm_test_dir_delete.status == 200 # FIXME - #- nm_test_dir_delete.status == 404 - -- name: Test directory after delete (normal mode) - vsphere_file: - <<: *vsphere_conn_dir - path: '{{ directory }}' - state: file - ignore_errors: true - register: nm_test_dir_delete - -- name: Verify nm_test_dir_delete - assert: - that: - - nm_test_dir_delete is success # FIXME - - nm_test_dir_delete is not changed #FIXME - #- nm_test_dir_delete is failed - #- nm_test_dir_delete.size == None - #- nm_test_dir_delete.state == 'file' - - nm_test_dir_delete.status == 200 # FIXME - #- nm_test_dir_delete.status == 404 diff --git a/test/sanity/ignore.txt b/test/sanity/ignore.txt index cd22ba8e57..a290c597a1 100644 --- a/test/sanity/ignore.txt +++ b/test/sanity/ignore.txt @@ -1,7 +1,3 @@ -contrib/inventory/vmware.py future-import-boilerplate -contrib/inventory/vmware.py metaclass-boilerplate -contrib/inventory/vmware_inventory.py future-import-boilerplate -contrib/inventory/vmware_inventory.py metaclass-boilerplate docs/bin/find-plugin-refs.py future-import-boilerplate docs/bin/find-plugin-refs.py metaclass-boilerplate docs/docsite/_extensions/pygments_lexer.py future-import-boilerplate @@ -235,8 +231,6 @@ lib/ansible/module_utils/urls.py future-import-boilerplate lib/ansible/module_utils/urls.py metaclass-boilerplate lib/ansible/module_utils/urls.py pylint:blacklisted-name lib/ansible/module_utils/urls.py replace-urlopen -lib/ansible/module_utils/vca.py future-import-boilerplate -lib/ansible/module_utils/vca.py metaclass-boilerplate lib/ansible/module_utils/yumdnf.py future-import-boilerplate lib/ansible/module_utils/yumdnf.py metaclass-boilerplate lib/ansible/modules/cloud/amazon/aws_netapp_cvs_FileSystems.py validate-modules:parameter-list-no-elements @@ -1540,132 +1534,6 @@ lib/ansible/modules/cloud/ovirt/ovirt_vnic_profile.py metaclass-boilerplate lib/ansible/modules/cloud/ovirt/ovirt_vnic_profile.py validate-modules:parameter-list-no-elements lib/ansible/modules/cloud/ovirt/ovirt_vnic_profile.py validate-modules:parameter-type-not-in-doc lib/ansible/modules/cloud/ovirt/ovirt_vnic_profile_info.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/_vmware_dns_config.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/_vmware_drs_group_facts.py validate-modules:doc-required-mismatch -lib/ansible/modules/cloud/vmware/vca_fw.py validate-modules:doc-default-does-not-match-spec -lib/ansible/modules/cloud/vmware/vca_fw.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/vmware/vca_fw.py validate-modules:doc-required-mismatch -lib/ansible/modules/cloud/vmware/vca_fw.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/vca_fw.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/vmware/vca_fw.py validate-modules:undocumented-parameter -lib/ansible/modules/cloud/vmware/vca_nat.py validate-modules:doc-default-does-not-match-spec -lib/ansible/modules/cloud/vmware/vca_nat.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/vmware/vca_nat.py validate-modules:doc-required-mismatch -lib/ansible/modules/cloud/vmware/vca_nat.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/vca_nat.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/vmware/vca_nat.py validate-modules:undocumented-parameter -lib/ansible/modules/cloud/vmware/vca_vapp.py validate-modules:doc-default-does-not-match-spec -lib/ansible/modules/cloud/vmware/vca_vapp.py validate-modules:doc-missing-type -lib/ansible/modules/cloud/vmware/vca_vapp.py validate-modules:doc-required-mismatch -lib/ansible/modules/cloud/vmware/vca_vapp.py validate-modules:invalid-ansiblemodule-schema -lib/ansible/modules/cloud/vmware/vca_vapp.py validate-modules:undocumented-parameter -lib/ansible/modules/cloud/vmware/vmware_category.py validate-modules:doc-elements-mismatch -lib/ansible/modules/cloud/vmware/vmware_category.py validate-modules:invalid-ansiblemodule-schema -lib/ansible/modules/cloud/vmware/vmware_cfg_backup.py validate-modules:doc-required-mismatch -lib/ansible/modules/cloud/vmware/vmware_cluster.py validate-modules:invalid-ansiblemodule-schema -lib/ansible/modules/cloud/vmware/vmware_cluster.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/vmware/vmware_cluster_drs.py validate-modules:invalid-ansiblemodule-schema -lib/ansible/modules/cloud/vmware/vmware_cluster_ha.py validate-modules:doc-elements-mismatch -lib/ansible/modules/cloud/vmware/vmware_content_library_manager.py validate-modules:doc-required-mismatch -lib/ansible/modules/cloud/vmware/vmware_datastore_info.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/vmware_deploy_ovf.py use-argspec-type-path -lib/ansible/modules/cloud/vmware/vmware_deploy_ovf.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/vmware/vmware_drs_group.py validate-modules:doc-required-mismatch -lib/ansible/modules/cloud/vmware/vmware_drs_group.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/vmware_drs_group_info.py validate-modules:doc-required-mismatch -lib/ansible/modules/cloud/vmware/vmware_dvs_host.py validate-modules:doc-elements-mismatch -lib/ansible/modules/cloud/vmware/vmware_dvs_host.py validate-modules:doc-required-mismatch -lib/ansible/modules/cloud/vmware/vmware_dvs_host.py validate-modules:missing-suboption-docs -lib/ansible/modules/cloud/vmware/vmware_dvs_host.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/vmware_dvs_host.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/vmware/vmware_dvs_host.py validate-modules:undocumented-parameter -lib/ansible/modules/cloud/vmware/vmware_dvs_portgroup.py validate-modules:doc-choices-do-not-match-spec -lib/ansible/modules/cloud/vmware/vmware_dvs_portgroup.py validate-modules:doc-default-does-not-match-spec -lib/ansible/modules/cloud/vmware/vmware_dvs_portgroup.py validate-modules:missing-suboption-docs -lib/ansible/modules/cloud/vmware/vmware_dvs_portgroup.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/vmware/vmware_dvs_portgroup.py validate-modules:undocumented-parameter -lib/ansible/modules/cloud/vmware/vmware_dvs_portgroup_find.py validate-modules:required_if-requirements-type -lib/ansible/modules/cloud/vmware/vmware_dvswitch.py validate-modules:missing-suboption-docs -lib/ansible/modules/cloud/vmware/vmware_dvswitch.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/vmware/vmware_dvswitch.py validate-modules:undocumented-parameter -lib/ansible/modules/cloud/vmware/vmware_dvswitch_lacp.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/vmware_dvswitch_nioc.py validate-modules:doc-choices-do-not-match-spec -lib/ansible/modules/cloud/vmware/vmware_dvswitch_nioc.py validate-modules:doc-default-does-not-match-spec -lib/ansible/modules/cloud/vmware/vmware_dvswitch_nioc.py validate-modules:doc-elements-mismatch -lib/ansible/modules/cloud/vmware/vmware_dvswitch_nioc.py validate-modules:doc-required-mismatch -lib/ansible/modules/cloud/vmware/vmware_dvswitch_nioc.py validate-modules:missing-suboption-docs -lib/ansible/modules/cloud/vmware/vmware_dvswitch_nioc.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/vmware/vmware_dvswitch_nioc.py validate-modules:undocumented-parameter -lib/ansible/modules/cloud/vmware/vmware_dvswitch_pvlans.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/vmware_dvswitch_uplink_pg.py validate-modules:doc-choices-do-not-match-spec -lib/ansible/modules/cloud/vmware/vmware_dvswitch_uplink_pg.py validate-modules:doc-default-does-not-match-spec -lib/ansible/modules/cloud/vmware/vmware_dvswitch_uplink_pg.py validate-modules:missing-suboption-docs -lib/ansible/modules/cloud/vmware/vmware_dvswitch_uplink_pg.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/vmware_dvswitch_uplink_pg.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/vmware/vmware_dvswitch_uplink_pg.py validate-modules:undocumented-parameter -lib/ansible/modules/cloud/vmware/vmware_guest.py validate-modules:doc-required-mismatch -lib/ansible/modules/cloud/vmware/vmware_guest.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/vmware_guest.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/vmware/vmware_guest.py validate-modules:undocumented-parameter -lib/ansible/modules/cloud/vmware/vmware_guest_boot_manager.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/vmware_guest_controller.py validate-modules:doc-elements-mismatch -lib/ansible/modules/cloud/vmware/vmware_guest_custom_attribute_defs.py validate-modules:doc-required-mismatch -lib/ansible/modules/cloud/vmware/vmware_guest_custom_attributes.py validate-modules:doc-required-mismatch -lib/ansible/modules/cloud/vmware/vmware_guest_custom_attributes.py validate-modules:missing-suboption-docs -lib/ansible/modules/cloud/vmware/vmware_guest_custom_attributes.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/vmware_guest_custom_attributes.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/vmware/vmware_guest_custom_attributes.py validate-modules:undocumented-parameter -lib/ansible/modules/cloud/vmware/vmware_guest_disk.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/vmware_guest_file_operation.py validate-modules:doc-choices-do-not-match-spec -lib/ansible/modules/cloud/vmware/vmware_guest_file_operation.py validate-modules:doc-required-mismatch -lib/ansible/modules/cloud/vmware/vmware_guest_file_operation.py validate-modules:missing-suboption-docs -lib/ansible/modules/cloud/vmware/vmware_guest_file_operation.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/vmware/vmware_guest_file_operation.py validate-modules:undocumented-parameter -lib/ansible/modules/cloud/vmware/vmware_guest_info.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/vmware_guest_network.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/vmware_guest_sendkey.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/vmware_guest_serial_port.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/vmware_guest_snapshot.py validate-modules:doc-required-mismatch -lib/ansible/modules/cloud/vmware/vmware_host_acceptance.py validate-modules:parameter-state-invalid-choice -lib/ansible/modules/cloud/vmware/vmware_host_datastore.py validate-modules:doc-required-mismatch -lib/ansible/modules/cloud/vmware/vmware_host_dns.py validate-modules:mutually_exclusive-unknown -lib/ansible/modules/cloud/vmware/vmware_host_dns.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/vmware_host_facts.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/vmware_host_firewall_manager.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/vmware_host_lockdown.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/vmware_host_ntp.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/vmware_host_snmp.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/vmware_local_role_manager.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/vmware_portgroup.py validate-modules:doc-choices-do-not-match-spec -lib/ansible/modules/cloud/vmware/vmware_portgroup.py validate-modules:missing-suboption-docs -lib/ansible/modules/cloud/vmware/vmware_portgroup.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/vmware_portgroup.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/vmware/vmware_portgroup.py validate-modules:undocumented-parameter -lib/ansible/modules/cloud/vmware/vmware_tag_manager.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/vmware_vcenter_settings.py validate-modules:doc-default-does-not-match-spec -lib/ansible/modules/cloud/vmware/vmware_vcenter_settings.py validate-modules:missing-suboption-docs -lib/ansible/modules/cloud/vmware/vmware_vcenter_settings.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/vmware/vmware_vcenter_settings.py validate-modules:undocumented-parameter -lib/ansible/modules/cloud/vmware/vmware_vcenter_statistics.py validate-modules:doc-choices-do-not-match-spec -lib/ansible/modules/cloud/vmware/vmware_vcenter_statistics.py validate-modules:doc-default-does-not-match-spec -lib/ansible/modules/cloud/vmware/vmware_vcenter_statistics.py validate-modules:missing-suboption-docs -lib/ansible/modules/cloud/vmware/vmware_vcenter_statistics.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/vmware/vmware_vcenter_statistics.py validate-modules:undocumented-parameter -lib/ansible/modules/cloud/vmware/vmware_vm_host_drs_rule.py validate-modules:doc-required-mismatch -lib/ansible/modules/cloud/vmware/vmware_vm_host_drs_rule.py validate-modules:required_if-is_one_of-type -lib/ansible/modules/cloud/vmware/vmware_vm_shell.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/vmware_vm_vm_drs_rule.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/vmware_vmkernel.py validate-modules:doc-choices-do-not-match-spec -lib/ansible/modules/cloud/vmware/vmware_vmkernel.py validate-modules:doc-default-does-not-match-spec -lib/ansible/modules/cloud/vmware/vmware_vmkernel.py validate-modules:missing-suboption-docs -lib/ansible/modules/cloud/vmware/vmware_vmkernel.py validate-modules:mutually_exclusive-unknown -lib/ansible/modules/cloud/vmware/vmware_vmkernel.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/vmware/vmware_vmkernel.py validate-modules:undocumented-parameter -lib/ansible/modules/cloud/vmware/vmware_vspan_session.py validate-modules:missing-suboption-docs -lib/ansible/modules/cloud/vmware/vmware_vspan_session.py validate-modules:parameter-type-not-in-doc -lib/ansible/modules/cloud/vmware/vmware_vspan_session.py validate-modules:undocumented-parameter -lib/ansible/modules/cloud/vmware/vmware_vswitch.py validate-modules:parameter-list-no-elements -lib/ansible/modules/cloud/vmware/vsphere_copy.py validate-modules:undocumented-parameter lib/ansible/modules/commands/command.py validate-modules:doc-missing-type lib/ansible/modules/commands/command.py validate-modules:nonexistent-parameter-documented lib/ansible/modules/commands/command.py validate-modules:parameter-list-no-elements @@ -4201,7 +4069,6 @@ lib/ansible/plugins/action/normal.py action-plugin-docs # default action plugin lib/ansible/plugins/action/nxos.py action-plugin-docs # base class for deprecated network platform modules using `connection: local` lib/ansible/plugins/action/vyos.py action-plugin-docs # base class for deprecated network platform modules using `connection: local` lib/ansible/plugins/cache/base.py ansible-doc!skip # not a plugin, but a stub for backwards compatibility -lib/ansible/plugins/connection/vmware_tools.py yamllint:unparsable-with-libyaml lib/ansible/plugins/doc_fragments/asa.py future-import-boilerplate lib/ansible/plugins/doc_fragments/asa.py metaclass-boilerplate lib/ansible/plugins/doc_fragments/aws.py future-import-boilerplate @@ -4282,12 +4149,6 @@ lib/ansible/plugins/doc_fragments/url.py future-import-boilerplate lib/ansible/plugins/doc_fragments/url.py metaclass-boilerplate lib/ansible/plugins/doc_fragments/validate.py future-import-boilerplate lib/ansible/plugins/doc_fragments/validate.py metaclass-boilerplate -lib/ansible/plugins/doc_fragments/vca.py future-import-boilerplate -lib/ansible/plugins/doc_fragments/vca.py metaclass-boilerplate -lib/ansible/plugins/doc_fragments/vmware.py future-import-boilerplate -lib/ansible/plugins/doc_fragments/vmware.py metaclass-boilerplate -lib/ansible/plugins/doc_fragments/vmware_rest_client.py future-import-boilerplate -lib/ansible/plugins/doc_fragments/vmware_rest_client.py metaclass-boilerplate lib/ansible/plugins/doc_fragments/vyos.py future-import-boilerplate lib/ansible/plugins/doc_fragments/vyos.py metaclass-boilerplate lib/ansible/plugins/lookup/sequence.py pylint:blacklisted-name @@ -4510,9 +4371,6 @@ test/support/windows-integration/plugins/modules/win_security_policy.ps1 pslint! test/support/windows-integration/plugins/modules/win_shell.ps1 pslint!skip test/support/windows-integration/plugins/modules/win_wait_for.ps1 pslint!skip test/units/config/manager/test_find_ini_config_file.py future-import-boilerplate -test/units/contrib/inventory/test_vmware_inventory.py future-import-boilerplate -test/units/contrib/inventory/test_vmware_inventory.py metaclass-boilerplate -test/units/contrib/inventory/test_vmware_inventory.py pylint:blacklisted-name test/units/executor/test_play_iterator.py pylint:blacklisted-name test/units/inventory/test_group.py future-import-boilerplate test/units/inventory/test_group.py metaclass-boilerplate diff --git a/test/units/contrib/inventory/test_vmware_inventory.py b/test/units/contrib/inventory/test_vmware_inventory.py deleted file mode 100644 index 8ecc8efcb6..0000000000 --- a/test/units/contrib/inventory/test_vmware_inventory.py +++ /dev/null @@ -1,102 +0,0 @@ -import json -import os -import pytest -import sys - -BASIC_INVENTORY = { - 'all': { - 'hosts': ['foo', 'bar'] - }, - '_meta': { - 'hostvars': { - 'foo': {'hostname': 'foo'}, - 'bar': {'hostname': 'bar'} - } - } -} - - -class FakeArgs(object): - debug = False - write_dumpfile = None - load_dumpfile = None - host = False - list = True - - -@pytest.fixture -def vmware_inventory(): - inventory_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', 'contrib', 'inventory')) - - sys.path.append(inventory_dir) - - try: - import vmware_inventory - except BaseException as ex: - pytest.skip(ex) - finally: - sys.path.remove(inventory_dir) - - return vmware_inventory - - -def test_host_info_returns_single_host(vmware_inventory): - vmw = vmware_inventory.VMWareInventory(load=False) - vmw.inventory = BASIC_INVENTORY - foo = vmw.get_host_info('foo') - bar = vmw.get_host_info('bar') - assert foo == {'hostname': 'foo'} - assert bar == {'hostname': 'bar'} - - -def test_show_returns_serializable_data(vmware_inventory): - fakeargs = FakeArgs() - vmw = vmware_inventory.VMWareInventory(load=False) - vmw.args = fakeargs - vmw.inventory = BASIC_INVENTORY - showdata = vmw.show() - json.loads(showdata) - - -def test_show_list_returns_serializable_data(vmware_inventory): - fakeargs = FakeArgs() - vmw = vmware_inventory.VMWareInventory(load=False) - vmw.args = fakeargs - vmw.args.list = True - vmw.inventory = BASIC_INVENTORY - showdata = vmw.show() - json.loads(showdata) - - -def test_show_list_returns_all_data(vmware_inventory): - fakeargs = FakeArgs() - vmw = vmware_inventory.VMWareInventory(load=False) - vmw.args = fakeargs - vmw.args.list = True - vmw.inventory = BASIC_INVENTORY - showdata = vmw.show() - expected = json.dumps(BASIC_INVENTORY, indent=2) - assert showdata == expected - - -def test_show_host_returns_serializable_data(vmware_inventory): - fakeargs = FakeArgs() - vmw = vmware_inventory.VMWareInventory(load=False) - vmw.args = fakeargs - vmw.args.host = 'foo' - vmw.inventory = BASIC_INVENTORY - showdata = vmw.show() - json.loads(showdata) - - -def test_show_host_returns_just_host(vmware_inventory): - fakeargs = FakeArgs() - vmw = vmware_inventory.VMWareInventory(load=False) - vmw.args = fakeargs - vmw.args.list = False - vmw.args.host = 'foo' - vmw.inventory = BASIC_INVENTORY - showdata = vmw.show() - expected = BASIC_INVENTORY['_meta']['hostvars']['foo'] - expected = json.dumps(expected, indent=2) - assert showdata == expected diff --git a/test/units/module_utils/test_vmware.py b/test/units/module_utils/test_vmware.py deleted file mode 100644 index 375e78de07..0000000000 --- a/test/units/module_utils/test_vmware.py +++ /dev/null @@ -1,228 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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 - -import ssl -import sys -import pytest - -pyvmomi = pytest.importorskip('pyVmomi') - -from units.compat import mock - -import ansible.module_utils.vmware as vmware_module_utils - - -test_data = [ - ( - dict( - username='Administrator@vsphere.local', - password='Esxi@123$%', - hostname=False, - validate_certs=False, - ), - "Hostname parameter is missing. Please specify this parameter in task or" - " export environment variable like 'export VMWARE_HOST=ESXI_HOSTNAME'" - ), - ( - dict( - username=False, - password='Esxi@123$%', - hostname='esxi1', - validate_certs=False, - ), - "Username parameter is missing. Please specify this parameter in task or" - " export environment variable like 'export VMWARE_USER=ESXI_USERNAME'" - ), - ( - dict( - username='Administrator@vsphere.local', - password=False, - hostname='esxi1', - validate_certs=False, - ), - "Password parameter is missing. Please specify this parameter in task or" - " export environment variable like 'export VMWARE_PASSWORD=ESXI_PASSWORD'" - ), - ( - dict( - username='Administrator@vsphere.local', - password='Esxi@123$%', - hostname='esxi1', - validate_certs=True, - ), - "Unknown error while connecting to vCenter or ESXi API at esxi1:443" - ), - ( - dict( - username='Administrator@vsphere.local', - password='Esxi@123$%', - hostname='esxi1', - proxy_host='myproxyserver.com', - proxy_port=80, - validate_certs=False, - ), - " [proxy: myproxyserver.com:80]" - ), -] - -test_ids = [ - 'hostname', - 'username', - 'password', - 'validate_certs', - 'valid_http_proxy', -] - - -class FailJsonException(BaseException): - pass - - -@pytest.fixture -def fake_ansible_module(): - ret = mock.Mock() - ret.params = test_data[3][0] - ret.tmpdir = None - ret.fail_json.side_effect = FailJsonException() - return ret - - -def fake_connect_to_api(module, return_si=None): - return None, mock.Mock(), - - -testdata = [ - ('HAS_PYVMOMI', 'PyVmomi'), - ('HAS_REQUESTS', 'requests'), -] - - -@pytest.mark.parametrize("key,libname", testdata) -def test_lib_loading_failure(monkeypatch, fake_ansible_module, key, libname): - """ Test if Pyvmomi is present or not""" - monkeypatch.setattr(vmware_module_utils, key, False) - with pytest.raises(FailJsonException): - vmware_module_utils.PyVmomi(fake_ansible_module) - error_str = 'Failed to import the required Python library (%s)' % libname - assert fake_ansible_module.fail_json.called_once() - assert error_str in fake_ansible_module.fail_json.call_args[1]['msg'] - - -@pytest.mark.skipif(sys.version_info < (2, 7), reason="requires python2.7 and greater") -@pytest.mark.parametrize("params, msg", test_data, ids=test_ids) -def test_required_params(request, params, msg, fake_ansible_module): - """ Test if required params are correct or not""" - fake_ansible_module.params = params - with pytest.raises(FailJsonException): - vmware_module_utils.connect_to_api(fake_ansible_module) - assert fake_ansible_module.fail_json.called_once() - assert msg in fake_ansible_module.fail_json.call_args[1]['msg'] - - -def test_validate_certs(monkeypatch, fake_ansible_module): - """ Test if SSL is required or not""" - fake_ansible_module.params = test_data[3][0] - - monkeypatch.setattr(vmware_module_utils, 'ssl', None) - with pytest.raises(FailJsonException): - vmware_module_utils.PyVmomi(fake_ansible_module) - msg = 'pyVim does not support changing verification mode with python < 2.7.9.' \ - ' Either update python or use validate_certs=false.' - assert fake_ansible_module.fail_json.called_once() - assert msg in fake_ansible_module.fail_json.call_args[1]['msg'] - - -def test_vmdk_disk_path_split(monkeypatch, fake_ansible_module): - """ Test vmdk_disk_path_split function""" - fake_ansible_module.params = test_data[0][0] - - monkeypatch.setattr(vmware_module_utils, 'connect_to_api', fake_connect_to_api) - pyv = vmware_module_utils.PyVmomi(fake_ansible_module) - v = pyv.vmdk_disk_path_split('[ds1] VM_0001/VM0001_0.vmdk') - assert v == ('ds1', 'VM_0001/VM0001_0.vmdk', 'VM0001_0.vmdk', 'VM_0001') - - -def test_vmdk_disk_path_split_negative(monkeypatch, fake_ansible_module): - """ Test vmdk_disk_path_split function""" - fake_ansible_module.params = test_data[0][0] - - monkeypatch.setattr(vmware_module_utils, 'connect_to_api', fake_connect_to_api) - with pytest.raises(FailJsonException): - pyv = vmware_module_utils.PyVmomi(fake_ansible_module) - pyv.vmdk_disk_path_split('[ds1]') - assert fake_ansible_module.fail_json.called_once() - assert 'Bad path' in fake_ansible_module.fail_json.call_args[1]['msg'] - - -@pytest.mark.skipif(sys.version_info < (2, 7), reason="requires python2.7 and greater") -def test_connect_to_api_validate_certs(monkeypatch, fake_ansible_module): - monkeypatch.setattr(vmware_module_utils, 'connect', mock.Mock()) - - def MockSSLContext(proto): - ssl_context.proto = proto - return ssl_context - - # New Python with SSLContext + validate_certs=True - vmware_module_utils.connect.reset_mock() - ssl_context = mock.Mock() - monkeypatch.setattr(vmware_module_utils.ssl, 'SSLContext', MockSSLContext) - fake_ansible_module.params['validate_certs'] = True - vmware_module_utils.connect_to_api(fake_ansible_module) - assert ssl_context.proto == ssl.PROTOCOL_SSLv23 - assert ssl_context.verify_mode == ssl.CERT_REQUIRED - assert ssl_context.check_hostname is True - vmware_module_utils.connect.SmartConnect.assert_called_once_with( - host='esxi1', - port=443, - pwd='Esxi@123$%', - user='Administrator@vsphere.local', - sslContext=ssl_context) - - # New Python with SSLContext + validate_certs=False - vmware_module_utils.connect.reset_mock() - ssl_context = mock.Mock() - monkeypatch.setattr(vmware_module_utils.ssl, 'SSLContext', MockSSLContext) - fake_ansible_module.params['validate_certs'] = False - vmware_module_utils.connect_to_api(fake_ansible_module) - assert ssl_context.proto == ssl.PROTOCOL_SSLv23 - assert ssl_context.verify_mode == ssl.CERT_NONE - assert ssl_context.check_hostname is False - vmware_module_utils.connect.SmartConnect.assert_called_once_with( - host='esxi1', - port=443, - pwd='Esxi@123$%', - user='Administrator@vsphere.local', - sslContext=ssl_context) - - # Old Python with no SSLContext + validate_certs=True - vmware_module_utils.connect.reset_mock() - ssl_context = mock.Mock() - ssl_context.proto = None - monkeypatch.delattr(vmware_module_utils.ssl, 'SSLContext') - fake_ansible_module.params['validate_certs'] = True - with pytest.raises(FailJsonException): - vmware_module_utils.connect_to_api(fake_ansible_module) - assert ssl_context.proto is None - fake_ansible_module.fail_json.assert_called_once_with(msg=( - 'pyVim does not support changing verification mode with python ' - '< 2.7.9. Either update python or use validate_certs=false.')) - assert not vmware_module_utils.connect.SmartConnect.called - - # Old Python with no SSLContext + validate_certs=False - vmware_module_utils.connect.reset_mock() - ssl_context = mock.Mock() - ssl_context.proto = None - monkeypatch.delattr(vmware_module_utils.ssl, 'SSLContext', raising=False) - fake_ansible_module.params['validate_certs'] = False - vmware_module_utils.connect_to_api(fake_ansible_module) - assert ssl_context.proto is None - vmware_module_utils.connect.SmartConnect.assert_called_once_with( - host='esxi1', - port=443, - pwd='Esxi@123$%', - user='Administrator@vsphere.local') diff --git a/test/units/modules/cloud/vmware/test_data/test_vmware_guest_with_parameters.json b/test/units/modules/cloud/vmware/test_data/test_vmware_guest_with_parameters.json deleted file mode 100644 index ce5e27c776..0000000000 --- a/test/units/modules/cloud/vmware/test_data/test_vmware_guest_with_parameters.json +++ /dev/null @@ -1,106 +0,0 @@ -[ - [ - { - "name": "sample_vm_001", - "hostname": "esxi01.example.com", - "username": "administrator@vsphere.local", - "password": "Secret@123$%", - "validate_certs": "True" - }, - { - "failed": "True", - "msg": "Unknown error while connecting to vCenter or ESXi API" - } - ], - [ - { - "name": "sample_vm_001" - }, - { - "failed": "True", - "msg": "Hostname parameter is missing." - } - ], - [ - { - "uuid": "52f7b088-357e-bb81-59ec-9d9389c7d89e" - }, - { - "failed": "True", - "msg": "Hostname parameter is missing." - } - ], - [ - { - "name": "sample_vm_001", - "hostname": "esxi01.example.com" - }, - { - "failed": "True", - "msg": "Username parameter is missing." - } - ], - [ - { - "name": "sample_vm_001", - "hostname": "esxi01.example.com", - "username": "administrator@vsphere.local" - }, - { - "failed": "True", - "msg": "Password parameter is missing." - } - ], - [ - { - "name": "sample_vm_001", - "hostname": "esxi01.example.com", - "username": "administrator@vsphere.local", - "password": "Secret@123$%" - }, - { - "failed": "True", - "msg": "Unknown error while connecting to vCenter or ESXi API" - } - ], - [ - { - "name": "sample_vm_001", - "hostname": "esxi01.example.com", - "username": "administrator@vsphere.local", - "password": "Secret@123$%", - "validate_certs": "False" - }, - { - "failed": "True", - "msg": "Unknown error while connecting to vCenter or ESXi API" - } - ], - [ - { - "name": "sample_vm_001", - "hostname": "esxi01.example.com", - "username": "administrator@vsphere.local", - "password": "Secret@123$%", - "port": "8443" - }, - { - "failed": "True", - "msg": "8443" - } - ], - [ - { - "name": "sample_vm_001", - "hostname": "esxi01.example.com", - "username": "administrator@vsphere.local", - "password": "Secret@123$%", - "validate_certs": "True" - }, - { - "test_ssl_context": "True", - "failed": "True", - "msg": "pyVim does not support changing verification mode with python < 2.7.9. Either update python or use validate_certs=false." - } - ] -] diff --git a/test/units/modules/cloud/vmware/test_vmware_guest.py b/test/units/modules/cloud/vmware/test_vmware_guest.py deleted file mode 100644 index 613d680eeb..0000000000 --- a/test/units/modules/cloud/vmware/test_vmware_guest.py +++ /dev/null @@ -1,52 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright: (c) 2018, Ansible Project -# Copyright: (c) 2018, Abhijeet Kasurde <akasurde@redhat.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 - -import os -import sys -import pytest -import json - -pyvmomi = pytest.importorskip('pyVmomi') - -if sys.version_info < (2, 7): - pytestmark = pytest.mark.skip("vmware_guest Ansible modules require Python >= 2.7") - - -from ansible.modules.cloud.vmware import vmware_guest - -curr_dir = os.path.dirname(__file__) -test_data_file = open(os.path.join(curr_dir, 'test_data', 'test_vmware_guest_with_parameters.json'), 'r') -TEST_CASES = json.loads(test_data_file.read()) -test_data_file.close() - - -@pytest.mark.parametrize('patch_ansible_module', [{}], indirect=['patch_ansible_module']) -@pytest.mark.usefixtures('patch_ansible_module') -def test_vmware_guest_wo_parameters(capfd): - with pytest.raises(SystemExit): - vmware_guest.main() - out, err = capfd.readouterr() - results = json.loads(out) - assert results['failed'] - assert "one of the following is required: name, uuid" in results['msg'] - - -@pytest.mark.parametrize('patch_ansible_module, testcase', TEST_CASES, indirect=['patch_ansible_module']) -@pytest.mark.usefixtures('patch_ansible_module') -def test_vmware_guest_with_parameters(mocker, capfd, testcase): - if testcase.get('test_ssl_context', None): - class mocked_ssl: - pass - mocker.patch('ansible.module_utils.vmware.ssl', new=mocked_ssl) - - with pytest.raises(SystemExit): - vmware_guest.main() - out, err = capfd.readouterr() - results = json.loads(out) - assert str(results['failed']) == testcase['failed'] - assert testcase['msg'] in results['msg'] |