mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge pull request #40677 from rallytime/merge-develop
[develop] Merge forward from nitrogen to develop
This commit is contained in:
commit
88f514835d
22 changed files with 675 additions and 249 deletions
|
@ -746,6 +746,10 @@
|
|||
#
|
||||
#zmq_monitor: False
|
||||
|
||||
# Number of times to try to authenticate with the salt master when reconnecting
|
||||
# to the master
|
||||
#tcp_authentication_retries: 5
|
||||
|
||||
###### Module configuration #####
|
||||
###########################################
|
||||
# Salt allows for modules to be passed arbitrary configuration data, any data
|
||||
|
|
|
@ -2274,6 +2274,20 @@ ZeroMQ is installed.
|
|||
|
||||
.. conf_minion:: failhard
|
||||
|
||||
``tcp_authentication_retries``
|
||||
------------------------------
|
||||
|
||||
Default: ``5``
|
||||
|
||||
The number of times to retry authenticating with the salt master when it comes
|
||||
back online.
|
||||
|
||||
Zeromq does a lot to make sure when connections come back online that they
|
||||
reauthenticate. The tcp transport should try to connect with a new connection
|
||||
if the old one times out on reauthenticating.
|
||||
|
||||
`-1` for infinite tries.
|
||||
|
||||
``failhard``
|
||||
------------
|
||||
|
||||
|
|
|
@ -47,9 +47,9 @@ has now been extended to pillar SLS files as well. See :ref:`here
|
|||
Grains Changes
|
||||
==============
|
||||
|
||||
- The ``os_release`` grain has been changed from a string to an integer.
|
||||
State files, especially those using a templating language like Jinja
|
||||
may need to be adjusted to account for this change.
|
||||
- The ``osmajorrelease`` grain has been changed from a string to an integer.
|
||||
State files, especially those using a templating language like Jinja, may
|
||||
need to be adjusted to account for this change.
|
||||
- Add ability to specify disk backing mode in the VMWare salt cloud profile.
|
||||
|
||||
State Module Changes
|
||||
|
@ -61,48 +61,50 @@ State Module Changes
|
|||
start/stop the service using the ``--no-block`` flag in the ``systemctl``
|
||||
command. On non-systemd minions, a warning will be issued.
|
||||
|
||||
- The :py:func:`module.run <salt.states.module.run>` state has dropped its previous
|
||||
syntax with ``m_`` prefix for reserved keywords. Additionally, it allows
|
||||
running several functions in a batch.
|
||||
- The :py:func:`module.run <salt.states.module.run>` state has dropped its
|
||||
previous syntax with ``m_`` prefix for reserved keywords. Additionally, it
|
||||
allows running several functions in a batch.
|
||||
|
||||
.. note::
|
||||
It is nesessary to explicitly turn on the new behaviour (see below)
|
||||
.. note::
|
||||
It is necessary to explicitly turn on the new behavior (see below)
|
||||
|
||||
Before and after:
|
||||
.. code-block:: yaml
|
||||
|
||||
.. code-block:: yaml
|
||||
# Before
|
||||
run_something:
|
||||
module.run:
|
||||
- name: mymodule.something
|
||||
- m_name: 'some name'
|
||||
- kwargs: {
|
||||
first_arg: 'one',
|
||||
second_arg: 'two',
|
||||
do_stuff: 'True'
|
||||
}
|
||||
|
||||
# Before
|
||||
run_something:
|
||||
module.run:
|
||||
- name: mymodule.something
|
||||
- m_name: 'some name'
|
||||
- kwargs: {
|
||||
first_arg: 'one',
|
||||
second_arg: 'two',
|
||||
do_stuff: 'True'
|
||||
}
|
||||
|
||||
# After
|
||||
run_something:
|
||||
module.run:
|
||||
mymodule.something:
|
||||
- name: some name
|
||||
- first_arg: one
|
||||
- second_arg: two
|
||||
- do_stuff: True
|
||||
|
||||
- Previous behaviour of the function :py:func:`module.run <salt.states.module.run>` is
|
||||
still kept by default and can be bypassed in case you want to use behaviour above.
|
||||
Please keep in mind that the old syntax will no longer be supported in the ``Oxygen``
|
||||
release of Salt. To enable the new behavior, add the following to the minion config file:
|
||||
# After
|
||||
run_something:
|
||||
module.run:
|
||||
mymodule.something:
|
||||
- name: some name
|
||||
- first_arg: one
|
||||
- second_arg: two
|
||||
- do_stuff: True
|
||||
|
||||
|
||||
.. code-block:: yaml
|
||||
Since a lot of users are already using :py:func:`module.run
|
||||
<salt.states.module.run>` states, this new behavior must currently be
|
||||
explicitly turned on, to allow users to take their time updating their SLS
|
||||
files. However, please keep in mind that the new syntax will take effect in
|
||||
the next feature release of Salt (Oxygen) and the old usage will no longer be
|
||||
supported at that time.
|
||||
|
||||
use_superseded:
|
||||
- module.run
|
||||
To enable the new behavior for :py:func:`module.run <salt.states.module.run>`,
|
||||
add the following to the minion config file:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
use_superseded:
|
||||
- module.run
|
||||
|
||||
|
||||
Execution Module Changes
|
||||
|
@ -128,6 +130,8 @@ Execution Module Changes
|
|||
- A ``pkg.list_repo_pkgs`` function has been added for both
|
||||
:py:func:`Debian/Ubuntu <salt.modules.aptpkg.list_repo_pkgs>` and
|
||||
:py:func:`Arch Linux <salt.modules.pacman.list_repo_pkgs>`-based distros.
|
||||
- The :mod:`system <salt.modules.system>` module changed its return format
|
||||
from "HH:MM AM/PM" to "HH:MM:SS AM/PM" for `get_system_time`.
|
||||
|
||||
|
||||
Proxy Module Changes
|
||||
|
@ -149,29 +153,26 @@ connection with the remote device only when required.
|
|||
Wildcard Versions in :py:func:`pkg.installed <salt.states.pkg.installed>` States
|
||||
================================================================================
|
||||
|
||||
The :py:func:`pkg.installed <salt.states.pkg.installed>` state now supports
|
||||
wildcards in package versions, for the following platforms:
|
||||
- The :py:func:`pkg.installed <salt.states.pkg.installed>` state now supports
|
||||
wildcards in package versions, for the following platforms:
|
||||
|
||||
- Debian/Ubuntu
|
||||
- RHEL/CentOS
|
||||
- Arch Linux
|
||||
- Debian/Ubuntu
|
||||
- RHEL/CentOS
|
||||
- Arch Linux
|
||||
|
||||
This support also extends to any derivatives of these distros, which use the
|
||||
:mod:`aptpkg <salt.modules.aptpkg>`, :mod:`yumpkg <salt.modules.yumpkg>`, or
|
||||
:mod:`pacman <salt.modules.pacman>` providers for the ``pkg`` virtual module.
|
||||
This support also extends to any derivatives of these distros, which use the
|
||||
:mod:`aptpkg <salt.modules.aptpkg>`, :mod:`yumpkg <salt.modules.yumpkg>`, or
|
||||
:mod:`pacman <salt.modules.pacman>` providers for the ``pkg`` virtual module.
|
||||
|
||||
Using wildcards can be useful for packages where the release name is built into
|
||||
the version in some way, such as for RHEL/CentOS which typically has version
|
||||
numbers like ``1.2.34-5.el7``. An example of the usage for this would be:
|
||||
Using wildcards can be useful for packages where the release name is built into
|
||||
the version in some way, such as for RHEL/CentOS which typically has version
|
||||
numbers like ``1.2.34-5.el7``. An example of the usage for this would be:
|
||||
|
||||
.. code-block:: yaml
|
||||
.. code-block:: yaml
|
||||
|
||||
mypkg:
|
||||
pkg.installed:
|
||||
- version: '1.2.34*'
|
||||
|
||||
- The :mod:`system <salt.modules.system>` module changed the returned format
|
||||
from "HH:MM AM/PM" to "HH:MM:SS AM/PM" for `get_system_time`.
|
||||
mypkg:
|
||||
pkg.installed:
|
||||
- version: '1.2.34*'
|
||||
|
||||
Master Configuration Additions
|
||||
==============================
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
../salt-api.service
|
14
pkg/suse/salt-api.service
Normal file
14
pkg/suse/salt-api.service
Normal file
|
@ -0,0 +1,14 @@
|
|||
[Unit]
|
||||
Description=The Salt API
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
User=salt
|
||||
Type=simple
|
||||
Environment=SHELL=/bin/bash
|
||||
LimitNOFILE=8192
|
||||
ExecStart=/usr/bin/salt-api
|
||||
TimeoutStopSec=3
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -567,10 +567,20 @@ class LocalClient(object):
|
|||
if 'gather_job_timeout' in kwargs:
|
||||
opts['gather_job_timeout'] = kwargs['gather_job_timeout']
|
||||
|
||||
eauth = {}
|
||||
if 'eauth' in kwargs:
|
||||
eauth['eauth'] = kwargs.pop('eauth')
|
||||
if 'username' in kwargs:
|
||||
eauth['username'] = kwargs.pop('username')
|
||||
if 'password' in kwargs:
|
||||
eauth['password'] = kwargs.pop('password')
|
||||
if 'token' in kwargs:
|
||||
eauth['token'] = kwargs.pop('token')
|
||||
|
||||
for key, val in six.iteritems(self.opts):
|
||||
if key not in opts:
|
||||
opts[key] = val
|
||||
batch = salt.cli.batch.Batch(opts, quiet=True)
|
||||
batch = salt.cli.batch.Batch(opts, eauth=eauth, quiet=True)
|
||||
for ret in batch.run():
|
||||
yield ret
|
||||
|
||||
|
|
|
@ -218,7 +218,7 @@ def prep_trans_tar(opts, file_client, chunks, file_refs, pillar=None, id_=None):
|
|||
files = ''
|
||||
if files:
|
||||
for filename in files:
|
||||
fn = filename[len(cache_dest):].strip('/')
|
||||
fn = filename[len(file_client.get_cachedir(cache_dest)):].strip('/')
|
||||
tgt = os.path.join(
|
||||
env_root,
|
||||
short,
|
||||
|
|
|
@ -1035,6 +1035,10 @@ VALID_OPTS = {
|
|||
# django auth
|
||||
'django_auth_path': str,
|
||||
'django_auth_settings': str,
|
||||
|
||||
# Number of times to try to auth with the master on a reconnect with the
|
||||
# tcp transport
|
||||
'tcp_authentication_retries': int,
|
||||
}
|
||||
|
||||
# default configurations
|
||||
|
@ -1176,6 +1180,7 @@ DEFAULT_MINION_OPTS = {
|
|||
'file_buffer_size': 262144,
|
||||
'tcp_pub_port': 4510,
|
||||
'tcp_pull_port': 4511,
|
||||
'tcp_authentication_retries': 5,
|
||||
'log_file': os.path.join(salt.syspaths.LOGS_DIR, 'minion'),
|
||||
'log_level': 'warning',
|
||||
'log_level_logfile': None,
|
||||
|
|
|
@ -5,41 +5,59 @@ Junos Syslog Engine
|
|||
|
||||
.. versionadded:: Nitrogen
|
||||
|
||||
An engine that listen to syslog message from Junos devices,
|
||||
|
||||
:depends: pyparsing, twisted
|
||||
|
||||
|
||||
An engine that listens to syslog message from Junos devices,
|
||||
extract event information and generate message on SaltStack bus.
|
||||
|
||||
One can customize the name of the topic.
|
||||
The event data consists of the following fields:
|
||||
a. hostname
|
||||
b. hostip
|
||||
c. daemon
|
||||
d. event
|
||||
e. severity
|
||||
f. priority
|
||||
g. timestamp
|
||||
h. message
|
||||
i. pid
|
||||
j. raw (the raw event data forwarded from the device)
|
||||
The topic can consist of any of the combination of above fields,
|
||||
The event topic sent to salt is dynamically generated according to the topic title
|
||||
specified by the user. The incoming event data (from the junos device) consists
|
||||
of the following fields:
|
||||
|
||||
1. hostname
|
||||
2. hostip
|
||||
3. daemon
|
||||
4. event
|
||||
5. severity
|
||||
6. priority
|
||||
7. timestamp
|
||||
8. message
|
||||
9. pid
|
||||
10. raw (the raw event data forwarded from the device)
|
||||
|
||||
The topic title can consist of any of the combination of above fields,
|
||||
but the topic has to start with ‘jnpr/syslog’.
|
||||
So, we can have different combinations like:
|
||||
• jnpr/syslog/hostip/daemon/event
|
||||
• jnpr/syslog/daemon/severity
|
||||
The default topic is ‘jnpr/syslog/hostname/event’.
|
||||
The topic is to be specified in the configuration file.
|
||||
So, we can have different combinations:
|
||||
- jnpr/syslog/hostip/daemon/event
|
||||
- jnpr/syslog/daemon/severity
|
||||
|
||||
The corresponding dynamic topic sent on salt event bus would look something like:
|
||||
|
||||
- jnpr/syslog/1.1.1.1/mgd/UI_COMMIT_COMPLETED
|
||||
- jnpr/syslog/sshd/7
|
||||
The default topic title is ‘jnpr/syslog/hostname/event’.
|
||||
|
||||
The user can choose the type of data he/she wants of the event bus.
|
||||
Like, if one wants events pertaining to a particular daemon, he/she can
|
||||
Like, if one wants only events pertaining to a particular daemon, he/she can
|
||||
specify that in the configuration file:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
daemon: mgd
|
||||
|
||||
One can even have a list of daemons like:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
daemon:
|
||||
- mgd
|
||||
- sshd
|
||||
|
||||
:configuration:
|
||||
Example configuration
|
||||
Example configuration (to be written in master config file)
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
engines:
|
||||
- junos_syslog:
|
||||
|
@ -49,15 +67,21 @@ One can even have a list of daemons like:
|
|||
- mgd
|
||||
- sshd
|
||||
|
||||
For junos_syslog engine to receive events syslog must be set on junos device.
|
||||
For junos_syslog engine to receive events, syslog must be set on the junos device.
|
||||
This can be done via following configuration:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
set system syslog host <ip-of-the-salt-device> port 516 any any
|
||||
|
||||
Here is a sample syslog event which is received from the junos device:
|
||||
'<30>May 29 05:18:12 bng-ui-vm-9 mspd[1492]: No chassis configuration found'
|
||||
Below is a sample syslog event which is received from the junos device:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
'<30>May 29 05:18:12 bng-ui-vm-9 mspd[1492]: No chassis configuration found'
|
||||
|
||||
The source for parsing the syslog messages is taken from:
|
||||
https://gist.github.com/leandrosilva/3651640#file-xlog-py
|
||||
https://gist.github.com/leandrosilva/3651640#file-xlog-py
|
||||
'''
|
||||
from __future__ import absolute_import
|
||||
|
||||
|
@ -92,12 +116,12 @@ def __virtual__():
|
|||
Load only if twisted and pyparsing libs are present.
|
||||
'''
|
||||
if not HAS_TWISTED_AND_PYPARSING:
|
||||
return (False, 'junos_syslog could not be loaded. \
|
||||
Make sure you have twisted and pyparsing python libraries.')
|
||||
return (False, 'junos_syslog could not be loaded.'
|
||||
' Make sure you have twisted and pyparsing python libraries.')
|
||||
return True
|
||||
|
||||
|
||||
class Parser(object):
|
||||
class _Parser(object):
|
||||
|
||||
def __init__(self):
|
||||
ints = Word(nums)
|
||||
|
@ -210,11 +234,11 @@ class Parser(object):
|
|||
return payload
|
||||
|
||||
|
||||
class SyslogServerFactory(DatagramProtocol):
|
||||
class _SyslogServerFactory(DatagramProtocol):
|
||||
|
||||
def __init__(self, options):
|
||||
self.options = options
|
||||
self.obj = Parser()
|
||||
self.obj = _Parser()
|
||||
data = [
|
||||
"hostip",
|
||||
"priority",
|
||||
|
@ -360,5 +384,5 @@ class SyslogServerFactory(DatagramProtocol):
|
|||
def start(port=516, **kwargs):
|
||||
|
||||
log.info('Starting junos syslog engine (port {0})'.format(port))
|
||||
reactor.listenUDP(port, SyslogServerFactory(kwargs))
|
||||
reactor.listenUDP(port, _SyslogServerFactory(kwargs))
|
||||
reactor.run()
|
||||
|
|
|
@ -132,11 +132,7 @@ class Client(object):
|
|||
'''
|
||||
Return the local location to cache the file, cache dirs will be made
|
||||
'''
|
||||
if cachedir is None:
|
||||
cachedir = self.opts['cachedir']
|
||||
elif not os.path.isabs(cachedir):
|
||||
cachedir = os.path.join(self.opts['cachedir'], cachedir)
|
||||
|
||||
cachedir = self.get_cachedir(cachedir)
|
||||
dest = salt.utils.path_join(cachedir,
|
||||
'files',
|
||||
saltenv,
|
||||
|
@ -159,6 +155,13 @@ class Client(object):
|
|||
yield dest
|
||||
os.umask(cumask)
|
||||
|
||||
def get_cachedir(self, cachedir=None):
|
||||
if cachedir is None:
|
||||
cachedir = self.opts['cachedir']
|
||||
elif not os.path.isabs(cachedir):
|
||||
cachedir = os.path.join(self.opts['cachedir'], cachedir)
|
||||
return cachedir
|
||||
|
||||
def get_file(self,
|
||||
path,
|
||||
dest='',
|
||||
|
@ -250,10 +253,7 @@ class Client(object):
|
|||
# prefix = ''
|
||||
# else:
|
||||
# prefix = separated[0]
|
||||
if cachedir is None:
|
||||
cachedir = self.opts['cachedir']
|
||||
elif not os.path.isabs(cachedir):
|
||||
cachedir = os.path.join(self.opts['cachedir'], cachedir)
|
||||
cachedir = self.get_cachedir(cachedir)
|
||||
|
||||
dest = salt.utils.path_join(cachedir, 'files', saltenv)
|
||||
for fn_ in self.file_list_emptydirs(saltenv):
|
||||
|
@ -818,22 +818,6 @@ class LocalClient(Client):
|
|||
if not fnd_path:
|
||||
return ''
|
||||
|
||||
try:
|
||||
fnd_mode = fnd.get('stat', [])[0]
|
||||
except (IndexError, TypeError):
|
||||
fnd_mode = None
|
||||
|
||||
if not salt.utils.is_windows():
|
||||
if fnd_mode is not None:
|
||||
try:
|
||||
if os.stat(dest).st_mode != fnd_mode:
|
||||
try:
|
||||
os.chmod(dest, fnd_mode)
|
||||
except OSError as exc:
|
||||
log.warning('Failed to chmod %s: %s', dest, exc)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return fnd_path
|
||||
|
||||
def file_list(self, saltenv='base', prefix=''):
|
||||
|
@ -1085,47 +1069,7 @@ class RemoteClient(Client):
|
|||
mode_local = None
|
||||
|
||||
if hash_local == hash_server:
|
||||
if not salt.utils.is_windows():
|
||||
if mode_server is None:
|
||||
log.debug('No file mode available for \'%s\'', path)
|
||||
elif mode_local is None:
|
||||
log.debug(
|
||||
'No file mode available for \'%s\'',
|
||||
dest2check
|
||||
)
|
||||
else:
|
||||
if mode_server == mode_local:
|
||||
log.info(
|
||||
'Fetching file from saltenv \'%s\', '
|
||||
'** skipped ** latest already in cache '
|
||||
'\'%s\', mode up-to-date', saltenv, path
|
||||
)
|
||||
else:
|
||||
try:
|
||||
os.chmod(dest2check, mode_server)
|
||||
log.info(
|
||||
'Fetching file from saltenv \'%s\', '
|
||||
'** updated ** latest already in cache, '
|
||||
'\'%s\', mode updated from %s to %s',
|
||||
saltenv,
|
||||
path,
|
||||
salt.utils.st_mode_to_octal(mode_local),
|
||||
salt.utils.st_mode_to_octal(mode_server)
|
||||
)
|
||||
except OSError as exc:
|
||||
log.warning(
|
||||
'Failed to chmod %s: %s', dest2check, exc
|
||||
)
|
||||
# We may not have been able to check/set the mode, but we
|
||||
# don't want to re-download the file because of a failure
|
||||
# in mode checking. Return the cached path.
|
||||
return dest2check
|
||||
else:
|
||||
log.info(
|
||||
'Fetching file from saltenv \'%s\', ** skipped ** '
|
||||
'latest already in cache \'%s\'', saltenv, path
|
||||
)
|
||||
return dest2check
|
||||
return dest2check
|
||||
|
||||
log.debug(
|
||||
'Fetching file from saltenv \'%s\', ** attempting ** \'%s\'',
|
||||
|
@ -1242,23 +1186,6 @@ class RemoteClient(Client):
|
|||
saltenv, path
|
||||
)
|
||||
|
||||
if not salt.utils.is_windows():
|
||||
if mode_server is not None:
|
||||
try:
|
||||
if os.stat(dest).st_mode != mode_server:
|
||||
try:
|
||||
os.chmod(dest, mode_server)
|
||||
log.info(
|
||||
'Fetching file from saltenv \'%s\', '
|
||||
'** done ** \'%s\', mode set to %s',
|
||||
saltenv,
|
||||
path,
|
||||
salt.utils.st_mode_to_octal(mode_server)
|
||||
)
|
||||
except OSError:
|
||||
log.warning('Failed to chmod %s: %s', dest, exc)
|
||||
except OSError:
|
||||
pass
|
||||
return dest
|
||||
|
||||
def file_list(self, saltenv='base', prefix=''):
|
||||
|
|
|
@ -1669,7 +1669,14 @@ def os_data():
|
|||
continue
|
||||
osrelease_info[idx] = int(value)
|
||||
grains['osrelease_info'] = tuple(osrelease_info)
|
||||
grains['osmajorrelease'] = str(grains['osrelease_info'][0]) # This will be an integer in the two releases
|
||||
try:
|
||||
grains['osmajorrelease'] = int(grains['osrelease_info'][0])
|
||||
except (IndexError, TypeError, ValueError):
|
||||
log.debug(
|
||||
'Unable to derive osmajorrelease from osrelease_info \'%s\'. '
|
||||
'The osmajorrelease grain will not be set.',
|
||||
grains['osrelease_info']
|
||||
)
|
||||
os_name = grains['os' if grains.get('os') in (
|
||||
'FreeBSD', 'OpenBSD', 'NetBSD', 'Mac', 'Raspbian') else 'osfullname']
|
||||
grains['osfinger'] = '{0}-{1}'.format(
|
||||
|
|
|
@ -632,6 +632,28 @@ def hash_file(path, saltenv='base'):
|
|||
return _client().hash_file(path, saltenv)
|
||||
|
||||
|
||||
def stat_file(path, saltenv='base', octal=True):
|
||||
'''
|
||||
Return the permissions of a file, to get the permissions of a file on the
|
||||
salt master file server prepend the path with salt://<file on server>
|
||||
otherwise, prepend the file with / for a local file.
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' cp.stat_file salt://path/to/file
|
||||
'''
|
||||
path, senv = salt.utils.url.split_env(path)
|
||||
if senv:
|
||||
saltenv = senv
|
||||
|
||||
stat = _client().hash_and_stat_file(path, saltenv)[1]
|
||||
if stat is None:
|
||||
return stat
|
||||
return salt.utils.st_mode_to_octal(stat[0]) if octal is True else stat[0]
|
||||
|
||||
|
||||
def push(path, keep_symlinks=False, upload_path=None, remove_source=False):
|
||||
'''
|
||||
WARNING Files pushed to the master will have global read permissions..
|
||||
|
|
|
@ -5240,7 +5240,7 @@ def sls(name, mods=None, saltenv='base', **kwargs):
|
|||
copy_to(name,
|
||||
trans_tar,
|
||||
os.path.join(trans_dest_path, 'salt_state.tgz'),
|
||||
exec_driver='nsenter',
|
||||
exec_driver=_get_exec_driver(),
|
||||
overwrite=True)
|
||||
|
||||
# Now execute the state into the container
|
||||
|
|
|
@ -4395,7 +4395,7 @@ def check_managed_changes(
|
|||
if _urlparse(source).scheme in ('salt', 'file') \
|
||||
or source.startswith('/'):
|
||||
try:
|
||||
mode = salt.utils.st_mode_to_octal(os.stat(sfn).st_mode)
|
||||
mode = __salt__['cp.stat_file'](source, saltenv=saltenv, octal=True)
|
||||
except Exception as exc:
|
||||
log.warning('Unable to stat %s: %s', sfn, exc)
|
||||
changes = check_file_meta(name, sfn, source, source_sum, user,
|
||||
|
@ -4661,6 +4661,13 @@ def manage_file(name,
|
|||
a local file on the minion), the mode of the destination file will be
|
||||
set to the mode of the source file.
|
||||
|
||||
.. note:: keep_mode does not work with salt-ssh.
|
||||
|
||||
As a consequence of how the files are transfered to the minion, and
|
||||
the inability to connect back to the master with salt-ssh, salt is
|
||||
unable to stat the file as it exists on the fileserver and thus
|
||||
cannot mirror the mode on the salt-ssh minion
|
||||
|
||||
encoding : None
|
||||
If None, str() will be applied to contents.
|
||||
If not None, specified encoding will be used.
|
||||
|
@ -4710,7 +4717,7 @@ def manage_file(name,
|
|||
if _urlparse(source).scheme in ('salt', 'file') \
|
||||
or source.startswith('/'):
|
||||
try:
|
||||
mode = salt.utils.st_mode_to_octal(os.stat(sfn).st_mode)
|
||||
mode = __salt__['cp.stat_file'](source, saltenv=saltenv, octal=True)
|
||||
except Exception as exc:
|
||||
log.warning('Unable to stat %s: %s', sfn, exc)
|
||||
|
||||
|
|
|
@ -1,6 +1,17 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Module to interact with Junos devices.
|
||||
|
||||
:maturity: new
|
||||
:dependencies: junos-eznc, jxmlease
|
||||
|
||||
.. note::
|
||||
|
||||
Those who wish to use junos-eznc (PyEZ) version >= 2.1.0, must
|
||||
use the latest salt code from github until the next release.
|
||||
|
||||
Refer to :mod:`junos <salt.proxy.junos>` for information on connecting to junos proxy.
|
||||
|
||||
'''
|
||||
from __future__ import absolute_import
|
||||
|
||||
|
@ -19,6 +30,7 @@ except ImportError:
|
|||
try:
|
||||
# pylint: disable=W0611
|
||||
from jnpr.junos import Device
|
||||
from jnpr.junos.utils.config import Config
|
||||
from jnpr.junos.utils.sw import SW
|
||||
from jnpr.junos.utils.scp import SCP
|
||||
import jnpr.junos.utils
|
||||
|
@ -394,7 +406,7 @@ def commit(**kwargs):
|
|||
|
||||
def rollback(id=0, **kwargs):
|
||||
'''
|
||||
To rollback the last committed configuration changes
|
||||
To rollback the last committed configuration changes and commit the same.
|
||||
|
||||
Usage:
|
||||
|
||||
|
@ -471,7 +483,7 @@ def rollback(id=0, **kwargs):
|
|||
ret['out'] = False
|
||||
ret['message'] = \
|
||||
'Rollback successful but commit failed with error "{0}"'\
|
||||
.format(exception)
|
||||
.format(exception)
|
||||
return ret
|
||||
else:
|
||||
ret['message'] = 'Rollback succesfull but pre-commit check failed.'
|
||||
|
@ -757,6 +769,8 @@ def install_config(path=None, **kwargs):
|
|||
the content is treated as Junos OS 'set' commands.(default = None)
|
||||
Optional
|
||||
* kwargs: Keyworded arguments which can be provided like-
|
||||
* mode: The mode in which the configuration is locked.
|
||||
(Options: private, dynamic, batch, exclusive; default= exclusive)
|
||||
* dev_timeout:
|
||||
Set NETCONF RPC timeout. Can be used for commands which
|
||||
take a while to execute. (default = 30 seconds)
|
||||
|
@ -767,6 +781,17 @@ def install_config(path=None, **kwargs):
|
|||
Specify whether the configuration file uses "replace:" statements.
|
||||
Those statements under the 'replace' tag will only be changed.\
|
||||
(default = False)
|
||||
* format:
|
||||
Determines the format of the contents.
|
||||
* update:
|
||||
Compare a complete loaded configuration against
|
||||
the candidate configuration. For each hierarchy level or
|
||||
configuration object that is different in the two configurations,
|
||||
the version in the loaded configuration replaces the version in the
|
||||
candidate configuration. When the configuration is later committed,
|
||||
only system processes that are affected by the changed configuration
|
||||
elements parse the new configuration. This action is supported from
|
||||
PyEZ 2.1 (default = False)
|
||||
* comment:
|
||||
Provide a comment to the commit. (default = None)
|
||||
* confirm:
|
||||
|
@ -850,64 +875,66 @@ def install_config(path=None, **kwargs):
|
|||
op['merge'] = True
|
||||
del op['overwrite']
|
||||
|
||||
try:
|
||||
conn.cu.load(**op)
|
||||
|
||||
except Exception as exception:
|
||||
ret['message'] = 'Could not load configuration due to : "{0}"'.format(
|
||||
exception)
|
||||
ret['format'] = template_format
|
||||
ret['out'] = False
|
||||
return ret
|
||||
|
||||
finally:
|
||||
safe_rm(template_cached_path)
|
||||
|
||||
config_diff = conn.cu.diff()
|
||||
if config_diff is None:
|
||||
ret['message'] = 'Configuration already applied!'
|
||||
ret['out'] = True
|
||||
return ret
|
||||
|
||||
commit_params = {}
|
||||
if 'confirm' in op:
|
||||
commit_params['confirm'] = op['confirm']
|
||||
if 'comment' in op:
|
||||
commit_params['comment'] = op['comment']
|
||||
|
||||
try:
|
||||
check = conn.cu.commit_check()
|
||||
except Exception as exception:
|
||||
ret['message'] = \
|
||||
'Commit check threw the following exception: "{0}"'\
|
||||
.format(exception)
|
||||
|
||||
ret['out'] = False
|
||||
return ret
|
||||
|
||||
if check:
|
||||
db_mode = op.pop('mode', 'exclusive')
|
||||
with Config(conn, mode=db_mode) as cu:
|
||||
try:
|
||||
conn.cu.commit(**commit_params)
|
||||
ret['message'] = 'Successfully loaded and committed!'
|
||||
cu.load(**op)
|
||||
|
||||
except Exception as exception:
|
||||
ret['message'] = \
|
||||
'Commit check successful but commit failed with "{0}"'\
|
||||
.format(exception)
|
||||
ret['message'] = 'Could not load configuration due to : "{0}"'.format(
|
||||
exception)
|
||||
ret['format'] = template_format
|
||||
ret['out'] = False
|
||||
return ret
|
||||
else:
|
||||
ret['message'] = 'Loaded configuration but commit check failed.'
|
||||
ret['out'] = False
|
||||
conn.cu.rollback()
|
||||
|
||||
try:
|
||||
if write_diff and config_diff is not None:
|
||||
with fopen(write_diff, 'w') as fp:
|
||||
fp.write(config_diff)
|
||||
except Exception as exception:
|
||||
ret['message'] = 'Could not write into diffs_file due to: "{0}"'.format(
|
||||
exception)
|
||||
ret['out'] = False
|
||||
finally:
|
||||
safe_rm(template_cached_path)
|
||||
|
||||
config_diff = cu.diff()
|
||||
if config_diff is None:
|
||||
ret['message'] = 'Configuration already applied!'
|
||||
ret['out'] = True
|
||||
return ret
|
||||
|
||||
commit_params = {}
|
||||
if 'confirm' in op:
|
||||
commit_params['confirm'] = op['confirm']
|
||||
if 'comment' in op:
|
||||
commit_params['comment'] = op['comment']
|
||||
|
||||
try:
|
||||
check = cu.commit_check()
|
||||
except Exception as exception:
|
||||
ret['message'] = \
|
||||
'Commit check threw the following exception: "{0}"'\
|
||||
.format(exception)
|
||||
|
||||
ret['out'] = False
|
||||
return ret
|
||||
|
||||
if check:
|
||||
try:
|
||||
cu.commit(**commit_params)
|
||||
ret['message'] = 'Successfully loaded and committed!'
|
||||
except Exception as exception:
|
||||
ret['message'] = \
|
||||
'Commit check successful but commit failed with "{0}"'\
|
||||
.format(exception)
|
||||
ret['out'] = False
|
||||
return ret
|
||||
else:
|
||||
ret['message'] = 'Loaded configuration but commit check failed.'
|
||||
ret['out'] = False
|
||||
cu.rollback()
|
||||
|
||||
try:
|
||||
if write_diff and config_diff is not None:
|
||||
with fopen(write_diff, 'w') as fp:
|
||||
fp.write(config_diff)
|
||||
except Exception as exception:
|
||||
ret['message'] = 'Could not write into diffs_file due to: "{0}"'.format(
|
||||
exception)
|
||||
ret['out'] = False
|
||||
|
||||
return ret
|
||||
|
||||
|
@ -1070,3 +1097,212 @@ def file_copy(src=None, dest=None):
|
|||
ret['message'] = 'Could not copy file : "{0}"'.format(exception)
|
||||
ret['out'] = False
|
||||
return ret
|
||||
|
||||
|
||||
def lock():
|
||||
"""
|
||||
Attempts an exclusive lock on the candidate configuration. This
|
||||
is a non-blocking call.
|
||||
|
||||
.. note::
|
||||
Any user who wishes to use lock, must necessarily unlock the
|
||||
configuration too. Ensure :py:func:`unlock <salt.modules.junos.unlock>`
|
||||
is called in the same orchestration run in which the lock is called.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'device_name' junos.lock
|
||||
|
||||
"""
|
||||
conn = __proxy__['junos.conn']()
|
||||
ret = dict()
|
||||
ret['out'] = True
|
||||
try:
|
||||
conn.cu.lock()
|
||||
ret['message'] = "Successfully locked the configuration."
|
||||
except jnpr.junos.exception.LockError as exception:
|
||||
ret['message'] = 'Could not gain lock due to : "{0}"'.format(exception)
|
||||
ret['out'] = False
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def unlock():
|
||||
"""
|
||||
Unlocks the candidate configuration.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'device_name' junos.unlock
|
||||
|
||||
"""
|
||||
conn = __proxy__['junos.conn']()
|
||||
ret = dict()
|
||||
ret['out'] = True
|
||||
try:
|
||||
conn.cu.unlock()
|
||||
ret['message'] = "Successfully unlocked the configuration."
|
||||
except jnpr.junos.exception.UnlockError as exception:
|
||||
ret['message'] = \
|
||||
'Could not unlock configuration due to : "{0}"'.format(exception)
|
||||
ret['out'] = False
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def load(path=None, **kwargs):
|
||||
"""
|
||||
|
||||
Loads the configuration from the file provided onto the device.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'device_name' junos.load 'salt://production/network/routers/config.set'
|
||||
|
||||
salt 'device_name' junos.load 'salt://templates/replace_config.conf' replace=True
|
||||
|
||||
salt 'device_name' junos.load 'salt://my_new_configuration.conf' overwrite=True
|
||||
|
||||
salt 'device_name' junos.load 'salt://syslog_template.conf' template_vars='{"syslog_host": "10.180.222.7"}'
|
||||
|
||||
Parameters:
|
||||
Required
|
||||
* path:
|
||||
Path where the configuration/template file is present. If the file has a \
|
||||
'*.conf' extension,
|
||||
the content is treated as text format. If the file has a '*.xml' \
|
||||
extension,
|
||||
the content is treated as XML format. If the file has a '*.set' \
|
||||
extension,
|
||||
the content is treated as Junos OS 'set' commands.(default = None)
|
||||
Optional
|
||||
* kwargs: Keyworded arguments which can be provided like-
|
||||
* overwrite:
|
||||
Set to True if you want this file is to completely replace the\
|
||||
configuration file. (default = False)
|
||||
* replace:
|
||||
Specify whether the configuration file uses "replace:" statements.
|
||||
Those statements under the 'replace' tag will only be changed.\
|
||||
(default = False)
|
||||
* format:
|
||||
Determines the format of the contents.
|
||||
* update:
|
||||
Compare a complete loaded configuration against
|
||||
the candidate configuration. For each hierarchy level or
|
||||
configuration object that is different in the two configurations,
|
||||
the version in the loaded configuration replaces the version in the
|
||||
candidate configuration. When the configuration is later committed,
|
||||
only system processes that are affected by the changed configuration
|
||||
elements parse the new configuration. This action is supported from
|
||||
PyEZ 2.1 (default = False)
|
||||
* template_vars:
|
||||
Variables to be passed into the template processing engine in addition
|
||||
to those present in __pillar__, __opts__, __grains__, etc.
|
||||
You may reference these variables in your template like so:
|
||||
{{ template_vars["var_name"] }}
|
||||
|
||||
|
||||
"""
|
||||
conn = __proxy__['junos.conn']()
|
||||
ret = dict()
|
||||
ret['out'] = True
|
||||
|
||||
if path is None:
|
||||
ret['message'] = \
|
||||
'Please provide the salt path where the configuration is present'
|
||||
ret['out'] = False
|
||||
return ret
|
||||
|
||||
op = dict()
|
||||
if '__pub_arg' in kwargs:
|
||||
if kwargs['__pub_arg']:
|
||||
if isinstance(kwargs['__pub_arg'][-1], dict):
|
||||
op.update(kwargs['__pub_arg'][-1])
|
||||
else:
|
||||
op.update(kwargs)
|
||||
|
||||
template_vars = dict()
|
||||
if "template_vars" in op:
|
||||
template_vars = op["template_vars"]
|
||||
|
||||
template_cached_path = files.mkstemp()
|
||||
__salt__['cp.get_template'](
|
||||
path,
|
||||
template_cached_path,
|
||||
template_vars=template_vars)
|
||||
|
||||
if not os.path.isfile(template_cached_path):
|
||||
ret['message'] = 'Invalid file path.'
|
||||
ret['out'] = False
|
||||
return ret
|
||||
|
||||
if os.path.getsize(template_cached_path) == 0:
|
||||
ret['message'] = 'Template failed to render'
|
||||
ret['out'] = False
|
||||
return ret
|
||||
|
||||
op['path'] = template_cached_path
|
||||
|
||||
if 'format' not in op:
|
||||
if path.endswith('set'):
|
||||
template_format = 'set'
|
||||
elif path.endswith('xml'):
|
||||
template_format = 'xml'
|
||||
else:
|
||||
template_format = 'text'
|
||||
|
||||
op['format'] = template_format
|
||||
|
||||
if 'replace' in op and op['replace']:
|
||||
op['merge'] = False
|
||||
del op['replace']
|
||||
elif 'overwrite' in op and op['overwrite']:
|
||||
op['overwrite'] = True
|
||||
elif 'overwrite' in op and not op['overwrite']:
|
||||
op['merge'] = True
|
||||
del op['overwrite']
|
||||
|
||||
try:
|
||||
conn.cu.load(**op)
|
||||
ret['message'] = "Successfully loaded the configuration."
|
||||
except Exception as exception:
|
||||
ret['message'] = 'Could not load configuration due to : "{0}"'.format(
|
||||
exception)
|
||||
ret['format'] = template_format
|
||||
ret['out'] = False
|
||||
return ret
|
||||
finally:
|
||||
safe_rm(template_cached_path)
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def commit_check():
|
||||
"""
|
||||
|
||||
Perform a commit check on the configuration.
|
||||
|
||||
Usage:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'device_name' junos.commit_check
|
||||
|
||||
"""
|
||||
conn = __proxy__['junos.conn']()
|
||||
ret = dict()
|
||||
ret['out'] = True
|
||||
try:
|
||||
conn.cu.commit_check()
|
||||
ret['message'] = 'Commit check succeeded.'
|
||||
except Exception as exception:
|
||||
ret['message'] = 'Commit check failed with {0}'.format(exception)
|
||||
ret['out'] = False
|
||||
|
||||
return ret
|
||||
|
|
|
@ -113,6 +113,20 @@ class NetapiClient(object):
|
|||
local = salt.client.get_local_client(mopts=self.opts)
|
||||
return local.cmd_subset(*args, **kwargs)
|
||||
|
||||
def local_batch(self, *args, **kwargs):
|
||||
'''
|
||||
Run :ref:`execution modules <all-salt.modules>` against batches of minions
|
||||
|
||||
.. versionadded:: 0.8.4
|
||||
|
||||
Wraps :py:meth:`salt.client.LocalClient.cmd_batch`
|
||||
|
||||
:return: Returns the result from the exeuction module for each batch of
|
||||
returns
|
||||
'''
|
||||
local = salt.client.get_local_client(mopts=self.opts)
|
||||
return local.cmd_batch(*args, **kwargs)
|
||||
|
||||
def ssh(self, *args, **kwargs):
|
||||
'''
|
||||
Run salt-ssh commands synchronously
|
||||
|
|
|
@ -1735,6 +1735,13 @@ def managed(name,
|
|||
the ``contents`` options, setting the ``mode`` to ``keep`` is also
|
||||
incompatible with the ``contents`` options.
|
||||
|
||||
.. note:: keep does not work with salt-ssh.
|
||||
|
||||
As a consequence of how the files are transfered to the minion, and
|
||||
the inability to connect back to the master with salt-ssh, salt is
|
||||
unable to stat the file as it exists on the fileserver and thus
|
||||
cannot mirror the mode on the salt-ssh minion
|
||||
|
||||
template
|
||||
If this setting is applied, the named templating engine will be used to
|
||||
render the downloaded file. The following templates are supported:
|
||||
|
|
|
@ -3,7 +3,14 @@
|
|||
State modules to interact with Junos devices.
|
||||
==============================================
|
||||
|
||||
State module to connect the junos devices connected via a junos proxy.
|
||||
:maturity: new
|
||||
:dependencies: junos-eznc, jxmlease
|
||||
|
||||
.. note::
|
||||
|
||||
Those who wish to use junos-eznc (PyEZ) version >= 2.1.0, must
|
||||
use the latest salt code from github until the next release.
|
||||
|
||||
Refer to :mod:`junos <salt.proxy.junos>` for information on connecting to junos proxy.
|
||||
'''
|
||||
from __future__ import absolute_import
|
||||
|
@ -281,8 +288,8 @@ def install_config(name, **kwargs):
|
|||
|
||||
Parameters:
|
||||
Required
|
||||
* path or template_path (Either one of the keyword must be there):
|
||||
Path where the configuration file is present. If the file has a \
|
||||
* name:
|
||||
Path where the configuration/template file is present. If the file has a \
|
||||
'*.conf' extension,
|
||||
the content is treated as text format. If the file has a '*.xml' \
|
||||
extension,
|
||||
|
@ -291,8 +298,6 @@ def install_config(name, **kwargs):
|
|||
the content is treated as Junos OS 'set' commands.(default = None)
|
||||
Optional
|
||||
* kwargs: Keyworded arguments which can be provided like-
|
||||
* template_path:
|
||||
Path where the jinja template is present on the master.
|
||||
* template_vars:
|
||||
The dictionary of data for the jinja variables present in the \
|
||||
jinja template
|
||||
|
@ -396,3 +401,119 @@ def file_copy(name, dest=None, **kwargs):
|
|||
ret = {'name': name, 'changes': {}, 'result': True, 'comment': ''}
|
||||
ret['changes'] = __salt__['junos.file_copy'](name, dest, **kwargs)
|
||||
return ret
|
||||
|
||||
|
||||
def lock(name):
|
||||
"""
|
||||
Attempts an exclusive lock on the candidate configuration. This
|
||||
is a non-blocking call.
|
||||
|
||||
.. note::
|
||||
Any user who wishes to use lock, must necessarily unlock the
|
||||
configuration too. Ensure :py:func:`unlock <salt.states.junos.unlock>`
|
||||
is called in the same orchestration run in which the lock is called.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
lock the config:
|
||||
junos.lock
|
||||
|
||||
"""
|
||||
ret = {'name': name, 'changes': {}, 'result': True, 'comment': ''}
|
||||
ret['changes'] = __salt__['junos.lock']()
|
||||
return ret
|
||||
|
||||
|
||||
def unlock(name):
|
||||
"""
|
||||
Unlocks the candidate configuration.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
unlock the config:
|
||||
junos.unlock
|
||||
|
||||
"""
|
||||
ret = {'name': name, 'changes': {}, 'result': True, 'comment': ''}
|
||||
ret['changes'] = __salt__['junos.unlock']()
|
||||
return ret
|
||||
|
||||
|
||||
def load(name, **kwargs):
|
||||
"""
|
||||
Loads the configuration provided onto the junos device.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
Install the mentioned config:
|
||||
junos:
|
||||
- load
|
||||
- path: salt//configs/interface.set
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
Install the mentioned config:
|
||||
junos:
|
||||
- load
|
||||
- template_path: salt//configs/interface.set
|
||||
- template_vars:
|
||||
interface_name: lo0
|
||||
description: Creating interface via SaltStack.
|
||||
|
||||
|
||||
Parameters:
|
||||
Required
|
||||
* name:
|
||||
Path where the configuration/template file is present. If the file has a \
|
||||
'*.conf' extension,
|
||||
the content is treated as text format. If the file has a '*.xml' \
|
||||
extension,
|
||||
the content is treated as XML format. If the file has a '*.set' \
|
||||
extension,
|
||||
the content is treated as Junos OS 'set' commands.(default = None)
|
||||
Optional
|
||||
* kwargs: Keyworded arguments which can be provided like-
|
||||
* overwrite:
|
||||
Set to True if you want this file is to completely replace the\
|
||||
configuration file. (default = False)
|
||||
* replace:
|
||||
Specify whether the configuration file uses "replace:" statements.
|
||||
Those statements under the 'replace' tag will only be changed.\
|
||||
(default = False)
|
||||
* format:
|
||||
Determines the format of the contents.
|
||||
* update:
|
||||
Compare a complete loaded configuration against
|
||||
the candidate configuration. For each hierarchy level or
|
||||
configuration object that is different in the two configurations,
|
||||
the version in the loaded configuration replaces the version in the
|
||||
candidate configuration. When the configuration is later committed,
|
||||
only system processes that are affected by the changed configuration
|
||||
elements parse the new configuration. This action is supported from
|
||||
PyEZ 2.1 (default = False)
|
||||
* template_vars:
|
||||
Variables to be passed into the template processing engine in addition
|
||||
to those present in __pillar__, __opts__, __grains__, etc.
|
||||
You may reference these variables in your template like so:
|
||||
{{ template_vars["var_name"] }}
|
||||
|
||||
"""
|
||||
ret = {'name': name, 'changes': {}, 'result': True, 'comment': ''}
|
||||
ret['changes'] = __salt__['junos.load'](name, **kwargs)
|
||||
return ret
|
||||
|
||||
|
||||
def commit_check(name):
|
||||
"""
|
||||
|
||||
Perform a commit check on the configuration.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
perform commit check:
|
||||
junos.commit_check
|
||||
|
||||
"""
|
||||
ret = {'name': name, 'changes': {}, 'result': True, 'comment': ''}
|
||||
ret['changes'] = __salt__['junos.commit_check']()
|
||||
return ret
|
||||
|
|
|
@ -408,7 +408,14 @@ class AsyncTCPPubChannel(salt.transport.mixins.auth.AESPubClientMixin, salt.tran
|
|||
raise tornado.gen.Return(True)
|
||||
|
||||
if force_auth or not self.auth.authenticated:
|
||||
yield self.auth.authenticate()
|
||||
count = 0
|
||||
while count <= self.opts['tcp_authentication_retries'] or self.opts['tcp_authentication_retries'] < 0:
|
||||
try:
|
||||
yield self.auth.authenticate()
|
||||
break
|
||||
except SaltClientError as exc:
|
||||
log.debug(exc)
|
||||
count += 1
|
||||
try:
|
||||
ret = yield _do_transfer()
|
||||
raise tornado.gen.Return(ret)
|
||||
|
|
|
@ -1153,7 +1153,7 @@ class GitPython(GitProvider):
|
|||
'''
|
||||
Using the blob object, write the file to the destination path
|
||||
'''
|
||||
with salt.utils.fopen(dest, 'w+') as fp_:
|
||||
with salt.utils.fopen(dest, 'wb+') as fp_:
|
||||
blob.stream_data(fp_)
|
||||
|
||||
|
||||
|
@ -1819,7 +1819,7 @@ class Pygit2(GitProvider):
|
|||
'''
|
||||
Using the blob object, write the file to the destination path
|
||||
'''
|
||||
with salt.utils.fopen(dest, 'w+') as fp_:
|
||||
with salt.utils.fopen(dest, 'wb+') as fp_:
|
||||
fp_.write(blob.data)
|
||||
|
||||
|
||||
|
|
|
@ -207,7 +207,8 @@ class CkMinions(object):
|
|||
'''
|
||||
if isinstance(expr, six.string_types):
|
||||
expr = [m for m in expr.split(',') if m]
|
||||
return [x for x in expr if x in self._pki_minions()]
|
||||
minions = self._pki_minions()
|
||||
return [x for x in expr if x in minions]
|
||||
|
||||
def _check_pcre_minions(self, expr, greedy): # pylint: disable=unused-argument
|
||||
'''
|
||||
|
|
|
@ -30,6 +30,9 @@ import signal
|
|||
import select
|
||||
import logging
|
||||
|
||||
# Import salt libs
|
||||
from salt.ext import six
|
||||
|
||||
mswindows = (sys.platform == "win32")
|
||||
|
||||
try:
|
||||
|
@ -566,7 +569,10 @@ class Terminal(object):
|
|||
try:
|
||||
if self.stdin_logger:
|
||||
self.stdin_logger.log(self.stdin_logger_level, data)
|
||||
written = os.write(self.child_fd, data)
|
||||
if six.PY3:
|
||||
written = os.write(self.child_fd, data.encode(__salt_system_encoding__))
|
||||
else:
|
||||
written = os.write(self.child_fd, data)
|
||||
except OSError as why:
|
||||
if why.errno == errno.EPIPE: # broken pipe
|
||||
os.close(self.child_fd)
|
||||
|
|
|
@ -262,7 +262,7 @@ PATCHLEVEL = 3
|
|||
'osfullname': "SLES",
|
||||
'osrelease': '11.3',
|
||||
'osrelease_info': [11, 3],
|
||||
'osmajorrelease': '11',
|
||||
'osmajorrelease': 11,
|
||||
'files': ["/etc/SuSE-release"],
|
||||
}
|
||||
self._run_suse_os_grains_tests(_os_release_map)
|
||||
|
@ -286,7 +286,7 @@ PATCHLEVEL = 3
|
|||
'osfullname': "SLES",
|
||||
'osrelease': '11.4',
|
||||
'osrelease_info': [11, 4],
|
||||
'osmajorrelease': '11',
|
||||
'osmajorrelease': 11,
|
||||
'files': ["/etc/os-release"],
|
||||
}
|
||||
self._run_suse_os_grains_tests(_os_release_map)
|
||||
|
@ -310,7 +310,7 @@ PATCHLEVEL = 3
|
|||
'osfullname': "SLES",
|
||||
'osrelease': '12',
|
||||
'osrelease_info': [12],
|
||||
'osmajorrelease': '12',
|
||||
'osmajorrelease': 12,
|
||||
'files': ["/etc/os-release"],
|
||||
}
|
||||
self._run_suse_os_grains_tests(_os_release_map)
|
||||
|
@ -334,7 +334,7 @@ PATCHLEVEL = 3
|
|||
'osfullname': "SLES",
|
||||
'osrelease': '12.1',
|
||||
'osrelease_info': [12, 1],
|
||||
'osmajorrelease': '12',
|
||||
'osmajorrelease': 12,
|
||||
'files': ["/etc/os-release"],
|
||||
}
|
||||
self._run_suse_os_grains_tests(_os_release_map)
|
||||
|
@ -358,7 +358,7 @@ PATCHLEVEL = 3
|
|||
'osfullname': "Leap",
|
||||
'osrelease': '42.1',
|
||||
'osrelease_info': [42, 1],
|
||||
'osmajorrelease': '42',
|
||||
'osmajorrelease': 42,
|
||||
'files': ["/etc/os-release"],
|
||||
}
|
||||
self._run_suse_os_grains_tests(_os_release_map)
|
||||
|
@ -382,7 +382,7 @@ PATCHLEVEL = 3
|
|||
'osfullname': "Tumbleweed",
|
||||
'osrelease': '20160504',
|
||||
'osrelease_info': [20160504],
|
||||
'osmajorrelease': '20160504',
|
||||
'osmajorrelease': 20160504,
|
||||
'files': ["/etc/os-release"],
|
||||
}
|
||||
self._run_suse_os_grains_tests(_os_release_map)
|
||||
|
@ -404,7 +404,7 @@ PATCHLEVEL = 3
|
|||
'osfullname': 'Ubuntu',
|
||||
'osrelease': '16.04',
|
||||
'osrelease_info': [16, 4],
|
||||
'osmajorrelease': '16',
|
||||
'osmajorrelease': 16,
|
||||
'osfinger': 'Ubuntu-16.04',
|
||||
}
|
||||
self._run_ubuntu_os_grains_tests(_os_release_map)
|
||||
|
|
Loading…
Add table
Reference in a new issue