Merge pull request #21990 from basepi/merge-forward-2015.2

Merge forward from 2014.7 to 2015.2
This commit is contained in:
Nicole Thomas 2015-03-25 10:26:05 -06:00
commit 31d45bc782
12 changed files with 332 additions and 113 deletions

View File

@ -1,9 +1,10 @@
##### Primary configuration settings #####
##########################################
# This configuration file is used to manage the behavior of the Salt Master.
# Values that are commented out but have no space after the comment are
# defaults that need not be set in the config. If there is a space after the
# comment that the value is presented as an example and is not the default.
# Values that are commented out but have an empty line after the comment are
# defaults that do not need to be set in the config. If there is no blank line
# after the comment then the value is presented as an example and is not the
# default.
# Per default, the master will automatically include all config files
# from master.d/*.conf (master.d is a directory in the same directory
@ -237,7 +238,7 @@
# larry:
# - test.ping
# - network.*
#
# Blacklist any of the following users or modules
#
# This example would blacklist all non sudo users, including root from
@ -262,7 +263,7 @@
# pam:
# fred:
# - test.*
#
# Time (in seconds) for a newly generated token to live. Default: 12 hours
#token_expire: 43200
@ -387,7 +388,7 @@
# prod:
# - /srv/salt/prod/services
# - /srv/salt/prod/states
#
#file_roots:
# base:
# - /srv/salt
@ -492,8 +493,8 @@
# within the repository. The path is defined relative to the root of the
# repository and defaults to the repository root.
#gitfs_root: somefolder/otherfolder
#
#
##### Pillar settings #####
##########################################
# Salt Pillars allow for the building of global data that can be made selectively
@ -526,13 +527,23 @@
# master config file that can then be used on minions.
#pillar_opts: False
# The pillar_safe_render_error option prevents the master from passing piller
# The pillar_safe_render_error option prevents the master from passing piller
# render errors to the minion. This is set on by default because the error could
# contain templating data which would give that minion information it shouldn't
# have, like a password! When set true the error message will only show:
# Rendering SLS 'my.sls' failed. Please see master log for details.
#pillar_safe_render_error: True
# The pillar_source_merging_strategy option allows you to configure merging strategy
# between different sources. It accepts four values: recurse, aggregate, overwrite,
# or smart. Recurse will merge recursively mapping of data. Aggregate instructs
# aggregation of elements between sources that use the #!yamlex renderer. Overwrite
# will verwrite elements according the order in which they are processed. This is
# behavior of the 2014.1 branch and earlier. Smart guesses the best strategy based
# on the "renderer" setting and is the default value.
#pillar_source_merging_strategy: smart
##### Syndic settings #####
##########################################
# The Salt syndic is used to pass commands through a master from a higher
@ -599,8 +610,8 @@
#peer_run:
# foo.example.com:
# - manage.up
#
#
##### Mine settings #####
##########################################
# Restrict mine.get access from minions. By default any minion has a full access
@ -685,10 +696,10 @@
##############################################
# Location of the repo on the master:
#win_repo: '/srv/salt/win/repo'
#
# Location of the master's repo cache file:
#win_repo_mastercachefile: '/srv/salt/win/repo/winrepo.p'
#
# List of git repositories to include with the local repo:
#win_gitrepos:
# - 'https://github.com/saltstack/salt-winrepo.git'

View File

@ -1,10 +1,10 @@
##### Primary configuration settings #####
##########################################
##########################################
# This configuration file is used to manage the behavior of the Salt Minion.
# With the exception of the location of the Salt Master Server, values that
# are commented out but have no space after the comment are defaults that need
# not be set in the config. If there is a space after the comment that the value
# is presented as an example and is not the default.
# With the exception of the location of the Salt Master Server, values that are
# commented out but have an empty line after the comment are defaults that need
# not be set in the config. If there is no blank line after the comment, the
# value is presented as an example and is not the default.
# Per default the minion will automatically include all config files
# from minion.d/*.conf (minion.d is a directory in the same directory
@ -68,7 +68,7 @@
# deployment: datacenter4
# cabinet: 13
# cab_u: 14-15
#
# Where cache data goes.
#cachedir: /var/cache/salt/minion
@ -215,7 +215,8 @@
# recon_default: 100
# recon_max: 5000
# recon_randomize: False
#
#
# The loop_interval sets how long in seconds the minion will wait between
# evaluating the scheduler and running cleanup tasks. This defaults to a
# sane 60 seconds, but if the minion scheduler needs to be evaluated more
@ -276,8 +277,9 @@
#include:
# - /etc/salt/extra_config
# - /etc/roles/webserver
#
#
#
##### Minion module management #####
##########################################
# Disable specific modules. This allows the admin to limit the level of
@ -427,8 +429,8 @@
#pillar_roots:
# base:
# - /srv/pillar
#
#
###### Security settings #####
###########################################
# Enable "open mode", this mode still maintains encryption, but turns off
@ -554,8 +556,8 @@
#
# A dict for the test module:
#test.baz: {spam: sausage, cheese: bread}
#
#
###### Update settings ######
###########################################
# Using the features in Esky, a salt minion can both run as a frozen app and

