Merge branch '2015.8' into 'develop'

Conflicts:
  - doc/ref/states/all/index.rst
  - salt/cloud/__init__.py
  - salt/minion.py
  - salt/modules/file.py
  - salt/modules/guestfs.py
  - salt/modules/ipmi.py
  - salt/modules/osquery.py
  - salt/modules/parted.py
  - salt/modules/seed.py
  - salt/modules/virt.py
  - salt/modules/yumpkg.py
  - salt/modules/zypper.py
  - salt/states/boto_elb.py
  - salt/states/pkg.py
This commit is contained in:
rallytime 2016-01-26 16:19:39 -07:00
commit 4fa80f2d5e
48 changed files with 1418 additions and 359 deletions

View file

@ -409,7 +409,7 @@ epub_publisher = epub_author
epub_copyright = copyright
epub_scheme = 'URL'
epub_identifier = 'http://saltstack.org/'
epub_identifier = 'http://saltstack.com/'
#epub_tocdepth = 3

View file

@ -35,3 +35,4 @@ Reference
engines/all/index
sdb/all/index
serializers/all/index
queues/all/index

View file

@ -1,4 +1,4 @@
.. _all-salt.modules:
.. _all-salt_modules:
======================================
Full list of builtin execution modules
@ -260,7 +260,6 @@ Full list of builtin execution modules
redismod
reg
rest_package
rest_sample
rest_service
restartcheck
ret

View file

@ -1,6 +0,0 @@
========================
salt.modules.rest_sample
========================
.. automodule:: salt.modules.rest_sample
:members:

View file

@ -1,6 +0,0 @@
===============================
salt.modules.system_rest_sample
===============================
.. automodule:: salt.modules.system_rest_sample
:members:

View file

@ -0,0 +1,13 @@
.. _all-salt.queues:
===========================
Full list of builtin queues
===========================
.. currentmodule:: salt.queues
.. autosummary::
:toctree:
:template: autosummary.rst.tmpl
sqlite_queue

View file

@ -76,6 +76,7 @@ Full list of builtin state modules
gem
git
github
glance
glusterfs
gnomedesktop
gpg

View file

@ -60,13 +60,13 @@ Google Compute Engine Setup
#. Key Format
*If you are using ``libcloud >= 0.17.0`` it is recommended that you use the ``JSON
format`` file you downloaded above and skip to the `Provider Configuration`_ section
below, using the JSON file **_in place of 'NEW.pem'_** in the documentation.
If you are using an older version of libcloud or are unsure of the version you
have, please follow the instructions below to generate and format a new P12 key.*
.. note:: If you are using ``libcloud >= 0.17.0`` it is recommended that you use the ``JSON
format`` file you downloaded above and skip to the `Provider Configuration`_ section
below, using the JSON file **in place of 'NEW.pem'** in the documentation.
If you are using an older version of libcloud or are unsure of the version you
have, please follow the instructions below to generate and format a new P12 key.
In the new *Service Account* section, click *Generate new P12 key*, which
will automatically download a ``.p12`` private key file. The ``.p12``
private key needs to be converted to a format compatible with libcloud.

View file

