Merge pull request #42601 from rallytime/merge-2017.7

[2017.7] Merge forward from 2016.11 to 2017.7
This commit is contained in:
Nicole Thomas 2017-07-27 16:32:06 -06:00 committed by GitHub
commit e2dd443002
20 changed files with 130 additions and 63 deletions

View File

@ -405,6 +405,29 @@ similar to the following:
return __virtualname__
return False
The ``__virtual__()`` function can return a ``True`` or ``False`` boolean, a tuple,
or a string. If it returns a ``True`` value, this ``__virtualname__`` module-level
attribute can be set as seen in the above example. This is the string that the module
should be referred to as.
When ``__virtual__()`` returns a tuple, the first item should be a boolean and the
second should be a string. This is typically done when the module should not load. The
first value of the tuple is ``False`` and the second is the error message to display
for why the module did not load.
For example:
.. code-block:: python
def __virtual__():
'''
Only load if git exists on the system
'''
if salt.utils.which('git') is None:
return (False,
'The git execution module cannot be loaded: git unavailable.')
else:
return True
Documentation
=============

View File

@ -75,7 +75,7 @@ The default location for the pillar is in /srv/pillar.
.. note::
The pillar location can be configured via the `pillar_roots` option inside
The pillar location can be configured via the ``pillar_roots`` option inside
the master configuration file. It must not be in a subdirectory of the state
tree or file_roots. If the pillar is under file_roots, any pillar targeting
can be bypassed by minions.
@ -242,7 +242,7 @@ set in the minion's pillar, then the default of ``httpd`` will be used.
.. note::
Under the hood, pillar is just a Python dict, so Python dict methods such
as `get` and `items` can be used.
as ``get`` and ``items`` can be used.
Pillar Makes Simple States Grow Easily
======================================
@ -303,6 +303,18 @@ Where the vimrc source location can now be changed via pillar:
Ensuring that the right vimrc is sent out to the correct minions.
The pillar top file must include a reference to the new sls pillar file:
``/srv/pillar/top.sls``:
.. code-block:: yaml
base:
'*':
- pkg
- edit.vim
Setting Pillar Data on the Command Line
=======================================

View File

@ -9,5 +9,4 @@ Set Python=%SaltDir%\bin\python.exe
Set Script=%SaltDir%\bin\Scripts\salt-call
:: Launch Script
"%Python%" "%Script%" %*
"%Python%" -E -s "%Script%" %*

View File

@ -9,5 +9,4 @@ Set Python=%SaltDir%\bin\python.exe
Set Script=%SaltDir%\bin\Scripts\salt-cp
:: Launch Script
"%Python%" "%Script%" %*
"%Python%" -E -s "%Script%" %*

View File

@ -9,5 +9,4 @@ Set Python=%SaltDir%\bin\python.exe
Set Script=%SaltDir%\bin\Scripts\salt-key
:: Launch Script
"%Python%" "%Script%" %*
"%Python%" -E -s "%Script%" %*

View File

@ -9,5 +9,4 @@ Set Python=%SaltDir%\bin\python.exe
Set Script=%SaltDir%\bin\Scripts\salt-master
:: Launch Script
"%Python%" "%Script%" %*
"%Python%" -E -s "%Script%" %*

View File

@ -12,5 +12,4 @@ Set Script=%SaltDir%\bin\Scripts\salt-minion
net stop salt-minion
:: Launch Script
"%Python%" "%Script%" -l debug
"%Python%" -E -s "%Script%" -l debug

View File

@ -9,5 +9,4 @@ Set Python=%SaltDir%\bin\python.exe
Set Script=%SaltDir%\bin\Scripts\salt-minion
:: Launch Script
"%Python%" "%Script%" %*
"%Python%" -E -s "%Script%" %*

View File

@ -9,5 +9,4 @@ Set Python=%SaltDir%\bin\python.exe
Set Script=%SaltDir%\bin\Scripts\salt-run
:: Launch Script
"%Python%" "%Script%" %*
"%Python%" -E -s "%Script%" %*

View File

@ -9,5 +9,4 @@ Set Python=%SaltDir%\bin\python.exe
Set Script=%SaltDir%\bin\Scripts\salt
:: Launch Script
"%Python%" "%Script%" %*
"%Python%" -E -s "%Script%" %*

View File

@ -379,8 +379,7 @@ Section -Post
WriteRegStr HKLM "${PRODUCT_MINION_REGKEY}" "Path" "$INSTDIR\bin\"
; Register the Salt-Minion Service
nsExec::Exec "nssm.exe install salt-minion $INSTDIR\bin\python.exe $INSTDIR\bin\Scripts\salt-minion -c $INSTDIR\conf -l quiet"
nsExec::Exec "nssm.exe set salt-minion AppEnvironmentExtra PYTHONHOME="
nsExec::Exec "nssm.exe install salt-minion $INSTDIR\bin\python.exe -E -s $INSTDIR\bin\Scripts\salt-minion -c $INSTDIR\conf -l quiet"
nsExec::Exec "nssm.exe set salt-minion Description Salt Minion from saltstack.com"
nsExec::Exec "nssm.exe set salt-minion Start SERVICE_AUTO_START"
nsExec::Exec "nssm.exe set salt-minion AppNoConsole 1"