View File

@ -1854,7 +1854,7 @@ Default: ``False``
Default: ``smart``
The pillar_source_merging_strategy option allows you to configure merging
strategy between different sources. It accepts 3 values:
strategy between different sources. It accepts 4 values:
* recurse:
@ -1920,37 +1920,37 @@ strategy between different sources. It accepts 3 values:
* overwrite:
Will use the behaviour of the 2014.1 branch and earlier.
Will use the behaviour of the 2014.1 branch and earlier.
Overwrites elements according the order in which they are processed.
Overwrites elements according the order in which they are processed.
First pillar processed:
First pillar processed:
.. code-block:: yaml
.. code-block:: yaml
A:
first_key: blah
second_key: blah
A:
first_key: blah
second_key: blah
Second pillar processed:
Second pillar processed:
.. code-block:: yaml
.. code-block:: yaml
A:
third_key: blah
fourth_key: blah
A:
third_key: blah
fourth_key: blah
will be merged as:
will be merged as:
.. code-block:: yaml
.. code-block:: yaml
A:
third_key: blah
fourth_key: blah
A:
third_key: blah
fourth_key: blah
* smart (default):
Guesses the best strategy based on the "renderer" setting.
Guesses the best strategy based on the "renderer" setting.
Syndic Server Settings

View File

@ -0,0 +1,140 @@
===========================
Salt 2014.7.3 Release Notes
===========================
:release: TBA
Version 2014.7.3 is a bugfix release for :doc:`2014.7.2
</topics/releases/2014.7.2>`.
Changes:
- Multi-master minions mode no longer route fileclient operations asymetrically.
This fixes the source of many multi-master bugs where the minion would
become unrepsonsive from one or more masters.
- Fix bug wherein network.iface could produce stack traces.
- net.arp will no longer be made available unless arp is installed on the
system.
- Major performance improvements to Saltnado
- Allow KVM module to operate under KVM itself or VMWare Fusion
- Various fixes to the Windows installation scripts
- Fix issue where the syndic would not correctly propogate loads to the master
job cache.
- Improve error handling on invalid /etc/network/interfaces file in salt
networking modules
- Fix bug where a reponse status was not checked for in fileclient.get_url
- Enable eauth when running salt in batch mode
- Increase timeout in Boto Route53 module
- Fix bugs with Salt's 'tar' module option parsing
- Fix parsing of NTP servers on Windows
- Fix issue with blockdev tuning not reporting changes correctly
- Update to the latest Salt bootstrap script
- Update Linode salt-cloud driver to use either linode-python or
apache-libcloud
- Fix for s3.query function to return correct headers
- Fix for s3.head returning None for files that exist
- Fix the disable function in win_service module so that the service is
disabled correctly
- Fix race condition between master and minion when making a directory when
both daemons are on the same host
- Fix an issue where file.recurse would fail at the root of an svn repo
when the repo has a mountpoint
- Fix an issue where file.recurse would fail at the root of an hgfs repo
when the repo has a mountpoint
- Fix an issue where file.recurse would fail at the root of an gitfs repo
when the repo has a mountpoint
- Add status.master capability for Windows.
- Various fixes to ssh_known_hosts
- Various fixes to states.network bonding for Debian
- The debian_ip.get_interfaces module no longer removes nameservers.
- Better integration between grains.virtual and systemd-detect-virt and
virt-what
- Fix traceback in sysctl.present state output
- Fix for issue where mount.mounted would fail when superopts were not a part
of mount.active (extended=True). Also mount.mounted various fixes for Solaris
and FreeBSD.
- Fix error where datetimes were not correctly safeguarded before being passed
into msgpack.
- Fix file.replace regressions. If the pattern is not found, and if dry run is False,
and if `backup` is False, and if a pre-existing file exists with extension `.bak`,
then that backup file will be overwritten. This backup behavior is a result of how `fileinput`
works. Fixing it requires either passing through the file twice (the
first time only to search for content and set a flag), or rewriting
`file.replace` so it doesn't use `fileinput`
- VCS filreserver fixes/optimizations
- Catch fileserver configuration errors on master start
- Raise errors on invalid gitfs configurations
- set_locale when locale file does not exist (Redhat family)
- Fix to correctly count active devices when created mdadm array with spares
- Fix to correctly target minions in batch mode
- Support ssh:// urls using the gitfs dulwhich backend
- New fileserver runner
- Fix various bugs with argument parsing to the publish module.
- Fix disk.usage for Synology OS
- Fix issue with tags occurring twice with docker.pulled
- Fix incorrect key error in SMTP returner
- Fix condition which would remount loopback filesystems on every state run
- Remove requsites from listens after they are called in the state system
- Make system implementation of service.running aware of legacy service calls
- Fix issue where publish.publish would not handle duplicate responses gracefully.
- Accept Kali Linux for aptpkg salt execution module
- Fix bug where cmd.which could not handle a dirname as an argument
- Fix issue in ps.pgrep where exceptions were thrown on Windows.
Known issues:
- In multimaster mode, a minion may become temporarily unresponsive
if modules or pillars are refreshed at the same time that one
or more masters are down. This can be worked around by setting
'auth_timeout' and 'auth_tries' down to shorter periods.