@ -9,12 +9,28 @@ command authorization to any external authentication system, such as PAM or LDAP
.. note::
eAuth using the PAM external auth system requires salt-master to be run as
eAuth using the PAM external auth system requires salt-master to be run as
root as this system needs root access to check authentication.
Access Control System
---------------------
.. note:: When to Use ``client_acl`` and ``external_auth``
``client_acl`` is useful for allowing local system users to run Salt
commands without giving them root access. If you can log into the Salt
master directly, then ``client_acl`` will allow you to use Salt without
root privileges. If the local system is configured to authenticate against
a remote system, like LDAP or Active Directory, then ``client_acl`` will
interact with the remote system transparently.
``external_auth`` is useful for ``salt-api`` or for making your own scripts
that use Salt's Python API. It can be used at the CLI (with the ``-a``
flag) but it is more cumbersome as there are more steps involved. The only
time it is useful at the CLI is when the local system is *not* configured
to authenticate against an external service *but* you still want Salt to
authenticate against an external service.
The external authentication system allows for specific users to be granted
access to execute specific functions on specific minions. Access is configured
in the master configuration file and uses the :ref:`access control system

View file

@ -0,0 +1,5 @@
==========================================
Salt 2015.5.10 Release Notes (In Progress)
==========================================
In progress, not yet released.

View file

@ -21,3 +21,900 @@ Core Changes
salt '*' state.apply edit.vim mock=True
.. _`#28994`: https://github.com/saltstack/salt/pull/28994
Changes for v2015.8.3..v2015.8.4
--------------------------------
Extended changelog courtesy of Todd Stansell (https://github.com/tjstansell/salt-changelogs):
*Generated at: 2016-01-25T17:48:35Z*
Total Merges: **320**
Changes:
- **PR** `#30613`_: (*basepi*) Fix minion/syndic clearfuncs
- **PR** `#30609`_: (*seanjnkns*) Fix documentation for pillar_merge_lists which default is False, not …
- **PR** `#30584`_: (*julianbrost*) file.line state: add missing colon in docstring
- **PR** `#30589`_: (*terminalmage*) Merge 2015.5 into 2015.8
- **PR** `#30599`_: (*multani*) Documentation formatting fixes
- **PR** `#30554`_: (*rallytime*) Make the salt-cloud actions output more verbose and helpful
- **PR** `#30549`_: (*techhat*) Salt Virt cleanup
- **PR** `#30553`_: (*techhat*) AWS: Support 17-character IDs
- **PR** `#30532`_: (*whiteinge*) Add execution module for working in sls files
- **PR** `#30529`_: (*terminalmage*) Merge 2015.5 into 2015.8
- **PR** `#30526`_: (*twangboy*) Added FlushKey to make sure it's changes are saved to disk
- **PR** `#30521`_: (*basepi*) [2015.8] Merge forward from 2015.5 to 2015.8
- **PR** `#30485`_: (*jtand*) Updated pip_state to work with pip 8.0 on 2015.8
- **PR** `#30494`_: (*isbm*) Zypper: info_installed — 'errors' flag change to type 'boolean'
- **PR** `#30506`_: (*jacksontj*) Properly remove newlines after reading the file
- **PR** `#30508`_: (*rallytime*) Fix Linode driver cloning functionality
- **PR** `#30522`_: (*terminalmage*) Update git.list_worktree tests to reflect new return data
- **PR** `#30483`_: (*borgstrom*) Pyobjects recursive import support (for 2015.8)
- **PR** `#30491`_: (*jacksontj*) Add multi-IP support to network state
- **PR** `#30496`_: (*anlutro*) Fix KeyError when adding ignored pillars
- **PR** `#30359`_: (*kingsquirrel152*) Removes suspected copy/paste error for zmq_filtering functionailty
- **PR** `#30448`_: (*cournape*) Fix osx scripts location
- **PR** `#30457`_: (*rallytime*) Remove fsutils references from modules list
- **PR** `#30453`_: (*rallytime*) Make sure private AND public IPs are listed for Linode driver
- **PR** `#30458`_: (*rallytime*) Back-port `#30062`_ to 2015.8
- **PR** `#30468`_: (*timcharper*) make note of s3 role assumption in upcoming changelog
- **PR** `#30470`_: (*whiteinge*) Add example of the match_dict format to accept_dict wheel function
- **PR** `#30450`_: (*gtmanfred*) fix extension loading in novaclient
- **PR** `#30212`_: (*abednarik*) Fix incorrect file permissions in file.line
- **PR** `#29947`_: (*jfindlay*) fileclient: decode file list from master
- **PR** `#30363`_: (*terminalmage*) Use native "list" subcommand to list git worktrees
- **PR** `#30445`_: (*jtand*) Boto uses False for is_default instead of None
- **PR** `#30406`_: (*frioux*) Add an example of how to use file.managed/check_cmd
- **PR** `#30424`_: (*isbm*) Check if byte strings are properly encoded in UTF-8
- **PR** `#30405`_: (*jtand*) Updated glusterfs.py for python2.6 compatibility.
- **PR** `#30396`_: (*pass-by-value*) Remove hardcoded val
- **PR** `#30391`_: (*jtand*) Added else statements
- **PR** `#30375`_: (*rallytime*) Wrap formatted log statements with six.u() in cloud/__init__.py
- **PR** `#30384`_: (*isbm*) Bugfix: info_available does not work correctly on SLE 11 series
- **PR** `#30376`_: (*pritambaral*) Fix FLO_DIR path in 2015.8
- **PR** `#30389`_: (*jtand*) Older versions of ipset don't support comments
- **PR** `#30373`_: (*basepi*) [2015.8] Merge forward from 2015.5 to 2015.8
- **PR** `#30372`_: (*jacobhammons*) Updated man pages for 2015.8.4, updated copyright to 2016
- **PR** `#30370`_: (*rallytime*) Remove incomplete function
- **PR** `#30366`_: (*rallytime*) Back-port `#28702`_ to 2015.8
- **PR** `#30361`_: (*cro*) Flip the sense of the test for proxymodule imports, add more fns for esxi proxy
- **PR** `#30267`_: (*isbm*) Fix RPM issues with the date/time and add package attributes filtering
- **PR** `#30360`_: (*jfindlay*) file.remove, file.absent: mention recursive dir removal
- **PR** `#30221`_: (*mbarrien*) No rolcatupdate for user_exist in Postgres>=9.5 `#26845`_
- **PR** `#30358`_: (*terminalmage*) Add libgit2 version to versions-report
- **PR** `#30346`_: (*pass-by-value*) Prevent orphaned volumes
- **PR** `#30349`_: (*rallytime*) Back-port `#30347`_ to 2015.8
- **PR** `#30354`_: (*anlutro*) Make sure all ignore_missing SLSes are catched
- **PR** `#30356`_: (*nmadhok*) Adding code author
- **PR** `#30340`_: (*jtand*) Updated seed_test.py for changes made to seed module
- **PR** `#30339`_: (*jfindlay*) Backport `#26511`_
- **PR** `#30343`_: (*rallytime*) Fix 2015.8 from incomplete back-port
- **PR** `#30342`_: (*eliasp*) Correct whitespace placement in error message
- **PR** `#30308`_: (*rallytime*) Back-port `#30257`_ to 2015.8
- **PR** `#30187`_: (*rallytime*) Back-port `#27606`_ to 2015.8
- **PR** `#30223`_: (*serge-p*) adding support for DragonFly BSD
- **PR** `#30238`_: (*rallytime*) Reinit crypto before calling RSA.generate when generating keys.
- **PR** `#30246`_: (*dmacvicar*) Add missing return data to scheduled jobs (`#24237`_)
- **PR** `#30292`_: (*thegoodduke*) ipset: fix test=true & add comment for every entry
- **PR** `#30275`_: (*abednarik*) Add permanent argument in firewalld.
- **PR** `#30328`_: (*cachedout*) Fix file test
- **PR** `#30310`_: (*pass-by-value*) Empty bucket fix
- **PR** `#30211`_: (*techhat*) Execute choot on the correct path
- **PR** `#30309`_: (*rallytime*) Back-port `#30304`_ to 2015.8
- **PR** `#30278`_: (*nmadhok*) If datacenter is specified in the config, then look for managed objects under it
- **PR** `#30305`_: (*jacobhammons*) Changed examples to use the "example.com" domain instead of "mycompan…
- **PR** `#30249`_: (*mpreziuso*) Fixes performance and timeout issues on win_pkg.install
- **PR** `#30217`_: (*pass-by-value*) Make sure cloud actions can be called via salt run
- **PR** `#30268`_: (*terminalmage*) Optimize file_tree ext_pillar and update file.managed to allow for binary contents
- **PR** `#30245`_: (*rallytime*) Boto secgroup/iam_role: Add note stating us-east-1 is default region
- **PR** `#30299`_: (*rallytime*) ESXi Proxy minions states are located at salt.states.esxi, not vsphere.
- **PR** `#30202`_: (*opdude*) Fixed the periodic call to beacons
- **PR** `#30303`_: (*jacobhammons*) Changed notes to indicate that functions are matched using regular ex…
- **PR** `#30284`_: (*terminalmage*) salt.utils.gitfs: Fix Dulwich env detection and submodule handling
- **PR** `#30280`_: (*jfindlay*) add state mocking to release notes
- **PR** `#30273`_: (*rallytime*) Back-port `#30121`_ to 2015.8
- **PR** `#30301`_: (*cachedout*) Accept whatever comes into hightstate mock for state tests
- **PR** `#30282`_: (*cachedout*) Fix file.append logic
- **PR** `#30289`_: (*cro*) Fix problems with targeting proxies by grains
- **PR** `#30293`_: (*cro*) Ensure we don't log stuff we shouldn't
- **PR** `#30279`_: (*cachedout*) Allow modules to be packed into boto utils
- **PR** `#30186`_: (*rallytime*) Update CLI Examples in boto_ec2 module to reflect correct arg/kwarg positioning
- **PR** `#30156`_: (*abednarik*) Add option in file.append to ignore_whitespace.
- **PR** `#30189`_: (*rallytime*) Back-port `#30185`_ to 2015.8
- **PR** `#30215`_: (*jacobhammons*) Assorted doc bug fixes
- **PR** `#30206`_: (*cachedout*) Revert "Fix incorrect file permissions in file.line"
- **PR** `#30190`_: (*jacobhammons*) Updated doc site banners
- **PR** `#30180`_: (*jfindlay*) modules.x509._dec2hex: add fmt index for 2.6 compat
- **PR** `#30179`_: (*terminalmage*) Backport `#26962`_ to 2015.8 branch
- **PR** `#29693`_: (*abednarik*) Handle missing source file in ssh_auth.
- **PR** `#30155`_: (*rallytime*) Update boto_secgroup and boto_iam_role docs to only use region OR profile
- **PR** `#30158`_: (*rallytime*) Move _option(value) calls to __salt__['config.option'] in boto utils
- **PR** `#30160`_: (*dmurphy18*) Fix parsing disk usage for line with no number and AIX values in Kilos
- **PR** `#30162`_: (*rallytime*) Update list_present and append grains state function docs to be more clear.
- **PR** `#30163`_: (*rallytime*) Add warning about using "=" in file.line function
- **PR** `#30164`_: (*basepi*) [2015.8] Merge forward from 2015.5 to 2015.8
- **PR** `#30168`_: (*abednarik*) Fix incorrect file permissions in file.line
- **PR** `#30154`_: (*Oro*) Fix file serialize on windows
- **PR** `#30144`_: (*rallytime*) Added generic ESXCLI command ability to ESXi Proxy Minion
- **PR** `#30142`_: (*terminalmage*) Fix dockerng.push, and allow for multiple images
- **PR** `#30075`_: (*joejulian*) Convert glusterfs module to use xml
- **PR** `#30129`_: (*optix2000*) Clean up _uptodate() in git state
- **PR** `#30139`_: (*rallytime*) Back-port `#29589`_ to 2015.8
- **PR** `#30124`_: (*abednarik*) Update regex to detect ip alias in OpenBSD.
- **PR** `#30133`_: (*stanislavb*) Fix typo in gpgkey URL
- **PR** `#30126`_: (*stanislavb*) Log S3 API error message
- **PR** `#30128`_: (*oeuftete*) Log retryable transport errors as warnings
- **PR** `#30096`_: (*cachedout*) Add rm_special to crontab module
- **PR** `#30106`_: (*techhat*) Ensure last dir
- **PR** `#30101`_: (*gtmanfred*) fix bug where nova driver exits with no adminPass
- **PR** `#30090`_: (*techhat*) Add argument to isdir()
- **PR** `#30094`_: (*rallytime*) Fix doc formatting for cloud.create example in module.py state
- **PR** `#30095`_: (*rallytime*) Add the list_nodes_select function to linode driver
- **PR** `#30082`_: (*abednarik*) Fixed saltversioninfo grain return
- **PR** `#30084`_: (*rallytime*) Back-port `#29987`_ to 2015.8
- **PR** `#30071`_: (*rallytime*) Merge branch '2015.5' into '2015.8'
- **PR** `#30067`_: (*ryan-lane*) Pass in kwargs to boto_secgroup.convert_to_group_ids explicitly
- **PR** `#30069`_: (*techhat*) Ensure that pki_dir exists
- **PR** `#30064`_: (*rallytime*) Add Syndic documentation to miscellaneous Salt Cloud config options
- **PR** `#30049`_: (*rallytime*) Add some more unit tests for the vsphere execution module
- **PR** `#30060`_: (*rallytime*) Back-port `#27104`_ to 2015.8
- **PR** `#30048`_: (*jacobhammons*) Remove internal APIs from rest_cherrypy docs.
- **PR** `#30043`_: (*rallytime*) Be explicit about importing from salt.utils.jinja to avoid circular imports
- **PR** `#30038`_: (*rallytime*) Back-port `#30017`_ to 2015.8
- **PR** `#30036`_: (*rallytime*) Back-port `#29995`_ to 2015.8
- **PR** `#30035`_: (*rallytime*) Back-port `#29895`_ to 2015.8
- **PR** `#30034`_: (*rallytime*) Back-port `#29893`_ to 2015.8
- **PR** `#30033`_: (*rallytime*) Back-port `#29876`_ to 2015.8
- **PR** `#30029`_: (*terminalmage*) git.latest: Fix handling of nonexistant branches
- **PR** `#30016`_: (*anlutro*) Properly normalize locales in locale.gen_locale
- **PR** `#30015`_: (*anlutro*) locale module: don't escape the slash in \\n
- **PR** `#30022`_: (*gqgunhed*) Two minor typos fixed
- **PR** `#30026`_: (*anlutro*) states.at: fix wrong variable being used
- **PR** `#29966`_: (*multani*) Fix bigip state/module documentation + serializers documentation
- **PR** `#29904`_: (*twangboy*) Improvements to osx packaging scripts
- **PR** `#29950`_: (*multani*) boto_iam: fix deletion of IAM users when using delete_keys=true
- **PR** `#29937`_: (*multani*) Fix states.boto_iam group users
- **PR** `#29934`_: (*multani*) Fix state.boto_iam virtual name
- **PR** `#29943`_: (*cachedout*) Check args correctly in boto_rds
- **PR** `#29924`_: (*gqgunhed*) fixed: uptime now working on non-US Windows
- **PR** `#29883`_: (*serge-p*) fix for nfs mounts in _active_mounts_openbsd()
- **PR** `#29894`_: (*techhat*) Support Saltfile in SPM
- **PR** `#29856`_: (*rallytime*) Added some initial unit tests for the salt.modules.vsphere.py file
- **PR** `#29855`_: (*rallytime*) Back-port `#29740`_ to 2015.8
- **PR** `#29890`_: (*multani*) Various documentation fixes
- **PR** `#29850`_: (*basepi*) [2015.8] Merge forward from 2015.5 to 2015.8
- **PR** `#29811`_: (*anlutro*) influxdb: add retention policy module functions
- **PR** `#29814`_: (*basepi*) [2015.8][Windows] Fix multi-master on windows
- **PR** `#29819`_: (*rallytime*) Add esxi module and state to docs build
- **PR** `#29832`_: (*jleimbach*) Fixed typo in order to use the keyboard module for RHEL without systemd
- **PR** `#29803`_: (*rallytime*) Add vSphere module to doc ref module tree
- **PR** `#29767`_: (*abednarik*) Hosts file update in mod_hostname.
- **PR** `#29772`_: (*terminalmage*) pygit2: skip submodules when traversing tree
- **PR** `#29765`_: (*gtmanfred*) allow nova driver to be boot from volume
- **PR** `#29773`_: (*l2ol33rt*) Append missing wget in debian installation guide
- **PR** `#29800`_: (*rallytime*) Back-port `#29769`_ to 2015.8
- **PR** `#29775`_: (*paulnivin*) Change listen requisite resolution from name to ID declaration
- **PR** `#29754`_: (*rallytime*) Back-port `#29719`_ to 2015.8
- **PR** `#29713`_: (*The-Loeki*) Pillar-based cloud providers still forcing use of deprecated 'provider'
- **PR** `#29729`_: (*rallytime*) Further clarifications on "unless" and "onlyif" requisites.
- **PR** `#29737`_: (*akissa*) fix pillar sqlite3 documentation examples
- **PR** `#29743`_: (*akissa*) fix pillar sqlite not honouring config options
- **PR** `#29723`_: (*rallytime*) Clarify db_user and db_password kwargs for postgres_user.present state function
- **PR** `#29722`_: (*rallytime*) Link "stateful" kwargs to definition of what "stateful" means for cmd state.
- **PR** `#29724`_: (*rallytime*) Add examples of using multiple matching levels to Pillar docs
- **PR** `#29726`_: (*cachedout*) Disable some boto tests per resolution of moto issue
- **PR** `#29708`_: (*lagesag*) Fix test=True for file.directory with recurse ignore_files/ignore_dirs.
- **PR** `#29642`_: (*cachedout*) Correctly restart deamonized minions on failure
- **PR** `#29599`_: (*cachedout*) Clean up minion shutdown
- **PR** `#29675`_: (*clinta*) allow returning all refs
- **PR** `#29683`_: (*rallytime*) Catch more specific error to pass the error message through elegantly.
- **PR** `#29687`_: (*basepi*) [2015.8] Merge forward from 2015.5 to 2015.8
- **PR** `#29681`_: (*clinta*) fix bare/mirror in git.latest
- **PR** `#29644`_: (*rallytime*) Fixed a couple more ESXi proxy minion bugs
- **PR** `#29645`_: (*rallytime*) Back-port `#29558`_ to 2015.8
- **PR** `#29632`_: (*jfindlay*) reduce severity of tls module __virtual__ logging
- **PR** `#29606`_: (*abednarik*) Fixed duplicate mtu entry in RedHat 7 network configuration.
- **PR** `#29613`_: (*rallytime*) Various ESXi Proxy Minion Bug Fixes
- **PR** `#29628`_: (*DmitryKuzmenko*) Don't create io_loop before fork
- **PR** `#29609`_: (*basepi*) [2015.8][salt-ssh] Add ability to set salt-ssh command umask in roster
- **PR** `#29603`_: (*basepi*) Fix orchestration failure-checking
- **PR** `#29597`_: (*terminalmage*) dockerng: Prevent exception when API response contains empty dictionary
- **PR** `#29596`_: (*rallytime*) Back-port `#29587`_ to 2015.8
- **PR** `#29588`_: (*rallytime*) Added ESXi Proxy Minion Tutorial
- **PR** `#29572`_: (*gtmanfred*) [nova] use old discover_extensions if available
- **PR** `#29545`_: (*terminalmage*) git.latest: init submodules if not yet initialized
- **PR** `#29548`_: (*rallytime*) Back-port `#29449`_ to 2015.8
- **PR** `#29547`_: (*rallytime*) Refactored ESXCLI-based functions to accept a list of esxi_hosts
- **PR** `#29563`_: (*anlutro*) Fix a call to deprecated method in python-influxdb
- **PR** `#29565`_: (*bdrung*) Fix typos and missing release note
- **PR** `#29540`_: (*basepi*) [2015.8] Merge forward from 2015.5 to 2015.8
- **PR** `#29499`_: (*rallytime*) Initial commit of ESXi Proxy Minion
- **PR** `#29526`_: (*jfindlay*) 2015.8.2 notes: add note about not being released
- **PR** `#29531`_: (*jfindlay*) grains.core: handle undefined variable
- **PR** `#29538`_: (*basepi*) [2015.8] [salt-ssh] Remove umask around actual execution for salt-ssh
- **PR** `#29505`_: (*rallytime*) Update boto_rds state docs to include funky yaml syntax for "tags" option.
- **PR** `#29513`_: (*bdrung*) Drop obsolete syslog.target from systemd services
- **PR** `#29500`_: (*rallytime*) Back-port `#29467`_ to 2015.8
- **PR** `#29463`_: (*abednarik*) Add **kwargs to debconf.set.
- **PR** `#29399`_: (*jfindlay*) modules.status: add human_readable option to uptime
- **PR** `#29433`_: (*cro*) Files for building .pkg files for MacOS X
- **PR** `#29455`_: (*jfindlay*) modules.nova.__init__: do not return ``None``
- **PR** `#29454`_: (*jfindlay*) rh_service module __virtual__ return error messages
- **PR** `#29476`_: (*tbaker57*) Doc fix - route_table_present needs subnet_names (not subnets) as a key
- **PR** `#29487`_: (*rallytime*) Back-port `#29450`_ to 2015.8
- **PR** `#29441`_: (*rallytime*) Make sure docs line up with blade_idrac function specs
- **PR** `#29440`_: (*rallytime*) Back-port `#28925`_ to 2015.8
- **PR** `#29435`_: (*galet*) Grains return wrong OS version and other OS related values for Oracle Linux
- **PR** `#29430`_: (*rall0r*) Fix host.present state limitation
- **PR** `#29417`_: (*jacobhammons*) Repo install updates
- **PR** `#29402`_: (*techhat*) Add rate limiting to linode
- **PR** `#29400`_: (*twangboy*) Fix `#19332`_
- **PR** `#29398`_: (*cachedout*) Lint 29288
- **PR** `#29331`_: (*DmitryKuzmenko*) Bugfix - `#29116`_ raet dns error
- **PR** `#29390`_: (*jacobhammons*) updated version numbers in documentation
- **PR** `#29381`_: (*nmadhok*) No need to deepcopy since six.iterkeys() creates a copy
- **PR** `#29349`_: (*cro*) Fix mis-setting chassis names
- **PR** `#29334`_: (*rallytime*) Back-port `#29237`_ to 2015.8
- **PR** `#29300`_: (*ticosax*) [dockerng] Add support for volume management in dockerng
- **PR** `#29218`_: (*clan*) check service enable state in test mode
- **PR** `#29315`_: (*jfindlay*) dev tutorial doc: fix markup errors
- **PR** `#29317`_: (*basepi*) [2015.8] Merge forward from 2015.5 to 2015.8
- **PR** `#29240`_: (*clan*) handle acl_type [[d]efault:][user|group|mask|other]
- **PR** `#29305`_: (*lorengordon*) Add 'file' as a source_hash proto
- **PR** `#29272`_: (*jfindlay*) win_status module: handle 12 hour time in uptime
- **PR** `#29289`_: (*terminalmage*) file.managed: Allow local file sources to use source_hash
- **PR** `#29264`_: (*anlutro*) Prevent ssh_auth.absent from running when test=True
- **PR** `#29277`_: (*terminalmage*) Update git_pillar runner to support new git ext_pillar config schema
- **PR** `#29283`_: (*cachedout*) Single-quotes and use format
- **PR** `#29139`_: (*thomaso-mirodin*) [salt-ssh] Add a range roster and range targeting options for the flat roster
- **PR** `#29282`_: (*cachedout*) dev docs: add development tutorial
- **PR** `#28994`_: (*timcharper*) add support to s3 for aws role assumption
- **PR** `#29278`_: (*techhat*) Add verify_log to SPM
- **PR** `#29067`_: (*jacksontj*) Fix infinite recursion in state compiler for prereq of SLSs
- **PR** `#29207`_: (*jfindlay*) do not shadow ret function argument
- **PR** `#29215`_: (*rallytime*) Back-port `#29192`_ to 2015.8
- **PR** `#29217`_: (*clan*) show duration only if state_output_profile is False
- **PR** `#29221`_: (*ticosax*) [dokcerng] Docu network mode
- **PR** `#29269`_: (*jfindlay*) win_status module: fix function names in docs
- **PR** `#29213`_: (*rallytime*) Move _wait_for_task func from vmware cloud to vmware utils
- **PR** `#29271`_: (*techhat*) Pass full path for digest (SPM)
- **PR** `#29244`_: (*isbm*) List products consistently across all SLES systems
- **PR** `#29255`_: (*garethgreenaway*) fixes to consul module
- **PR** `#29208`_: (*whytewolf*) Glance more profile errors
- **PR** `#29200`_: (*jfindlay*) mount state: unmount by device is optional
- **PR** `#29205`_: (*trevor-h*) Fixes `#29187`_ - using winrm on EC2
- **PR** `#29170`_: (*cachedout*) Migrate pydsl tests to integration test suite
- **PR** `#29198`_: (*jfindlay*) rh_ip module: only set the mtu once
- **PR** `#29135`_: (*jfindlay*) ssh_known_hosts.present state: catch not found exc
- **PR** `#29196`_: (*s0undt3ch*) We need novaclient imported to compare versions
- **PR** `#29059`_: (*terminalmage*) Work around upstream pygit2 bug
- **PR** `#29112`_: (*eliasp*) Prevent backtrace (KeyError) in `ssh_known_hosts.present` state
- **PR** `#29178`_: (*whytewolf*) Profile not being passed to keystone.endpoint_get in _auth. so if a p…
.. _`#19332`: https://github.com/saltstack/salt/issues/19332
.. _`#29116`: https://github.com/saltstack/salt/issues/29116
.. _`#29187`: https://github.com/saltstack/salt/issues/29187
.. _`#23825`: https://github.com/saltstack/salt/pull/23825
.. _`#26511`: https://github.com/saltstack/salt/pull/26511
.. _`#26853`: https://github.com/saltstack/salt/pull/26853
.. _`#26962`: https://github.com/saltstack/salt/pull/26962
.. _`#27104`: https://github.com/saltstack/salt/pull/27104
.. _`#27606`: https://github.com/saltstack/salt/pull/27606
.. _`#27953`: https://github.com/saltstack/salt/pull/27953
.. _`#28131`: https://github.com/saltstack/salt/pull/28131
.. _`#28189`: https://github.com/saltstack/salt/pull/28189
.. _`#28191`: https://github.com/saltstack/salt/pull/28191
.. _`#28420`: https://github.com/saltstack/salt/pull/28420
.. _`#28423`: https://github.com/saltstack/salt/pull/28423
.. _`#28431`: https://github.com/saltstack/salt/pull/28431
.. _`#28501`: https://github.com/saltstack/salt/pull/28501
.. _`#28656`: https://github.com/saltstack/salt/pull/28656
.. _`#28702`: https://github.com/saltstack/salt/pull/28702
.. _`#28925`: https://github.com/saltstack/salt/pull/28925
.. _`#28994`: https://github.com/saltstack/salt/pull/28994
.. _`#29059`: https://github.com/saltstack/salt/pull/29059
.. _`#29067`: https://github.com/saltstack/salt/pull/29067
.. _`#29112`: https://github.com/saltstack/salt/pull/29112
.. _`#29126`: https://github.com/saltstack/salt/pull/29126
.. _`#29135`: https://github.com/saltstack/salt/pull/29135
.. _`#29139`: https://github.com/saltstack/salt/pull/29139
.. _`#29165`: https://github.com/saltstack/salt/pull/29165
.. _`#29170`: https://github.com/saltstack/salt/pull/29170
.. _`#29178`: https://github.com/saltstack/salt/pull/29178
.. _`#29192`: https://github.com/saltstack/salt/pull/29192
.. _`#29196`: https://github.com/saltstack/salt/pull/29196
.. _`#29198`: https://github.com/saltstack/salt/pull/29198
.. _`#29200`: https://github.com/saltstack/salt/pull/29200
.. _`#29204`: https://github.com/saltstack/salt/pull/29204
.. _`#29205`: https://github.com/saltstack/salt/pull/29205
.. _`#29207`: https://github.com/saltstack/salt/pull/29207
.. _`#29208`: https://github.com/saltstack/salt/pull/29208
.. _`#29213`: https://github.com/saltstack/salt/pull/29213
.. _`#29214`: https://github.com/saltstack/salt/pull/29214
.. _`#29215`: https://github.com/saltstack/salt/pull/29215
.. _`#29216`: https://github.com/saltstack/salt/pull/29216
.. _`#29217`: https://github.com/saltstack/salt/pull/29217
.. _`#29218`: https://github.com/saltstack/salt/pull/29218
.. _`#29221`: https://github.com/saltstack/salt/pull/29221
.. _`#29237`: https://github.com/saltstack/salt/pull/29237
.. _`#29240`: https://github.com/saltstack/salt/pull/29240
.. _`#29244`: https://github.com/saltstack/salt/pull/29244
.. _`#29255`: https://github.com/saltstack/salt/pull/29255
.. _`#29261`: https://github.com/saltstack/salt/pull/29261
.. _`#29264`: https://github.com/saltstack/salt/pull/29264
.. _`#29269`: https://github.com/saltstack/salt/pull/29269
.. _`#29271`: https://github.com/saltstack/salt/pull/29271
.. _`#29272`: https://github.com/saltstack/salt/pull/29272
.. _`#29276`: https://github.com/saltstack/salt/pull/29276
.. _`#29277`: https://github.com/saltstack/salt/pull/29277
.. _`#29278`: https://github.com/saltstack/salt/pull/29278
.. _`#29279`: https://github.com/saltstack/salt/pull/29279
.. _`#29280`: https://github.com/saltstack/salt/pull/29280
.. _`#29282`: https://github.com/saltstack/salt/pull/29282
.. _`#29283`: https://github.com/saltstack/salt/pull/29283
.. _`#29288`: https://github.com/saltstack/salt/pull/29288
.. _`#29289`: https://github.com/saltstack/salt/pull/29289
.. _`#29296`: https://github.com/saltstack/salt/pull/29296
.. _`#29300`: https://github.com/saltstack/salt/pull/29300
.. _`#29305`: https://github.com/saltstack/salt/pull/29305
.. _`#29315`: https://github.com/saltstack/salt/pull/29315
.. _`#29316`: https://github.com/saltstack/salt/pull/29316
.. _`#29317`: https://github.com/saltstack/salt/pull/29317
.. _`#29331`: https://github.com/saltstack/salt/pull/29331
.. _`#29333`: https://github.com/saltstack/salt/pull/29333
.. _`#29334`: https://github.com/saltstack/salt/pull/29334
.. _`#29336`: https://github.com/saltstack/salt/pull/29336
.. _`#29348`: https://github.com/saltstack/salt/pull/29348
.. _`#29349`: https://github.com/saltstack/salt/pull/29349
.. _`#29381`: https://github.com/saltstack/salt/pull/29381
.. _`#29389`: https://github.com/saltstack/salt/pull/29389
.. _`#29390`: https://github.com/saltstack/salt/pull/29390
.. _`#29392`: https://github.com/saltstack/salt/pull/29392
.. _`#29398`: https://github.com/saltstack/salt/pull/29398
.. _`#29399`: https://github.com/saltstack/salt/pull/29399
.. _`#29400`: https://github.com/saltstack/salt/pull/29400
.. _`#29402`: https://github.com/saltstack/salt/pull/29402
.. _`#29417`: https://github.com/saltstack/salt/pull/29417
.. _`#29418`: https://github.com/saltstack/salt/pull/29418
.. _`#29430`: https://github.com/saltstack/salt/pull/29430
.. _`#29433`: https://github.com/saltstack/salt/pull/29433
.. _`#29435`: https://github.com/saltstack/salt/pull/29435
.. _`#29439`: https://github.com/saltstack/salt/pull/29439
.. _`#29440`: https://github.com/saltstack/salt/pull/29440
.. _`#29441`: https://github.com/saltstack/salt/pull/29441
.. _`#29449`: https://github.com/saltstack/salt/pull/29449
.. _`#29450`: https://github.com/saltstack/salt/pull/29450
.. _`#29454`: https://github.com/saltstack/salt/pull/29454
.. _`#29455`: https://github.com/saltstack/salt/pull/29455
.. _`#29461`: https://github.com/saltstack/salt/pull/29461
.. _`#29463`: https://github.com/saltstack/salt/pull/29463
.. _`#29467`: https://github.com/saltstack/salt/pull/29467
.. _`#29469`: https://github.com/saltstack/salt/pull/29469
.. _`#29476`: https://github.com/saltstack/salt/pull/29476
.. _`#29487`: https://github.com/saltstack/salt/pull/29487
.. _`#29499`: https://github.com/saltstack/salt/pull/29499
.. _`#29500`: https://github.com/saltstack/salt/pull/29500
.. _`#29504`: https://github.com/saltstack/salt/pull/29504
.. _`#29505`: https://github.com/saltstack/salt/pull/29505
.. _`#29507`: https://github.com/saltstack/salt/pull/29507
.. _`#29513`: https://github.com/saltstack/salt/pull/29513
.. _`#29526`: https://github.com/saltstack/salt/pull/29526
.. _`#29527`: https://github.com/saltstack/salt/pull/29527
.. _`#29531`: https://github.com/saltstack/salt/pull/29531
.. _`#29538`: https://github.com/saltstack/salt/pull/29538
.. _`#29539`: https://github.com/saltstack/salt/pull/29539
.. _`#29540`: https://github.com/saltstack/salt/pull/29540
.. _`#29545`: https://github.com/saltstack/salt/pull/29545
.. _`#29547`: https://github.com/saltstack/salt/pull/29547
.. _`#29548`: https://github.com/saltstack/salt/pull/29548
.. _`#29558`: https://github.com/saltstack/salt/pull/29558
.. _`#29563`: https://github.com/saltstack/salt/pull/29563
.. _`#29565`: https://github.com/saltstack/salt/pull/29565
.. _`#29572`: https://github.com/saltstack/salt/pull/29572
.. _`#29587`: https://github.com/saltstack/salt/pull/29587
.. _`#29588`: https://github.com/saltstack/salt/pull/29588
.. _`#29589`: https://github.com/saltstack/salt/pull/29589
.. _`#29596`: https://github.com/saltstack/salt/pull/29596
.. _`#29597`: https://github.com/saltstack/salt/pull/29597
.. _`#29599`: https://github.com/saltstack/salt/pull/29599
.. _`#29603`: https://github.com/saltstack/salt/pull/29603
.. _`#29606`: https://github.com/saltstack/salt/pull/29606
.. _`#29609`: https://github.com/saltstack/salt/pull/29609
.. _`#29613`: https://github.com/saltstack/salt/pull/29613
.. _`#29628`: https://github.com/saltstack/salt/pull/29628
.. _`#29632`: https://github.com/saltstack/salt/pull/29632
.. _`#29642`: https://github.com/saltstack/salt/pull/29642
.. _`#29644`: https://github.com/saltstack/salt/pull/29644
.. _`#29645`: https://github.com/saltstack/salt/pull/29645
.. _`#29646`: https://github.com/saltstack/salt/pull/29646
.. _`#29673`: https://github.com/saltstack/salt/pull/29673
.. _`#29675`: https://github.com/saltstack/salt/pull/29675
.. _`#29681`: https://github.com/saltstack/salt/pull/29681
.. _`#29683`: https://github.com/saltstack/salt/pull/29683
.. _`#29687`: https://github.com/saltstack/salt/pull/29687
.. _`#29693`: https://github.com/saltstack/salt/pull/29693
.. _`#29708`: https://github.com/saltstack/salt/pull/29708
.. _`#29713`: https://github.com/saltstack/salt/pull/29713
.. _`#29715`: https://github.com/saltstack/salt/pull/29715
.. _`#29719`: https://github.com/saltstack/salt/pull/29719
.. _`#29721`: https://github.com/saltstack/salt/pull/29721
.. _`#29722`: https://github.com/saltstack/salt/pull/29722
.. _`#29723`: https://github.com/saltstack/salt/pull/29723
.. _`#29724`: https://github.com/saltstack/salt/pull/29724
.. _`#29725`: https://github.com/saltstack/salt/pull/29725
.. _`#29726`: https://github.com/saltstack/salt/pull/29726
.. _`#29729`: https://github.com/saltstack/salt/pull/29729
.. _`#29730`: https://github.com/saltstack/salt/pull/29730
.. _`#29737`: https://github.com/saltstack/salt/pull/29737
.. _`#29740`: https://github.com/saltstack/salt/pull/29740
.. _`#29743`: https://github.com/saltstack/salt/pull/29743
.. _`#29754`: https://github.com/saltstack/salt/pull/29754
.. _`#29765`: https://github.com/saltstack/salt/pull/29765
.. _`#29767`: https://github.com/saltstack/salt/pull/29767
.. _`#29769`: https://github.com/saltstack/salt/pull/29769
.. _`#29772`: https://github.com/saltstack/salt/pull/29772
.. _`#29773`: https://github.com/saltstack/salt/pull/29773
.. _`#29775`: https://github.com/saltstack/salt/pull/29775
.. _`#29800`: https://github.com/saltstack/salt/pull/29800
.. _`#29803`: https://github.com/saltstack/salt/pull/29803
.. _`#29811`: https://github.com/saltstack/salt/pull/29811
.. _`#29814`: https://github.com/saltstack/salt/pull/29814
.. _`#29819`: https://github.com/saltstack/salt/pull/29819
.. _`#29832`: https://github.com/saltstack/salt/pull/29832
.. _`#29850`: https://github.com/saltstack/salt/pull/29850
.. _`#29855`: https://github.com/saltstack/salt/pull/29855
.. _`#29856`: https://github.com/saltstack/salt/pull/29856
.. _`#29858`: https://github.com/saltstack/salt/pull/29858
.. _`#29876`: https://github.com/saltstack/salt/pull/29876
.. _`#29883`: https://github.com/saltstack/salt/pull/29883
.. _`#29890`: https://github.com/saltstack/salt/pull/29890
.. _`#29893`: https://github.com/saltstack/salt/pull/29893
.. _`#29894`: https://github.com/saltstack/salt/pull/29894
.. _`#29895`: https://github.com/saltstack/salt/pull/29895
.. _`#29904`: https://github.com/saltstack/salt/pull/29904
.. _`#29908`: https://github.com/saltstack/salt/pull/29908
.. _`#29909`: https://github.com/saltstack/salt/pull/29909
.. _`#29924`: https://github.com/saltstack/salt/pull/29924
.. _`#29934`: https://github.com/saltstack/salt/pull/29934
.. _`#29937`: https://github.com/saltstack/salt/pull/29937
.. _`#29941`: https://github.com/saltstack/salt/pull/29941
.. _`#29943`: https://github.com/saltstack/salt/pull/29943
.. _`#29947`: https://github.com/saltstack/salt/pull/29947
.. _`#29949`: https://github.com/saltstack/salt/pull/29949
.. _`#29950`: https://github.com/saltstack/salt/pull/29950
.. _`#29966`: https://github.com/saltstack/salt/pull/29966
.. _`#29987`: https://github.com/saltstack/salt/pull/29987
.. _`#29995`: https://github.com/saltstack/salt/pull/29995
.. _`#30015`: https://github.com/saltstack/salt/pull/30015
.. _`#30016`: https://github.com/saltstack/salt/pull/30016
.. _`#30017`: https://github.com/saltstack/salt/pull/30017
.. _`#30022`: https://github.com/saltstack/salt/pull/30022
.. _`#30025`: https://github.com/saltstack/salt/pull/30025
.. _`#30026`: https://github.com/saltstack/salt/pull/30026
.. _`#30029`: https://github.com/saltstack/salt/pull/30029
.. _`#30033`: https://github.com/saltstack/salt/pull/30033
.. _`#30034`: https://github.com/saltstack/salt/pull/30034
.. _`#30035`: https://github.com/saltstack/salt/pull/30035
.. _`#30036`: https://github.com/saltstack/salt/pull/30036
.. _`#30038`: https://github.com/saltstack/salt/pull/30038
.. _`#30043`: https://github.com/saltstack/salt/pull/30043
.. _`#30048`: https://github.com/saltstack/salt/pull/30048
.. _`#30049`: https://github.com/saltstack/salt/pull/30049
.. _`#30059`: https://github.com/saltstack/salt/pull/30059
.. _`#30060`: https://github.com/saltstack/salt/pull/30060
.. _`#30062`: https://github.com/saltstack/salt/pull/30062
.. _`#30064`: https://github.com/saltstack/salt/pull/30064
.. _`#30067`: https://github.com/saltstack/salt/pull/30067
.. _`#30069`: https://github.com/saltstack/salt/pull/30069
.. _`#30070`: https://github.com/saltstack/salt/pull/30070
.. _`#30071`: https://github.com/saltstack/salt/pull/30071
.. _`#30075`: https://github.com/saltstack/salt/pull/30075
.. _`#30082`: https://github.com/saltstack/salt/pull/30082
.. _`#30084`: https://github.com/saltstack/salt/pull/30084
.. _`#30086`: https://github.com/saltstack/salt/pull/30086
.. _`#30089`: https://github.com/saltstack/salt/pull/30089
.. _`#30090`: https://github.com/saltstack/salt/pull/30090
.. _`#30093`: https://github.com/saltstack/salt/pull/30093
.. _`#30094`: https://github.com/saltstack/salt/pull/30094
.. _`#30095`: https://github.com/saltstack/salt/pull/30095
.. _`#30096`: https://github.com/saltstack/salt/pull/30096
.. _`#30097`: https://github.com/saltstack/salt/pull/30097
.. _`#30101`: https://github.com/saltstack/salt/pull/30101
.. _`#30106`: https://github.com/saltstack/salt/pull/30106
.. _`#30110`: https://github.com/saltstack/salt/pull/30110
.. _`#30118`: https://github.com/saltstack/salt/pull/30118
.. _`#30121`: https://github.com/saltstack/salt/pull/30121
.. _`#30124`: https://github.com/saltstack/salt/pull/30124
.. _`#30125`: https://github.com/saltstack/salt/pull/30125
.. _`#30126`: https://github.com/saltstack/salt/pull/30126
.. _`#30127`: https://github.com/saltstack/salt/pull/30127
.. _`#30128`: https://github.com/saltstack/salt/pull/30128
.. _`#30129`: https://github.com/saltstack/salt/pull/30129
.. _`#30133`: https://github.com/saltstack/salt/pull/30133
.. _`#30139`: https://github.com/saltstack/salt/pull/30139
.. _`#30142`: https://github.com/saltstack/salt/pull/30142
.. _`#30144`: https://github.com/saltstack/salt/pull/30144
.. _`#30154`: https://github.com/saltstack/salt/pull/30154
.. _`#30155`: https://github.com/saltstack/salt/pull/30155
.. _`#30156`: https://github.com/saltstack/salt/pull/30156
.. _`#30158`: https://github.com/saltstack/salt/pull/30158
.. _`#30160`: https://github.com/saltstack/salt/pull/30160
.. _`#30162`: https://github.com/saltstack/salt/pull/30162
.. _`#30163`: https://github.com/saltstack/salt/pull/30163
.. _`#30164`: https://github.com/saltstack/salt/pull/30164
.. _`#30166`: https://github.com/saltstack/salt/pull/30166
.. _`#30168`: https://github.com/saltstack/salt/pull/30168
.. _`#30170`: https://github.com/saltstack/salt/pull/30170
.. _`#30179`: https://github.com/saltstack/salt/pull/30179
.. _`#30180`: https://github.com/saltstack/salt/pull/30180
.. _`#30184`: https://github.com/saltstack/salt/pull/30184
.. _`#30185`: https://github.com/saltstack/salt/pull/30185
.. _`#30186`: https://github.com/saltstack/salt/pull/30186
.. _`#30187`: https://github.com/saltstack/salt/pull/30187
.. _`#30189`: https://github.com/saltstack/salt/pull/30189
.. _`#30190`: https://github.com/saltstack/salt/pull/30190
.. _`#30191`: https://github.com/saltstack/salt/pull/30191
.. _`#30202`: https://github.com/saltstack/salt/pull/30202
.. _`#30206`: https://github.com/saltstack/salt/pull/30206
.. _`#30207`: https://github.com/saltstack/salt/pull/30207
.. _`#30211`: https://github.com/saltstack/salt/pull/30211
.. _`#30212`: https://github.com/saltstack/salt/pull/30212
.. _`#30215`: https://github.com/saltstack/salt/pull/30215
.. _`#30217`: https://github.com/saltstack/salt/pull/30217
.. _`#30221`: https://github.com/saltstack/salt/pull/30221
.. _`#30223`: https://github.com/saltstack/salt/pull/30223
.. _`#30231`: https://github.com/saltstack/salt/pull/30231
.. _`#30237`: https://github.com/saltstack/salt/pull/30237
.. _`#30238`: https://github.com/saltstack/salt/pull/30238
.. _`#30245`: https://github.com/saltstack/salt/pull/30245
.. _`#30246`: https://github.com/saltstack/salt/pull/30246
.. _`#30248`: https://github.com/saltstack/salt/pull/30248
.. _`#30249`: https://github.com/saltstack/salt/pull/30249
.. _`#30257`: https://github.com/saltstack/salt/pull/30257
.. _`#30267`: https://github.com/saltstack/salt/pull/30267
.. _`#30268`: https://github.com/saltstack/salt/pull/30268
.. _`#30273`: https://github.com/saltstack/salt/pull/30273
.. _`#30275`: https://github.com/saltstack/salt/pull/30275
.. _`#30278`: https://github.com/saltstack/salt/pull/30278
.. _`#30279`: https://github.com/saltstack/salt/pull/30279
.. _`#30280`: https://github.com/saltstack/salt/pull/30280
.. _`#30282`: https://github.com/saltstack/salt/pull/30282
.. _`#30284`: https://github.com/saltstack/salt/pull/30284
.. _`#30289`: https://github.com/saltstack/salt/pull/30289
.. _`#30291`: https://github.com/saltstack/salt/pull/30291
.. _`#30292`: https://github.com/saltstack/salt/pull/30292
.. _`#30293`: https://github.com/saltstack/salt/pull/30293
.. _`#30299`: https://github.com/saltstack/salt/pull/30299
.. _`#30301`: https://github.com/saltstack/salt/pull/30301
.. _`#30303`: https://github.com/saltstack/salt/pull/30303
.. _`#30304`: https://github.com/saltstack/salt/pull/30304
.. _`#30305`: https://github.com/saltstack/salt/pull/30305
.. _`#30308`: https://github.com/saltstack/salt/pull/30308
.. _`#30309`: https://github.com/saltstack/salt/pull/30309
.. _`#30310`: https://github.com/saltstack/salt/pull/30310
.. _`#30328`: https://github.com/saltstack/salt/pull/30328
.. _`#30339`: https://github.com/saltstack/salt/pull/30339
.. _`#30340`: https://github.com/saltstack/salt/pull/30340
.. _`#30342`: https://github.com/saltstack/salt/pull/30342
.. _`#30343`: https://github.com/saltstack/salt/pull/30343
.. _`#30346`: https://github.com/saltstack/salt/pull/30346
.. _`#30347`: https://github.com/saltstack/salt/pull/30347
.. _`#30349`: https://github.com/saltstack/salt/pull/30349
.. _`#30354`: https://github.com/saltstack/salt/pull/30354
.. _`#30356`: https://github.com/saltstack/salt/pull/30356
.. _`#30358`: https://github.com/saltstack/salt/pull/30358
.. _`#30359`: https://github.com/saltstack/salt/pull/30359
.. _`#30360`: https://github.com/saltstack/salt/pull/30360
.. _`#30361`: https://github.com/saltstack/salt/pull/30361
.. _`#30363`: https://github.com/saltstack/salt/pull/30363
.. _`#30364`: https://github.com/saltstack/salt/pull/30364
.. _`#30366`: https://github.com/saltstack/salt/pull/30366
.. _`#30370`: https://github.com/saltstack/salt/pull/30370
.. _`#30372`: https://github.com/saltstack/salt/pull/30372
.. _`#30373`: https://github.com/saltstack/salt/pull/30373
.. _`#30374`: https://github.com/saltstack/salt/pull/30374
.. _`#30375`: https://github.com/saltstack/salt/pull/30375
.. _`#30376`: https://github.com/saltstack/salt/pull/30376
.. _`#30384`: https://github.com/saltstack/salt/pull/30384
.. _`#30389`: https://github.com/saltstack/salt/pull/30389
.. _`#30391`: https://github.com/saltstack/salt/pull/30391
.. _`#30396`: https://github.com/saltstack/salt/pull/30396
.. _`#30405`: https://github.com/saltstack/salt/pull/30405
.. _`#30406`: https://github.com/saltstack/salt/pull/30406
.. _`#30420`: https://github.com/saltstack/salt/pull/30420
.. _`#30424`: https://github.com/saltstack/salt/pull/30424
.. _`#30443`: https://github.com/saltstack/salt/pull/30443
.. _`#30445`: https://github.com/saltstack/salt/pull/30445
.. _`#30448`: https://github.com/saltstack/salt/pull/30448
.. _`#30450`: https://github.com/saltstack/salt/pull/30450
.. _`#30453`: https://github.com/saltstack/salt/pull/30453
.. _`#30457`: https://github.com/saltstack/salt/pull/30457
.. _`#30458`: https://github.com/saltstack/salt/pull/30458
.. _`#30459`: https://github.com/saltstack/salt/pull/30459
.. _`#30468`: https://github.com/saltstack/salt/pull/30468
.. _`#30470`: https://github.com/saltstack/salt/pull/30470
.. _`#30478`: https://github.com/saltstack/salt/pull/30478
.. _`#30482`: https://github.com/saltstack/salt/pull/30482
.. _`#30483`: https://github.com/saltstack/salt/pull/30483
.. _`#30484`: https://github.com/saltstack/salt/pull/30484
.. _`#30485`: https://github.com/saltstack/salt/pull/30485
.. _`#30491`: https://github.com/saltstack/salt/pull/30491
.. _`#30494`: https://github.com/saltstack/salt/pull/30494
.. _`#30496`: https://github.com/saltstack/salt/pull/30496
.. _`#30506`: https://github.com/saltstack/salt/pull/30506
.. _`#30508`: https://github.com/saltstack/salt/pull/30508
.. _`#30512`: https://github.com/saltstack/salt/pull/30512
.. _`#30521`: https://github.com/saltstack/salt/pull/30521
.. _`#30522`: https://github.com/saltstack/salt/pull/30522
.. _`#30526`: https://github.com/saltstack/salt/pull/30526
.. _`#30529`: https://github.com/saltstack/salt/pull/30529
.. _`#30530`: https://github.com/saltstack/salt/pull/30530
.. _`#30532`: https://github.com/saltstack/salt/pull/30532
.. _`#30548`: https://github.com/saltstack/salt/pull/30548
.. _`#30549`: https://github.com/saltstack/salt/pull/30549
.. _`#30553`: https://github.com/saltstack/salt/pull/30553
.. _`#30554`: https://github.com/saltstack/salt/pull/30554
.. _`#30582`: https://github.com/saltstack/salt/pull/30582
.. _`#30584`: https://github.com/saltstack/salt/pull/30584
.. _`#30589`: https://github.com/saltstack/salt/pull/30589
.. _`#30599`: https://github.com/saltstack/salt/pull/30599
.. _`#30609`: https://github.com/saltstack/salt/pull/30609
.. _`#30613`: https://github.com/saltstack/salt/pull/30613

View file

@ -273,8 +273,8 @@ This shell command can find wrong characters in your SLS files:
Alternatively you can toggle the `yaml_utf8` setting in your master configuration
file. This is still an experimental setting but it should manage the right
encoding conversion in salt after yaml states compilations.
file. This is still an experimental setting but it should manage the right
encoding conversion in salt after yaml states compilations.
Underscores stripped in Integer Definitions
===========================================

View file

@ -76,7 +76,7 @@ ensures that the server has the Apache webserver installed.
.. note::
For a complete explanation on Salt States, see the `tutorial
<http://docs.saltstack.org/en/latest/topics/tutorials/states_pt1.html>`_.
<http://docs.saltstack.com/en/latest/topics/tutorials/states_pt1.html>`_.
1. Create the ``top.sls`` file:

View file

@ -1 +0,0 @@
salt

View file

@ -1 +0,0 @@
salt

View file

@ -1 +0,0 @@
salt

View file

@ -1 +0,0 @@
salt

View file

@ -1 +0,0 @@
salt

View file

@ -1 +0,0 @@
salt

View file

@ -56,7 +56,7 @@
<documentation>
<doc_link name="SaltStack Documentation"
uri="http://docs.saltstack.org"/>
uri="http://docs.saltstack.com"/>
</documentation>
</template>
</service>

View file

@ -56,7 +56,7 @@
<documentation>
<doc_link name="SaltStack Documentation"
uri="http://docs.saltstack.org"/>
uri="http://docs.saltstack.com"/>
</documentation>
</template>
</service>

View file

@ -56,7 +56,7 @@
<documentation>
<doc_link name="SaltStack Documentation"
uri="http://docs.saltstack.org"/>
uri="http://docs.saltstack.com"/>
</documentation>
</template>
</service>

View file

@ -66,7 +66,7 @@
<documentation>
<doc_link name="SaltStack Documentation"
uri="http://docs.saltstack.org"/>
uri="http://docs.saltstack.com"/>
</documentation>
</template>
</service>

View file

@ -67,7 +67,7 @@
<documentation>
<doc_link name="SaltStack Documentation"
uri="http://docs.saltstack.org"/>
uri="http://docs.saltstack.com"/>
</documentation>
</template>
</service>

View file

@ -62,7 +62,7 @@
<documentation>
<doc_link name="SaltStack Documentation"
uri="http://docs.saltstack.org"/>
uri="http://docs.saltstack.com"/>
</documentation>
</template>
</service>

View file

@ -61,7 +61,7 @@
<documentation>
<doc_link name="SaltStack Documentation"
uri="http://docs.saltstack.org"/>
uri="http://docs.saltstack.com"/>
</documentation>
</template>
</service>

View file

@ -61,7 +61,7 @@
<documentation>
<doc_link name="SaltStack Documentation"
uri="http://docs.saltstack.org"/>
uri="http://docs.saltstack.com"/>
</documentation>
</template>
</service>

View file

@ -61,7 +61,7 @@
<documentation>
<doc_link name="SaltStack Documentation"
uri="http://docs.saltstack.org"/>
uri="http://docs.saltstack.com"/>
</documentation>
</template>
</service>

View file

@ -1440,6 +1440,7 @@ class Cloud(object):
Perform an action on a VM which may be specific to this cloud provider
'''
ret = {}
invalid_functions = {}
names = set(names)
for alias, drivers in six.iteritems(self.map_providers_parallel()):
@ -1448,6 +1449,7 @@ class Cloud(object):
for driver, vms in six.iteritems(drivers):
if not names:
break
valid_function = True
fun = '{0}.{1}'.format(driver, self.opts['action'])
if fun not in self.clouds:
log.info(
@ -1455,7 +1457,7 @@ class Cloud(object):
fun
)
)
continue
valid_function = False
for vm_name, vm_details in six.iteritems(vms):
if not names:
break
@ -1468,6 +1470,14 @@ class Cloud(object):
'list:\'{2}\''.format(vm_name, driver, names)
)
continue
# Build the dictionary of invalid functions with their associated VMs.
if valid_function is False:
if invalid_functions.get(fun) is None:
invalid_functions.update({fun: []})
invalid_functions[fun].append(vm_name)
continue
with context.func_globals_inject(
self.clouds[fun],
__active_provider_name__=':'.join([alias, driver])
@ -1494,10 +1504,33 @@ class Cloud(object):
)
names.remove(vm_name)
# Set the return information for the VMs listed in the invalid_functions dict.
missing_vms = set()
if invalid_functions:
ret['Invalid Actions'] = invalid_functions
invalid_func_vms = set()
for key, val in six.iteritems(invalid_functions):
invalid_func_vms = invalid_func_vms.union(set(val))
# Find the VMs that are in names, but not in set of invalid functions.
missing_vms = names.difference(invalid_func_vms)
if missing_vms:
ret['Not Found'] = list(missing_vms)
ret['Not Actioned/Not Running'] = list(names)
if not names:
return ret
# Don't return missing VM information for invalid functions until after we've had a
# Chance to return successful actions. If a function is valid for one driver, but
# Not another, we want to make sure the successful action is returned properly.
if missing_vms:
return ret
# If we reach this point, the Not Actioned and Not Found lists will be the same,
# But we want to list both for clarity/consistency with the invalid functions lists.
ret['Not Actioned/Not Running'] = list(names)
ret['Not Found'] = list(names)
return ret
def do_function(self, prov, func, kwargs):
@ -2320,5 +2353,3 @@ def _destroy_multiprocessing(*args, **kw):
def _create_multiprocessing(*args, **kw):
return communicator(create_multiprocessing)(*args[0], **kw)
#

View file

@ -3120,7 +3120,7 @@ def _get_node(name=None, instance_id=None, location=None):
params = {'Action': 'DescribeInstances'}
if str(name).startswith('i-') and len(name) == 10:
if str(name).startswith('i-') and (len(name) == 10 or len(name) == 19):
instance_id = name
if instance_id:

View file

@ -1879,8 +1879,12 @@ class Minion(MinionBase):
self.destroy()
def _handle_payload(self, payload):
if payload is not None and self._target_load(payload['load']):
self._handle_decoded_payload(payload['load'])
if payload is not None and payload['enc'] == 'aes':
if self._target_load(payload['load']):
self._handle_decoded_payload(payload['load'])
# If it's not AES, and thus has not been verified, we do nothing.
# In the future, we could add support for some clearfuncs, but
# the minion currently has no need.
def _target_load(self, load):
# Verify that the publication is valid
@ -2055,9 +2059,12 @@ class Syndic(Minion):
self.pub_channel.on_recv(self._process_cmd_socket)
def _process_cmd_socket(self, payload):
if payload is not None:
log.trace('Handling payload') # pylint: disable=no-member
if payload is not None and payload['enc'] == 'aes':
log.trace('Handling payload')
self._handle_decoded_payload(payload['load'])
# If it's not AES, and thus has not been verified, we do nothing.
# In the future, we could add support for some clearfuncs, but
# the syndic currently has no need.
def _reset_event_aggregation(self):
self.jids = {}

View file

@ -168,7 +168,7 @@ def get_elb_config(name, region=None, key=None, keyid=None, profile=None):
return ret
except boto.exception.BotoServerError as error:
log.debug(error)
return []
return {}
def listener_dict_to_tuple(listener):

View file

@ -10,10 +10,13 @@ from __future__ import absolute_import
import os
import tempfile
import hashlib
import logging
# Import Salt libs
import salt.utils
log = logging.getLogger(__name__)
def __virtual__():
'''
@ -40,22 +43,24 @@ def mount(location, access='rw', root=None):
'guest',
location.lstrip(os.sep).replace('/', '.')
)
log.debug('Using root {0}'.format(root))
if not os.path.isdir(root):
try:
os.makedirs(root)
except OSError:
# somehow the directory already exists
# Somehow the path already exists
pass
while True:
if os.listdir(root):
# Stuf is in there, don't use it
# Stuff is in there, don't use it
hash_type = getattr(hashlib, __opts__.get('hash_type', 'md5'))
rand = hash_type(os.urandom(32)).hexdigest()
root = os.path.join(
tempfile.gettempdir(),
'guest',
location.lstrip(os.sep).replace('/', '.') + rand
)
)
log.debug('Establishing new root as {0}'.format(root))
else:
break
cmd = 'guestmount -i -a {0} --{1} {2}'.format(location, access, root)