View File

@ -1030,10 +1030,18 @@ def ssh_interface(vm_):
Return the ssh_interface type to connect to. Either 'public_ips' (default)
or 'private_ips'.
'''
return config.get_cloud_config_value(
ret = config.get_cloud_config_value(
'ssh_interface', vm_, __opts__, default='public_ips',
search_global=False
)
if ret not in ('public_ips', 'private_ips'):
log.warning((
'Invalid ssh_interface: {0}. '
'Allowed options are ("public_ips", "private_ips"). '
'Defaulting to "public_ips".'
).format(ret))
ret = 'public_ips'
return ret
def get_ssh_gateway_config(vm_):

View File

@ -373,17 +373,18 @@ class AsyncAuth(object):
loop_instance_map = AsyncAuth.instance_map[io_loop]
key = cls.__key(opts)
if key not in loop_instance_map:
auth = loop_instance_map.get(key)
if auth is None:
log.debug('Initializing new AsyncAuth for {0}'.format(key))
# we need to make a local variable for this, as we are going to store
# it in a WeakValueDictionary-- which will remove the item if no one
# references it-- this forces a reference while we return to the caller
new_auth = object.__new__(cls)
new_auth.__singleton_init__(opts, io_loop=io_loop)
loop_instance_map[key] = new_auth
auth = object.__new__(cls)
auth.__singleton_init__(opts, io_loop=io_loop)
loop_instance_map[key] = auth
else:
log.debug('Re-using AsyncAuth for {0}'.format(key))
return loop_instance_map[key]
return auth
@classmethod
def __key(cls, opts, io_loop=None):
@ -1009,14 +1010,15 @@ class SAuth(AsyncAuth):
Only create one instance of SAuth per __key()
'''
key = cls.__key(opts)
if key not in SAuth.instances:
auth = SAuth.instances.get(key)
if auth is None:
log.debug('Initializing new SAuth for {0}'.format(key))
new_auth = object.__new__(cls)
new_auth.__singleton_init__(opts)
SAuth.instances[key] = new_auth
auth = object.__new__(cls)
auth.__singleton_init__(opts)
SAuth.instances[key] = auth
else:
log.debug('Re-using SAuth for {0}'.format(key))
return SAuth.instances[key]
return auth
@classmethod
def __key(cls, opts, io_loop=None):

View File

@ -710,18 +710,21 @@ def check_hash(path, file_hash):
hash
The hash to check against the file specified in the ``path`` argument.
For versions 2016.11.4 and newer, the hash can be specified without an
.. versionchanged:: 2016.11.4
For this and newer versions the hash can be specified without an
accompanying hash type (e.g. ``e138491e9d5b97023cea823fe17bac22``),
but for earlier releases it is necessary to also specify the hash type
in the format ``<hash_type>:<hash_value>`` (e.g.
``md5:e138491e9d5b97023cea823fe17bac22``).
in the format ``<hash_type>=<hash_value>`` (e.g.
``md5=e138491e9d5b97023cea823fe17bac22``).
CLI Example:
.. code-block:: bash
salt '*' file.check_hash /etc/fstab e138491e9d5b97023cea823fe17bac22
salt '*' file.check_hash /etc/fstab md5:e138491e9d5b97023cea823fe17bac22
salt '*' file.check_hash /etc/fstab md5=e138491e9d5b97023cea823fe17bac22
'''
path = os.path.expanduser(path)

View File

@ -216,7 +216,7 @@ def align_check(device, part_type, partition):
'Invalid partition passed to partition.align_check'
)
cmd = 'parted -m -s {0} align-check {1} {2}'.format(
cmd = 'parted -m {0} align-check {1} {2}'.format(
device, part_type, partition
)
out = __salt__['cmd.run'](cmd).splitlines()

View File

@ -135,6 +135,7 @@ def _safe_output(line):
'''
return not any([
line.startswith('Listing') and line.endswith('...'),
line.startswith('Listing') and '\t' not in line,
'...done' in line,
line.startswith('WARNING:')
])

View File