View File

@ -300,9 +300,13 @@ def _file_lists(load, form):
rel_fn = rel_fn.replace('\\', '/')
ret['files'].append(rel_fn)
if save_cache:
salt.fileserver.write_file_list_cache(
__opts__, ret, list_cache, w_lock
)
try:
salt.fileserver.write_file_list_cache(
__opts__, ret, list_cache, w_lock
)
except NameError:
# Catch msgpack error in salt-ssh
pass
return ret.get(form, [])
# Shouldn't get here, but if we do, this prevents a TypeError
return []

View File

@ -1519,12 +1519,17 @@ class Minion(MinionBase):
'''
Refresh the pillar
'''
self.opts['pillar'] = salt.pillar.get_pillar(
self.opts,
self.opts['grains'],
self.opts['id'],
self.opts['environment'],
).compile_pillar()
try:
self.opts['pillar'] = salt.pillar.get_pillar(
self.opts,
self.opts['grains'],
self.opts['id'],
self.opts['environment'],
).compile_pillar()
except SaltClientError:
# Do not exit if a pillar refresh fails.
log.error('Pillar data could not be refreshed. '
'One or more masters may be down!')
self.module_refresh(force_refresh)
def manage_schedule(self, package):

View File

@ -14,6 +14,7 @@ import socket
# Import salt libs
import salt.utils
import salt.utils.decorators as decorators
import salt.utils.network
from salt.exceptions import CommandExecutionError
import salt.utils.validate.net
@ -586,6 +587,7 @@ def dig(host):
return __salt__['cmd.run'](cmd)
@decorators.which('arp')
def arp():
'''
Return the arp table from the minion

View File

@ -252,7 +252,7 @@ def host_keys(keydir=None):
for fn_ in os.listdir(keydir):
if fn_.startswith('ssh_host_'):
top = fn_.split('.')
comps = fn_.split('_')
comps = top[0].split('_')
kname = comps[2]
if len(top) > 1:
kname += '.{0}'.format(top[1])
@ -261,7 +261,11 @@ def host_keys(keydir=None):
# As of RFC 4716 "a key file is a text file, containing a sequence of lines",
# although some SSH implementations (e.g. OpenSSH) manage their own format(s).
# Please see #20708 for a discussion about how to handle SSH key files in the future
keys[kname] = _fh.read.strip()
keys[kname] = _fh.readline()
# only read the whole file if it is not in the legacy 1.1 binary format
if keys[kname] != "SSH PRIVATE KEY FILE FORMAT 1.1\n":
keys[kname] += _fh.read()
keys[kname] = keys[kname].strip()
except (IOError, OSError):
keys[kname] = ''
return keys

View File

@ -1542,8 +1542,6 @@ def is_kvm_hyper():
salt '*' virt.is_kvm_hyper
'''
if __grains__['virtual'] != 'physical':
return False
try:
if 'kvm_' not in salt.utils.fopen('/proc/modules').read():
return False

View File