View file

@ -428,7 +428,7 @@ def last(attrs=None, where=None):
def listening_ports(attrs=None, where=None):
r'''
Return listening_ports\_ information from osquery
Return listening_ports information from osquery
CLI Example:
@ -441,7 +441,7 @@ def listening_ports(attrs=None, where=None):
def logged_in_users(attrs=None, where=None):
r'''
Return logged_in_users\_ information from osquery
Return logged_in_users information from osquery
CLI Example:
@ -454,7 +454,7 @@ def logged_in_users(attrs=None, where=None):
def mounts(attrs=None, where=None):
r'''
Return mounts\_ information from osquery
Return mounts information from osquery
CLI Example:

View file

@ -127,8 +127,6 @@ def probe(*devices):
def list_(device, unit=None):
'''
partition.list device unit
Prints partition information of given <device>
CLI Examples:
@ -195,8 +193,6 @@ def list_(device, unit=None):
def align_check(device, part_type, partition):
'''
partition.align_check device part_type partition
Check if partition satisfies the alignment constraint of part_type.
Type must be "minimal" or "optimal".
@ -229,8 +225,6 @@ def align_check(device, part_type, partition):
def check(device, minor):
'''
partition.check device minor
Checks if the file system on partition <minor> has any errors.
CLI Example:
@ -255,11 +249,9 @@ def check(device, minor):
def cp(device, from_minor, to_minor): # pylint: disable=C0103
'''
partition.check device from_minor to_minor
Copies the file system on the partition <from-minor> to partition
<to-minor>, deleting the original contents of the destination
partition.
<to-minor>, deleting the original contents of the destination
partition.
CLI Example:
@ -284,8 +276,6 @@ def cp(device, from_minor, to_minor): # pylint: disable=C0103
def get_id(device, minor):
'''
partition.get_id
Prints the system ID for the partition. Some typical values are::
b: FAT32 (vfat)
@ -317,8 +307,6 @@ def get_id(device, minor):
def set_id(device, minor, system_id):
'''
partition.set_id
Sets the system ID for the partition. Some typical values are::
b: FAT32 (vfat)
@ -376,12 +364,9 @@ def system_types():
def mkfs(device, fs_type):
'''
partition.mkfs device fs_type
Makes a file system <fs_type> on partition <device>, destroying all data
that resides on that partition. <fs_type> must be one of "ext2",
"fat32", "fat16", "linux-swap" or "reiserfs" (if libreiserfs is
installed)
that resides on that partition. <fs_type> must be one of "ext2", "fat32",
"fat16", "linux-swap" or "reiserfs" (if libreiserfs is installed)
CLI Example:
@ -409,9 +394,8 @@ def mkfs(device, fs_type):
def mklabel(device, label_type):
'''
partition.mklabel device label_type
Create a new disklabel (partition table) of label_type.
Type should be one of "aix", "amiga", "bsd", "dvh", "gpt", "loop", "mac",
"msdos", "pc98", or "sun".
@ -435,11 +419,9 @@ def mklabel(device, label_type):
def mkpart(device, part_type, fs_type=None, start=None, end=None):
'''
partition.mkpart device part_type fs_type start end
Make a part_type partition for filesystem fs_type, beginning at start and
ending at end (by default in megabytes). part_type should be one of
"primary", "logical", or "extended".
ending at end (by default in megabytes). part_type should be one of
"primary", "logical", or "extended".
CLI Examples:
@ -480,13 +462,12 @@ def mkpart(device, part_type, fs_type=None, start=None, end=None):
def mkpartfs(device, part_type, fs_type, start, end):
'''
partition.mkpartfs device part_type fs_type start end
Make a <part_type> partition with a new filesystem of <fs_type>, beginning
at <start> and ending at <end> (by default in megabytes). <part_type>
should be one of "primary", "logical", or "extended". <fs_type> must be
one of "ext2", "fat32", "fat16", "linux-swap" or "reiserfs" (if
libreiserfs is installed)
at <start> and ending at <end> (by default in megabytes).
<part_type> should be one of "primary", "logical", or "extended". <fs_type>
must be one of "ext2", "fat32", "fat16", "linux-swap" or "reiserfs" (if
libreiserfs is installed)
CLI Example:
@ -519,10 +500,8 @@ def mkpartfs(device, part_type, fs_type, start, end):
def name(device, partition, name):
'''
partition.name device partition name
Set the name of partition to name. This option works only on Mac, PC98,
and GPT disklabels. The name can be placed in quotes, if necessary.
Set the name of partition to name. This option works only on Mac, PC98, and
GPT disklabels. The name can be placed in quotes, if necessary.
CLI Example:
@ -553,11 +532,9 @@ def name(device, partition, name):
def rescue(device, start, end):
'''
partition.rescue device start end
Rescue a lost partition that was located somewhere between start and end.
If a partition is found, parted will ask if you want to create an
entry for it in the partition table.
If a partition is found, parted will ask if you want to create an
entry for it in the partition table.
CLI Example:
@ -576,13 +553,12 @@ def rescue(device, start, end):
def resize(device, minor, start, end):
'''
partition.resize device minor, start, end
Resizes the partition with number <minor>.
Resizes the partition with number <minor>. The partition will start <start>
from the beginning of the disk, and end <end> from the beginning of the
disk. resize never changes the minor number. Extended partitions can be
resized, so long as the new extended partition completely contains all
logical partitions.
The partition will start <start> from the beginning of the disk, and end
<end> from the beginning of the disk. resize never changes the minor number.
Extended partitions can be resized, so long as the new extended partition
completely contains all logical partitions.
CLI Example:
@ -612,8 +588,6 @@ def resize(device, minor, start, end):
def rm(device, minor): # pylint: disable=C0103
'''
partition.rm device minor
Removes the partition with number <minor>.
CLI Example:
@ -638,11 +612,10 @@ def rm(device, minor): # pylint: disable=C0103
def set_(device, minor, flag, state):
'''
partition.set device minor flag state
Changes a flag on the partition with number <minor>.
Changes a flag on the partition with number <minor>. A flag can be either
"on" or "off". Some or all of these flags will be available, depending
on what disk label you are using.
A flag can be either "on" or "off". Some or all of these flags will be
available, depending on what disk label you are using.
Valid flags are: bios_grub, legacy_boot, boot, lba, root, swap, hidden, raid,
LVM, PALO, PREP, DIAG
@ -676,8 +649,6 @@ def set_(device, minor, flag, state):
def toggle(device, partition, flag):
'''
partition.toggle device partition flag
Toggle the state of <flag> on <partition>. Valid flags are the same as
the set command.
@ -707,8 +678,6 @@ def toggle(device, partition, flag):
def exists(device=''):
'''
partition.exists device
Check to see if the partition exists
CLI Example:

