mirror of
https://github.com/ansible-collections/community.general.git
synced 2026-05-07 13:52:54 +00:00
Merge branch 'v2_final' into devel_switch_v2
Conflicts: lib/ansible/inventory/__init__.py lib/ansible/modules/core lib/ansible/utils/__init__.py lib/ansible/utils/module_docs.py
This commit is contained in:
@@ -45,7 +45,7 @@ SELINUX_SPECIAL_FS="<<SELINUX_SPECIAL_FILESYSTEMS>>"
|
||||
# can be inserted in any module source automatically by including
|
||||
# #<<INCLUDE_ANSIBLE_MODULE_COMMON>> on a blank line by itself inside
|
||||
# of an ansible module. The source of this common code lives
|
||||
# in lib/ansible/module_common.py
|
||||
# in ansible/executor/module_common.py
|
||||
|
||||
import locale
|
||||
import os
|
||||
@@ -67,6 +67,7 @@ import pwd
|
||||
import platform
|
||||
import errno
|
||||
import tempfile
|
||||
from itertools import imap, repeat
|
||||
|
||||
try:
|
||||
import json
|
||||
@@ -237,7 +238,7 @@ def load_platform_subclass(cls, *args, **kwargs):
|
||||
return super(cls, subclass).__new__(subclass)
|
||||
|
||||
|
||||
def json_dict_unicode_to_bytes(d):
|
||||
def json_dict_unicode_to_bytes(d, encoding='utf-8'):
|
||||
''' Recursively convert dict keys and values to byte str
|
||||
|
||||
Specialized for json return because this only handles, lists, tuples,
|
||||
@@ -245,17 +246,17 @@ def json_dict_unicode_to_bytes(d):
|
||||
'''
|
||||
|
||||
if isinstance(d, unicode):
|
||||
return d.encode('utf-8')
|
||||
return d.encode(encoding)
|
||||
elif isinstance(d, dict):
|
||||
return dict(map(json_dict_unicode_to_bytes, d.iteritems()))
|
||||
return dict(imap(json_dict_unicode_to_bytes, d.iteritems(), repeat(encoding)))
|
||||
elif isinstance(d, list):
|
||||
return list(map(json_dict_unicode_to_bytes, d))
|
||||
return list(imap(json_dict_unicode_to_bytes, d, repeat(encoding)))
|
||||
elif isinstance(d, tuple):
|
||||
return tuple(map(json_dict_unicode_to_bytes, d))
|
||||
return tuple(imap(json_dict_unicode_to_bytes, d, repeat(encoding)))
|
||||
else:
|
||||
return d
|
||||
|
||||
def json_dict_bytes_to_unicode(d):
|
||||
def json_dict_bytes_to_unicode(d, encoding='utf-8'):
|
||||
''' Recursively convert dict keys and values to byte str
|
||||
|
||||
Specialized for json return because this only handles, lists, tuples,
|
||||
@@ -263,13 +264,13 @@ def json_dict_bytes_to_unicode(d):
|
||||
'''
|
||||
|
||||
if isinstance(d, str):
|
||||
return unicode(d, 'utf-8')
|
||||
return unicode(d, encoding)
|
||||
elif isinstance(d, dict):
|
||||
return dict(map(json_dict_bytes_to_unicode, d.iteritems()))
|
||||
return dict(imap(json_dict_bytes_to_unicode, d.iteritems(), repeat(encoding)))
|
||||
elif isinstance(d, list):
|
||||
return list(map(json_dict_bytes_to_unicode, d))
|
||||
return list(imap(json_dict_bytes_to_unicode, d, repeat(encoding)))
|
||||
elif isinstance(d, tuple):
|
||||
return tuple(map(json_dict_bytes_to_unicode, d))
|
||||
return tuple(imap(json_dict_bytes_to_unicode, d, repeat(encoding)))
|
||||
else:
|
||||
return d
|
||||
|
||||
@@ -363,9 +364,9 @@ class AnsibleModule(object):
|
||||
# reset to LANG=C if it's an invalid/unavailable locale
|
||||
self._check_locale()
|
||||
|
||||
(self.params, self.args) = self._load_params()
|
||||
self.params = self._load_params()
|
||||
|
||||
self._legal_inputs = ['CHECKMODE', 'NO_LOG']
|
||||
self._legal_inputs = ['_ansible_check_mode', '_ansible_no_log']
|
||||
|
||||
self.aliases = self._handle_aliases()
|
||||
|
||||
@@ -579,7 +580,7 @@ class AnsibleModule(object):
|
||||
if len(context) > i:
|
||||
if context[i] is not None and context[i] != cur_context[i]:
|
||||
new_context[i] = context[i]
|
||||
if context[i] is None:
|
||||
elif context[i] is None:
|
||||
new_context[i] = cur_context[i]
|
||||
|
||||
if cur_context != new_context:
|
||||
@@ -898,7 +899,7 @@ class AnsibleModule(object):
|
||||
|
||||
def _check_for_check_mode(self):
|
||||
for (k,v) in self.params.iteritems():
|
||||
if k == 'CHECKMODE':
|
||||
if k == '_ansible_check_mode':
|
||||
if not self.supports_check_mode:
|
||||
self.exit_json(skipped=True, msg="remote module does not support check mode")
|
||||
if self.supports_check_mode:
|
||||
@@ -906,13 +907,13 @@ class AnsibleModule(object):
|
||||
|
||||
def _check_for_no_log(self):
|
||||
for (k,v) in self.params.iteritems():
|
||||
if k == 'NO_LOG':
|
||||
if k == '_ansible_no_log':
|
||||
self.no_log = self.boolean(v)
|
||||
|
||||
def _check_invalid_arguments(self):
|
||||
for (k,v) in self.params.iteritems():
|
||||
# these should be in legal inputs already
|
||||
#if k in ('CHECKMODE', 'NO_LOG'):
|
||||
#if k in ('_ansible_check_mode', '_ansible_no_log'):
|
||||
# continue
|
||||
if k not in self._legal_inputs:
|
||||
self.fail_json(msg="unsupported parameter for module: %s" % k)
|
||||
@@ -930,7 +931,7 @@ class AnsibleModule(object):
|
||||
for check in spec:
|
||||
count = self._count_terms(check)
|
||||
if count > 1:
|
||||
self.fail_json(msg="parameters are mutually exclusive: %s" % check)
|
||||
self.fail_json(msg="parameters are mutually exclusive: %s" % (check,))
|
||||
|
||||
def _check_required_one_of(self, spec):
|
||||
if spec is None:
|
||||
@@ -948,7 +949,7 @@ class AnsibleModule(object):
|
||||
non_zero = [ c for c in counts if c > 0 ]
|
||||
if len(non_zero) > 0:
|
||||
if 0 in counts:
|
||||
self.fail_json(msg="parameters are required together: %s" % check)
|
||||
self.fail_json(msg="parameters are required together: %s" % (check,))
|
||||
|
||||
def _check_required_arguments(self):
|
||||
''' ensure all required arguments are present '''
|
||||
@@ -1102,20 +1103,11 @@ class AnsibleModule(object):
|
||||
|
||||
def _load_params(self):
|
||||
''' read the input and return a dictionary and the arguments string '''
|
||||
args = MODULE_ARGS
|
||||
items = shlex.split(args)
|
||||
params = {}
|
||||
for x in items:
|
||||
try:
|
||||
(k, v) = x.split("=",1)
|
||||
except Exception, e:
|
||||
self.fail_json(msg="this module requires key=value arguments (%s)" % (items))
|
||||
if k in params:
|
||||
self.fail_json(msg="duplicate parameter: %s (value=%s)" % (k, v))
|
||||
params[k] = v
|
||||
params2 = json_dict_unicode_to_bytes(json.loads(MODULE_COMPLEX_ARGS))
|
||||
params2.update(params)
|
||||
return (params2, args)
|
||||
params = json_dict_unicode_to_bytes(json.loads(MODULE_COMPLEX_ARGS))
|
||||
if params is None:
|
||||
params = dict()
|
||||
return params
|
||||
|
||||
|
||||
def _log_invocation(self):
|
||||
''' log that ansible ran the module '''
|
||||
@@ -1236,13 +1228,17 @@ class AnsibleModule(object):
|
||||
self.fail_json(msg='Boolean %s not in either boolean list' % arg)
|
||||
|
||||
def jsonify(self, data):
|
||||
for encoding in ("utf-8", "latin-1", "unicode_escape"):
|
||||
for encoding in ("utf-8", "latin-1"):
|
||||
try:
|
||||
return json.dumps(data, encoding=encoding)
|
||||
# Old systems using simplejson module does not support encoding keyword.
|
||||
except TypeError, e:
|
||||
return json.dumps(data)
|
||||
except UnicodeDecodeError, e:
|
||||
# Old systems using old simplejson module does not support encoding keyword.
|
||||
except TypeError:
|
||||
try:
|
||||
new_data = json_dict_bytes_to_unicode(data, encoding=encoding)
|
||||
except UnicodeDecodeError:
|
||||
continue
|
||||
return json.dumps(new_data)
|
||||
except UnicodeDecodeError:
|
||||
continue
|
||||
self.fail_json(msg='Invalid unicode encoding encountered')
|
||||
|
||||
@@ -1479,7 +1475,7 @@ class AnsibleModule(object):
|
||||
msg = None
|
||||
st_in = None
|
||||
|
||||
# Set a temporart env path if a prefix is passed
|
||||
# Set a temporary env path if a prefix is passed
|
||||
env=os.environ
|
||||
if path_prefix:
|
||||
env['PATH']="%s:%s" % (path_prefix, env['PATH'])
|
||||
|
||||
@@ -471,29 +471,19 @@ class Facts(object):
|
||||
pass
|
||||
|
||||
def get_public_ssh_host_keys(self):
|
||||
dsa_filename = '/etc/ssh/ssh_host_dsa_key.pub'
|
||||
rsa_filename = '/etc/ssh/ssh_host_rsa_key.pub'
|
||||
ecdsa_filename = '/etc/ssh/ssh_host_ecdsa_key.pub'
|
||||
keytypes = ('dsa', 'rsa', 'ecdsa', 'ed25519')
|
||||
|
||||
if self.facts['system'] == 'Darwin':
|
||||
dsa_filename = '/etc/ssh_host_dsa_key.pub'
|
||||
rsa_filename = '/etc/ssh_host_rsa_key.pub'
|
||||
ecdsa_filename = '/etc/ssh_host_ecdsa_key.pub'
|
||||
dsa = get_file_content(dsa_filename)
|
||||
rsa = get_file_content(rsa_filename)
|
||||
ecdsa = get_file_content(ecdsa_filename)
|
||||
if dsa is None:
|
||||
dsa = 'NA'
|
||||
keydir = '/etc'
|
||||
else:
|
||||
self.facts['ssh_host_key_dsa_public'] = dsa.split()[1]
|
||||
if rsa is None:
|
||||
rsa = 'NA'
|
||||
else:
|
||||
self.facts['ssh_host_key_rsa_public'] = rsa.split()[1]
|
||||
if ecdsa is None:
|
||||
ecdsa = 'NA'
|
||||
else:
|
||||
self.facts['ssh_host_key_ecdsa_public'] = ecdsa.split()[1]
|
||||
keydir = '/etc/ssh'
|
||||
|
||||
for type_ in keytypes:
|
||||
key_filename = '%s/ssh_host_%s_key.pub' % (keydir, type_)
|
||||
keydata = get_file_content(key_filename)
|
||||
if keydata is not None:
|
||||
factname = 'ssh_host_key_%s_public' % type_
|
||||
self.facts[factname] = keydata.split()[1]
|
||||
|
||||
def get_pkg_mgr_facts(self):
|
||||
self.facts['pkg_mgr'] = 'unknown'
|
||||
|
||||
@@ -142,14 +142,14 @@ Function ConvertTo-Bool
|
||||
return
|
||||
}
|
||||
|
||||
# Helper function to calculate a hash of a file in a way which powershell 3
|
||||
# Helper function to calculate md5 of a file in a way which powershell 3
|
||||
# and above can handle:
|
||||
Function Get-FileChecksum($path)
|
||||
Function Get-FileMd5($path)
|
||||
{
|
||||
$hash = ""
|
||||
If (Test-Path -PathType Leaf $path)
|
||||
{
|
||||
$sp = new-object -TypeName System.Security.Cryptography.SHA1CryptoServiceProvider;
|
||||
$sp = new-object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider;
|
||||
$fp = [System.IO.File]::Open($path, [System.IO.Filemode]::Open, [System.IO.FileAccess]::Read);
|
||||
[System.BitConverter]::ToString($sp.ComputeHash($fp)).Replace("-", "").ToLower();
|
||||
$fp.Dispose();
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# (c) 2015, Joseph Callen <jcallen () csc.com>
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
|
||||
try:
|
||||
import atexit
|
||||
import time
|
||||
# requests is required for exception handling of the ConnectionError
|
||||
import requests
|
||||
from pyVim import connect
|
||||
from pyVmomi import vim, vmodl
|
||||
HAS_PYVMOMI = True
|
||||
except ImportError:
|
||||
HAS_PYVMOMI = False
|
||||
|
||||
|
||||
class TaskError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def wait_for_task(task):
|
||||
|
||||
while True:
|
||||
if task.info.state == vim.TaskInfo.State.success:
|
||||
return True, task.info.result
|
||||
if task.info.state == vim.TaskInfo.State.error:
|
||||
try:
|
||||
raise TaskError(task.info.error)
|
||||
except AttributeError:
|
||||
raise TaskError("An unknown error has occurred")
|
||||
if task.info.state == vim.TaskInfo.State.running:
|
||||
time.sleep(15)
|
||||
if task.info.state == vim.TaskInfo.State.queued:
|
||||
time.sleep(15)
|
||||
|
||||
|
||||
def find_dvspg_by_name(dv_switch, portgroup_name):
|
||||
|
||||
portgroups = dv_switch.portgroup
|
||||
|
||||
for pg in portgroups:
|
||||
if pg.name == portgroup_name:
|
||||
return pg
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def find_cluster_by_name_datacenter(datacenter, cluster_name):
|
||||
|
||||
host_folder = datacenter.hostFolder
|
||||
for folder in host_folder.childEntity:
|
||||
if folder.name == cluster_name:
|
||||
return folder
|
||||
return None
|
||||
|
||||
|
||||
def find_datacenter_by_name(content, datacenter_name):
|
||||
|
||||
datacenters = get_all_objs(content, [vim.Datacenter])
|
||||
for dc in datacenters:
|
||||
if dc.name == datacenter_name:
|
||||
return dc
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def find_dvs_by_name(content, switch_name):
|
||||
|
||||
vmware_distributed_switches = get_all_objs(content, [vim.dvs.VmwareDistributedVirtualSwitch])
|
||||
for dvs in vmware_distributed_switches:
|
||||
if dvs.name == switch_name:
|
||||
return dvs
|
||||
return None
|
||||
|
||||
|
||||
def find_hostsystem_by_name(content, hostname):
|
||||
|
||||
host_system = get_all_objs(content, [vim.HostSystem])
|
||||
for host in host_system:
|
||||
if host.name == hostname:
|
||||
return host
|
||||
return None
|
||||
|
||||
|
||||
def vmware_argument_spec():
|
||||
|
||||
return dict(
|
||||
hostname=dict(type='str', required=True),
|
||||
username=dict(type='str', aliases=['user', 'admin'], required=True),
|
||||
password=dict(type='str', aliases=['pass', 'pwd'], required=True, no_log=True),
|
||||
)
|
||||
|
||||
|
||||
def connect_to_api(module, disconnect_atexit=True):
|
||||
|
||||
hostname = module.params['hostname']
|
||||
username = module.params['username']
|
||||
password = module.params['password']
|
||||
try:
|
||||
service_instance = connect.SmartConnect(host=hostname, user=username, pwd=password)
|
||||
|
||||
# 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)
|
||||
return service_instance.RetrieveContent()
|
||||
except vim.fault.InvalidLogin as invalid_login:
|
||||
module.fail_json(msg=invalid_login.msg, apierror=str(invalid_login))
|
||||
except requests.ConnectionError as connection_error:
|
||||
module.fail_json(msg="Unable to connect to vCenter or ESXi API on TCP/443.", apierror=str(connection_error))
|
||||
|
||||
|
||||
def get_all_objs(content, vimtype):
|
||||
|
||||
obj = {}
|
||||
container = content.viewManager.CreateContainerView(content.rootFolder, vimtype, True)
|
||||
for managed_object_ref in container.view:
|
||||
obj.update({managed_object_ref: managed_object_ref.name})
|
||||
return obj
|
||||
Reference in New Issue
Block a user