@ -26,12 +26,11 @@ Example output::
from __future__ import absolute_import
# Import python libs
from numbers import Number
import re
# Import salt libs
import salt.utils
import salt.output
from salt.ext.six import string_types
from salt.utils import get_colors, sdecode
class NestDisplay(object):
@ -39,7 +38,13 @@ class NestDisplay(object):
Manage the nested display contents
'''
def __init__(self):
self.colors = salt.utils.get_colors(__opts__.get('color'))
self.colors = get_colors(__opts__.get('color'))
self.__dict__.update(
get_colors(
__opts__.get('color')
)
)
self.strip_colors = __opts__.get('strip_colors', True)
def ustring(self,
indent,
@ -49,69 +54,87 @@ class NestDisplay(object):
suffix='',
endc=None):
if endc is None:
endc = self.colors['ENDC']
endc = self.ENDC
indent *= ' '
fmt = u'{0}{1}{2}{3}{4}{5}'
try:
return u'{0}{1}{2}{3}{4}{5}\n'.format(
indent, color, prefix, msg, endc, suffix)
return fmt.format(indent, color, prefix, msg, endc, suffix)
except UnicodeDecodeError:
return u'{0}{1}{2}{3}{4}{5}\n'.format(
indent, color, prefix, salt.utils.sdecode(msg), endc, suffix)
return fmt.format(indent, color, prefix, sdecode(msg), endc, suffix)
def display(self, ret, indent, prefix, out):
'''
Recursively iterate down through data structures to determine output
'''
strip_colors = __opts__.get('strip_colors', True)
if ret is None or ret is True or ret is False:
out += self.ustring(
' ' * indent,
self.colors['YELLOW'],
ret,
prefix=prefix)
out.append(
self.ustring(
indent,
self.YELLOW,
ret,
prefix=prefix
)
)
# Number includes all python numbers types
# (float, int, long, complex, ...)
elif isinstance(ret, Number):
out += self.ustring(
' ' * indent,
self.colors['YELLOW'],
ret,
prefix=prefix)
out.append(
self.ustring(
indent,
self.YELLOW,
ret,
prefix=prefix
)
)
elif isinstance(ret, string_types):
lines = re.split(r'\r?\n', ret)
for line in lines:
if strip_colors:
for line in ret.splitlines():
if self.strip_colors:
line = salt.output.strip_esc_sequence(line)
out += self.ustring(
' ' * indent,
self.colors['GREEN'],
line,
prefix=prefix)
elif isinstance(ret, list) or isinstance(ret, tuple):
out.append(
self.ustring(
indent,
self.GREEN,
line,
prefix=prefix
)
)
elif isinstance(ret, (list, tuple)):
for ind in ret:
if isinstance(ind, (list, tuple, dict)):
out += self.ustring(' ' * indent,
self.colors['GREEN'],
'|_')
out.append(
self.ustring(
indent,
self.GREEN,
'|_'
)
)
prefix = '' if isinstance(ind, dict) else '- '
out = self.display(ind, indent + 2, prefix, out)
self.display(ind, indent + 2, prefix, out)
else:
out = self.display(ind, indent, '- ', out)
self.display(ind, indent, '- ', out)
elif isinstance(ret, dict):
if indent:
out += self.ustring(
' ' * indent,
self.colors['CYAN'],
'-' * 10)
out.append(
self.ustring(
indent,
self.CYAN,
'----------'
)
)
for key in sorted(ret):
val = ret[key]
out += self.ustring(
' ' * indent,
self.colors['CYAN'],
key,
suffix=":",
prefix=prefix)
out = self.display(val, indent + 4, '', out)
out.append(
self.ustring(
indent,
self.CYAN,
key,
suffix=':',
prefix=prefix
)
)
self.display(val, indent + 4, '', out)
return out
@ -120,4 +143,6 @@ def output(ret):
Display ret data
'''
nest = NestDisplay()
return nest.display(ret, __opts__.get('nested_indent', 0), '', '')
return '\n'.join(
nest.display(ret, __opts__.get('nested_indent', 0), '', [])
)

View File

@ -31,7 +31,7 @@ def update(dest, upd):
and isinstance(val, collections.Mapping):
ret = update(dest_subkey, val)
dest[key] = ret
else:
elif key:
dest[key] = upd[key]
return dest

View File

@ -721,28 +721,56 @@ def _ipv4_to_bits(ipaddr):
return ''.join([bin(int(x))[2:].rjust(8, '0') for x in ipaddr.split('.')])
def _get_iface_info(iface):
'''
If `iface` is available, return interface info and no error, otherwise
return no info and log and return an error
'''
iface_info = interfaces()
if iface in iface_info.keys():
return iface_info, False
else:
error_msg = ('Interface "{0}" not in available interfaces: "{1}"'
''.format(iface, '", "'.join(iface_info.keys())))
log.error(error_msg)
return None, error_msg
def hw_addr(iface):
'''
Return the hardware address (a.k.a. MAC address) for a given interface
'''
return interfaces().get(iface, {}).get('hwaddr', '')
iface_info, error = _get_iface_info(iface)
if error is False:
return iface_info.get(iface, {}).get('hwaddr', '')
else:
return error
def interface(iface):
'''
Return the interface details
Return the details of `iface` or an error if it does not exist
'''
return interfaces().get(iface, {}).get('inet', '')
iface_info, error = _get_iface_info(iface)
if error is False:
return iface_info.get(iface, {}).get('inet', '')
else:
return error
def interface_ip(iface):
'''
Return the interface details
Return `iface` IPv4 addr or an error if `iface` does not exist
'''
try:
return interfaces().get(iface, {}).get('inet', {})[0].get('address', {})
except KeyError:
return {} # iface has no IP
iface_info, error = _get_iface_info(iface)
if error is False:
return iface_info.get(iface, {}).get('inet', {})[0].get('address', '')
else:
return error
def subnets():