View file

@ -92,7 +92,7 @@ def _umount(mpt, ftype):
def apply_(path, id_=None, config=None, approve_key=True, install=True,
prep_install=False, mount_point=None):
prep_install=False, pub_key=None, priv_key=None, mount_point=None):
'''
Seed a location (disk image, directory, or block device) with the
minion config, approve the minion's key, and/or install salt-minion.
@ -132,18 +132,27 @@ def apply_(path, id_=None, config=None, approve_key=True, install=True,
return '{0} does not exist'.format(path)
ftype = stats['type']
path = stats['target']
log.debug('Mounting {0} at {1}'.format(ftype, path))
try:
os.makedirs(path)
except OSError:
# The directory already exists
pass
mpt = _mount(path, ftype, mount_point)
if not mpt:
return '{0} could not be mounted'.format(path)
tmp = os.path.join(mpt, 'tmp')
log.debug('Attempting to create directory {0}'.format(tmp))
try:
os.makedirs(tmp)
except OSError:
if not os.path.isdir(tmp):
raise
cfg_files = mkconfig(config, tmp=tmp, id_=id_, approve_key=approve_key)
cfg_files = mkconfig(config, tmp=tmp, id_=id_, approve_key=approve_key,
pub_key=pub_key, priv_key=priv_key)
if _check_install(mpt):
# salt-minion is already installed, just move the config and keys
@ -163,8 +172,7 @@ def apply_(path, id_=None, config=None, approve_key=True, install=True,
os.rename(cfg_files['config'], os.path.join(mpt, 'etc/salt/minion'))
res = True
elif install:
log.info('attempting to install salt-minion to '
'{0}'.format(mpt))
log.info('Attempting to install salt-minion to {0}'.format(mpt))
res = _install(mpt)
elif prep_install:
log.error('The prep_install option is no longer supported. Please use '
@ -220,12 +228,16 @@ def mkconfig(config=None,
privkeyfn = os.path.join(tmp, 'minion.pem')
preseeded = pub_key and priv_key
if preseeded:
log.debug('Writing minion.pub to {0}'.format(pubkeyfn))
log.debug('Writing minion.pem to {0}'.format(privkeyfn))
with salt.utils.fopen(pubkeyfn, 'w') as fic:
fic.write(_file_or_content(pub_key))
with salt.utils.fopen(privkeyfn, 'w') as fic:
fic.write(_file_or_content(priv_key))
os.chmod(pubkeyfn, 0o600)
os.chmod(privkeyfn, 0o600)
with salt.utils.fopen(pubkeyfn, 'w') as fic:
fic.write(_file_or_content(pub_key))
else:
salt.crypt.gen_keys(tmp, 'minion', 2048)
if approve_key and not preseeded:
@ -242,7 +254,6 @@ def _install(mpt):
install it.
Return True if install is successful or already installed.
'''
_check_resolv(mpt)
boot_, tmppath = (prep_bootstrap(mpt)
or salt.syspaths.BOOTSTRAP)