@ -875,12 +875,26 @@ def set_wu_settings(level=None,
Change Windows Update settings. If no parameters are passed, the current
value will be returned.
Supported:
- Windows Vista / Server 2008
- Windows 7 / Server 2008R2
- Windows 8 / Server 2012
- Windows 8.1 / Server 2012R2
.. note:
Microsoft began using the Unified Update Platform (UUP) starting with
Windows 10 / Server 2016. The Windows Update settings have changed and
the ability to 'Save' Windows Update settings has been removed. Windows
Update settings are read-only. See MSDN documentation:
https://msdn.microsoft.com/en-us/library/aa385829(v=vs.85).aspx
:param int level:
Number from 1 to 4 indicating the update level:
1. Never check for updates
2. Check for updates but let me choose whether to download and install them
3. Download updates but let me choose whether to install them
4. Install updates automatically
:param bool recommended:
Boolean value that indicates whether to include optional or recommended
updates when a search for updates and installation of updates is
@ -923,8 +937,28 @@ def set_wu_settings(level=None,
salt '*' win_wua.set_wu_settings level=4 recommended=True featured=False
'''
ret = {}
ret['Success'] = True
# The AutomaticUpdateSettings.Save() method used in this function does not
# work on Windows 10 / Server 2016. It is called in throughout this function
# like this:
#
# obj_au = win32com.client.Dispatch('Microsoft.Update.AutoUpdate')
# obj_au_settings = obj_au.Settings
# obj_au_settings.Save()
#
# The `Save()` method reports success but doesn't actually change anything.
# Windows Update settings are read-only in Windows 10 / Server 2016. There's
# a little blurb on MSDN that mentions this, but gives no alternative for
# changing these settings in Windows 10 / Server 2016.
#
# https://msdn.microsoft.com/en-us/library/aa385829(v=vs.85).aspx
#
# Apparently the Windows Update framework in Windows Vista - Windows 8.1 has
# been changed quite a bit in Windows 10 / Server 2016. It is now called the
# Unified Update Platform (UUP). I haven't found an API or a Powershell
# commandlet for working with the the UUP. Perhaps there will be something
# forthcoming. The `win_lgpo` module might be an option for changing the
# Windows Update settings using local group policy.
ret = {'Success': True}
# Initialize the PyCom system
pythoncom.CoInitialize()

View File

@ -250,15 +250,16 @@ class IPCClient(object):
# FIXME
key = str(socket_path)
if key not in loop_instance_map:
client = loop_instance_map.get(key)
if client is None:
log.debug('Initializing new IPCClient for path: {0}'.format(key))
new_client = object.__new__(cls)
client = object.__new__(cls)
# FIXME
new_client.__singleton_init__(io_loop=io_loop, socket_path=socket_path)
loop_instance_map[key] = new_client
client.__singleton_init__(io_loop=io_loop, socket_path=socket_path)
loop_instance_map[key] = client
else:
log.debug('Re-using IPCClient for {0}'.format(key))
return loop_instance_map[key]
return client
def __singleton_init__(self, socket_path, io_loop=None):
'''

View File

@ -221,17 +221,18 @@ class AsyncTCPReqChannel(salt.transport.client.ReqChannel):
loop_instance_map = cls.instance_map[io_loop]
key = cls.__key(opts, **kwargs)
if key not in loop_instance_map:
obj = loop_instance_map.get(key)
if obj is None:
log.debug('Initializing new AsyncTCPReqChannel for {0}'.format(key))
# we need to make a local variable for this, as we are going to store
# it in a WeakValueDictionary-- which will remove the item if no one
# references it-- this forces a reference while we return to the caller
new_obj = object.__new__(cls)
new_obj.__singleton_init__(opts, **kwargs)
loop_instance_map[key] = new_obj
obj = object.__new__(cls)
obj.__singleton_init__(opts, **kwargs)
loop_instance_map[key] = obj
else:
log.debug('Re-using AsyncTCPReqChannel for {0}'.format(key))
return loop_instance_map[key]
return obj
@classmethod
def __key(cls, opts, **kwargs):

View File

@ -80,28 +80,19 @@ class AsyncZeroMQReqChannel(salt.transport.client.ReqChannel):
loop_instance_map = cls.instance_map[io_loop]
key = cls.__key(opts, **kwargs)
if key not in loop_instance_map:
obj = loop_instance_map.get(key)
if obj is None:
log.debug('Initializing new AsyncZeroMQReqChannel for {0}'.format(key))
# we need to make a local variable for this, as we are going to store
# it in a WeakValueDictionary-- which will remove the item if no one
# references it-- this forces a reference while we return to the caller
new_obj = object.__new__(cls)
new_obj.__singleton_init__(opts, **kwargs)
loop_instance_map[key] = new_obj
obj = object.__new__(cls)
obj.__singleton_init__(opts, **kwargs)
loop_instance_map[key] = obj
log.trace('Inserted key into loop_instance_map id {0} for key {1} and process {2}'.format(id(loop_instance_map), key, os.getpid()))
else:
log.debug('Re-using AsyncZeroMQReqChannel for {0}'.format(key))
try:
return loop_instance_map[key]
except KeyError:
# In iterating over the loop_instance_map, we may have triggered
# garbage collection. Therefore, the key is no longer present in
# the map. Re-gen and add to map.
log.debug('Initializing new AsyncZeroMQReqChannel due to GC for {0}'.format(key))
new_obj = object.__new__(cls)
new_obj.__singleton_init__(opts, **kwargs)
loop_instance_map[key] = new_obj
return loop_instance_map[key]
return obj
def __deepcopy__(self, memo):
cls = self.__class__