View file

@ -30,6 +30,7 @@ from salt.ext.six.moves import StringIO as _StringIO # pylint: disable=import-e
from xml.dom import minidom
try:
import libvirt # pylint: disable=import-error
from libvirt import libvirtError
HAS_LIBVIRT = True
except ImportError:
HAS_LIBVIRT = False
@ -142,7 +143,7 @@ def __get_conn():
__esxi_auth(),
0]],
'qemu': [libvirt.open, [conn_str]],
}
}
hypervisor = __salt__['config.get']('libvirt:hypervisor', 'qemu')
@ -234,7 +235,7 @@ def _gen_xml(name,
hypervisor,
**kwargs):
'''
Generate the XML string to define a libvirt vm
Generate the XML string to define a libvirt VM
'''
hypervisor = 'vmware' if hypervisor == 'esxi' else hypervisor
mem = mem * 1024 # MB
@ -521,9 +522,9 @@ def _nic_profile(profile_name, hypervisor, **kwargs):
attributes[key] = value
def _assign_mac(attributes):
dmac = '{0}_mac'.format(attributes['name'])
if dmac in kwargs:
dmac = kwargs[dmac]
dmac = kwargs.get('dmac', None)
if dmac is not None:
log.debug('DMAC address is {0}'.format(dmac))
if salt.utils.validate.net.mac(dmac):
attributes['mac'] = dmac
else:
@ -550,6 +551,11 @@ def init(name,
start=True, # pylint: disable=redefined-outer-name
disk='default',
saltenv='base',
seed=True,
install=True,
pub_key=None,
priv_key=None,
seed_cmd='seed.apply',
**kwargs):
'''
Initialize a new vm
@ -562,17 +568,21 @@ def init(name,
salt 'hypervisor' virt.init vm_name 4 512 nic=profile disk=profile
'''
hypervisor = __salt__['config.get']('libvirt:hypervisor', hypervisor)
log.debug('Using hyperisor {0}'.format(hypervisor))
nicp = _nic_profile(nic, hypervisor, **kwargs)
log.debug('NIC profile is {0}'.format(nicp))
diskp = None
seedable = False
if image: # with disk template image
log.debug('Image {0} will be used'.format(image))
# if image was used, assume only one disk, i.e. the
# 'default' disk profile
# TODO: make it possible to use disk profiles and use the
# template image as the system disk
diskp = _disk_profile('default', hypervisor, **kwargs)
log.debug('Disk profile is {0}'.format(diskp))
# When using a disk profile extract the sole dict key of the first
# array element as the filename for disk
@ -582,9 +592,10 @@ def init(name,
if hypervisor in ['esxi', 'vmware']:
# TODO: we should be copying the image file onto the ESX host
raise SaltInvocationError('virt.init does not support image '
'template template in conjunction '
'with esxi hypervisor')
raise SaltInvocationError(
'virt.init does not support image template template in '
'conjunction with esxi hypervisor'
)
elif hypervisor in ['qemu', 'kvm']:
img_dir = __salt__['config.option']('virt.images')
img_dest = os.path.join(
@ -594,55 +605,71 @@ def init(name,
)
img_dir = os.path.dirname(img_dest)
sfn = __salt__['cp.cache_file'](image, saltenv)
if not os.path.isdir(img_dir):
os.makedirs(img_dir)
log.debug('Image directory is {0}'.format(img_dir))
try:
os.makedirs(img_dir)
except OSError:
pass
try:
log.debug('Copying {0} to {1}'.format(sfn, img_dest))
salt.utils.files.copyfile(sfn, img_dest)
mask = os.umask(0)
os.umask(mask)
# Apply umask and remove exec bit
mode = (0o0777 ^ mask) & 0o0666
os.chmod(img_dest, mode)
except (IOError, OSError) as e:
raise CommandExecutionError('problem copying image. {0} - {1}'.format(image, e))
seedable = True
else:
log.error('unsupported hypervisor when handling disk image')
log.error('Unsupported hypervisor when handling disk image')
else:
# no disk template image specified, create disks based on disk profile
diskp = _disk_profile(disk, hypervisor, **kwargs)
log.debug('No image specified, disk profile will be used: {0}'.format(diskp))
if hypervisor in ['qemu', 'kvm']:
# TODO: we should be creating disks in the local filesystem with
# qemu-img
raise SaltInvocationError('virt.init does not support disk '
'profiles in conjunction with '
'qemu/kvm at this time, use image '
'template instead')
raise SaltInvocationError(
'virt.init does not support disk profiles in conjunction with '
'qemu/kvm at this time, use image template instead'
)
else:
# assume libvirt manages disks for us
for disk in diskp:
for disk_name, args in six.iteritems(disk):
xml = _gen_vol_xml(name,
disk_name,
args['size'],
hypervisor)
log.debug('Generating libvirt XML for {0}'.format(disk))
xml = _gen_vol_xml(
name,
disk_name,
args['size'],
hypervisor,
)
define_vol_xml_str(xml)
log.debug('Generating VM XML')
xml = _gen_xml(name, cpu, mem, diskp, nicp, hypervisor, **kwargs)
define_xml_str(xml)
try:
define_xml_str(xml)
except libvirtError:
# This domain already exists
pass
if kwargs.get('seed') and seedable:
install = kwargs.get('install', True)
seed_cmd = kwargs.get('seed_cmd', 'seed.apply')
__salt__[seed_cmd](img_dest,
id_=name,
config=kwargs.get('config'),
install=install)
if seed and seedable:
log.debug('Seed command is {0}'.format(seed_cmd))
__salt__[seed_cmd](
img_dest,
id_=name,
config=kwargs.get('config'),
install=install,
pub_key=pub_key,
priv_key=priv_key,
)
if start:
log.debug('Creating {0}'.format(name))
_get_domain(name).create()
return True

View file

@ -640,6 +640,7 @@ def install(name=None,
sources=None,
downloadonly=None,
skip_verify=False,
version=None,
**kwargs):
'''
Install the passed package(s), add refresh=True to run 'zypper refresh'
@ -711,23 +712,20 @@ def install(name=None,
'new': '<new-version>'}}
'''
try:
pkg_params, pkg_type = __salt__['pkg_resource.parse_targets'](
name, pkgs, sources, **kwargs
)
pkg_params, pkg_type = __salt__['pkg_resource.parse_targets'](name, pkgs, sources, **kwargs)
except MinionError as exc:
raise CommandExecutionError(exc)
if pkg_params is None or len(pkg_params) == 0:
return {}
version_num = kwargs.get('version')
version_num = version
if version_num:
if pkgs is None and sources is None:
# Allow "version" to work for single package target
pkg_params = {name: version_num}
else:
log.warning('\'version\' parameter will be ignored for multiple '
'package targets')
log.warning("'version' parameter will be ignored for multiple package targets")
if pkg_type == 'repository':
targets = []
@ -736,18 +734,13 @@ def install(name=None,
if version_num is None:
targets.append(param)
else:
match = re.match('^([<>])?(=)?([^<>=]+)$', version_num)
match = re.match(r'^([<>])?(=)?([^<>=]+)$', version_num)
if match:
gt_lt, equal, verstr = match.groups()
prefix = gt_lt or ''
prefix += equal or ''
# If no prefix characters were supplied, use '='
prefix = prefix or '='
targets.append('{0}{1}{2}'.format(param, prefix, verstr))
targets.append('{0}{1}{2}'.format(param, ((gt_lt or '') + (equal or '')) or '=', verstr))
log.debug(targets)
else:
msg = ('Invalid version string \'{0}\' for package '
'\'{1}\''.format(version_num, name))
msg = ('Invalid version string {0!r} for package {1!r}'.format(version_num, name))
problems.append(msg)
if problems:
for problem in problems:
@ -781,21 +774,14 @@ def install(name=None,
while targets:
cmd = cmd_install + targets[:500]
targets = targets[500:]
out = __salt__['cmd.run_all'](cmd,
output_loglevel='trace',
python_shell=False)
if out['retcode'] != 0 and out['stderr']:
errors.append(out['stderr'])
for line in out.splitlines():
match = re.match(
"^The selected package '([^']+)'.+has lower version",
line
)
if match:
downgrades.append(match.group(1))
call = __salt__['cmd.run_all'](cmd, output_loglevel='trace', python_shell=False)
if call['retcode'] != 0:
raise CommandExecutionError(call['stderr']) # Fixme: This needs a proper report mechanism.
else:
for line in call['stdout'].splitlines():
match = re.match(r"^The selected package '([^']+)'.+has lower version", line)
if match:
downgrades.append(match.group(1))
while downgrades:
cmd = cmd_install + ['--force'] + downgrades[:500]

View file

@ -5,11 +5,13 @@ Control virtual machines via Salt
# Import python libs
from __future__ import absolute_import, print_function
import os.path
import logging
# Import Salt libs
import salt.client
import salt.utils.virt
import salt.utils.cloud
import salt.key
from salt.exceptions import SaltClientError
@ -19,14 +21,13 @@ import salt.ext.six as six
log = logging.getLogger(__name__)
def _determine_hyper(data, omit=''):
def _determine_host(data, omit=''):
'''
Determine what the most resource free hypervisor is based on the given
data
Determine what the most resource free host is based on the given data
'''
# This is just checking for the hyper with the most free ram, this needs
# This is just checking for the host with the most free ram, this needs
# to be much more complicated.
hyper = ''
host = ''
bestmem = 0
for hv_, comps in six.iteritems(data):
if hv_ == omit:
@ -35,13 +36,13 @@ def _determine_hyper(data, omit=''):
continue
if comps.get('freemem', 0) > bestmem:
bestmem = comps['freemem']
hyper = hv_
return hyper
host = hv_
return host
def _find_vm(name, data, quiet=False):
'''
Scan the query data for the named vm
Scan the query data for the named VM
'''
for hv_ in data:
# Check if data is a dict, and not '"virt.full_info" is not available.'
@ -55,12 +56,20 @@ def _find_vm(name, data, quiet=False):
return {}
def query(hyper=None, quiet=False):
def query(host=None, quiet=False, hyper=None):
'''
Query the virtual machines. When called without options all hypervisors
are detected and a full query is returned. A single hypervisor can be
passed in to specify an individual hypervisor to query.
Query the virtual machines. When called without options all hosts
are detected and a full query is returned. A single host can be
passed in to specify an individual host to query.
'''
if hyper is not None:
salt.utils.warn_until(
'Carbon',
'Please use "host" instead of "hyper". The "hyper" argument will '
'be removed in the Carbon release of Salt'
)
host = hyper
if quiet:
log.warn('\'quiet\' is deprecated. Please migrate to --quiet')
ret = {}
@ -74,8 +83,8 @@ def query(hyper=None, quiet=False):
continue
chunk = {}
id_ = next(info.iterkeys())
if hyper:
if hyper != id_:
if host:
if host != id_:
continue
if not isinstance(info[id_], dict):
continue
@ -92,13 +101,21 @@ def query(hyper=None, quiet=False):
return ret
def list(hyper=None, quiet=False): # pylint: disable=redefined-builtin
def list(host=None, quiet=False, hyper=None): # pylint: disable=redefined-builtin
'''
List the virtual machines on each hyper, this is a simplified query,
showing only the virtual machine names belonging to each hypervisor.
A single hypervisor can be passed in to specify an individual hypervisor
List the virtual machines on each host, this is a simplified query,
showing only the virtual machine names belonging to each host.
A single host can be passed in to specify an individual host
to list.
'''
if hyper is not None:
salt.utils.warn_until(
'Carbon',
'Please use "host" instead of "hyper". The "hyper" argument will '
'be removed in the Carbon release of Salt'
)
host = hyper
if quiet:
log.warn('\'quiet\' is deprecated. Please migrate to --quiet')
ret = {}
@ -111,8 +128,8 @@ def list(hyper=None, quiet=False): # pylint: disable=redefined-builtin
continue
chunk = {}
id_ = next(six.iterkeys(info))
if hyper:
if hyper != id_:
if host:
if host != id_:
continue
if not isinstance(info[id_], dict):
continue
@ -134,22 +151,36 @@ def list(hyper=None, quiet=False): # pylint: disable=redefined-builtin
return ret
def next_host():
'''
Return the host to use for the next autodeployed VM. This queries
the available host and executes some math the determine the most
"available" next host.
'''
host = _determine_host(query(quiet=True))
print(host)
return host
def next_hyper():
'''
Return the hypervisor to use for the next autodeployed vm. This queries
the available hypervisors and executes some math the determine the most
"available" next hypervisor.
Return the host to use for the next autodeployed VM. This queries
the available host and executes some math the determine the most
"available" next host.
'''
hyper = _determine_hyper(query(quiet=True))
print(hyper)
return hyper
salt.utils.warn_until(
'Carbon',
'Please use "host" instead of "hyper". The "hyper" argument will '
'be removed in the Carbon release of Salt'
)
return next_host()
def hyper_info(hyper=None):
def host_info(host=None):
'''
Return information about the hypervisors connected to this master
Return information about the host connected to this master
'''
data = query(hyper, quiet=True)
data = query(host, quiet=True)
for id_ in data:
if 'vm_info' in data[id_]:
data[id_].pop('vm_info')
@ -157,15 +188,32 @@ def hyper_info(hyper=None):
return data
def hyper_info(hyper=None):
'''
Return information about the host connected to this master
'''
salt.utils.warn_until(
'Carbon',
'Please use "host" instead of "hyper". The "hyper" argument will '
'be removed in the Carbon release of Salt'
)
return host_info(hyper)
def init(
name,
cpu,
mem,
image,
hyper=None,
hypervisor='kvm',
host=None,
seed=True,
nic='default',
install=True):
install=True,
start=True,
disk='default',
saltenv='base'):
'''
This routine is used to create a new virtual machine. This routines takes
a number of options to determine what the newly created virtual machine
@ -186,58 +234,94 @@ def init(
The network location of the virtual machine image, commonly a location
on the salt fileserver, but http, https and ftp can also be used.
hyper
The hypervisor to use for the new virtual machine, if this is omitted
Salt will automatically detect what hypervisor to use.
hypervisor
The hypervisor to use for the new virtual machine. Default is 'kvm'.
host
The host to use for the new virtual machine, if this is omitted
Salt will automatically detect what host to use.
seed
Set to False to prevent Salt from seeding the new virtual machine.
nic
The nic profile to use, defaults to the "default" nic profile which
assumes a single network interface per vm associated with the "br0"
assumes a single network interface per VM associated with the "br0"
bridge on the master.
install
Set to False to prevent Salt from installing a minion on the new vm
Set to False to prevent Salt from installing a minion on the new VM
before it spins up.
disk
The disk profile to use
saltenv
The Salt environment to use
'''
__jid_event__.fire_event({'message': 'Searching for Hypervisors'}, 'progress')
data = query(hyper, quiet=True)
if hyper is not None:
salt.utils.warn_until(
'Carbon',
'Please use "host" instead of "hyper". The "hyper" argument will '
'be removed in the Carbon release of Salt'
)
host = hyper
__jid_event__.fire_event({'message': 'Searching for hosts'}, 'progress')
data = query(host, quiet=True)
# Check if the name is already deployed
for hyper in data:
if 'vm_info' in data[hyper]:
if name in data[hyper]['vm_info']:
__jid_event__.fire_event({'message': 'Virtual machine {0} is already deployed'.format(name)}, 'progress')
for node in data:
if 'vm_info' in data[node]:
if name in data[node]['vm_info']:
__jid_event__.fire_event(
{'message': 'Virtual machine {0} is already deployed'.format(name)},
'progress'
)
return 'fail'
if hyper is None:
hyper = _determine_hyper(data)
if host is None:
host = _determine_host(data)
if hyper not in data or not hyper:
__jid_event__.fire_event({'message': 'Hypervisor {0} was not found'.format(hyper)}, 'progress')
if host not in data or not host:
__jid_event__.fire_event(
{'message': 'Host {0} was not found'.format(host)},
'progress'
)
return 'fail'
pub_key = None
priv_key = None
if seed:
__jid_event__.fire_event({'message': 'Minion will be preseeded'}, 'progress')
kv_ = salt.utils.virt.VirtKey(hyper, name, __opts__)
kv_.authorize()
priv_key, pub_key = salt.utils.cloud.gen_keys()
accepted_key = os.path.join(__opts__['pki_dir'], 'minions', name)
with salt.utils.fopen(accepted_key, 'w') as fp_:
fp_.write(pub_key)
client = salt.client.get_local_client(__opts__['conf_file'])
__jid_event__.fire_event({'message': 'Creating VM {0} on hypervisor {1}'.format(name, hyper)}, 'progress')
__jid_event__.fire_event(
{'message': 'Creating VM {0} on host {1}'.format(name, host)},
'progress'
)
try:
cmd_ret = client.cmd_iter(
hyper,
host,
'virt.init',
[
name,
cpu,
mem,
image,
'seed={0}'.format(seed),
'nic={0}'.format(nic),
'install={0}'.format(install),
nic,
hypervisor,
start,
disk,
saltenv,
seed,
install,
pub_key,
priv_key,
],
timeout=600)
except SaltClientError as client_error:
@ -253,13 +337,13 @@ def init(
print('VM {0} initialization failed. Returned error: {1}'.format(name, ret[minion_id]['ret']))
return 'fail'
__jid_event__.fire_event({'message': 'VM {0} initialized on hypervisor {1}'.format(name, hyper)}, 'progress')
__jid_event__.fire_event({'message': 'VM {0} initialized on host {1}'.format(name, host)}, 'progress')
return 'good'
def vm_info(name, quiet=False):
'''
Return the information on the named vm
Return the information on the named VM
'''
data = query(quiet=True)
return _find_vm(name, data, quiet)
@ -267,18 +351,18 @@ def vm_info(name, quiet=False):
def reset(name):
'''
Force power down and restart an existing vm
Force power down and restart an existing VM
'''
ret = {}
client = salt.client.get_local_client(__opts__['conf_file'])
data = vm_info(name, quiet=True)
if not data:
__jid_event__.fire_event({'message': 'Failed to find vm {0} to reset'.format(name)}, 'progress')
__jid_event__.fire_event({'message': 'Failed to find VM {0} to reset'.format(name)}, 'progress')
return 'fail'
hyper = next(six.iterkeys(data))
host = next(six.iterkeys(data))
try:
cmd_ret = client.cmd_iter(
hyper,
host,
'virt.reset',
[name],
timeout=600)
@ -298,15 +382,15 @@ def start(name):
client = salt.client.get_local_client(__opts__['conf_file'])
data = vm_info(name, quiet=True)
if not data:
__jid_event__.fire_event({'message': 'Failed to find vm {0} to start'.format(name)}, 'progress')
__jid_event__.fire_event({'message': 'Failed to find VM {0} to start'.format(name)}, 'progress')
return 'fail'
hyper = next(six.iterkeys(data))
if data[hyper][name]['state'] == 'running':
host = next(six.iterkeys(data))
if data[host][name]['state'] == 'running':
print('VM {0} is already running'.format(name))
return 'bad state'
try:
cmd_ret = client.cmd_iter(
hyper,
host,
'virt.start',
[name],
timeout=600)
@ -326,15 +410,15 @@ def force_off(name):
client = salt.client.get_local_client(__opts__['conf_file'])
data = vm_info(name, quiet=True)
if not data:
print('Failed to find vm {0} to destroy'.format(name))
print('Failed to find VM {0} to destroy'.format(name))
return 'fail'
hyper = next(six.iterkeys(data))
if data[hyper][name]['state'] == 'shutdown':
host = next(six.iterkeys(data))
if data[host][name]['state'] == 'shutdown':
print('VM {0} is already shutdown'.format(name))
return'bad state'
try:
cmd_ret = client.cmd_iter(
hyper,
host,
'virt.destroy',
[name],
timeout=600)
@ -348,18 +432,18 @@ def force_off(name):
def purge(name, delete_key=True):
'''
Destroy the named vm
Destroy the named VM
'''
ret = {}
client = salt.client.get_local_client(__opts__['conf_file'])
data = vm_info(name, quiet=True)
if not data:
__jid_event__.fire_event({'error': 'Failed to find vm {0} to purge'.format(name)}, 'progress')
__jid_event__.fire_event({'error': 'Failed to find VM {0} to purge'.format(name)}, 'progress')
return 'fail'
hyper = next(six.iterkeys(data))
host = next(six.iterkeys(data))
try:
cmd_ret = client.cmd_iter(
hyper,
host,
'virt.purge',
[name, True],
timeout=600)
@ -370,6 +454,7 @@ def purge(name, delete_key=True):
ret.update(comp)
if delete_key:
log.debug('Deleting key {0}'.format(name))
skey = salt.key.Key(__opts__)
skey.delete_key(name)
__jid_event__.fire_event({'message': 'Purged VM {0}'.format(name)}, 'progress')
@ -378,7 +463,7 @@ def purge(name, delete_key=True):
def pause(name):
'''
Pause the named vm
Pause the named VM
'''
ret = {}
client = salt.client.get_local_client(__opts__['conf_file'])
@ -387,13 +472,13 @@ def pause(name):
if not data:
__jid_event__.fire_event({'error': 'Failed to find VM {0} to pause'.format(name)}, 'progress')
return 'fail'
hyper = next(six.iterkeys(data))
if data[hyper][name]['state'] == 'paused':
host = next(six.iterkeys(data))
if data[host][name]['state'] == 'paused':
__jid_event__.fire_event({'error': 'VM {0} is already paused'.format(name)}, 'progress')
return 'bad state'
try:
cmd_ret = client.cmd_iter(
hyper,
host,
'virt.pause',
[name],
timeout=600)
@ -407,7 +492,7 @@ def pause(name):
def resume(name):
'''
Resume a paused vm
Resume a paused VM
'''
ret = {}
client = salt.client.get_local_client(__opts__['conf_file'])
@ -415,13 +500,13 @@ def resume(name):
if not data:
__jid_event__.fire_event({'error': 'Failed to find VM {0} to pause'.format(name)}, 'progress')
return 'not found'
hyper = next(six.iterkeys(data))
if data[hyper][name]['state'] != 'paused':
host = next(six.iterkeys(data))
if data[host][name]['state'] != 'paused':
__jid_event__.fire_event({'error': 'VM {0} is not paused'.format(name)}, 'progress')
return 'bad state'
try:
cmd_ret = client.cmd_iter(
hyper,
host,
'virt.resume',
[name],
timeout=600)
@ -435,36 +520,36 @@ def resume(name):
def migrate(name, target=''):
'''
Migrate a vm from one hypervisor to another. This routine will just start
Migrate a VM from one host to another. This routine will just start
the migration and display information on how to look up the progress.
'''
client = salt.client.get_local_client(__opts__['conf_file'])
data = query(quiet=True)
origin_data = _find_vm(name, data, quiet=True)
try:
origin_hyper = list(origin_data.keys())[0]
origin_host = list(origin_data.keys())[0]
except IndexError:
__jid_event__.fire_event({'error': 'Named vm {0} was not found to migrate'.format(name)}, 'progress')
__jid_event__.fire_event({'error': 'Named VM {0} was not found to migrate'.format(name)}, 'progress')
return ''
disks = origin_data[origin_hyper][name]['disks']
disks = origin_data[origin_host][name]['disks']
if not origin_data:
__jid_event__.fire_event({'error': 'Named vm {0} was not found to migrate'.format(name)}, 'progress')
__jid_event__.fire_event({'error': 'Named VM {0} was not found to migrate'.format(name)}, 'progress')
return ''
if not target:
target = _determine_hyper(data, origin_hyper)
target = _determine_host(data, origin_host)
if target not in data:
__jid_event__.fire_event({'error': 'Target hypervisor {0} not found'.format(origin_data)}, 'progress')
__jid_event__.fire_event({'error': 'Target host {0} not found'.format(origin_data)}, 'progress')
return ''
try:
client.cmd(target, 'virt.seed_non_shared_migrate', [disks, True])
jid = client.cmd_async(origin_hyper,
jid = client.cmd_async(origin_host,
'virt.migrate_non_shared',
[name, target])
except SaltClientError as client_error:
return 'Virtual machine {0} could not be migrated: {1}'.format(name, client_error)
msg = ('The migration of virtual machine {0} to hypervisor {1} has begun, '
msg = ('The migration of virtual machine {0} to host {1} has begun, '
'and can be tracked via jid {2}. The ``salt-run virt.query`` '
'runner can also be used, the target vm will be shown as paused '
'runner can also be used, the target VM will be shown as paused '
'until the migration is complete.').format(name, target, jid)
__jid_event__.fire_event({'message': msg}, 'progress')

View file

@ -383,31 +383,33 @@ def present(
lb = __salt__['boto_elb.get_elb_config'](
name, region, key, keyid, profile
)
for cname in cnames:
_ret = None
dns_provider = 'boto_route53'
cname['record_type'] = 'CNAME'
cname['value'] = lb['dns_name']
if 'provider' in cname:
dns_provider = cname.pop('provider')
if dns_provider == 'boto_route53':
if 'profile' not in cname:
cname['profile'] = profile
if 'key' not in cname:
cname['key'] = key
if 'keyid' not in cname:
cname['keyid'] = keyid
if 'region' not in cname:
cname['region'] = region
if 'wait_for_sync' not in cname:
cname['wait_for_sync'] = wait_for_sync
_ret = __states__['.'.join([dns_provider, 'present'])](**cname)
ret['changes'] = dictupdate.update(ret['changes'], _ret['changes'])
ret['comment'] = ' '.join([ret['comment'], _ret['comment']])
if not _ret['result']:
ret['result'] = _ret['result']
if ret['result'] is False:
return ret
if len(lb) > 0:
for cname in cnames:
_ret = None
dns_provider = 'boto_route53'
cname['record_type'] = 'CNAME'
cname['value'] = lb['dns_name']
if 'provider' in cname:
dns_provider = cname.pop('provider')
if dns_provider == 'boto_route53':
if 'profile' not in cname:
cname['profile'] = profile
if 'key' not in cname:
cname['key'] = key
if 'keyid' not in cname:
cname['keyid'] = keyid
if 'region' not in cname:
cname['region'] = region
if 'wait_for_sync' not in cname:
cname['wait_for_sync'] = wait_for_sync
_ret = __states__['.'.join([dns_provider, 'present'])](**cname)
ret['changes'] = dictupdate.update(ret['changes'], _ret['changes'])
ret['comment'] = ' '.join([ret['comment'], _ret['comment']])
if not _ret['result']:
ret['result'] = _ret['result']
if ret['result'] is False:
return ret
_ret = _alarms_present(name, alarms, alarms_from_pillar, region, key, keyid, profile)
ret['changes'] = dictupdate.update(ret['changes'], _ret['changes'])
ret['comment'] = ' '.join([ret['comment'], _ret['comment']])

View file

@ -2581,7 +2581,7 @@ def line(name, content, match=None, mode=None, location=None,
.. code-block: yaml
/etc/myconfig.conf
/etc/myconfig.conf:
file.line:
- mode: ensure
- content: my key = my value

View file

@ -47,6 +47,7 @@ argument, to avoid a collision with the ``name`` argument.
Here is a list of keywords hidden by the state system, which must be prefixed
with ``m_``:
* fun
* name
* names

View file

@ -1447,8 +1447,7 @@ def latest(
'''
rtag = __gen_rtag()
refresh = bool(
salt.utils.is_true(refresh)
or (os.path.isfile(rtag) and refresh is not False)
salt.utils.is_true(refresh) or (os.path.isfile(rtag) and refresh is not False)
)
if kwargs.get('sources'):
@ -1466,7 +1465,15 @@ def latest(
'comment': 'Invalidly formatted "pkgs" parameter. See '
'minion log.'}
else:
desired_pkgs = [name]
if isinstance(pkgs, list) and len(pkgs) == 0:
return {
'name': name,
'changes': {},
'result': True,
'comment': 'No packages to install provided'
}
else:
desired_pkgs = [name]
cur = __salt__['pkg.version'](*desired_pkgs, **kwargs)
try:
@ -1505,33 +1512,29 @@ def latest(
log.error(msg)
problems.append(msg)
else:
if salt.utils.compare_versions(ver1=cur[pkg],
oper='!=',
ver2=avail[pkg],
cmp_func=cmp_func):
if salt.utils.compare_versions(ver1=cur[pkg], oper='!=', ver2=avail[pkg], cmp_func=cmp_func):
targets[pkg] = avail[pkg]
else:
if not cur[pkg] or __salt__['portage_config.is_changed_uses'](pkg):
targets[pkg] = avail[pkg]
else:
for pkg in desired_pkgs:
if not avail[pkg]:
if not cur[pkg]:
if pkg not in avail:
if not cur.get(pkg):
msg = 'No information found for \'{0}\'.'.format(pkg)
log.error(msg)
problems.append(msg)
elif not cur[pkg] \
or salt.utils.compare_versions(ver1=cur[pkg],
oper='<',
ver2=avail[pkg],
cmp_func=cmp_func):
elif not cur.get(pkg) \
or salt.utils.compare_versions(ver1=cur[pkg], oper='<', ver2=avail[pkg], cmp_func=cmp_func):
targets[pkg] = avail[pkg]
if problems:
return {'name': name,
'changes': {},
'result': False,
'comment': ' '.join(problems)}
return {
'name': name,
'changes': {},
'result': False,
'comment': ' '.join(problems)
}
if targets:
# Find up-to-date packages

View file

@ -47,28 +47,31 @@ def joined(name, host, user='rabbit', ram_node=None, runas='root'):
'''
ret = {'name': name, 'result': True, 'comment': '', 'changes': {}}
result = {}
joined = __salt__['rabbitmq.cluster_status']()
if '{0}@{1}'.format(user, host) in joined:
status = __salt__['rabbitmq.cluster_status']()
if '{0}@{1}'.format(user, host) in status:
ret['comment'] = 'Already in cluster'
return ret
if not __opts__['test']:
result = __salt__['rabbitmq.join_cluster'](host,
user,
ram_node,
runas=runas)
if 'Error' in result:
ret['result'] = False
ret['comment'] = result['Error']
return ret
elif 'Join' in result:
ret['comment'] = result['Join']
# If we've reached this far before returning, we have changes.
ret['changes'] = {'old': '', 'new': '{0}@{1}'.format(user, host)}
if __opts__['test']:
ret['result'] = None
ret['comment'] = 'Node is set to join cluster {0}@{1}'.format(
user, host)
return ret
result = __salt__['rabbitmq.join_cluster'](host, user,
ram_node, runas=runas)
if 'Error' in result:
ret['result'] = False
ret['comment'] = result['Error']
elif 'Join' in result:
ret['comment'] = result['Join']
ret['changes'] = {'old': '', 'new': '{0}@{1}'.format(user, host)}
return ret

View file

@ -75,33 +75,40 @@ def present(name,
ret['comment'] = 'Policy {0} {1} is already present'.format(vhost, name)
return ret
if __opts__['test']:
ret['result'] = None
if not policy:
if not policy:
ret['changes'].update({'old': {}, 'new': name})
if __opts__['test']:
ret['comment'] = 'Policy {0} {1} is set to be created'.format(vhost, name)
elif updates:
else:
log.debug('Policy doesn\'t exist - Creating')
result = __salt__['rabbitmq.set_policy'](vhost,
name,
pattern,
definition,
priority=priority,
runas=runas)
elif updates:
ret['changes'].update({'old': policy, 'new': updates})
if __opts__['test']:
ret['comment'] = 'Policy {0} {1} is set to be updated'.format(vhost, name)
else:
changes = {'new': '', 'old': ''}
if not policy:
changes['new'] = policy
log.debug(
"Policy doesn't exist - Creating")
result = __salt__['rabbitmq.set_policy'](
vhost, name, pattern, definition, priority=priority, runas=runas)
elif updates:
changes['old'] = policy
changes['new'] = updates
else:
log.debug('Policy exists but needs updating')
result = __salt__['rabbitmq.set_policy'](
vhost, name, pattern, definition, priority=priority, runas=runas)
result = __salt__['rabbitmq.set_policy'](vhost,
name,
pattern,
definition,
priority=priority,
runas=runas)
if 'Error' in result:
ret['result'] = False
ret['comment'] = result['Error']
elif 'Set' in result:
ret['comment'] = result['Set']
ret['changes'] = changes
if 'Error' in result:
ret['result'] = False
ret['comment'] = result['Error']
elif ret['changes'] == {}:
ret['comment'] = '\'{0}\' is already in the desired state.'.format(name)
elif __opts__['test']:
ret['result'] = None
elif 'Set' in result:
ret['comment'] = result['Set']
return ret
@ -125,19 +132,23 @@ def absent(name,
vhost, name, runas=runas)
if not policy_exists:
ret['comment'] = 'Policy {0} {1} is not present'.format(vhost, name)
ret['comment'] = 'Policy \'{0} {1}\' is not present.'.format(vhost, name)
return ret
if __opts__['test']:
ret['result'] = None
ret['comment'] = 'Removing policy {0} {1}'.format(vhost, name)
else:
if not __opts__['test']:
result = __salt__['rabbitmq.delete_policy'](vhost, name, runas=runas)
if 'Error' in result:
ret['result'] = False
ret['comment'] = result['Error']
return ret
elif 'Deleted' in result:
ret['comment'] = 'Deleted'
ret['changes'] = {'new': '', 'old': name}
# If we've reached this far before returning, we have changes.
ret['changes'] = {'new': '', 'old': name}
if __opts__['test']:
ret['result'] = None
ret['comment'] = 'Policy \'{0} {1}\' will be removed.'.format(vhost, name)
return ret

View file

@ -131,7 +131,7 @@ class OptionParser(optparse.OptionParser, object):
usage = '%prog'
epilog = ('You can find additional help about %prog issuing "man %prog" '
'or on http://docs.saltstack.org')
'or on http://docs.saltstack.com')
description = None
# Private attributes

View file

@ -51,7 +51,8 @@ class RabbitmqClusterTestCase(TestCase):
with patch.dict(rabbitmq_cluster.__opts__, {"test": True}):
ret.update({'result': None,
'comment': 'Node is set to join '
'cluster rahulha@salt'})
'cluster rahulha@salt',
'changes': {'new': 'rahulha@salt', 'old': ''}})
self.assertDictEqual(rabbitmq_cluster.joined('salt', 'salt',
'rahulha'), ret)
@ -60,7 +61,8 @@ class RabbitmqClusterTestCase(TestCase):
with patch.dict(rabbitmq_cluster.__salt__,
{"rabbitmq.join_cluster": mock}):
ret.update({'result': False,
'comment': 'ERR'})
'comment': 'ERR',
'changes': {}})
self.assertDictEqual(rabbitmq_cluster.joined('salt',
'salt',
'rahulha'),

View file

@ -56,8 +56,9 @@ class RabbitmqPolicyTestCase(TestCase):
definition), ret)
with patch.dict(rabbitmq_policy.__opts__, {'test': True}):
comt = ('Policy / HA is set to be created')
ret.update({'comment': comt, 'result': None})
comment = 'Policy / HA is set to be created'
changes = {'new': 'HA', 'old': {}}
ret.update({'comment': comment, 'result': None, 'changes': changes})
self.assertDictEqual(rabbitmq_policy.present(name, pattern,
definition), ret)
@ -77,13 +78,14 @@ class RabbitmqPolicyTestCase(TestCase):
mock = MagicMock(side_effect=[False, True])
with patch.dict(rabbitmq_policy.__salt__,
{'rabbitmq.policy_exists': mock}):
comt = ('Policy / HA is not present')
ret.update({'comment': comt})
comment = 'Policy \'/ HA\' is not present.'
ret.update({'comment': comment})
self.assertDictEqual(rabbitmq_policy.absent(name), ret)
with patch.dict(rabbitmq_policy.__opts__, {'test': True}):
comt = ('Removing policy / HA')
ret.update({'comment': comt, 'result': None})
comment = 'Policy \'/ HA\' will be removed.'
changes = {'new': '', 'old': 'HA'}
ret.update({'comment': comment, 'result': None, 'changes': changes})
self.assertDictEqual(rabbitmq_policy.absent(name), ret)