Merge remote-tracking branch 'upstream/2015.8' into merge-forward-develop

Conflicts:
    doc/topics/cloud/digitalocean.rst
    salt/cloud/clouds/digital_ocean.py
    salt/cloud/clouds/linode.py
    salt/loader.py
    salt/modules/blockdev.py
    salt/modules/boto_route53.py
    salt/modules/boto_vpc.py
    salt/modules/bsd_shadow.py
    salt/modules/file.py
    salt/modules/rabbitmq.py
    salt/modules/schedule.py
    salt/modules/win_network.py
    salt/runners/state.py
    salt/spm/__init__.py
    tests/unit/modules/blockdev_test.py
This commit is contained in:
Colton Myers 2015-11-02 18:19:01 -07:00
commit 32969b2408
119 changed files with 2772 additions and 1068 deletions

View File

@ -4,7 +4,7 @@
``spm`` ``spm``
======= =======
Salt Package Manager :ref:`Salt Package Manager <spm>`
Synopsis Synopsis
======== ========

View File

@ -14,13 +14,25 @@ More information about Azure is located at `http://www.windowsazure.com/
Dependencies Dependencies
============ ============
* The `Azure <https://pypi.python.org/pypi/azure>`_ Python SDK >= 0.11.1. * The `Azure <https://pypi.python.org/pypi/azure>`_ Python SDK >= 0.10.2 and < 1.0.0
* The python-requests library, for Python < 2.7.9. * The python-requests library, for Python < 2.7.9.
* A Microsoft Azure account * A Microsoft Azure account
* OpenSSL (to generate the certificates) * OpenSSL (to generate the certificates)
* `Salt <https://github.com/saltstack/salt>`_ * `Salt <https://github.com/saltstack/salt>`_
.. note::
The Azure driver is currently being updated to work with the new version of
the Python Azure SDK, 1.0.0. However until that process is complete, this
driver will not work with Azure 1.0.0. Please be sure you're running on a
minimum version of 0.10.2 and less than version 1.0.0.
See `Issue #27980`_ for more information.
.. _Issue #27980: https://github.com/saltstack/salt/issues/27980
Configuration Configuration
============= =============

View File

@ -45,14 +45,14 @@ Set up an initial profile at ``/etc/salt/cloud.profiles`` or in the
.. code-block:: yaml .. code-block:: yaml
digitalocean-ubuntu: digitalocean-ubuntu:
provider: my-digitalocean-config provider: my-digitalocean-config
image: 14.04 x64 image: 14.04 x64
size: 512MB size: 512MB
location: New York 1 location: New York 1
private_networking: True private_networking: True
backups_enabled: True backups_enabled: True
ipv6: True ipv6: True
create_dns_record: True create_dns_record: True
Locations can be obtained using the ``--list-locations`` option for the ``salt-cloud`` Locations can be obtained using the ``--list-locations`` option for the ``salt-cloud``
command: command:
@ -134,6 +134,28 @@ command:
True True
...SNIP... ...SNIP...
Profile Specifics:
------------------
ssh_username
------------
If using a FreeBSD image from Digital Ocean, you'll need to set the ``ssh_username``
setting to ``freebsd`` in your profile configuration.
.. code-block:: yaml
digitalocean-freebsd:
provider: my-digitalocean-config
image: 10.2
size: 512MB
ssh_username: freebsd
Miscellaneous Information
=========================
.. note:: .. note::
DigitalOcean's concept of ``Applications`` is nothing more than a DigitalOcean's concept of ``Applications`` is nothing more than a

View File

@ -414,13 +414,17 @@ from the Salt Master. For example:
{% set some_data = salt.pillar.get('some_data', {'sane default': True}) %} {% set some_data = salt.pillar.get('some_data', {'sane default': True}) %}
{# or #}
{% import_yaml 'path/to/file.yaml' as some_data %}
{# or #} {# or #}
{% load_json 'path/to/file.json' as some_data %} {% import_json 'path/to/file.json' as some_data %}
{# or #} {# or #}
{% load_text 'path/to/ssh_key.pub' as ssh_pub_key %} {% import_text 'path/to/ssh_key.pub' as ssh_pub_key %}
{# or #} {# or #}

View File

@ -55,13 +55,18 @@ Silent Installer Options
======================== ========================
The installer can be run silently by providing the `/S` option at the command The installer can be run silently by providing the `/S` option at the command
line. The options `/master` and `/minion-name` allow for configuring the master line. The installer also accepts the following options for configuring the Salt
hostname and minion name, respectively. Here's an example of using the silent Minion silently:
installer:
- `/master=` A string value to set the IP address or host name of the master. Default value is 'salt'
- `/minion-name=` A string value to set the minion name. Default is 'hostname'
- `/start-service=` Either a 1 or 0. '1' will start the service, '0' will not. Default is to start the service after installation.
Here's an example of using the silent installer:
.. code-block:: bat .. code-block:: bat
Salt-Minion-0.17.0-Setup-amd64.exe /S /master=yoursaltmaster /minion-name=yourminionname Salt-Minion-2015.5.6-Setup-amd64.exe /S /master=yoursaltmaster /minion-name=yourminionname /start-service=0
Running the Salt Minion on Windows as an Unprivileged User Running the Salt Minion on Windows as an Unprivileged User

View File

@ -39,6 +39,12 @@ SPM (Salt Package Manager)
Allows Salt formulas to be packaged for ease of deployment. See :ref:`spm <spm>`. Allows Salt formulas to be packaged for ease of deployment. See :ref:`spm <spm>`.
.. note::
The spm executable was not included in the Debian or Ubuntu packages for the
2015.8.0 or the 2015.8.1 releases. This executable will be included in an
upcoming release. As a workaround, copy the SPM script from the salt library
installation into ``/usr/local/bin`` or your local equivalent.
Specify a Single Environment for Top Files Specify a Single Environment for Top Files
========================================== ==========================================

View File

@ -3,7 +3,7 @@
==================== ====================
Salt Package Manager Salt Package Manager
==================== ====================
The Salt Package Manager, or SPM, allows Salt formulas to be packaged, for ease The Salt Package Manager, or :ref:`SPM <spm-cli>`, allows Salt formulas to be packaged, for ease
of deployment. The design of SPM was influenced by other existing packaging of deployment. The design of SPM was influenced by other existing packaging
systems including RPM, Yum, and Pacman. systems including RPM, Yum, and Pacman.
@ -60,6 +60,10 @@ For instance, if this version was released in June 2015, the package version
should be ``201506``. If multiple releases are made in a month, the ``release`` should be ``201506``. If multiple releases are made in a month, the ``release``
field should be used. field should be used.
minimum_version
~~~~~~~~~~~~~~~
Minimum recommended version of Salt to use this formula. Not currently enforced.
release release
~~~~~~~ ~~~~~~~
This field refers primarily to a release of a version, but also to multiple This field refers primarily to a release of a version, but also to multiple
@ -71,6 +75,7 @@ summary
A one-line description of the package. A one-line description of the package.
description description
~~~~~~~~~~~
A more detailed description of the package which can contain more than one line. A more detailed description of the package which can contain more than one line.
Optional Fields Optional Fields
@ -94,7 +99,15 @@ are already treated specially, such as ``pillar.example`` and ``_modules/``.
dependencies dependencies
~~~~~~~~~~~~ ~~~~~~~~~~~~
A list of packages which must be installed before this package can function. A list of packages which must be installed before this package can function. If
a matching package is found in an SPM repository, the dependency is installed
automatically.
recommended
~~~~~~~~~~~
A list of optional packages that are recommended to be installed with the
package. This list is displayed in an informational message
when the package is installed to SPM.
Building a Package Building a Package
------------------ ------------------
@ -167,11 +180,11 @@ To install from a repository, use the ``spm install`` command:
spm install apache spm install apache
To install from a local file, use the ``spm local_install`` command: To install from a local file, use the ``spm local install`` command:
.. code-block:: bash .. code-block:: bash
spm local_install /srv/spm/apache-201506-1.spm spm local install /srv/spm/apache-201506-1.spm
Currently, SPM does not check to see if files are already in place before Currently, SPM does not check to see if files are already in place before
installing them. That means that existing files will be overwritten without installing them. That means that existing files will be overwritten without
@ -243,8 +256,8 @@ By default, package files are installed using the ``local`` module. This module
applies files to the local filesystem, on the machine that the package is applies files to the local filesystem, on the machine that the package is
installed on. installed on.
Please see the SPM Development Guide for information on creating new modules Please see the :ref:`SPM Development Guide <spm-development>` for information
for package file management. on creating new modules for package file management.
SPM Configuration SPM Configuration

View File

@ -67,3 +67,42 @@ nodegroup`` on the line directly following the nodegroup name.
A limited amount of functionality, such as targeting with -N from the command-line may be A limited amount of functionality, such as targeting with -N from the command-line may be
available without a restart. available without a restart.
Using Nodegroups in SLS files
=============================
To use Nodegroups in Jinja logic for SLS files, the :conf_master:`pillar_opts` option in
``/etc/salt/master`` must be set to "True". This will pass the master's configuration as
Pillar data to each minion.
.. note::
If the master's configuration contains any sensitive data, this will be passed to each minion.
Do not enable this option if you have any configuration data that you do not want to get
on your minions.
Also, if you make changes to your nodegroups, you might need to run
``salt '*' saltutil.refresh_pillar`` after restarting the master.
Once pillar_opts is enabled, you can find the nodegroups under the "master" pillar.
To make sure that only the correct minions are targeted,
you should use each matcher for the nodegroup definition.
For example, to check if a minion is in the 'webserver' nodegroup:
.. code-block:: yaml
nodegroups:
webserver: 'G@os:Debian and L@minion1,minion2'
.. code-block:: yaml
{% if grains.id in salt['pillar.get']('master:nodegroups:webserver', [])
and grains.os in salt['pillar.get']('master:nodegroups:webserver', []) %}
...
{% endif %}
.. note::
If you do not include all of the matchers used to define a nodegroup,
Salt might incorrectly target minions that meet some of the nodegroup
requirements, but not all of them.

View File

@ -4,10 +4,26 @@
MinionFS Backend Walkthrough MinionFS Backend Walkthrough
============================ ============================
Propagating Files
=================
.. versionadded:: 2014.1.0 .. versionadded:: 2014.1.0
Sometimes, you might need to propagate files that are generated on a minion. Sometimes, one might need to propagate files that are generated on a minion.
Salt already has a feature to send files from a minion to the master: Salt already has a feature to send files from a minion to the master.
Enabling File Propagation
=========================
To enable propagation, the :conf_master:`file_recv` option needs to be set to ``True``.
.. code-block:: yaml
file_recv: True
These changes require a restart of the master, then new requests for the
``salt://minion-id/`` protocol will send files that are pushed by ``cp.push``
from ``minion-id`` to the master.
.. code-block:: bash .. code-block:: bash
@ -24,6 +40,9 @@ This command will store the file, including its full path, under
<salt.modules.cp.push>`. To get up to speed, check out the <salt.modules.cp.push>`. To get up to speed, check out the
:doc:`walkthrough </topics/tutorials/walkthrough>`. :doc:`walkthrough </topics/tutorials/walkthrough>`.
MinionFS Backend
================
Since it is not a good idea to expose the whole :conf_master:`cachedir`, MinionFS Since it is not a good idea to expose the whole :conf_master:`cachedir`, MinionFS
should be used to send these files to other minions. should be used to send these files to other minions.
@ -136,4 +155,4 @@ Or we can use a more elegant and salty way to add an SSH key:
.. [*] Yes, that was the actual key on my server, but the server is already destroyed. .. [*] Yes, that was the actual key on my server, but the server is already destroyed.

View File

@ -321,6 +321,19 @@ Nested pillar values can also be set via the command line:
the key that is passed in will overwrite the entire value of that key, the key that is passed in will overwrite the entire value of that key,
rather than merging only the specified value set via the command line. rather than merging only the specified value set via the command line.
The example below will swap the value for vim with telnet in the previously
specified list, notice the nested pillar dict:
.. code-block:: bash
salt '*' state.sls edit.vim pillar='{"pkgs": {"vim": "telnet"}}'
.. note::
This will attempt to install telnet on your minions, feel free to
uninstall the package or replace telnet value with anything else.
More On Pillar More On Pillar
============== ==============

View File

@ -31,6 +31,14 @@ You can specify multiple :ref:`state-declaration` under an
Try stopping Apache before running ``state.highstate`` once again and observe Try stopping Apache before running ``state.highstate`` once again and observe
the output. the output.
.. note::
For those running RedhatOS derivatives (Centos, AWS), you will want to specify the
service name to be httpd. More on state service here, :mod:`service state
<salt.states.service>`. With the example above, just add "- name: httpd"
above the require line and with the same spacing.
Require other states Require other states
==================== ====================

View File

@ -6,7 +6,7 @@
!define PRODUCT_UNINST_ROOT_KEY "HKLM" !define PRODUCT_UNINST_ROOT_KEY "HKLM"
; MUI 1.67 compatible ------ ; MUI 1.67 compatible ------
!include "MUI.nsh" !include "MUI2.nsh"
!include "nsDialogs.nsh" !include "nsDialogs.nsh"
!include "LogicLib.nsh" !include "LogicLib.nsh"
@ -36,6 +36,7 @@ Var MasterHost
Var MasterHost_State Var MasterHost_State
Var MinionName Var MinionName
Var MinionName_State Var MinionName_State
Var StartService
; MUI Settings ; MUI Settings
!define MUI_ABORTWARNING !define MUI_ABORTWARNING
@ -54,6 +55,7 @@ Page custom nsDialogsPage nsDialogsPageLeave
!insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_PAGE_INSTFILES
; Finish page ; Finish page
!define MUI_PAGE_CUSTOMFUNCTION_SHOW FinishPage.Show
!define MUI_FINISHPAGE_RUN "$INSTDIR\nssm" !define MUI_FINISHPAGE_RUN "$INSTDIR\nssm"
!define MUI_FINISHPAGE_RUN_PARAMETERS "start salt-minion" !define MUI_FINISHPAGE_RUN_PARAMETERS "start salt-minion"
!insertmacro MUI_PAGE_FINISH !insertmacro MUI_PAGE_FINISH
@ -76,6 +78,7 @@ Page custom nsDialogsPage nsDialogsPageLeave
Function nsDialogsPage Function nsDialogsPage
nsDialogs::Create 1018 nsDialogs::Create 1018
Pop $Dialog Pop $Dialog
@ -110,6 +113,68 @@ Function nsDialogsPageLeave
FunctionEnd FunctionEnd
Function getMinionConfig
confFind:
IfFileExists "$INSTDIR\conf\minion" confFound confNotFound
confNotFound:
${If} $INSTDIR == "c:\salt\bin\Scripts"
StrCpy $INSTDIR "C:\salt"
goto confFind
${Else}
goto confReallyNotFound
${EndIf}
confFound:
FileOpen $0 "$INSTDIR\conf\minion" r
confLoop:
FileRead $0 $1
IfErrors EndOfFile
${StrLoc} $2 $1 "master:" ">"
${If} $2 == 0
${StrStrAdv} $2 $1 "master: " ">" ">" "0" "0" "0"
${Trim} $2 $2
StrCpy $MasterHost_State $2
${EndIf}
${StrLoc} $2 $1 "id:" ">"
${If} $2 == 0
${StrStrAdv} $2 $1 "id: " ">" ">" "0" "0" "0"
${Trim} $2 $2
StrCpy $MinionName_State $2
${EndIf}
Goto confLoop
EndOfFile:
FileClose $0
confReallyNotFound:
Push $R0
Push $R1
Push $R2
${GetParameters} $R0
${GetOptions} $R0 "/master=" $R1
${GetOptions} $R0 "/minion-name=" $R2
${IfNot} $R1 == ""
StrCpy $MasterHost_State $R1
${ElseIf} $MasterHost_State == ""
StrCpy $MasterHost_State "salt"
${EndIf}
${IfNot} $R2 == ""
StrCpy $MinionName_State $R2
${ElseIf} $MinionName_State == ""
StrCpy $MinionName_State "hostname"
${EndIf}
Pop $R2
Pop $R1
Pop $R0
FunctionEnd
Function updateMinionConfig Function updateMinionConfig
ClearErrors ClearErrors
@ -181,13 +246,54 @@ Section -Post
RMDir /R "$INSTDIR\var\cache\salt" ; removing cache from old version RMDir /R "$INSTDIR\var\cache\salt" ; removing cache from old version
Call updateMinionConfig Call updateMinionConfig
Call checkStartService
SectionEnd SectionEnd
Function FinishPage.Show
${IfNot} $StartService == 1
SendMessage $mui.FinishPage.Run ${BM_SETCHECK} ${BST_UNCHECKED} 0
${EndIf}
FunctionEnd
Function checkStartService
; Check if the start-service option was passed
Push $R0
Push $R1
${GetParameters} $R0
${GetOptions} $R0 "/start-service=" $R1
; If start-service was passed something, then set it
${IfNot} $R1 == ""
StrCpy $StartService $R1
; Otherwise default to 1
${Else}
StrCpy $StartService 1
${EndIf}
Pop $R0
Pop $R1
FunctionEnd
Function .onInstSuccess Function .onInstSuccess
; If the installer is running Silently, start the service ; If the installer is running Silently, start the service
IfSilent 0 +2 IfSilent silentOption notSilent
Exec 'net start salt-minion'
silentOption:
; If start-service is 1, then start the service
${If} $StartService == 1
Exec 'net start salt-minion'
${EndIf}
notSilent:
FunctionEnd FunctionEnd
@ -233,62 +339,37 @@ Function .onInit
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}" DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}"
confFind: Call getMinionConfig
IfFileExists "$INSTDIR\conf\minion" confFound confNotFound
confNotFound: ; Check for existing installation
ReadRegStr $R0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "UninstallString"
StrCmp $R0 "" skipUninstall
; Found existing installation, prompt to uninstall
MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION "${PRODUCT_NAME} is already installed. $\n$\nClick `OK` to remove the existing installation." /SD IDOK IDOK uninst
Abort
uninst:
; Make sure we're in the right directory
${If} $INSTDIR == "c:\salt\bin\Scripts" ${If} $INSTDIR == "c:\salt\bin\Scripts"
StrCpy $INSTDIR "C:\salt" StrCpy $INSTDIR "C:\salt"
goto confFind
${Else}
goto confReallyNotFound
${EndIf} ${EndIf}
confFound: ; Stop and remove the salt-minion service
FileOpen $0 "$INSTDIR\conf\minion" r ExecWait "net stop salt-minion"
ExecWait "sc delete salt-minion"
confLoop: ; Remove salt binaries and batch files
FileRead $0 $1 Delete "$INSTDIR\uninst.exe"
IfErrors EndOfFile Delete "$INSTDIR\nssm.exe"
${StrLoc} $2 $1 "master:" ">" Delete "$INSTDIR\salt*"
${If} $2 == 0 RMDir /r "$INSTDIR\bin"
${StrStrAdv} $2 $1 "master: " ">" ">" "0" "0" "0"
${Trim} $2 $2
StrCpy $MasterHost_State $2
${EndIf}
${StrLoc} $2 $1 "id:" ">" ; Remove registry entries
${If} $2 == 0 DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
${StrStrAdv} $2 $1 "id: " ">" ">" "0" "0" "0" DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}"
${Trim} $2 $2
StrCpy $MinionName_State $2
${EndIf}
Goto confLoop skipUninstall:
EndOfFile:
FileClose $0
confReallyNotFound:
Push $R0
Push $R1
Push $R2
${GetParameters} $R0
${GetOptions} $R0 "/master=" $R1
${GetOptions} $R0 "/minion-name=" $R2
${IfNot} $R1 == ""
StrCpy $MasterHost_State $R1
${ElseIf} $MasterHost_State == ""
StrCpy $MasterHost_State "salt"
${EndIf}
${IfNot} $R2 == ""
StrCpy $MinionName_State $R2
${ElseIf} $MinionName_State == ""
StrCpy $MinionName_State "hostname"
${EndIf}
Pop $R2
Pop $R1
Pop $R0
FunctionEnd FunctionEnd

View File

@ -46,6 +46,7 @@ from salt.exceptions import (
) )
import salt.ext.six as six import salt.ext.six as six
from salt.ext.six.moves import zip from salt.ext.six.moves import zip
from salt.ext.six import string_types
# Import Third Party Libs # Import Third Party Libs
try: try:
@ -206,6 +207,9 @@ def get_image(vm_):
vm_image = config.get_cloud_config_value( vm_image = config.get_cloud_config_value(
'image', vm_, __opts__, search_global=False 'image', vm_, __opts__, search_global=False
) )
if not isinstance(vm_image, string_types):
vm_image = str(vm_image)
for image in images: for image in images:
if vm_image in (images[image]['name'], if vm_image in (images[image]['name'],
images[image]['slug'], images[image]['slug'],

View File

@ -568,7 +568,7 @@ def create_disk_from_distro(vm_, linode_id, swap_size=None):
r''' r'''
Creates the disk for the Linode from the distribution. Creates the disk for the Linode from the distribution.
vm_ vm\_
The VM profile to create the disk for. The VM profile to create the disk for.
linode_id linode_id
@ -609,7 +609,7 @@ def create_swap_disk(vm_, linode_id, swap_size=None):
r''' r'''
Creates the disk for the specified Linode. Creates the disk for the specified Linode.
vm_ vm\_
The VM profile to create the swap disk for. The VM profile to create the swap disk for.
linode_id linode_id
@ -752,7 +752,7 @@ def get_disk_size(vm_, swap, linode_id):
r''' r'''
Returns the size of of the root disk in MB. Returns the size of of the root disk in MB.
vm_ vm\_
The VM to get the disk size for. The VM to get the disk size for.
''' '''
disk_size = get_linode(kwargs={'linode_id': linode_id})['TOTALHD'] disk_size = get_linode(kwargs={'linode_id': linode_id})['TOTALHD']
@ -765,7 +765,7 @@ def get_distribution_id(vm_):
r''' r'''
Returns the distribution ID for a VM Returns the distribution ID for a VM
vm_ vm\_
The VM to get the distribution ID for The VM to get the distribution ID for
''' '''
distributions = _query('avail', 'distributions')['DATA'] distributions = _query('avail', 'distributions')['DATA']
@ -894,7 +894,7 @@ def get_password(vm_):
r''' r'''
Return the password to use for a VM. Return the password to use for a VM.
vm_ vm\_
The configuration to obtain the password from. The configuration to obtain the password from.
''' '''
return config.get_cloud_config_value( return config.get_cloud_config_value(
@ -960,7 +960,7 @@ def get_pub_key(vm_):
r''' r'''
Return the SSH pubkey. Return the SSH pubkey.
vm_ vm\_
The configuration to obtain the public key from. The configuration to obtain the public key from.
''' '''
return config.get_cloud_config_value( return config.get_cloud_config_value(
@ -972,7 +972,7 @@ def get_swap_size(vm_):
r''' r'''
Returns the amoutn of swap space to be used in MB. Returns the amoutn of swap space to be used in MB.
vm_ vm\_
The VM profile to obtain the swap size from. The VM profile to obtain the swap size from.
''' '''
return config.get_cloud_config_value( return config.get_cloud_config_value(
@ -984,7 +984,7 @@ def get_vm_size(vm_):
r''' r'''
Returns the VM's size. Returns the VM's size.
vm_ vm\_
The VM to get the size for. The VM to get the size for.
''' '''
vm_size = config.get_cloud_config_value('size', vm_, __opts__) vm_size = config.get_cloud_config_value('size', vm_, __opts__)

View File

@ -645,7 +645,7 @@ def create(vm_):
return return
rackconnectv3 = config.get_cloud_config_value( rackconnectv3 = config.get_cloud_config_value(
'rackconnectv3', vm_, __opts__, default='False', 'rackconnectv3', vm_, __opts__, default=False,
search_global=False search_global=False
) )
@ -721,21 +721,29 @@ def create(vm_):
data.public_ips = access_ip data.public_ips = access_ip
return data return data
# populate return data with private_ips
# when ssh_interface is set to private_ips and public_ips exist
if not result and ssh_interface(vm_) == 'private_ips':
for private_ip in private:
ignore_ip = ignore_cidr(vm_, private_ip)
if private_ip not in data.private_ips and not ignore_ip:
result.append(private_ip)
if cloudnetwork(vm_) is True: if cloudnetwork(vm_) is True:
data.public_ips = access_ip data.public_ips = access_ip
return data return data
if public:
data.public_ips = public
if ssh_interface(vm_) != 'private_ips':
return data
if result: if result:
log.debug('result = {0}'.format(result)) log.debug('result = {0}'.format(result))
data.private_ips = result data.private_ips = result
if ssh_interface(vm_) == 'private_ips': if ssh_interface(vm_) == 'private_ips':
return data return data
if public:
data.public_ips = public
if ssh_interface(vm_) != 'private_ips':
return data
try: try:
data = salt.utils.cloud.wait_for_ip( data = salt.utils.cloud.wait_for_ip(
__query_node_data, __query_node_data,

View File

@ -2,6 +2,7 @@
''' '''
Saltify Module Saltify Module
============== ==============
The Saltify module is designed to install Salt on a remote machine, virtual or The Saltify module is designed to install Salt on a remote machine, virtual or
bare metal, using SSH. This module is useful for provisioning machines which bare metal, using SSH. This module is useful for provisioning machines which
are already installed, but not Salted. are already installed, but not Salted.

View File

@ -2748,6 +2748,8 @@ def apply_minion_config(overrides=None,
if overrides: if overrides:
opts.update(overrides) opts.update(overrides)
opts['__cli'] = os.path.basename(sys.argv[0])
if len(opts['sock_dir']) > len(opts['cachedir']) + 10: if len(opts['sock_dir']) > len(opts['cachedir']) + 10:
opts['sock_dir'] = os.path.join(opts['cachedir'], '.salt-unix') opts['sock_dir'] = os.path.join(opts['cachedir'], '.salt-unix')

View File

@ -28,6 +28,7 @@ import salt.utils.templates
import salt.utils.url import salt.utils.url
import salt.utils.gzip_util import salt.utils.gzip_util
import salt.utils.http import salt.utils.http
from salt.utils.locales import sdecode
from salt.utils.openstack.swift import SaltSwift from salt.utils.openstack.swift import SaltSwift
# pylint: disable=no-name-in-module,import-error # pylint: disable=no-name-in-module,import-error
@ -213,8 +214,7 @@ class Client(object):
ret = [] ret = []
path = salt.utils.locales.sdecode(path) path = self._check_proto(sdecode(path))
path = self._check_proto(path)
# We want to make sure files start with this *directory*, use # We want to make sure files start with this *directory*, use
# '/' explicitly because the master (that's generating the # '/' explicitly because the master (that's generating the
# list of files) only runs on POSIX # list of files) only runs on POSIX
@ -229,7 +229,6 @@ class Client(object):
# go through the list of all files finding ones that are in # go through the list of all files finding ones that are in
# the target directory and caching them # the target directory and caching them
for fn_ in self.file_list(saltenv): for fn_ in self.file_list(saltenv):
fn_ = salt.utils.locales.sdecode(fn_)
if fn_.strip() and fn_.startswith(path): if fn_.strip() and fn_.startswith(path):
if salt.utils.check_include_exclude( if salt.utils.check_include_exclude(
fn_, include_pat, exclude_pat): fn_, include_pat, exclude_pat):
@ -794,12 +793,8 @@ class LocalClient(Client):
os.path.join(path, prefix), followlinks=True os.path.join(path, prefix), followlinks=True
): ):
for fname in files: for fname in files:
ret.append( relpath = os.path.relpath(os.path.join(root, fname), path)
os.path.relpath( ret.append(sdecode(relpath))
os.path.join(root, fname),
path
)
)
return ret return ret
def file_list_emptydirs(self, saltenv='base', prefix='', env=None): def file_list_emptydirs(self, saltenv='base', prefix='', env=None):
@ -826,7 +821,7 @@ class LocalClient(Client):
os.path.join(path, prefix), followlinks=True os.path.join(path, prefix), followlinks=True
): ):
if len(dirs) == 0 and len(files) == 0: if len(dirs) == 0 and len(files) == 0:
ret.append(os.path.relpath(root, path)) ret.append(sdecode(os.path.relpath(root, path)))
return ret return ret
def dir_list(self, saltenv='base', prefix='', env=None): def dir_list(self, saltenv='base', prefix='', env=None):
@ -852,7 +847,7 @@ class LocalClient(Client):
for root, dirs, files in os.walk( for root, dirs, files in os.walk(
os.path.join(path, prefix), followlinks=True os.path.join(path, prefix), followlinks=True
): ):
ret.append(os.path.relpath(root, path)) ret.append(sdecode(os.path.relpath(root, path)))
return ret return ret
def hash_file(self, path, saltenv='base', env=None): def hash_file(self, path, saltenv='base', env=None):

View File

@ -1537,6 +1537,7 @@ def fqdn_ip6():
def ip_interfaces(): def ip_interfaces():
''' '''
Provide a dict of the connected interfaces and their ip addresses Provide a dict of the connected interfaces and their ip addresses
The addresses will be passed as a list for each interface
''' '''
# Provides: # Provides:
# ip_interfaces # ip_interfaces
@ -1564,6 +1565,7 @@ def ip_interfaces():
def ip4_interfaces(): def ip4_interfaces():
''' '''
Provide a dict of the connected interfaces and their ip4 addresses Provide a dict of the connected interfaces and their ip4 addresses
The addresses will be passed as a list for each interface
''' '''
# Provides: # Provides:
# ip_interfaces # ip_interfaces
@ -1588,6 +1590,7 @@ def ip4_interfaces():
def ip6_interfaces(): def ip6_interfaces():
''' '''
Provide a dict of the connected interfaces and their ip6 addresses Provide a dict of the connected interfaces and their ip6 addresses
The addresses will be passed as a list for each interface
''' '''
# Provides: # Provides:
# ip_interfaces # ip_interfaces

37
salt/grains/fx2.py Normal file
View File

@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
'''
Generate baseline proxy minion grains
'''
from __future__ import absolute_import
import salt.utils
__proxyenabled__ = ['rest_sample']
__virtualname__ = 'rest_sample'
def __virtual__():
if not salt.utils.is_proxy():
return False
else:
return __virtualname__
def kernel():
return {'kernel': 'proxy'}
def os():
return {'os': 'RestExampleOS'}
def location():
return {'location': 'In this darn virtual machine. Let me out!'}
def os_family():
return {'os_family': 'proxy'}
def os_data():
return {'os_data': 'funkyHttp release 1.0.a.4.g'}

View File

@ -43,11 +43,10 @@ def defaults():
def facts(): def facts():
if 'proxymodule' in __opts__: if 'junos.facts' in __proxy__:
if 'junos.facts' in __opts__['proxymodule']: facts = __proxy__['junos.facts']()
facts = __opts__['proxymodule']['junos.facts']() facts['version_info'] = 'override'
facts['version_info'] = 'override' return facts
return facts
return None return None

View File

@ -581,7 +581,7 @@ def grain_funcs(opts):
) )
def grains(opts, force_refresh=False): def grains(opts, force_refresh=False, proxy=None):
''' '''
Return the functions for the dynamic grains and the values for the static Return the functions for the dynamic grains and the values for the static
grains. grains.
@ -1095,7 +1095,7 @@ class LazyLoader(salt.utils.lazy.LazyDict):
log.error('Module/package collision: {0!r} and {1!r}'.format( log.error('Module/package collision: {0!r} and {1!r}'.format(
fpath, self.file_mapping[f_noext][0] fpath, self.file_mapping[f_noext][0]
)) ))
if suffix_order.index(ext) >= suffix_order.index(curr_ext): if not curr_ext or suffix_order.index(ext) >= suffix_order.index(curr_ext):
continue # Next filename continue # Next filename
# Made it this far - add it # Made it this far - add it

View File

@ -1206,6 +1206,13 @@ class Minion(MinionBase):
salt.utils.appendproctitle(data['jid']) salt.utils.appendproctitle(data['jid'])
# this seems awkward at first, but it's a workaround for Windows # this seems awkward at first, but it's a workaround for Windows
# multiprocessing communication. # multiprocessing communication.
if sys.platform.startswith('win') and \
opts['multiprocessing'] and \
not salt.log.is_logging_configured():
# We have to re-init the logging system for Windows
salt.log.setup_console_logger(log_level=opts.get('log_level', 'info'))
if opts.get('log_file'):
salt.log.setup_logfile_logger(opts['log_file'], opts.get('log_level_logfile', 'info'))
if not minion_instance: if not minion_instance:
minion_instance = cls(opts) minion_instance = cls(opts)
ret = { ret = {

View File

@ -298,7 +298,7 @@ def latest_version(*names, **kwargs):
return ret return ret
# available_version is being deprecated # available_version is being deprecated
available_version = latest_version available_version = salt.utils.alias_function(latest_version, 'available_version')
def version(*names, **kwargs): def version(*names, **kwargs):

View File

@ -14,17 +14,28 @@ import logging
# Import salt libs # Import salt libs
import salt.utils import salt.utils
import salt.utils.decorators as decorators
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
__func_alias__ = {
'format_': 'format'
}
__virtualname__ = 'blockdev'
def __virtual__(): def __virtual__():
''' '''
Only work on POSIX-like systems Only load this module if the blockdev utility is available
''' '''
if salt.utils.is_windows(): if salt.utils.is_windows():
return False return (False, ('The {0} execution module '
return True 'is not supported on windows'.format(__virtualname__)))
elif not salt.utils.which('blockdev'):
return (False, ('Cannot load the {0} execution module: '
'blockdev utility not found'.format(__virtualname__)))
return __virtualname__
def tune(device, **kwargs): def tune(device, **kwargs):
@ -38,7 +49,7 @@ def tune(device, **kwargs):
.. code-block:: bash .. code-block:: bash
salt '*' blockdev.tune /dev/sda1 read-ahead=1024 read-write=True salt '*' blockdev.tune /dev/sdX1 read-ahead=1024 read-write=True
Valid options are: ``read-ahead``, ``filesystem-read-ahead``, Valid options are: ``read-ahead``, ``filesystem-read-ahead``,
``read-only``, ``read-write``. ``read-only``, ``read-write``.
@ -53,6 +64,7 @@ def tune(device, **kwargs):
return __salt__['disk.tune'](device, **kwargs) return __salt__['disk.tune'](device, **kwargs)
@decorators.which('wipefs')
def wipe(device): def wipe(device):
''' '''
Remove the filesystem information Remove the filesystem information
@ -64,7 +76,7 @@ def wipe(device):
.. code-block:: bash .. code-block:: bash
salt '*' blockdev.wipe /dev/sda1 salt '*' blockdev.wipe /dev/sdX1
''' '''
salt.utils.warn_until( salt.utils.warn_until(
'Carbon', 'Carbon',
@ -80,10 +92,14 @@ def dump(device, args=None):
.. deprecated:: Boron .. deprecated:: Boron
Use `disk.dump` Use `disk.dump`
args
a list containing only the desired arguments to return
CLI Example: CLI Example:
.. code-block:: bash .. code-block:: bash
salt '*' extfs.dump /dev/sda1 salt '*' blockdev.dump /dev/sdX1
''' '''
salt.utils.warn_until( salt.utils.warn_until(
'Carbon', 'Carbon',
@ -92,6 +108,94 @@ def dump(device, args=None):
return __salt__['disk.dump'](device, args) return __salt__['disk.dump'](device, args)
@decorators.which('sync')
@decorators.which('mkfs')
def format_(device, fs_type='ext4', inode_size=None, lazy_itable_init=None):
'''
Format a filesystem onto a block device
.. versionadded:: 2015.8.2
device
The block device in which to create the new filesystem
fs_type
The type of filesystem to create
inode_size
Size of the inodes
This option is only enabled for ext and xfs filesystems
lazy_itable_init
If enabled and the uninit_bg feature is enabled, the inode table will
not be fully initialized by mke2fs. This speeds up filesystem
initialization noticeably, but it requires the kernel to finish
initializing the filesystem in the background when the filesystem
is first mounted. If the option value is omitted, it defaults to 1 to
enable lazy inode table zeroing.
This option is only enabled for ext filesystems
CLI Example:
.. code-block:: bash
salt '*' blockdev.format /dev/sdX1
'''
cmd = ['mkfs', '-t', str(fs_type)]
if inode_size is not None:
if fs_type[:3] == 'ext':
cmd.extend(['-i', str(inode_size)])
elif fs_type == 'xfs':
cmd.extend(['-i', 'size={0}'.format(inode_size)])
if lazy_itable_init is not None:
if fs_type[:3] == 'ext':
cmd.extend(['-E', 'lazy_itable_init={0}'.format(lazy_itable_init)])
cmd.append(str(device))
mkfs_success = __salt__['cmd.retcode'](cmd, ignore_retcode=True) == 0
sync_success = __salt__['cmd.retcode']('sync', ignore_retcode=True) == 0
return all([mkfs_success, sync_success])
@decorators.which_bin(['lsblk', 'df'])
def fstype(device):
'''
Return the filesystem name of a block device
.. versionadded:: 2015.8.2
device
The name of the block device
CLI Example:
.. code-block:: bash
salt '*' blockdev.fstype /dev/sdX1
'''
if salt.utils.which('lsblk'):
lsblk_out = __salt__['cmd.run']('lsblk -o fstype {0}'.format(device)).splitlines()
if len(lsblk_out) > 1:
fs_type = lsblk_out[1].strip()
if fs_type:
return fs_type
if salt.utils.which('df'):
# the fstype was not set on the block device, so inspect the filesystem
# itself for its type
df_out = __salt__['cmd.run']('df -T {0}'.format(device)).splitlines()
if len(df_out) > 1:
fs_type = df_out[1]
if fs_type:
return fs_type
return ''
@decorators.which('resize2fs')
def resize2fs(device): def resize2fs(device):
''' '''
Resizes the filesystem. Resizes the filesystem.
@ -102,7 +206,7 @@ def resize2fs(device):
CLI Example: CLI Example:
.. code-block:: bash .. code-block:: bash
salt '*' blockdev.resize2fs /dev/sda1 salt '*' blockdev.resize2fs /dev/sdX1
''' '''
salt.utils.warn_until( salt.utils.warn_until(
'Carbon', 'Carbon',

View File

@ -338,7 +338,7 @@ def subnet_group_exists(name, tags=None, region=None, key=None, keyid=None, prof
salt myminion boto_elasticache.subnet_group_exists my-param-group \ salt myminion boto_elasticache.subnet_group_exists my-param-group \
region=us-east-1 region=us-east-1
''' '''
conn = _get_conn(region, key, keyid, profile) conn = _get_conn(region=region, key=key, keyid=keyid, profile=profile)
if not conn: if not conn:
return False return False
try: try:
@ -364,7 +364,7 @@ def create_subnet_group(name, description, subnet_ids, tags=None, region=None,
"group description" '[subnet-12345678, subnet-87654321]' \ "group description" '[subnet-12345678, subnet-87654321]' \
region=us-east-1 region=us-east-1
''' '''
conn = _get_conn(region, key, keyid, profile) conn = _get_conn(region=region, key=key, keyid=keyid, profile=profile)
if not conn: if not conn:
return False return False
if subnet_group_exists(name, tags, region, key, keyid, profile): if subnet_group_exists(name, tags, region, key, keyid, profile):
@ -438,7 +438,7 @@ def delete_subnet_group(name, region=None, key=None, keyid=None, profile=None):
salt myminion boto_elasticache.delete_subnet_group my-subnet-group \ salt myminion boto_elasticache.delete_subnet_group my-subnet-group \
region=us-east-1 region=us-east-1
''' '''
conn = _get_conn(region, key, keyid, profile) conn = _get_conn(region=region, key=key, keyid=keyid, profile=profile)
if not conn: if not conn:
return False return False
try: try:

View File

@ -164,7 +164,7 @@ def latest_version(*names, **kwargs):
return ret return ret
# available_version is being deprecated # available_version is being deprecated
available_version = latest_version available_version = salt.utils.alias_function(latest_version, 'available_version')
def remove(name=None, pkgs=None, **kwargs): def remove(name=None, pkgs=None, **kwargs):

View File

@ -146,7 +146,7 @@ def set_expire(name, expire):
def del_password(name): def del_password(name):
''' '''
.. versionadded:: 2015.8.3 .. versionadded:: 2015.8.2
Delete the password from name user Delete the password from name user

View File

@ -102,20 +102,34 @@ def chocolatey_version():
''' '''
if 'chocolatey._version' in __context__: if 'chocolatey._version' in __context__:
return __context__['chocolatey._version'] return __context__['chocolatey._version']
cmd = [_find_chocolatey(__context__, __salt__)]
out = __salt__['cmd.run'](cmd, python_shell=False) def find_version(legacy=False):
for line in out.splitlines(): cmd = [_find_chocolatey(__context__, __salt__)]
line = line.lower() if legacy:
if line.startswith('chocolatey v'): cmd.append('help')
__context__['chocolatey._version'] = line[12:] out = __salt__['cmd.run'](cmd, python_shell=False)
return __context__['chocolatey._version'] for line in out.splitlines():
elif line.startswith('version: '): line = line.lower()
try: if line.startswith('chocolatey v'):
__context__['chocolatey._version'] = \ __context__['chocolatey._version'] = line[12:]
line.split(None, 1)[-1].strip("'")
return __context__['chocolatey._version'] return __context__['chocolatey._version']
except Exception: elif line.startswith('version: '):
pass try:
__context__['chocolatey._version'] = \
line.split(None, 1)[-1].strip("'")
return __context__['chocolatey._version']
except Exception:
pass
return None
# First try to find if we have a newer version of choco
# which doesn't contain the help command,
# else try for a legacy version
for legacy in [False, True]:
ver = find_version(legacy=legacy)
if ver is not None:
return ver
raise CommandExecutionError('Unable to determine Chocolatey version') raise CommandExecutionError('Unable to determine Chocolatey version')

View File

@ -316,7 +316,7 @@ def list_tab(user):
return ret return ret
# For consistency's sake # For consistency's sake
ls = list_tab # pylint: disable=C0103 ls = salt.utils.alias_function(list_tab, 'ls')
def set_special(user, special, cmd): def set_special(user, special, cmd):
@ -526,7 +526,7 @@ def rm_job(user,
return comdat['stderr'] return comdat['stderr']
return ret return ret
rm = rm_job # pylint: disable=C0103 rm = salt.utils.alias_function(rm_job, 'rm')
def set_env(user, name, value=None): def set_env(user, name, value=None):

View File

@ -882,9 +882,9 @@ def _parse_settings_bond_1(opts, iface, bond_def):
if 'use_carrier' in opts: if 'use_carrier' in opts:
if opts['use_carrier'] in _CONFIG_TRUE: if opts['use_carrier'] in _CONFIG_TRUE:
bond.update({'use_carrier': 'on'}) bond.update({'use_carrier': '1'})
elif opts['use_carrier'] in _CONFIG_FALSE: elif opts['use_carrier'] in _CONFIG_FALSE:
bond.update({'use_carrier': 'off'}) bond.update({'use_carrier': '0'})
else: else:
valid = _CONFIG_TRUE + _CONFIG_FALSE valid = _CONFIG_TRUE + _CONFIG_FALSE
_raise_error_iface(iface, 'use_carrier', valid) _raise_error_iface(iface, 'use_carrier', valid)
@ -968,9 +968,9 @@ def _parse_settings_bond_3(opts, iface, bond_def):
if 'use_carrier' in opts: if 'use_carrier' in opts:
if opts['use_carrier'] in _CONFIG_TRUE: if opts['use_carrier'] in _CONFIG_TRUE:
bond.update({'use_carrier': 'on'}) bond.update({'use_carrier': '1'})
elif opts['use_carrier'] in _CONFIG_FALSE: elif opts['use_carrier'] in _CONFIG_FALSE:
bond.update({'use_carrier': 'off'}) bond.update({'use_carrier': '0'})
else: else:
valid = _CONFIG_TRUE + _CONFIG_FALSE valid = _CONFIG_TRUE + _CONFIG_FALSE
_raise_error_iface(iface, 'use_carrier', valid) _raise_error_iface(iface, 'use_carrier', valid)
@ -1012,9 +1012,9 @@ def _parse_settings_bond_4(opts, iface, bond_def):
if 'use_carrier' in opts: if 'use_carrier' in opts:
if opts['use_carrier'] in _CONFIG_TRUE: if opts['use_carrier'] in _CONFIG_TRUE:
bond.update({'use_carrier': 'on'}) bond.update({'use_carrier': '1'})
elif opts['use_carrier'] in _CONFIG_FALSE: elif opts['use_carrier'] in _CONFIG_FALSE:
bond.update({'use_carrier': 'off'}) bond.update({'use_carrier': '0'})
else: else:
valid = _CONFIG_TRUE + _CONFIG_FALSE valid = _CONFIG_TRUE + _CONFIG_FALSE
_raise_error_iface(iface, 'use_carrier', valid) _raise_error_iface(iface, 'use_carrier', valid)
@ -1055,9 +1055,9 @@ def _parse_settings_bond_5(opts, iface, bond_def):
if 'use_carrier' in opts: if 'use_carrier' in opts:
if opts['use_carrier'] in _CONFIG_TRUE: if opts['use_carrier'] in _CONFIG_TRUE:
bond.update({'use_carrier': 'on'}) bond.update({'use_carrier': '1'})
elif opts['use_carrier'] in _CONFIG_FALSE: elif opts['use_carrier'] in _CONFIG_FALSE:
bond.update({'use_carrier': 'off'}) bond.update({'use_carrier': '0'})
else: else:
valid = _CONFIG_TRUE + _CONFIG_FALSE valid = _CONFIG_TRUE + _CONFIG_FALSE
_raise_error_iface(iface, 'use_carrier', valid) _raise_error_iface(iface, 'use_carrier', valid)
@ -1091,9 +1091,9 @@ def _parse_settings_bond_6(opts, iface, bond_def):
if 'use_carrier' in opts: if 'use_carrier' in opts:
if opts['use_carrier'] in _CONFIG_TRUE: if opts['use_carrier'] in _CONFIG_TRUE:
bond.update({'use_carrier': 'on'}) bond.update({'use_carrier': '1'})
elif opts['use_carrier'] in _CONFIG_FALSE: elif opts['use_carrier'] in _CONFIG_FALSE:
bond.update({'use_carrier': 'off'}) bond.update({'use_carrier': '0'})
else: else:
valid = _CONFIG_TRUE + _CONFIG_FALSE valid = _CONFIG_TRUE + _CONFIG_FALSE
_raise_error_iface(iface, 'use_carrier', valid) _raise_error_iface(iface, 'use_carrier', valid)

View File

@ -3018,7 +3018,7 @@ def copy_from(name, source, dest, overwrite=False, makedirs=False):
# Docker cp gets a file from the container, alias this to copy_from # Docker cp gets a file from the container, alias this to copy_from
cp = copy_from cp = salt.utils.alias_function(copy_from, 'cp')
@_ensure_exists @_ensure_exists
@ -4302,7 +4302,7 @@ def pause(name):
.format(name))} .format(name))}
return _change_state(name, 'pause', 'paused') return _change_state(name, 'pause', 'paused')
freeze = pause freeze = salt.utils.alias_function(pause, 'freeze')
@_ensure_exists @_ensure_exists
@ -4497,7 +4497,7 @@ def unpause(name):
.format(name))} .format(name))}
return _change_state(name, 'unpause', 'running') return _change_state(name, 'unpause', 'running')
unfreeze = unpause unfreeze = salt.utils.alias_function(unpause, 'unfreeze')
def wait(name): def wait(name):

View File

@ -42,10 +42,10 @@ def __parse_drac(output):
drac[section].update(dict( drac[section].update(dict(
[[prop.strip() for prop in i.split('=')]] [[prop.strip() for prop in i.split('=')]]
)) ))
else: else:
section = i.strip()[:-1] section = i.strip()[1:-1]
if section not in drac and section: if section not in drac and section:
drac[section] = {} drac[section] = {}
return drac return drac
@ -125,11 +125,37 @@ def __execute_ret(command, host=None,
if len(l.strip()) == 0: if len(l.strip()) == 0:
continue continue
fmtlines.append(l) fmtlines.append(l)
if '=' in l:
continue
break
cmd['stdout'] = '\n'.join(fmtlines) cmd['stdout'] = '\n'.join(fmtlines)
return cmd return cmd
def get_dns_dracname(host=None,
admin_username=None, admin_password=None):
import pydevd
pydevd.settrace('172.16.207.1', port=65500, stdoutToServer=True, stderrToServer=True)
ret = __execute_ret('get iDRAC.NIC.DNSRacName', host=host,
admin_username=admin_username,
admin_password=admin_password)
parsed = __parse_drac(ret['stdout'])
return parsed
def set_dns_dracname(name,
host=None,
admin_username=None, admin_password=None):
ret = __execute_ret('set iDRAC.NIC.DNSRacName {0}'.format(name),
host=host,
admin_username=admin_username,
admin_password=admin_password)
return ret
def system_info(host=None, def system_info(host=None,
admin_username=None, admin_password=None, admin_username=None, admin_password=None,
module=None): module=None):
@ -645,6 +671,41 @@ def set_network(ip, netmask, gateway, host=None,
)) ))
def server_power(status, host=None,
admin_username=None,
admin_password=None,
module=None):
'''
status
One of 'powerup', 'powerdown', 'powercycle', 'hardreset',
'graceshutdown'
host
The chassis host.
admin_username
The username used to access the chassis.
admin_password
The password used to access the chassis.
module
The element to reboot on the chassis such as a blade. If not provided,
the chassis will be rebooted.
CLI Example:
.. code-block:: bash
salt dell dracr.server_reboot
salt dell dracr.server_reboot module=server-1
'''
return __execute_cmd('serveraction {0}'.format(status),
host=host, admin_username=admin_username,
admin_password=admin_password, module=module)
def server_reboot(host=None, def server_reboot(host=None,
admin_username=None, admin_username=None,
admin_password=None, admin_password=None,
@ -946,10 +1007,9 @@ def set_slotname(slot, name, host=None,
admin_username=root admin_password=secret admin_username=root admin_password=secret
''' '''
return __execute_cmd('setslotname -i {0} {1}'.format( return __execute_cmd('config -g cfgServerInfo -o cfgServerName -i {0} {1}'.format(slot, name),
slot, name[0:14], host=host, host=host, admin_username=admin_username,
admin_username=admin_username, admin_password=admin_password)
admin_password=admin_password))
def set_chassis_name(name, def set_chassis_name(name,
@ -1147,8 +1207,67 @@ def get_chassis_location(host=None,
''' '''
return system_info(host=host, return system_info(host=host,
admin_username=admin_username, admin_username=admin_username,
admin_password=admin_password)['Chassis Information']['Chassis Location'] admin_password=admin_password)['Chassis Information']['Chassis Location']
def set_chassis_datacenter(location,
host=None,
admin_username=None,
admin_password=None):
'''
Set the location of the chassis.
location
The name of the datacenter to be set on the chassis.
host
The chassis host.
admin_username
The username used to access the chassis.
admin_password
The password used to access the chassis.
CLI Example:
.. code-block:: bash
salt '*' dracr.set_chassis_datacenter datacenter-name host=111.222.333.444
admin_username=root admin_password=secret
'''
return set_general('cfgLocation', 'cfgLocationDatacenter', location,
host=host, admin_username=admin_username,
admin_password=admin_password)
def get_chassis_datacenter(host=None,
admin_username=None,
admin_password=None):
'''
Get the datacenter of the chassis.
host
The chassis host.
admin_username
The username used to access the chassis.
admin_password
The password used to access the chassis.
CLI Example:
.. code-block:: bash
salt '*' dracr.set_chassis_location host=111.222.333.444
admin_username=root admin_password=secret
'''
return get_general('cfgLocation', 'cfgLocationDatacenter', host=host,
admin_username=admin_username, admin_password=admin_password)
def set_general(cfg_sec, cfg_var, val, host=None, def set_general(cfg_sec, cfg_var, val, host=None,

View File

@ -237,7 +237,7 @@ def latest_version(*names, **kwargs):
return ret return ret
# available_version is being deprecated # available_version is being deprecated
available_version = latest_version available_version = salt.utils.alias_function(latest_version, 'available_version')
def _get_upgradable(backtrack=3): def _get_upgradable(backtrack=3):

View File

@ -51,16 +51,23 @@ def fire_master(data, tag, preload=None):
pass pass
return True return True
if preload: if preload or __opts__.get('__cli') == 'salt-call':
# If preload is specified, we must send a raw event (this is # If preload is specified, we must send a raw event (this is
# slower because it has to independently authenticate) # slower because it has to independently authenticate)
load = preload if 'master_uri' not in __opts__:
__opts__['master_uri'] = 'tcp://{ip}:{port}'.format(
ip=salt.utils.ip_bracket(__opts__['interface']),
port=__opts__.get('ret_port', '4506') # TODO, no fallback
)
auth = salt.crypt.SAuth(__opts__) auth = salt.crypt.SAuth(__opts__)
load.update({'id': __opts__['id'], load = {'id': __opts__['id'],
'tag': tag, 'tag': tag,
'data': data, 'data': data,
'tok': auth.gen_token('salt'), 'tok': auth.gen_token('salt'),
'cmd': '_minion_event'}) 'cmd': '_minion_event'}
if isinstance(preload, dict):
load.update(preload)
channel = salt.transport.Channel.factory(__opts__) channel = salt.transport.Channel.factory(__opts__)
try: try:

View File

@ -30,6 +30,7 @@ import tempfile
import time import time
import glob import glob
import hashlib import hashlib
import mmap
from functools import reduce # pylint: disable=redefined-builtin from functools import reduce # pylint: disable=redefined-builtin
from collections import Iterable, Mapping from collections import Iterable, Mapping
@ -1636,7 +1637,7 @@ def replace(path,
pattern, pattern,
repl, repl,
count=0, count=0,
flags=0, flags=8,
bufsize=1, bufsize=1,
append_if_not_found=False, append_if_not_found=False,
prepend_if_not_found=False, prepend_if_not_found=False,
@ -1670,14 +1671,14 @@ def replace(path,
A list of flags defined in the :ref:`re module documentation A list of flags defined in the :ref:`re module documentation
<contents-of-module-re>`. Each list item should be a string that will <contents-of-module-re>`. Each list item should be a string that will
correlate to the human-friendly flag name. E.g., ``['IGNORECASE', correlate to the human-friendly flag name. E.g., ``['IGNORECASE',
'MULTILINE']``. Note: multiline searches must specify ``file`` as the 'MULTILINE']``. Optionally, ``flags`` may be an int, with a value
``bufsize`` argument below. corresponding to the XOR (``|``) of all the desired flags. Defaults to
8 (which supports 'MULTILINE').
bufsize (int or str) bufsize (int or str)
How much of the file to buffer into memory at once. The How much of the file to buffer into memory at once. The
default value ``1`` processes one line at a time. The special value default value ``1`` processes one line at a time. The special value
``file`` may be specified which will read the entire file into memory ``file`` may be specified which will read the entire file into memory
before processing. Note: multiline searches must specify ``file`` before processing.
buffering.
append_if_not_found append_if_not_found
.. versionadded:: 2014.7.0 .. versionadded:: 2014.7.0
@ -1778,8 +1779,9 @@ def replace(path,
flags_num = _get_flags(flags) flags_num = _get_flags(flags)
cpattern = re.compile(str(pattern), flags_num) cpattern = re.compile(str(pattern), flags_num)
filesize = os.path.getsize(path)
if bufsize == 'file': if bufsize == 'file':
bufsize = os.path.getsize(path) bufsize = filesize
# Search the file; track if any changes have been made for the return val # Search the file; track if any changes have been made for the return val
has_changes = False has_changes = False
@ -1800,60 +1802,57 @@ def replace(path,
append_if_not_found) \ append_if_not_found) \
else repl else repl
if search_only: # mmap throws a ValueError if the file is empty, but if it is empty we
# should be able to skip the search anyway. NOTE: Is there a use case for
# searching an empty file with an empty pattern?
if filesize is not 0:
# First check the whole file, determine whether to make the replacement
# Searching first avoids modifying the time stamp if there are no changes
try: try:
# allow multiline searching # Use a read-only handle to open the file
with salt.utils.filebuffer.BufferedReader(path) as breader: with salt.utils.fopen(path,
for chunk in breader: mode='rb',
if re.search(cpattern, chunk): buffering=bufsize) as r_file:
return True r_data = mmap.mmap(r_file.fileno(),
return False 0,
access=mmap.ACCESS_READ)
if search_only:
# Just search; bail as early as a match is found
if re.search(cpattern, r_data):
return True # `with` block handles file closure
else:
result, nrepl = re.subn(cpattern, repl, r_data, count)
# found anything? (even if no change)
if nrepl > 0:
found = True
# Identity check the potential change
has_changes = True if pattern != repl else has_changes
if prepend_if_not_found or append_if_not_found:
# Search for content, to avoid pre/appending the
# content if it was pre/appended in a previous run.
if re.search('^{0}$'.format(re.escape(content)),
r_data,
flags=flags_num):
# Content was found, so set found.
found = True
# Keep track of show_changes here, in case the file isn't
# modified
if show_changes or append_if_not_found or \
prepend_if_not_found:
orig_file = r_data.read(filesize).splitlines(True)
new_file = result.splitlines(True)
except (OSError, IOError) as exc: except (OSError, IOError) as exc:
raise CommandExecutionError( raise CommandExecutionError(
"Unable to read file '{0}'. Exception: {1}".format(path, exc) "Unable to open file '{0}'. "
"Exception: {1}".format(path, exc)
) )
finally:
# First check the whole file, determine whether to make the replacement if r_data and isinstance(r_data, mmap.mmap):
# Searching first avoids modifying the time stamp if there are no changes r_data.close()
try:
# Use a read-only handle to open the file
with salt.utils.fopen(path,
mode='r',
buffering=bufsize) as r_file:
count_replaced = 0
for line in r_file:
if count == 0 or count_replaced <= count:
result, nrepl = re.subn(cpattern, repl, line, count)
count_replaced += nrepl
else:
break
# found anything? (even if no change)
if nrepl > 0:
found = True
if prepend_if_not_found or append_if_not_found:
# Search for content, so we don't continue pre/appending
# the content if it's been pre/appended in a previous run.
if re.search('^{0}$'.format(re.escape(content)), line):
# Content was found, so set found.
found = True
# Identity check each potential change until one change is made
if has_changes is False and result != line:
has_changes = True
# Keep track of show_changes here, in case the file isn't
# modified
if show_changes or append_if_not_found or \
prepend_if_not_found:
orig_file.append(line)
new_file.append(result)
except (OSError, IOError) as exc:
raise CommandExecutionError(
"Unable to open file '{0}'. Exception: {1}".format(path, exc)
)
if has_changes and not dry_run: if has_changes and not dry_run:
# Write the replacement text in this block. # Write the replacement text in this block.
@ -1874,26 +1873,25 @@ def replace(path,
with salt.utils.fopen(temp_file, with salt.utils.fopen(temp_file,
mode='r', mode='r',
buffering=bufsize) as r_file: buffering=bufsize) as r_file:
count_replaced = 0 r_data = mmap.mmap(r_file.fileno(),
for line in r_file: 0,
result, nrepl = re.subn(cpattern, repl, access=mmap.ACCESS_READ)
line, count) result, nrepl = re.subn(cpattern, repl,
if count == 0 or count_replaced <= count: r_data, count)
result, nrepl = re.subn(cpattern, repl, line, count) try:
count_replaced += nrepl w_file.write(result)
else: except (OSError, IOError) as exc:
result = line raise CommandExecutionError(
try: "Unable to write file '{0}'. Contents may "
w_file.write(result) "be truncated. Temporary file contains copy "
except (OSError, IOError) as exc: "at '{1}'. "
raise CommandExecutionError( "Exception: {2}".format(path, temp_file, exc)
"Unable to write file '{0}'. Contents may " )
"be truncated. Temporary file contains copy "
"at '{1}'. "
"Exception: {2}".format(path, temp_file, exc)
)
except (OSError, IOError) as exc: except (OSError, IOError) as exc:
raise CommandExecutionError("Exception: {0}".format(exc)) raise CommandExecutionError("Exception: {0}".format(exc))
finally:
if r_data and isinstance(r_data, mmap.mmap):
r_data.close()
except (OSError, IOError) as exc: except (OSError, IOError) as exc:
raise CommandExecutionError("Exception: {0}".format(exc)) raise CommandExecutionError("Exception: {0}".format(exc))
@ -2178,7 +2176,7 @@ def blockreplace(path,
def search(path, def search(path,
pattern, pattern,
flags=0, flags=8,
bufsize=1, bufsize=1,
ignore_if_missing=False, ignore_if_missing=False,
multiline=False multiline=False
@ -4720,7 +4718,7 @@ def list_backups(path, limit=None):
[files[x] for x in sorted(files, reverse=True)[:limit]] [files[x] for x in sorted(files, reverse=True)[:limit]]
))) )))
list_backup = list_backups list_backup = salt.utils.alias_function(list_backups, 'list_backup')
def list_backups_dir(path, limit=None): def list_backups_dir(path, limit=None):
@ -4892,7 +4890,7 @@ def delete_backup(path, backup_id):
return ret return ret
remove_backup = delete_backup remove_backup = salt.utils.alias_function(delete_backup, 'remove_backup')
def grep(path, def grep(path,

View File

@ -1,5 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
''' '''
Support for firewalld. Support for firewalld.
@ -12,6 +11,7 @@ import logging
import re import re
# Import Salt Libs # Import Salt Libs
from salt.exceptions import CommandExecutionError
import salt.utils import salt.utils
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -31,16 +31,18 @@ def __firewall_cmd(cmd):
''' '''
Return the firewall-cmd location Return the firewall-cmd location
''' '''
out = __salt__['cmd.run']('{0} {1}'.format( firewall_cmd = '{0} {1}'.format(salt.utils.which('firewall-cmd'), cmd)
salt.utils.which('firewall-cmd'), out = __salt__['cmd.run_all'](firewall_cmd)
cmd))
if out == 'success': if out['retcode'] != 0:
return 'success' if not out['stderr']:
elif 'Error' in out: msg = out['stdout']
return out[5:-5] else:
msg = out['stderr']
return out raise CommandExecutionError(
'firewall-cmd failed: {0}'.format(msg)
)
return out['stdout']
def __mgmt(name, _type, action): def __mgmt(name, _type, action):

View File

@ -192,7 +192,7 @@ def latest_version(*names, **kwargs):
return '' if len(names) == 1 else dict((x, '') for x in names) return '' if len(names) == 1 else dict((x, '') for x in names)
# available_version is being deprecated # available_version is being deprecated
available_version = latest_version available_version = salt.utils.alias_function(latest_version, 'available_version')
def version(*names, **kwargs): def version(*names, **kwargs):
@ -463,9 +463,9 @@ def remove(name=None, pkgs=None, **kwargs):
return salt.utils.compare_dicts(old, new) return salt.utils.compare_dicts(old, new)
# Support pkg.delete to remove packages to more closely match pkg_delete # Support pkg.delete to remove packages to more closely match pkg_delete
delete = remove delete = salt.utils.alias_function(remove, 'delete')
# No equivalent to purge packages, use remove instead # No equivalent to purge packages, use remove instead
purge = remove purge = salt.utils.alias_function(remove, 'purge')
def _rehash(): def _rehash():

View File

@ -978,7 +978,7 @@ def config_get_regexp(key,
ret.setdefault(param, []).append(value) ret.setdefault(param, []).append(value)
return ret return ret
config_get_regex = config_get_regexp config_get_regex = salt.utils.alias_function(config_get_regexp, 'config_get_regex')
def config_set(key, def config_set(key,

View File

@ -7,6 +7,9 @@ Virtual machine image management tools
from __future__ import absolute_import from __future__ import absolute_import
import logging import logging
# Import salt libs
import salt.utils
# Import 3rd-party libs # Import 3rd-party libs
import salt.ext.six as six import salt.ext.six as six
@ -36,7 +39,7 @@ def mount_image(location):
return '' return ''
# compatibility for api change # compatibility for api change
mnt_image = mount_image mnt_image = salt.utils.alias_function(mount_image, 'mnt_image')
def umount_image(mnt): def umount_image(mnt):

View File

@ -211,7 +211,7 @@ def list_tab(user):
return ret return ret
# For consistency's sake # For consistency's sake
ls = list_tab # pylint: disable=C0103 ls = salt.utils.alias_function(list_tab, 'ls')
def set_job(user, path, mask, cmd): def set_job(user, path, mask, cmd):
@ -315,4 +315,4 @@ def rm_job(user,
return ret return ret
rm = rm_job # pylint: disable=C0103 rm = salt.utils.alias_function(rm_job, 'rm')

View File

@ -261,6 +261,9 @@ def build_rule(table='filter', chain=None, command=None, position='', full=None,
del kwargs[multiport_arg] del kwargs[multiport_arg]
if 'comment' in kwargs: if 'comment' in kwargs:
if '-m comment' not in rule:
rule.append('-m comment')
rule.append('--comment "{0}"'.format(kwargs['comment'])) rule.append('--comment "{0}"'.format(kwargs['comment']))
del kwargs['comment'] del kwargs['comment']

View File

@ -52,17 +52,16 @@ def facts_refresh():
Reload the facts dictionary from the device. Usually only needed Reload the facts dictionary from the device. Usually only needed
if the device configuration is changed by some other actor. if the device configuration is changed by some other actor.
''' '''
return __proxy__['junos.refresh']()
return __opts__['proxymodule']['junos.refresh']()
def call_rpc(): def call_rpc():
return __opts__['proxymodule']['junos.rpc']() return __proxy__['junos.rpc']()
def set_hostname(hostname=None, commit_change=True): def set_hostname(hostname=None, commit_change=True):
conn = __opts__['proxymodule']['junos.conn']() conn = __proxy__['junos.conn']()
ret = dict() ret = dict()
if hostname is None: if hostname is None:
ret['out'] = False ret['out'] = False
@ -84,7 +83,7 @@ def set_hostname(hostname=None, commit_change=True):
def commit(): def commit():
conn = __opts__['proxymodule']['junos.conn']() conn = __proxy__['junos.conn']()
ret = {} ret = {}
commit_ok = conn.cu.commit_check() commit_ok = conn.cu.commit_check()
if commit_ok: if commit_ok:
@ -104,7 +103,7 @@ def commit():
def rollback(): def rollback():
ret = dict() ret = dict()
conn = __opts__['proxymodule']['junos.conn']() conn = __proxy__['junos.conn']()
ret['out'] = conn.cu.rollback(0) ret['out'] = conn.cu.rollback(0)
@ -118,7 +117,7 @@ def rollback():
def diff(): def diff():
conn = __opts__['proxymodule']['junos.conn']() conn = __proxy__['junos.conn']()
ret = dict() ret = dict()
ret['out'] = True ret['out'] = True
ret['message'] = conn.cu.diff() ret['message'] = conn.cu.diff()
@ -128,7 +127,18 @@ def diff():
def ping(): def ping():
conn = __opts__['proxymodule']['junos.conn']() conn = __proxy__['junos.conn']()
ret = dict() ret = dict()
ret['message'] = conn.probe() ret['message'] = conn.probe()
ret['out'] = True ret['out'] = True
return ret
def cli(command):
conn = __proxy__['junos.conn']()
ret = dict()
ret['message'] = conn.cli(command)
ret['out'] = True
return ret

View File

@ -2612,7 +2612,7 @@ def destroy(name, stop=False, path=None):
return _change_state('lxc-destroy', name, None, path=path) return _change_state('lxc-destroy', name, None, path=path)
# Compatibility between LXC and nspawn # Compatibility between LXC and nspawn
remove = destroy remove = salt.utils.alias_function(destroy, 'remove')
def exists(name, path=None): def exists(name, path=None):
@ -2955,7 +2955,7 @@ def set_password(name, users, password, encrypted=True, path=None):
) )
return True return True
set_pass = set_password set_pass = salt.utils.alias_function(set_password, 'set_pass')
def update_lxc_conf(name, lxc_conf, lxc_conf_unset, path=None): def update_lxc_conf(name, lxc_conf, lxc_conf_unset, path=None):
@ -4272,7 +4272,7 @@ def copy_to(name, source, dest, overwrite=False, makedirs=False, path=None):
overwrite=overwrite, overwrite=overwrite,
makedirs=makedirs) makedirs=makedirs)
cp = copy_to cp = salt.utils.alias_function(copy_to, 'cp')
def read_conf(conf_file, out_format='simple'): def read_conf(conf_file, out_format='simple'):

View File

@ -189,7 +189,7 @@ def latest_version(*names, **kwargs):
return ret return ret
# available_version is being deprecated # available_version is being deprecated
available_version = latest_version available_version = salt.utils.alias_function(latest_version, 'available_version')
def remove(name=None, pkgs=None, **kwargs): def remove(name=None, pkgs=None, **kwargs):

View File

@ -333,7 +333,7 @@ def filter_by(lookup, expr_form='compound', minion_id=None):
for key in lookup: for key in lookup:
if minion_id and expr_funcs[expr_form](key, minion_id): if minion_id and expr_funcs[expr_form](key, minion_id):
return lookup[key] return lookup[key]
elif expr_funcs[expr_form](key, minion_id): elif expr_funcs[expr_form](key):
return lookup[key] return lookup[key]
return None return None

View File

@ -12,6 +12,7 @@ from __future__ import absolute_import
import logging import logging
# Import salt libs # Import salt libs
import salt.utils
from salt.exceptions import CommandExecutionError, SaltInvocationError from salt.exceptions import CommandExecutionError, SaltInvocationError
from salt.ext.six import integer_types from salt.ext.six import integer_types
@ -234,7 +235,7 @@ def increment(key, delta=1, host=DEFAULT_HOST, port=DEFAULT_PORT):
except ValueError: except ValueError:
raise SaltInvocationError('Delta value must be an integer') raise SaltInvocationError('Delta value must be an integer')
incr = increment incr = salt.utils.alias_function(increment, 'incr')
def decrement(key, delta=1, host=DEFAULT_HOST, port=DEFAULT_PORT): def decrement(key, delta=1, host=DEFAULT_HOST, port=DEFAULT_PORT):
@ -265,4 +266,4 @@ def decrement(key, delta=1, host=DEFAULT_HOST, port=DEFAULT_PORT):
except ValueError: except ValueError:
raise SaltInvocationError('Delta value must be an integer') raise SaltInvocationError('Delta value must be an integer')
decr = decrement decr = salt.utils.alias_function(decrement, 'decr')

View File

@ -1,8 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
''' '''
Provides access to randomness generators.
=========================================
.. versionadded:: 2014.7.0 .. versionadded:: 2014.7.0
Provides access to randomness generators.
''' '''
from __future__ import absolute_import from __future__ import absolute_import
# Import python libs # Import python libs

View File

@ -728,7 +728,7 @@ def hw_addr(iface):
return salt.utils.network.hw_addr(iface) return salt.utils.network.hw_addr(iface)
# Alias hwaddr to preserve backward compat # Alias hwaddr to preserve backward compat
hwaddr = hw_addr hwaddr = salt.utils.alias_function(hw_addr, 'hwaddr')
def interface(iface): def interface(iface):
@ -874,7 +874,7 @@ def ip_addrs(interface=None, include_loopback=False, cidr=None):
else: else:
return addrs return addrs
ipaddrs = ip_addrs ipaddrs = salt.utils.alias_function(ip_addrs, 'ipaddrs')
def ip_addrs6(interface=None, include_loopback=False, cidr=None): def ip_addrs6(interface=None, include_loopback=False, cidr=None):
@ -898,7 +898,7 @@ def ip_addrs6(interface=None, include_loopback=False, cidr=None):
else: else:
return addrs return addrs
ipaddrs6 = ip_addrs6 ipaddrs6 = salt.utils.alias_function(ip_addrs6, 'ipaddrs6')
def get_hostname(): def get_hostname():

View File

@ -862,7 +862,7 @@ def list_running():
# 'machinectl list' shows only running containers, so allow this to work as an # 'machinectl list' shows only running containers, so allow this to work as an
# alias to nspawn.list_running # alias to nspawn.list_running
list_ = list_running list_ = salt.utils.alias_function(list_running, 'list_')
def list_stopped(): def list_stopped():
@ -1236,7 +1236,7 @@ def remove(name, stop=False):
# Compatibility between LXC and nspawn # Compatibility between LXC and nspawn
destroy = remove destroy = salt.utils.alias_function(remove, 'destroy')
@_ensure_exists @_ensure_exists
@ -1292,7 +1292,7 @@ def copy_to(name, source, dest, overwrite=False, makedirs=False):
overwrite=overwrite, overwrite=overwrite,
makedirs=makedirs) makedirs=makedirs)
cp = copy_to cp = salt.utils.alias_function(copy_to, 'cp')
# Everything below requres systemd >= 219 # Everything below requres systemd >= 219
@ -1455,4 +1455,4 @@ def pull_dkr(url, name, index):
''' '''
return _pull_image('dkr', url, name, index=index) return _pull_image('dkr', url, name, index=index)
pull_docker = pull_dkr pull_docker = salt.utils.alias_function(pull_dkr, 'pull_docker')

View File

@ -116,7 +116,7 @@ def latest_version(*names, **kwargs):
return ret return ret
# available_version is being deprecated # available_version is being deprecated
available_version = latest_version available_version = salt.utils.alias_function(latest_version, 'available_version')
def version(*names, **kwargs): def version(*names, **kwargs):

View File

@ -99,7 +99,7 @@ def latest_version(*names, **kwargs):
return ret return ret
# available_version is being deprecated # available_version is being deprecated
available_version = latest_version available_version = salt.utils.alias_function(latest_version, 'available_version')
def upgrade_available(name): def upgrade_available(name):

View File

@ -121,7 +121,7 @@ def list_windows(profile=None, api_key=None):
# The long version, added for consistency # The long version, added for consistency
list_maintenance_windows = list_windows list_maintenance_windows = salt.utils.alias_function(list_windows, 'list_maintenance_windows')
def list_policies(profile=None, api_key=None): def list_policies(profile=None, api_key=None):
@ -143,7 +143,7 @@ def list_policies(profile=None, api_key=None):
# The long version, added for consistency # The long version, added for consistency
list_escalation_policies = list_policies list_escalation_policies = salt.utils.alias_function(list_policies, 'list_escalation_policies')
def create_event(service_key=None, description=None, details=None, def create_event(service_key=None, description=None, details=None,

View File

@ -443,7 +443,7 @@ def mkpart(device, part_type, fs_type=None, start=None, end=None):
''' '''
_validate_device(device) _validate_device(device)
if not start or not end: if start in [None, ''] or end in [None, '']:
raise CommandExecutionError( raise CommandExecutionError(
'partition.mkpart requires a start and an end' 'partition.mkpart requires a start and an end'
) )

View File

@ -114,7 +114,7 @@ def items(*args, **kwargs):
return pillar.compile_pillar() return pillar.compile_pillar()
# Allow pillar.data to also be used to return pillar data # Allow pillar.data to also be used to return pillar data
data = items data = salt.utils.alias_function(items, 'data')
def _obfuscate_inner(var): def _obfuscate_inner(var):

View File

@ -178,7 +178,7 @@ def latest_version(*names, **kwargs):
# available_version is being deprecated # available_version is being deprecated
available_version = latest_version available_version = salt.utils.alias_function(latest_version, 'available_version')
def version(*names, **kwargs): def version(*names, **kwargs):

View File

@ -193,7 +193,7 @@ def version(*names, **kwargs):
]) ])
# Support pkg.info get version info, since this is the CLI usage # Support pkg.info get version info, since this is the CLI usage
info = version info = salt.utils.alias_function(version, 'info')
def refresh_db(jail=None, chroot=None, force=False): def refresh_db(jail=None, chroot=None, force=False):
@ -236,7 +236,7 @@ def refresh_db(jail=None, chroot=None, force=False):
# Support pkg.update to refresh the db, since this is the CLI usage # Support pkg.update to refresh the db, since this is the CLI usage
update = refresh_db update = salt.utils.alias_function(refresh_db, 'update')
def latest_version(*names, **kwargs): def latest_version(*names, **kwargs):
@ -305,7 +305,7 @@ def latest_version(*names, **kwargs):
# available_version is being deprecated # available_version is being deprecated
available_version = latest_version available_version = salt.utils.alias_function(latest_version, 'available_version')
def list_pkgs(versions_as_list=False, def list_pkgs(versions_as_list=False,
@ -952,9 +952,9 @@ def remove(name=None,
return salt.utils.compare_dicts(old, new) return salt.utils.compare_dicts(old, new)
# Support pkg.delete to remove packages, since this is the CLI usage # Support pkg.delete to remove packages, since this is the CLI usage
delete = remove delete = salt.utils.alias_function(remove, 'delete')
# No equivalent to purge packages, use remove instead # No equivalent to purge packages, use remove instead
purge = remove purge = salt.utils.alias_function(remove, 'purge')
def upgrade(*names, **kwargs): def upgrade(*names, **kwargs):

View File

@ -226,7 +226,7 @@ def latest_version(*names, **kwargs):
return ret return ret
# available_version is being deprecated # available_version is being deprecated
available_version = latest_version available_version = salt.utils.alias_function(latest_version, 'available_version')
def install(name=None, refresh=False, version=None, pkgs=None, **kwargs): def install(name=None, refresh=False, version=None, pkgs=None, **kwargs):

View File

@ -18,6 +18,7 @@ import salt.utils.itertools
import salt.ext.six as six import salt.ext.six as six
from salt.exceptions import SaltInvocationError from salt.exceptions import SaltInvocationError
from salt.ext.six.moves import range from salt.ext.six.moves import range
from salt.exceptions import CommandExecutionError
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -30,14 +31,15 @@ def __virtual__():
def _format_response(response, msg): def _format_response(response, msg):
error = 'RabbitMQ command failed: {0}'.format(response)
if isinstance(response, dict): if isinstance(response, dict):
if response['retcode'] != 0: if response['retcode'] != 0:
msg = 'Error' raise CommandExecutionError(error)
else: else:
msg = response['stdout'] msg = response['stdout']
else: else:
if 'Error' in response: if 'Error' in response:
msg = 'Error' raise CommandExecutionError(error)
return { return {
msg: response msg: response
} }
@ -703,8 +705,12 @@ def plugin_is_enabled(name, runas=None):
if runas is None: if runas is None:
runas = salt.utils.get_user() runas = salt.utils.get_user()
cmd = [_get_rabbitmq_plugin(), 'list', '-m', '-e'] cmd = [_get_rabbitmq_plugin(), 'list', '-m', '-e']
ret = __salt__['cmd.run'](cmd, runas=runas, python_shell=False) ret = __salt__['cmd.run_all'](cmd, python_shell=False, runas=runas)
return bool(name in ret) if ret['retcode'] != 0:
raise CommandExecutionError(
'RabbitMQ command failed: {0}'.format(ret['stderr'])
)
return bool(name in ret['stdout'])
def enable_plugin(name, runas=None): def enable_plugin(name, runas=None):

View File

@ -67,9 +67,9 @@ class Registry(object):
"HKU": _winreg.HKEY_USERS, "HKU": _winreg.HKEY_USERS,
} }
self.reflection_mask = { self.registry_32 = {
True: _winreg.KEY_ALL_ACCESS, True: _winreg.KEY_ALL_ACCESS | _winreg.KEY_WOW64_32KEY,
False: _winreg.KEY_ALL_ACCESS | _winreg.KEY_WOW64_64KEY, False: _winreg.KEY_ALL_ACCESS,
} }
self.vtype = { self.vtype = {
@ -106,7 +106,30 @@ def __virtual__():
return False return False
def read_key(hkey, path, key=None): def _key_exists(hive, key, use_32bit_registry=False):
'''
Check that the key is found in the registry
:param str hive: The hive to connect to.
:param str key: The key to check
:param bool use_32bit_registry: Look in the 32bit portion of the registry
:return: Returns True if found, False if not found
:rtype: bool
'''
registry = Registry()
hkey = registry.hkeys[hive]
access_mask = registry.registry_32[use_32bit_registry]
try:
handle = _winreg.OpenKey(hkey, key, 0, access_mask)
_winreg.CloseKey(handle)
return True
except WindowsError as exc: # pylint: disable=E0602
return False
def read_key(hkey, path, key=None, use_32bit_registry=False):
''' '''
.. important:: .. important::
The name of this function is misleading and will be changed to reflect The name of this function is misleading and will be changed to reflect
@ -146,36 +169,41 @@ def read_key(hkey, path, key=None):
'removed in Salt Boron') 'removed in Salt Boron')
return read_value(hive=hkey, return read_value(hive=hkey,
key=path, key=path,
vname=key) vname=key,
use_32bit_registry=use_32bit_registry)
return read_value(hive=hkey, key=path) return read_value(hive=hkey,
key=path,
use_32bit_registry=use_32bit_registry)
def read_value(hive, key, vname=None): def read_value(hive, key, vname=None, use_32bit_registry=False):
r''' r'''
Reads a registry value entry or the default value for a key. Reads a registry value entry or the default value for a key.
:param str hive: :param str hive: The name of the hive. Can be one of the following
The name of the hive. Can be one of the following
- HKEY_LOCAL_MACHINE or HKLM
- HKEY_CURRENT_USER or HKCU
- HKEY_USER or HKU
:param str key: - HKEY_LOCAL_MACHINE or HKLM
The key (looks like a path) to the value name. - HKEY_CURRENT_USER or HKCU
- HKEY_USER or HKU
:param str vname: :param str key: The key (looks like a path) to the value name.
The value name. These are the individual name/data pairs under the key.
If not passed, the key (Default) value will be returned
:return: :param str vname: The value name. These are the individual name/data pairs
A dictionary containing the passed settings as well as the value_data if under the key. If not passed, the key (Default) value will be returned
successful. If unsuccessful, sets success to False
:param bool use_32bit_registry: Accesses the 32bit portion of the registry
on 64 bit installations. On 32bit machines this is ignored.
:return: A dictionary containing the passed settings as well as the
value_data if successful. If unsuccessful, sets success to False
If vname is not passed:
- Returns the first unnamed value (Default) as a string.
- Returns none if first unnamed value is empty.
- Returns False if key not found.
If vname is not passed:
- Returns the first unnamed value (Default) as a string.
- Returns none if first unnamed value is empty.
- Returns False if key not found.
:rtype: dict :rtype: dict
CLI Example: CLI Example:
@ -199,9 +227,10 @@ def read_value(hive, key, vname=None):
registry = Registry() registry = Registry()
hkey = registry.hkeys[hive] hkey = registry.hkeys[hive]
access_mask = registry.registry_32[use_32bit_registry]
try: try:
handle = _winreg.OpenKey(hkey, key) handle = _winreg.OpenKey(hkey, key, 0, access_mask)
try: try:
vdata, vtype = _winreg.QueryValueEx(handle, vname) vdata, vtype = _winreg.QueryValueEx(handle, vname)
if vdata or vdata in [0, '']: if vdata or vdata in [0, '']:
@ -212,7 +241,6 @@ def read_value(hive, key, vname=None):
except WindowsError as exc: # pylint: disable=E0602 except WindowsError as exc: # pylint: disable=E0602
ret['vdata'] = ('(value not set)') ret['vdata'] = ('(value not set)')
ret['vtype'] = 'REG_SZ' ret['vtype'] = 'REG_SZ'
ret['success'] = True
except WindowsError as exc: # pylint: disable=E0602 except WindowsError as exc: # pylint: disable=E0602
log.debug(exc) log.debug(exc)
log.debug('Cannot find key: {0}\\{1}'.format(hive, key)) log.debug('Cannot find key: {0}\\{1}'.format(hive, key))
@ -222,7 +250,13 @@ def read_value(hive, key, vname=None):
return ret return ret
def set_key(hkey, path, value, key=None, vtype='REG_DWORD', reflection=True): def set_key(hkey,
path,
value,
key=None,
vtype='REG_DWORD',
reflection=True,
use_32bit_registry=False):
''' '''
.. important :: .. important ::
The name of this function is misleading and will be changed to reflect The name of this function is misleading and will be changed to reflect
@ -257,46 +291,57 @@ def set_key(hkey, path, value, key=None, vtype='REG_DWORD', reflection=True):
key=path, key=path,
vname=key, vname=key,
vdata=value, vdata=value,
vtype=vtype) vtype=vtype,
use_32bit_registry=use_32bit_registry)
return set_value(hive=hkey, key=path, vdata=value, vtype=vtype) return set_value(hive=hkey,
key=path,
vdata=value,
vtype=vtype,
use_32bit_registry=use_32bit_registry)
def set_value(hive, key, vname=None, vdata=None, vtype='REG_SZ', reflection=True): def set_value(hive,
key,
vname=None,
vdata=None,
vtype='REG_SZ',
reflection=True,
use_32bit_registry=False):
''' '''
Sets a registry value entry or the default value for a key. Sets a registry value entry or the default value for a key.
:param str hive: :param str hive: The name of the hive. Can be one of the following
The name of the hive. Can be one of the following
- HKEY_LOCAL_MACHINE or HKLM
- HKEY_CURRENT_USER or HKCU
- HKEY_USER or HKU
:param str key: - HKEY_LOCAL_MACHINE or HKLM
The key (looks like a path) to the value name. - HKEY_CURRENT_USER or HKCU
- HKEY_USER or HKU
:param str vname: :param str key: The key (looks like a path) to the value name.
The value name. These are the individual name/data pairs under the key.
If not passed, the key (Default) value will be set.
:param str vdata: :param str vname: The value name. These are the individual name/data pairs
The value data to be set. under the key. If not passed, the key (Default) value will be set.
:param str vtype: :param str vdata: The value data to be set.
The value type. Can be one of the following:
- REG_BINARY
- REG_DWORD
- REG_EXPAND_SZ
- REG_MULTI_SZ
- REG_SZ
:param bool reflection: :param str vtype: The value type. Can be one of the following:
A boolean value indicating that the value should also be set in the
Wow6432Node portion of the registry. Only applies to 64 bit Windows.
This setting is ignored for 32 bit Windows.
:return: - REG_BINARY
Returns True if successful, False if not - REG_DWORD
- REG_EXPAND_SZ
- REG_MULTI_SZ
- REG_SZ
:param bool reflection: A boolean value indicating that the value should
also be set in the Wow6432Node portion of the registry. Only applies to 64
bit Windows. This setting is ignored for 32 bit Windows.
.. deprecated:: 2015.8.2
Use `use_32bit_registry` instead. The parameter seems to have no effect
since Windows 7 / Windows 2008R2 removed support for reflection. The
parameter will be removed in Boron.
:return: Returns True if successful, False if not
:rtype: bool :rtype: bool
CLI Example: CLI Example:
@ -306,21 +351,29 @@ def set_value(hive, key, vname=None, vdata=None, vtype='REG_SZ', reflection=True
salt '*' reg.set_value HKEY_LOCAL_MACHINE 'SOFTWARE\\Salt' 'version' '2015.5.2' salt '*' reg.set_value HKEY_LOCAL_MACHINE 'SOFTWARE\\Salt' 'version' '2015.5.2'
''' '''
registry = Registry() registry = Registry()
hive = registry.hkeys[hive] hkey = registry.hkeys[hive]
vtype = registry.vtype[vtype] vtype = registry.vtype[vtype]
access_mask = registry.reflection_mask[reflection] access_mask = registry.registry_32[use_32bit_registry]
try: try:
handle = _winreg.CreateKeyEx(hive, key, 0, access_mask) handle = _winreg.CreateKeyEx(hkey, key, 0, access_mask)
if vtype == registry.vtype['REG_SZ']\
or vtype == registry.vtype['REG_BINARY']:
vdata = str(vdata)
_winreg.SetValueEx(handle, vname, 0, vtype, vdata) _winreg.SetValueEx(handle, vname, 0, vtype, vdata)
_winreg.CloseKey(handle) _winreg.CloseKey(handle)
return True return True
except (WindowsError, ValueError) as exc: # pylint: disable=E0602 except (WindowsError, ValueError, TypeError) as exc: # pylint: disable=E0602
log.error(exc, exc_info=True) log.error(exc, exc_info=True)
return False return False
def create_key(hkey, path, key=None, value=None, reflection=True): def create_key(hkey,
path,
key=None,
value=None,
reflection=True,
use_32bit_registry=False):
''' '''
.. important :: .. important ::
The name of this function is misleading and will be changed to reflect The name of this function is misleading and will be changed to reflect
@ -353,12 +406,17 @@ def create_key(hkey, path, key=None, value=None, reflection=True):
key=path, key=path,
vname=key, vname=key,
vdata=value, vdata=value,
vtype='REG_SZ') use_32bit_registry=use_32bit_registry)
return set_value(hive=hkey, key=path) return set_value(hive=hkey, key=path, use_32bit_registry=use_32bit_registry)
def delete_key(hkey, path, key=None, reflection=True, force=False): def delete_key(hkey,
path,
key=None,
reflection=True,
force=False,
use_32bit_registry=False):
''' '''
.. important:: .. important::
The name of this function is misleading and will be changed to reflect The name of this function is misleading and will be changed to reflect
@ -383,34 +441,31 @@ def delete_key(hkey, path, key=None, reflection=True, force=False):
salt '*' reg.delete_key HKEY_CURRENT_USER 'SOFTWARE\\Salt' salt '*' reg.delete_key HKEY_CURRENT_USER 'SOFTWARE\\Salt'
:param str hkey: (will be changed to hive) :param str hkey: (will be changed to hive) The name of the hive. Can be one
The name of the hive. Can be one of the following of the following
- HKEY_LOCAL_MACHINE or HKLM
- HKEY_CURRENT_USER or HKCU
- HKEY_USER or HKU
:param str path: (will be changed to key) - HKEY_LOCAL_MACHINE or HKLM
The key (looks like a path) to remove. - HKEY_CURRENT_USER or HKCU
- HKEY_USER or HKU
:param str key: (used incorrectly) :param str path: (will be changed to key) The key (looks like a path) to
Will be removed in Boron remove.
:param bool reflection: :param str key: (used incorrectly) Will be removed in Boron
A boolean value indicating that the value should also be removed from
the Wow6432Node portion of the registry. Only applies to 64 bit Windows.
This setting is ignored for 32 bit Windows.
Only applies to delete value. If the key parameter is passed, this :param bool reflection: A boolean value indicating that the value should
function calls delete_value instead. Will be changed in Boron. also be removed from the Wow6432Node portion of the registry. Only applies
to 64 bit Windows. This setting is ignored for 32 bit Windows.
:param bool force: Only applies to delete value. If the key parameter is passed, this function
A boolean value indicating that all subkeys should be removed as well. calls delete_value instead. Will be changed in Boron.
If this is set to False (default) and there are subkeys, the delete_key
function will fail.
:return: :param bool force: A boolean value indicating that all subkeys should be
Returns True if successful, False if not removed as well. If this is set to False (default) and there are subkeys,
If force=True, the results of delete_key_recursive are returned. the delete_key function will fail.
:return: Returns True if successful, False if not. If force=True, the
results of delete_key_recursive are returned.
:rtype: bool :rtype: bool
''' '''
@ -422,42 +477,46 @@ def delete_key(hkey, path, key=None, reflection=True, force=False):
return delete_value(hive=hkey, return delete_value(hive=hkey,
key=path, key=path,
vname=key, vname=key,
reflection=reflection) reflection=reflection,
use_32bit_registry=use_32bit_registry)
if force: if force:
return delete_key_recursive(hkey, path) return delete_key_recursive(hkey,
path,
use_32bit_registry=use_32bit_registry)
registry = Registry() registry = Registry()
hive = registry.hkeys[hkey] hive = registry.hkeys[hkey]
key = path key = path
access_mask = registry.registry_32[use_32bit_registry]
try: try:
# Can't use delete_value to delete a key # Can't use delete_value to delete a key
_winreg.DeleteKey(hive, key) key_handle = _winreg.OpenKey(hive, key, 0, access_mask)
_winreg.DeleteKey(key_handle, '')
_winreg.CloseKey(key_handle)
return True return True
except WindowsError as exc: # pylint: disable=E0602 except WindowsError as exc: # pylint: disable=E0602
log.error(exc, exc_info=True) log.error(exc, exc_info=True)
return False return False
def delete_key_recursive(hive, key): def delete_key_recursive(hive, key, use_32bit_registry=False):
''' '''
.. versionadded:: 2015.5.4 .. versionadded:: 2015.5.4
Delete a registry key to include all subkeys. Delete a registry key to include all subkeys.
:param hive: :param hive: The name of the hive. Can be one of the following
The name of the hive. Can be one of the following
- HKEY_LOCAL_MACHINE or HKLM
- HKEY_CURRENT_USER or HKCU
- HKEY_USER or HKU
:param key: - HKEY_LOCAL_MACHINE or HKLM
The key to remove (looks like a path) - HKEY_CURRENT_USER or HKCU
- HKEY_USER or HKU
:return: :param key: The key to remove (looks like a path)
A dictionary listing the keys that deleted successfully as well as those
that failed to delete. :return: A dictionary listing the keys that deleted successfully as well as
those that failed to delete.
:rtype: dict :rtype: dict
The following example will remove ``salt`` and all its subkeys from the The following example will remove ``salt`` and all its subkeys from the
@ -469,6 +528,15 @@ def delete_key_recursive(hive, key):
salt '*' reg.delete_key_recursive HKLM SOFTWARE\\salt salt '*' reg.delete_key_recursive HKLM SOFTWARE\\salt
''' '''
# Instantiate the registry object
registry = Registry()
hkey = registry.hkeys[hive]
key_path = key
access_mask = registry.registry_32[use_32bit_registry]
if not _key_exists(hive, key, use_32bit_registry):
return False
# Functions for traversing the registry tree # Functions for traversing the registry tree
def subkeys(key): def subkeys(key):
i = 0 i = 0
@ -480,70 +548,61 @@ def delete_key_recursive(hive, key):
except WindowsError: # pylint: disable=E0602 except WindowsError: # pylint: disable=E0602
break break
def traverse_registry_tree(hkey, keypath, ret): def traverse_registry_tree(hkey, keypath, ret, access_mask):
key = _winreg.OpenKey(hkey, keypath, 0, _winreg.KEY_READ) key = _winreg.OpenKey(hkey, keypath, 0, access_mask)
for subkeyname in subkeys(key): for subkeyname in subkeys(key):
subkeypath = r'{0}\{1}'.format(keypath, subkeyname) subkeypath = r'{0}\{1}'.format(keypath, subkeyname)
ret = traverse_registry_tree(hkey, subkeypath, ret) ret = traverse_registry_tree(hkey, subkeypath, ret, access_mask)
ret.append('{0}'.format(subkeypath)) ret.append('{0}'.format(subkeypath))
return ret return ret
# Instantiate the registry object
registry = Registry()
hkey = registry.hkeys[hive]
keypath = key
# Get a reverse list of registry keys to be deleted # Get a reverse list of registry keys to be deleted
key_list = [] key_list = []
key_list = traverse_registry_tree(hkey, keypath, key_list) key_list = traverse_registry_tree(hkey, key_path, key_list, access_mask)
# Add the top level key last, all subkeys must be deleted first
key_list.append(r'{0}'.format(key_path))
ret = {'Deleted': [], ret = {'Deleted': [],
'Failed': []} 'Failed': []}
# Delete all subkeys # Delete all sub_keys
for keypath in key_list: for sub_key_path in key_list:
try: try:
_winreg.DeleteKey(hkey, keypath) key_handle = _winreg.OpenKey(hkey, sub_key_path, 0, access_mask)
ret['Deleted'].append(r'{0}\{1}'.format(hive, keypath)) _winreg.DeleteKey(key_handle, '')
ret['Deleted'].append(r'{0}\{1}'.format(hive, sub_key_path))
except WindowsError as exc: # pylint: disable=E0602 except WindowsError as exc: # pylint: disable=E0602
log.error(exc, exc_info=True) log.error(exc, exc_info=True)
ret['Failed'].append(r'{0}\{1} {2}'.format(hive, key, exc)) ret['Failed'].append(r'{0}\{1} {2}'.format(hive, sub_key_path, exc))
# Delete the key now that all the subkeys are deleted
try:
_winreg.DeleteKey(hkey, key)
ret['Deleted'].append(r'{0}\{1}'.format(hive, key))
except WindowsError as exc: # pylint: disable=E0602
log.error(exc, exc_info=True)
ret['Failed'].append(r'{0}\{1} {2}'.format(hive, key, exc))
return ret return ret
def delete_value(hive, key, vname=None, reflection=True): def delete_value(hive, key, vname=None, reflection=True, use_32bit_registry=False):
''' '''
Delete a registry value entry or the default value for a key. Delete a registry value entry or the default value for a key.
:param str hive: :param str hive: The name of the hive. Can be one of the following
The name of the hive. Can be one of the following
- HKEY_LOCAL_MACHINE or HKLM
- HKEY_CURRENT_USER or HKCU
- HKEY_USER or HKU
:param str key: - HKEY_LOCAL_MACHINE or HKLM
The key (looks like a path) to the value name. - HKEY_CURRENT_USER or HKCU
- HKEY_USER or HKU
:param str vname: :param str key: The key (looks like a path) to the value name.
The value name. These are the individual name/data pairs under the key.
If not passed, the key (Default) value will be deleted.
:param bool reflection: :param str vname: The value name. These are the individual name/data pairs
A boolean value indicating that the value should also be set in the under the key. If not passed, the key (Default) value will be deleted.
Wow6432Node portion of the registry. Only applies to 64 bit Windows.
This setting is ignored for 32 bit Windows.
:return: :param bool reflection: A boolean value indicating that the value should
Returns True if successful, False if not also be set in the Wow6432Node portion of the registry. Only applies to 64
bit Windows. This setting is ignored for 32 bit Windows.
.. deprecated:: 2015.8.2
Use `use_32bit_registry` instead. The parameter seems to have no effect
since Windows 7 / Windows 2008R2 removed support for reflection. The
parameter will be removed in Boron.
:return: Returns True if successful, False if not
:rtype: bool :rtype: bool
CLI Example: CLI Example:
@ -554,7 +613,7 @@ def delete_value(hive, key, vname=None, reflection=True):
''' '''
registry = Registry() registry = Registry()
hive = registry.hkeys[hive] hive = registry.hkeys[hive]
access_mask = registry.reflection_mask[reflection] access_mask = registry.registry_32[use_32bit_registry]
try: try:
handle = _winreg.OpenKey(hive, key, 0, access_mask) handle = _winreg.OpenKey(hive, key, 0, access_mask)
@ -562,6 +621,5 @@ def delete_value(hive, key, vname=None, reflection=True):
_winreg.CloseKey(handle) _winreg.CloseKey(handle)
return True return True
except WindowsError as exc: # pylint: disable=E0602 except WindowsError as exc: # pylint: disable=E0602
_winreg.CloseKey(handle)
log.error(exc, exc_info=True) log.error(exc, exc_info=True)
return False return False

View File

@ -325,9 +325,9 @@ def _parse_settings_bond_1(opts, iface, bond_def):
if 'use_carrier' in opts: if 'use_carrier' in opts:
if opts['use_carrier'] in _CONFIG_TRUE: if opts['use_carrier'] in _CONFIG_TRUE:
bond.update({'use_carrier': 'on'}) bond.update({'use_carrier': '1'})
elif opts['use_carrier'] in _CONFIG_FALSE: elif opts['use_carrier'] in _CONFIG_FALSE:
bond.update({'use_carrier': 'off'}) bond.update({'use_carrier': '0'})
else: else:
valid = _CONFIG_TRUE + _CONFIG_FALSE valid = _CONFIG_TRUE + _CONFIG_FALSE
_raise_error_iface(iface, 'use_carrier', valid) _raise_error_iface(iface, 'use_carrier', valid)
@ -411,9 +411,9 @@ def _parse_settings_bond_3(opts, iface, bond_def):
if 'use_carrier' in opts: if 'use_carrier' in opts:
if opts['use_carrier'] in _CONFIG_TRUE: if opts['use_carrier'] in _CONFIG_TRUE:
bond.update({'use_carrier': 'on'}) bond.update({'use_carrier': '1'})
elif opts['use_carrier'] in _CONFIG_FALSE: elif opts['use_carrier'] in _CONFIG_FALSE:
bond.update({'use_carrier': 'off'}) bond.update({'use_carrier': '0'})
else: else:
valid = _CONFIG_TRUE + _CONFIG_FALSE valid = _CONFIG_TRUE + _CONFIG_FALSE
_raise_error_iface(iface, 'use_carrier', valid) _raise_error_iface(iface, 'use_carrier', valid)
@ -455,9 +455,9 @@ def _parse_settings_bond_4(opts, iface, bond_def):
if 'use_carrier' in opts: if 'use_carrier' in opts:
if opts['use_carrier'] in _CONFIG_TRUE: if opts['use_carrier'] in _CONFIG_TRUE:
bond.update({'use_carrier': 'on'}) bond.update({'use_carrier': '1'})
elif opts['use_carrier'] in _CONFIG_FALSE: elif opts['use_carrier'] in _CONFIG_FALSE:
bond.update({'use_carrier': 'off'}) bond.update({'use_carrier': '0'})
else: else:
valid = _CONFIG_TRUE + _CONFIG_FALSE valid = _CONFIG_TRUE + _CONFIG_FALSE
_raise_error_iface(iface, 'use_carrier', valid) _raise_error_iface(iface, 'use_carrier', valid)
@ -498,9 +498,9 @@ def _parse_settings_bond_5(opts, iface, bond_def):
if 'use_carrier' in opts: if 'use_carrier' in opts:
if opts['use_carrier'] in _CONFIG_TRUE: if opts['use_carrier'] in _CONFIG_TRUE:
bond.update({'use_carrier': 'on'}) bond.update({'use_carrier': '1'})
elif opts['use_carrier'] in _CONFIG_FALSE: elif opts['use_carrier'] in _CONFIG_FALSE:
bond.update({'use_carrier': 'off'}) bond.update({'use_carrier': '0'})
else: else:
valid = _CONFIG_TRUE + _CONFIG_FALSE valid = _CONFIG_TRUE + _CONFIG_FALSE
_raise_error_iface(iface, 'use_carrier', valid) _raise_error_iface(iface, 'use_carrier', valid)
@ -534,9 +534,9 @@ def _parse_settings_bond_6(opts, iface, bond_def):
if 'use_carrier' in opts: if 'use_carrier' in opts:
if opts['use_carrier'] in _CONFIG_TRUE: if opts['use_carrier'] in _CONFIG_TRUE:
bond.update({'use_carrier': 'on'}) bond.update({'use_carrier': '1'})
elif opts['use_carrier'] in _CONFIG_FALSE: elif opts['use_carrier'] in _CONFIG_FALSE:
bond.update({'use_carrier': 'off'}) bond.update({'use_carrier': '0'})
else: else:
valid = _CONFIG_TRUE + _CONFIG_FALSE valid = _CONFIG_TRUE + _CONFIG_FALSE
_raise_error_iface(iface, 'use_carrier', valid) _raise_error_iface(iface, 'use_carrier', valid)

View File

@ -427,7 +427,7 @@ def sync_output(saltenv=None, refresh=True):
refresh_modules() refresh_modules()
return ret return ret
sync_outputters = sync_output sync_outputters = salt.utils.alias_function(sync_output, 'sync_outputters')
def sync_utils(saltenv=None, refresh=True): def sync_utils(saltenv=None, refresh=True):
@ -554,7 +554,7 @@ def refresh_pillar():
ret = False # Effectively a no-op, since we can't really return without an event system ret = False # Effectively a no-op, since we can't really return without an event system
return ret return ret
pillar_refresh = refresh_pillar pillar_refresh = salt.utils.alias_function(refresh_pillar, 'pillar_refresh')
def refresh_modules(async=True): def refresh_modules(async=True):

View File

@ -350,7 +350,7 @@ def build_schedule_item(name, **kwargs):
schedule[name]['splay'] = kwargs['splay'] schedule[name]['splay'] = kwargs['splay']
for item in ['range', 'when', 'once', 'once_fmt', 'cron', 'returner', for item in ['range', 'when', 'once', 'once_fmt', 'cron', 'returner',
'return_config', 'return_kwargs', 'until']: 'return_config', 'return_kwargs', 'until', 'enabled']:
if item in kwargs: if item in kwargs:
schedule[name][item] = kwargs[item] schedule[name][item] = kwargs[item]

View File

@ -259,7 +259,7 @@ def latest_version(name, **kwargs):
return '' return ''
# available_version is being deprecated # available_version is being deprecated
available_version = latest_version available_version = salt.utils.alias_function(latest_version, 'available_version')
def get_fmri(name, **kwargs): def get_fmri(name, **kwargs):

View File

@ -150,7 +150,7 @@ def latest_version(*names, **kwargs):
return ret return ret
# available_version is being deprecated # available_version is being deprecated
available_version = latest_version available_version = salt.utils.alias_function(latest_version, 'available_version')
def upgrade_available(name): def upgrade_available(name):

133
salt/modules/ssh_service.py Normal file
View File

@ -0,0 +1,133 @@
# -*- coding: utf-8 -*-
'''
Provide the service module for the proxy-minion SSH sample
.. versionadded:: 2015.8.2
'''
# Import python libs
from __future__ import absolute_import
import logging
__proxyenabled__ = ['ssh_sample']
log = logging.getLogger(__name__)
__func_alias__ = {
'list_': 'list'
}
# Define the module's virtual name
__virtualname__ = 'service'
def __virtual__():
'''
Only work on systems that are a proxy minion
'''
if __grains__['os'] == 'proxy':
return __virtualname__
return False
def get_all():
'''
Return a list of all available services
CLI Example:
.. code-block:: bash
salt '*' service.get_all
'''
proxy_fn = 'ssh_sample.service_list'
return __proxy__[proxy_fn]()
def list_():
'''
Return a list of all available services.
CLI Example:
.. code-block:: bash
salt '*' service.list
'''
return get_all()
def start(name, sig=None):
'''
Start the specified service on the rest_sample
CLI Example:
.. code-block:: bash
salt '*' service.start <service name>
'''
proxy_fn = 'ssh_sample.service_start'
return __proxy__[proxy_fn](name)
def stop(name, sig=None):
'''
Stop the specified service on the rest_sample
CLI Example:
.. code-block:: bash
salt '*' service.stop <service name>
'''
proxy_fn = 'ssh_sample.service_stop'
return __proxy__[proxy_fn](name)
def restart(name, sig=None):
'''
Restart the specified service with rest_sample
CLI Example:
.. code-block:: bash
salt '*' service.restart <service name>
'''
proxy_fn = 'ssh_sample.service_restart'
return __proxy__[proxy_fn](name)
def status(name, sig=None):
'''
Return the status for a service via rest_sample, returns a bool
whether the service is running.
CLI Example:
.. code-block:: bash
salt '*' service.status <service name>
'''
proxy_fn = 'ssh_sample.service_status'
resp = __proxy__[proxy_fn](name)
if resp['comment'] == 'stopped':
return False
if resp['comment'] == 'running':
return True
def running(name, sig=None):
'''
Return whether this service is running.
'''
return status(name).get(name, False)
def enabled(name, sig=None):
'''
Only the 'redbull' service is 'enabled' in the test
'''
return name == 'redbull'

View File

@ -190,7 +190,7 @@ def versions_report():
return '\n'.join(salt.version.versions_report()) return '\n'.join(salt.version.versions_report())
versions = versions_report versions = salt.utils.alias_function(versions_report, 'versions')
def conf_test(): def conf_test():

View File

@ -231,7 +231,7 @@ def hw_addr(iface):
return salt.utils.network.hw_addr(iface) return salt.utils.network.hw_addr(iface)
# Alias hwaddr to preserve backward compat # Alias hwaddr to preserve backward compat
hwaddr = hw_addr hwaddr = salt.utils.alias_function(hw_addr, 'hwaddr')
def subnets(): def subnets():
@ -275,7 +275,7 @@ def ip_addrs(interface=None, include_loopback=False):
return salt.utils.network.ip_addrs(interface=interface, return salt.utils.network.ip_addrs(interface=interface,
include_loopback=include_loopback) include_loopback=include_loopback)
ipaddrs = ip_addrs ipaddrs = salt.utils.alias_function(ip_addrs, 'ipaddrs')
def ip_addrs6(interface=None, include_loopback=False): def ip_addrs6(interface=None, include_loopback=False):
@ -293,7 +293,7 @@ def ip_addrs6(interface=None, include_loopback=False):
return salt.utils.network.ip_addrs6(interface=interface, return salt.utils.network.ip_addrs6(interface=interface,
include_loopback=include_loopback) include_loopback=include_loopback)
ipaddrs6 = ip_addrs6 ipaddrs6 = salt.utils.alias_function(ip_addrs6, 'ipaddrs6')
def connect(host, port=None, **kwargs): def connect(host, port=None, **kwargs):

View File

@ -110,7 +110,7 @@ def latest_version(*names, **kwargs):
return ret return ret
# available_version is being deprecated # available_version is being deprecated
available_version = latest_version available_version = salt.utils.alias_function(latest_version, 'available_version')
def upgrade_available(name): def upgrade_available(name):

View File

@ -24,35 +24,91 @@ def info(name):
Return information for the specified user Return information for the specified user
This is just returns dummy data so that salt states can work. This is just returns dummy data so that salt states can work.
:param str name: The name of the user account to show.
CLI Example: CLI Example:
.. code-block:: bash .. code-block:: bash
salt '*' shadow.info root salt '*' shadow.info root
''' '''
ret = { info = __salt__['user.info'](name=name)
'name': name,
'passwd': '', ret = {'name': name,
'lstchg': '', 'passwd': '',
'min': '', 'lstchg': '',
'max': '', 'min': '',
'warn': '', 'max': '',
'inact': '', 'warn': '',
'expire': ''} 'inact': '',
'expire': ''}
if info:
ret = {'name': info['name'],
'passwd': 'Unavailable',
'lstchg': info['password_changed'],
'min': '',
'max': '',
'warn': '',
'inact': '',
'expire': info['expiration_date']}
return ret return ret
def set_expire(name, expire):
'''
Set the expiration date for a user account.
:param name: The name of the user account to edit.
:param expire: The date the account will expire.
:return: True if successful. False if unsuccessful.
:rtype: bool
'''
return __salt__['user.update'](name, expiration_date=expire)
def require_password_change(name):
'''
Require the user to change their password the next time they log in.
:param name: The name of the user account to require a password change.
:return: True if successful. False if unsuccessful.
:rtype: bool
'''
return __salt__['user.update'](name, expired=True)
def unlock_account(name):
'''
Unlocks a user account.
:param name: The name of the user account to unlock.
:return: True if successful. False if unsuccessful.
:rtype: bool
'''
return __salt__['user.update'](name, unlock_account=True)
def set_password(name, password): def set_password(name, password):
''' '''
Set the password for a named user. Set the password for a named user.
:param str name: The name of the user account
:param str password: The new password
:return: True if successful. False if unsuccessful.
:rtype: bool
CLI Example: CLI Example:
.. code-block:: bash .. code-block:: bash
salt '*' shadow.set_password root mysecretpassword salt '*' shadow.set_password root mysecretpassword
''' '''
cmd = ['net', 'user', name, password] return __salt__['user.update'](name=name, password=password)
ret = __salt__['cmd.run_all'](cmd, python_shell=False)
return not ret['retcode']

View File

@ -401,7 +401,7 @@ def set_computer_desc(desc=None):
return {'Computer Description': get_computer_desc()} return {'Computer Description': get_computer_desc()}
set_computer_description = set_computer_desc set_computer_description = salt.utils.alias_function(set_computer_desc, 'set_computer_description')
def get_system_info(): def get_system_info():
@ -434,7 +434,7 @@ def get_computer_desc():
return desc if desc else False return desc if desc else False
get_computer_description = get_computer_desc get_computer_description = salt.utils.alias_function(get_computer_desc, 'get_computer_description')
def get_hostname(): def get_hostname():

View File

@ -15,6 +15,8 @@ Module for managing Windows Users
This currently only works with local user accounts, not domain accounts This currently only works with local user accounts, not domain accounts
''' '''
from __future__ import absolute_import from __future__ import absolute_import
from datetime import datetime
import time
try: try:
from shlex import quote as _cmd_quote # pylint: disable=E0611 from shlex import quote as _cmd_quote # pylint: disable=E0611
@ -57,6 +59,59 @@ def __virtual__():
return False return False
def _get_date_time_format(dt_string):
'''
Copied from win_system.py (_get_date_time_format)
Function that detects the date/time format for the string passed.
:param str dt_string:
A date/time string
:return: The format of the passed dt_string
:rtype: str
'''
valid_formats = [
'%Y-%m-%d %I:%M:%S %p',
'%m-%d-%y %I:%M:%S %p',
'%m-%d-%Y %I:%M:%S %p',
'%m/%d/%y %I:%M:%S %p',
'%m/%d/%Y %I:%M:%S %p',
'%Y/%m/%d %I:%M:%S %p',
'%Y-%m-%d %I:%M:%S',
'%m-%d-%y %I:%M:%S',
'%m-%d-%Y %I:%M:%S',
'%m/%d/%y %I:%M:%S',
'%m/%d/%Y %I:%M:%S',
'%Y/%m/%d %I:%M:%S',
'%Y-%m-%d %I:%M %p',
'%m-%d-%y %I:%M %p',
'%m-%d-%Y %I:%M %p',
'%m/%d/%y %I:%M %p',
'%m/%d/%Y %I:%M %p',
'%Y/%m/%d %I:%M %p',
'%Y-%m-%d %I:%M',
'%m-%d-%y %I:%M',
'%m-%d-%Y %I:%M',
'%m/%d/%y %I:%M',
'%m/%d/%Y %I:%M',
'%Y/%m/%d %I:%M',
'%Y-%m-%d',
'%m-%d-%y',
'%m-%d-%Y',
'%m/%d/%y',
'%m/%d/%Y',
'%Y/%m/%d',
]
for dt_format in valid_formats:
try:
datetime.strptime(dt_string, dt_format)
return dt_format
except ValueError:
continue
return False
def add(name, def add(name,
password=None, password=None,
fullname=False, fullname=False,
@ -147,7 +202,13 @@ def update(name,
home=None, home=None,
homedrive=None, homedrive=None,
logonscript=None, logonscript=None,
profile=None): profile=None,
expiration_date=None,
expired=None,
account_disabled=None,
unlock_account=None,
password_never_expires=None,
disallow_change_password=None):
r''' r'''
Updates settings for the windows user. Name is the only required parameter. Updates settings for the windows user. Name is the only required parameter.
Settings will only be changed if the parameter is passed a value. Settings will only be changed if the parameter is passed a value.
@ -179,6 +240,27 @@ def update(name,
:param str profile: :param str profile:
The path to the user's profile directory. The path to the user's profile directory.
:param date expiration_date: The date and time when the account expires. Can
be a valid date/time string. To set to never expire pass the string 'Never'.
:param bool expired: Pass `True` to expire the account. The user will be
prompted to change their password at the next logon. Pass `False` to mark
the account as 'not expired'. You can't use this to negate the expiration if
the expiration was caused by the account expiring. You'll have to change
the `expiration_date` as well.
:param bool account_disabled: True disables the account. False enables the
account.
:param bool unlock_account: True unlocks a locked user account. False is
ignored.
:param bool password_never_expires: True sets the password to never expire.
False allows the password to expire.
:param bool disallow_change_password: True blocks the user from changing
the password. False allows the user to change the password.
:return: :return:
True if successful. False is unsuccessful. True if successful. False is unsuccessful.
:rtype: bool :rtype: bool
@ -219,6 +301,39 @@ def update(name,
user_info['full_name'] = fullname user_info['full_name'] = fullname
if profile: if profile:
user_info['profile'] = profile user_info['profile'] = profile
if expiration_date:
if expiration_date == 'Never':
user_info['acct_expires'] = win32netcon.TIMEQ_FOREVER
else:
date_format = _get_date_time_format(expiration_date)
if date_format:
dt_obj = datetime.strptime(expiration_date, date_format)
else:
return 'Invalid start_date'
user_info['acct_expires'] = time.mktime(dt_obj.timetuple())
if expired is not None:
if expired:
user_info['password_expired'] = 1
else:
user_info['password_expired'] = 0
if account_disabled is not None:
if account_disabled:
user_info['flags'] |= win32netcon.UF_ACCOUNTDISABLE
else:
user_info['flags'] ^= win32netcon.UF_ACCOUNTDISABLE
if unlock_account is not None:
if unlock_account:
user_info['flags'] ^= win32netcon.UF_LOCKOUT
if password_never_expires is not None:
if password_never_expires:
user_info['flags'] |= win32netcon.UF_DONT_EXPIRE_PASSWD
else:
user_info['flags'] ^= win32netcon.UF_DONT_EXPIRE_PASSWD
if disallow_change_password is not None:
if disallow_change_password:
user_info['flags'] |= win32netcon.UF_PASSWD_CANT_CHANGE
else:
user_info['flags'] ^= win32netcon.UF_PASSWD_CANT_CHANGE
# Apply new settings # Apply new settings
try: try:
@ -626,6 +741,14 @@ def info(name):
- home - home
- homedrive - homedrive
- groups - groups
- password_changed
- successful_logon_attempts
- failed_logon_attempts
- last_logon
- account_disabled
- account_locked
- password_never_expires
- disallow_change_password
- gid - gid
:rtype: dict :rtype: dict
@ -658,6 +781,19 @@ def info(name):
ret['active'] = (not bool(items['flags'] & win32netcon.UF_ACCOUNTDISABLE)) ret['active'] = (not bool(items['flags'] & win32netcon.UF_ACCOUNTDISABLE))
ret['logonscript'] = items['script_path'] ret['logonscript'] = items['script_path']
ret['profile'] = items['profile'] ret['profile'] = items['profile']
ret['failed_logon_attempts'] = items['bad_pw_count']
ret['successful_logon_attempts'] = items['num_logons']
secs = time.mktime(datetime.now().timetuple()) - items['password_age']
ret['password_changed'] = datetime.fromtimestamp(secs). \
strftime('%Y-%m-%d %H:%M:%S')
if items['last_logon'] == 0:
ret['last_logon'] = 'Never'
else:
ret['last_logon'] = datetime.fromtimestamp(items['last_logon']).\
strftime('%Y-%m-%d %H:%M:%S')
ret['expiration_date'] = datetime.fromtimestamp(items['acct_expires']).\
strftime('%Y-%m-%d %H:%M:%S')
ret['expired'] = items['password_expired'] == 1
if not ret['profile']: if not ret['profile']:
ret['profile'] = _get_userprofile_from_registry(name, ret['uid']) ret['profile'] = _get_userprofile_from_registry(name, ret['uid'])
ret['home'] = items['home_dir'] ret['home'] = items['home_dir']
@ -665,9 +801,30 @@ def info(name):
if not ret['home']: if not ret['home']:
ret['home'] = ret['profile'] ret['home'] = ret['profile']
ret['groups'] = groups ret['groups'] = groups
if items['flags'] & win32netcon.UF_DONT_EXPIRE_PASSWD == 0:
ret['password_never_expires'] = False
else:
ret['password_never_expires'] = True
if items['flags'] & win32netcon.UF_ACCOUNTDISABLE == 0:
ret['account_disabled'] = False
else:
ret['account_disabled'] = True
if items['flags'] & win32netcon.UF_LOCKOUT == 0:
ret['account_locked'] = False
else:
ret['account_locked'] = True
if items['flags'] & win32netcon.UF_PASSWD_CANT_CHANGE == 0:
ret['disallow_change_password'] = False
else:
ret['disallow_change_password'] = True
ret['gid'] = '' ret['gid'] = ''
return ret return ret
else:
return False
def _get_userprofile_from_registry(user, sid): def _get_userprofile_from_registry(user, sid):

View File

@ -439,7 +439,7 @@ def latest_version(*names, **kwargs):
return ret return ret
# available_version is being deprecated # available_version is being deprecated
available_version = latest_version available_version = salt.utils.alias_function(latest_version, 'available_version')
def upgrade_available(name): def upgrade_available(name):
@ -1808,7 +1808,7 @@ def group_install(name,
return install(pkgs=pkgs, **kwargs) return install(pkgs=pkgs, **kwargs)
groupinstall = group_install groupinstall = salt.utils.alias_function(group_install, 'groupinstall')
def list_repos(basedir=None): def list_repos(basedir=None):
@ -1978,6 +1978,14 @@ def mod_repo(repo, basedir=None, **kwargs):
del repo_opts[key] del repo_opts[key]
todelete.append(key) todelete.append(key)
# convert disabled=True to enabled=0 from pkgrepo state
if 'disabled' in repo_opts:
kw_disabled = repo_opts['disabled']
if kw_disabled is True or str(kw_disabled).lower() == 'true':
repo_opts['enabled'] = 0
del repo_opts['disabled']
todelete.append('disabled')
# Add baseurl or mirrorlist to the 'todelete' list if the other was # Add baseurl or mirrorlist to the 'todelete' list if the other was
# specified in the repo_opts # specified in the repo_opts
if 'mirrorlist' in repo_opts: if 'mirrorlist' in repo_opts:

View File

@ -95,7 +95,7 @@ def list_upgrades(refresh=True):
return ret return ret
# Provide a list_updates function for those used to using zypper list-updates # Provide a list_updates function for those used to using zypper list-updates
list_updates = list_upgrades list_updates = salt.utils.alias_function(list_upgrades, 'list_updates')
def info_installed(*names): def info_installed(*names):
@ -175,10 +175,10 @@ def info_available(*names, **kwargs):
if nfo.get('name'): if nfo.get('name'):
name = nfo.pop('name') name = nfo.pop('name')
ret[name] = nfo ret[name] = nfo
if nfo.get("status"): if nfo.get('status'):
nfo['status'] = nfo.get("status").split(" ")[0] nfo['status'] = nfo.get('status')
if nfo.get("installed"): if nfo.get('installed'):
nfo['installed'] = nfo.get("installed").lower() == "yes" and True or False nfo['installed'] = nfo.get('installed').lower() == 'yes' and True or False
return ret return ret
@ -227,13 +227,17 @@ def latest_version(*names, **kwargs):
for name in names: for name in names:
pkg_info = package_info.get(name, {}) pkg_info = package_info.get(name, {})
if pkg_info.get('status', '').lower() in ['not installed', 'out-of-date']: if pkg_info.get('status', '').lower() in ['not installed', 'out-of-date']:
ret[name] = pkg_info ret[name] = pkg_info.get('version')
# Return a string if only one package name passed
if len(names) == 1 and len(ret):
return ret[names[0]]
return ret return ret
# available_version is being deprecated # available_version is being deprecated
available_version = latest_version available_version = salt.utils.alias_function(latest_version, 'available_version')
def upgrade_available(name): def upgrade_available(name):

View File

@ -446,10 +446,12 @@ class Pillar(object):
self.opts.get('nodegroups', {}), self.opts.get('nodegroups', {}),
): ):
if saltenv not in matches: if saltenv not in matches:
matches[saltenv] = [] matches[saltenv] = env_matches = []
else:
env_matches = matches[saltenv]
for item in data: for item in data:
if isinstance(item, six.string_types): if isinstance(item, six.string_types) and item not in env_matches:
matches[saltenv].append(item) env_matches.append(item)
return matches return matches
def render_pstate(self, sls, saltenv, mods, defaults=None): def render_pstate(self, sls, saltenv, mods, defaults=None):
@ -528,20 +530,20 @@ class Pillar(object):
mods, mods,
defaults defaults
) )
if nstate: if nstate:
if key: if key:
nstate = { nstate = {
key: nstate key: nstate
} }
state = merge( state = merge(
state, state,
nstate, nstate,
self.merge_strategy, self.merge_strategy,
self.opts.get('renderer', 'yaml')) self.opts.get('renderer', 'yaml'))
if err: if err:
errors += err errors += err
return state, mods, errors return state, mods, errors
def render_pillar(self, matches): def render_pillar(self, matches):

View File

@ -397,9 +397,9 @@ def _legacy_git_pillar(minion_id, repo_string, pillar_dirs):
log.warning('Unrecognized extra parameter: {0}'.format(key)) log.warning('Unrecognized extra parameter: {0}'.format(key))
# environment is "different" from the branch # environment is "different" from the branch
branch, _, environment = branch_env.partition(':') cfg_branch, _, environment = branch_env.partition(':')
gitpil = _LegacyGitPillar(branch, repo_location, __opts__) gitpil = _LegacyGitPillar(cfg_branch, repo_location, __opts__)
branch = gitpil.branch branch = gitpil.branch
if environment == '': if environment == '':
@ -413,7 +413,9 @@ def _legacy_git_pillar(minion_id, repo_string, pillar_dirs):
pillar_dirs.setdefault(pillar_dir, {}) pillar_dirs.setdefault(pillar_dir, {})
if pillar_dirs[pillar_dir].get(branch, False): if cfg_branch == '__env__' and branch not in ['master', 'base']:
gitpil.update()
elif pillar_dirs[pillar_dir].get(branch, False):
return {} # we've already seen this combo return {} # we've already seen this combo
pillar_dirs[pillar_dir].setdefault(branch, True) pillar_dirs[pillar_dir].setdefault(branch, True)
@ -429,7 +431,7 @@ def _legacy_git_pillar(minion_id, repo_string, pillar_dirs):
pil = Pillar(opts, __grains__, minion_id, branch) pil = Pillar(opts, __grains__, minion_id, branch)
return pil.compile_pillar() return pil.compile_pillar(ext=False)
def _update(branch, repo_location): def _update(branch, repo_location):

View File

@ -1,8 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
''' '''
====== Dell FX2 chassis
fx2.py ================
======
.. versionadded:: 2015.8.2 .. versionadded:: 2015.8.2
@ -218,6 +217,13 @@ def chconfig(cmd, *args, **kwargs):
for k in kwargs.keys(): for k in kwargs.keys():
if k.startswith('__pub_'): if k.startswith('__pub_'):
kwargs.pop(k) kwargs.pop(k)
# Catch password reset
if cmd == 'change_password':
if 'username' in kwargs:
DETAILS['admin_username'] = kwargs['username']
if 'password' in kwargs:
DETAILS['admin_password'] = kwargs['password']
if 'dracr.'+cmd not in __salt__: if 'dracr.'+cmd not in __salt__:
return {'retcode': -1, 'message': 'dracr.' + cmd + ' is not available'} return {'retcode': -1, 'message': 'dracr.' + cmd + ' is not available'}
else: else:

View File

@ -10,9 +10,9 @@ from __future__ import absolute_import
import logging import logging
# Import 3rd-party libs # Import 3rd-party libs
# import jnpr.junos import jnpr.junos
# import jnpr.junos.utils import jnpr.junos.utils
# import jnpr.junos.utils.config import jnpr.junos.utils.config
import json import json
HAS_JUNOS = True HAS_JUNOS = True
@ -22,17 +22,18 @@ thisproxy = {}
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
# def __init__(opts):
# ''' def init(opts):
# Open the connection to the Junos device, login, and bind to the '''
# Resource class Open the connection to the Junos device, login, and bind to the
# ''' Resource class
# log.debug('Opening connection to junos') '''
# thisproxy['conn'] = jnpr.junos.Device(user=opts['proxy']['username'], log.debug('Opening connection to junos')
# host=opts['proxy']['host'], thisproxy['conn'] = jnpr.junos.Device(user=opts['proxy']['username'],
# password=opts['proxy']['passwd']) host=opts['proxy']['host'],
# thisproxy['conn'].open() password=opts['proxy']['passwd'])
# thisproxy['conn'].bind(cu=jnpr.junos.utils.config.Config) thisproxy['conn'].open()
thisproxy['conn'].bind(cu=jnpr.junos.utils.config.Config)
def conn(): def conn():

View File

@ -51,6 +51,19 @@ def init(opts):
return False return False
def ping():
'''
Required.
Ping the device on the other end of the connection
'''
try:
out, err = DETAILS['server'].sendline('help')
return True
except TerminalException as e:
log.error(e)
return False
def shutdown(opts): def shutdown(opts):
''' '''
Disconnect Disconnect
@ -96,13 +109,11 @@ def package_list():
def package_install(name, **kwargs): def package_install(name, **kwargs):
''' '''
Install a "package" on the REST server Install a "package" on the ssh server
''' '''
cmd = 'pkg_install ' + name cmd = 'pkg_install ' + name
if 'version' in kwargs: if 'version' in kwargs:
cmd += '/'+kwargs['version'] cmd += ' ' + kwargs['version']
else:
cmd += '/1.0'
# Send the command to execute # Send the command to execute
out, err = DETAILS['server'].sendline(cmd) out, err = DETAILS['server'].sendline(cmd)
@ -113,7 +124,7 @@ def package_install(name, **kwargs):
def package_remove(name): def package_remove(name):
''' '''
Remove a "package" on the REST server Remove a "package" on the ssh server
''' '''
cmd = 'pkg_remove ' + name cmd = 'pkg_remove ' + name
@ -122,3 +133,63 @@ def package_remove(name):
# "scrape" the output and return the right fields as a dict # "scrape" the output and return the right fields as a dict
return parse(out) return parse(out)
def service_list():
'''
Start a "service" on the ssh server
.. versionadded:: 2015.8.2
'''
cmd = 'ps'
# Send the command to execute
out, err = DETAILS['server'].sendline(cmd)
# "scrape" the output and return the right fields as a dict
return parse(out)
def service_start(name):
'''
Start a "service" on the ssh server
.. versionadded:: 2015.8.2
'''
cmd = 'start ' + name
# Send the command to execute
out, err = DETAILS['server'].sendline(cmd)
# "scrape" the output and return the right fields as a dict
return parse(out)
def service_stop(name):
'''
Stop a "service" on the ssh server
.. versionadded:: 2015.8.2
'''
cmd = 'stop ' + name
# Send the command to execute
out, err = DETAILS['server'].sendline(cmd)
# "scrape" the output and return the right fields as a dict
return parse(out)
def service_restart(name):
'''
Restart a "service" on the ssh server
.. versionadded:: 2015.8.2
'''
cmd = 'restart ' + name
# Send the command to execute
out, err = DETAILS['server'].sendline(cmd)
# "scrape" the output and return the right fields as a dict
return parse(out)

View File

@ -120,7 +120,7 @@ def list_windows(profile=None, api_key=None):
# The long version, added for consistency # The long version, added for consistency
list_maintenance_windows = list_windows list_maintenance_windows = salt.utils.alias_function(list_windows, 'list_maintenance_windows')
def list_policies(profile=None, api_key=None): def list_policies(profile=None, api_key=None):
@ -142,7 +142,7 @@ def list_policies(profile=None, api_key=None):
# The long version, added for consistency # The long version, added for consistency
list_escalation_policies = list_policies list_escalation_policies = salt.utils.alias_function(list_policies, 'list_escalation_policies')
def create_event(service_key=None, description=None, details=None, def create_event(service_key=None, description=None, details=None,

View File

@ -8,6 +8,7 @@ import logging
# Import salt libs # Import salt libs
import salt.loader import salt.loader
import salt.utils
import salt.utils.event import salt.utils.event
from salt.exceptions import SaltInvocationError from salt.exceptions import SaltInvocationError
@ -62,8 +63,8 @@ def orchestrate(mods, saltenv='base', test=None, exclude=None, pillar=None):
return ret return ret
# Aliases for orchestrate runner # Aliases for orchestrate runner
orch = orchestrate # pylint: disable=invalid-name orch = salt.utils.alias_function(orchestrate, 'orch')
sls = orchestrate # pylint: disable=invalid-name sls = salt.utils.alias_function(orchestrate, 'sls')
def orchestrate_single(fun, name, test=None, queue=False, pillar=None, **kwargs): def orchestrate_single(fun, name, test=None, queue=False, pillar=None, **kwargs):

View File

@ -653,6 +653,10 @@ class SPMClient(object):
self.formula_conf = formula_conf self.formula_conf = formula_conf
formula_tar = tarfile.open(out_path, 'w:bz2') formula_tar = tarfile.open(out_path, 'w:bz2')
# Add FORMULA first, to speed up create_repo on large packages
formula_tar.add(formula_path, formula_conf['name'], filter=self._exclude)
try: try:
formula_tar.add(self.abspath, formula_conf['name'], filter=self._exclude) formula_tar.add(self.abspath, formula_conf['name'], filter=self._exclude)
except TypeError: except TypeError:

View File

@ -48,7 +48,7 @@ import salt.utils.yamlloader as yamlloader
# Import third party libs # Import third party libs
# pylint: disable=import-error,no-name-in-module,redefined-builtin # pylint: disable=import-error,no-name-in-module,redefined-builtin
import salt.ext.six as six import salt.ext.six as six
from salt.ext.six.moves import range from salt.ext.six.moves import map, range
# pylint: enable=import-error,no-name-in-module,redefined-builtin # pylint: enable=import-error,no-name-in-module,redefined-builtin
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -549,7 +549,7 @@ class Compiler(object):
if isinstance(entry, dict): if isinstance(entry, dict):
low_name = next(six.iterkeys(entry)) low_name = next(six.iterkeys(entry))
live['name'] = low_name live['name'] = low_name
live.update(entry[low_name][0]) list(map(live.update, entry[low_name]))
else: else:
live['name'] = entry live['name'] = entry
live['name_order'] = name_order live['name_order'] = name_order
@ -1228,7 +1228,7 @@ class State(object):
if isinstance(entry, dict): if isinstance(entry, dict):
low_name = next(six.iterkeys(entry)) low_name = next(six.iterkeys(entry))
live['name'] = low_name live['name'] = low_name
live.update(entry[low_name][0]) list(map(live.update, entry[low_name]))
else: else:
live['name'] = entry live['name'] = entry
live['name_order'] = name_order live['name_order'] = name_order

View File

@ -83,9 +83,9 @@ def present(name, timespec, tag=None, user=None, job=None):
ret['comment'] = 'User: {0} is not exists'.format(user) ret['comment'] = 'User: {0} is not exists'.format(user)
ret['result'] = False ret['result'] = False
return ret return ret
ret['comment'] = __salt__['cmd.run']('{0}'.format(cmd), runas=user) ret['comment'] = __salt__['cmd.run']('{0}'.format(cmd), runas=user, python_shell=True)
else: else:
ret['comment'] = __salt__['cmd.run']('{0}'.format(cmd)) ret['comment'] = __salt__['cmd.run']('{0}'.format(cmd), python_shell=True)
return ret return ret

View File

@ -29,14 +29,17 @@ import os.path
# Import salt libs # Import salt libs
import salt.utils import salt.utils
__virtualname__ = 'blockdev'
def __virtual__(): def __virtual__():
''' '''
Only work on POSIX-like systems Only load this module if the blockdev execution module is available
''' '''
if salt.utils.is_windows(): if 'blockdev.tune' in __salt__:
return False return __virtualname__
return True return (False, ('Cannot load the {0} state module: '
'blockdev execution module not found'.format(__virtualname__)))
def tuned(name, **kwargs): def tuned(name, **kwargs):
@ -146,25 +149,8 @@ def formatted(name, fs_type='ext4', **kwargs):
ret['result'] = None ret['result'] = None
return ret return ret
cmd = 'mkfs -t {0} '.format(fs_type) __salt__['blockdev.format'](name, fs_type, **kwargs)
if 'inode_size' in kwargs: current_fs = __salt__['blockdev.fstype'](name)
if fs_type[:3] == 'ext':
cmd += '-i {0} '.format(kwargs['inode_size'])
elif fs_type == 'xfs':
cmd += '-i size={0} '.format(kwargs['inode_size'])
if 'lazy_itable_init' in kwargs:
if fs_type[:3] == 'ext':
cmd += '-E lazy_itable_init={0} '.format(kwargs['lazy_itable_init'])
cmd += name
__salt__['cmd.run'](cmd).splitlines()
__salt__['cmd.run']('sync').splitlines()
blk = __salt__['cmd.run']('lsblk -o fstype {0}'.format(name)).splitlines()
if len(blk) == 1:
current_fs = ''
else:
current_fs = blk[1]
if current_fs == fs_type: if current_fs == fs_type:
ret['comment'] = ('{0} has been formatted ' ret['comment'] = ('{0} has been formatted '

View File

@ -2,7 +2,7 @@
''' '''
Manage Elasticache Manage Elasticache
================== ==================
replication_group_description
.. versionadded:: 2014.7.0 .. versionadded:: 2014.7.0
Create, destroy and update Elasticache clusters. Be aware that this interacts Create, destroy and update Elasticache clusters. Be aware that this interacts

View File

@ -71,6 +71,12 @@ passed in as a dict, or as a string to pull from pillars or minion config:
key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs
''' '''
# Import Python Libs
from __future__ import absolute_import
# Import Salt Libs
from salt.utils import SaltInvocationError
def __virtual__(): def __virtual__():
''' '''
@ -144,10 +150,15 @@ def present(
if isinstance(value, list): if isinstance(value, list):
value = ','.join(value) value = ','.join(value)
record = __salt__['boto_route53.get_record'](name, zone, record_type, try:
False, region, key, keyid, record = __salt__['boto_route53.get_record'](name, zone, record_type,
profile, split_dns, False, region, key, keyid,
private_zone) profile, split_dns,
private_zone)
except SaltInvocationError as err:
ret['comment'] = 'Error: {0}'.format(err)
ret['result'] = False
return ret
if isinstance(record, dict) and not record: if isinstance(record, dict) and not record:
if __opts__['test']: if __opts__['test']:

View File

@ -217,6 +217,7 @@ except ImportError:
pass pass
# Import salt libs # Import salt libs
import salt.utils
from salt.exceptions import CommandExecutionError, SaltRenderError from salt.exceptions import CommandExecutionError, SaltRenderError
from salt.ext.six import string_types from salt.ext.six import string_types
@ -494,7 +495,7 @@ def wait(name,
# Alias "cmd.watch" to "cmd.wait", as this is a common misconfiguration # Alias "cmd.watch" to "cmd.wait", as this is a common misconfiguration
watch = wait watch = salt.utils.alias_function(wait, 'watch')
def wait_script(name, def wait_script(name,

View File

@ -4,24 +4,131 @@ Manage chassis via Salt Proxies.
.. versionadded:: 2015.8.2 .. versionadded:: 2015.8.2
Example managing a Dell chassis: Below is an example state that sets parameters just to show the basics.
.. code-block:: yaml .. code-block:: yaml
my-dell-chassis: my-dell-chassis:
chassis.dell: dellchassis.chassis:
- name: my-dell-chassis - chassis_name: my-dell-chassis
- datacenter: dc-1-us
- location: my-location - location: my-location
- mode: 2 - mode: 2
- idrac_launch: 1 - idrac_launch: 1
- slot_names: - slot_names:
- 1: my-slot-name - server-1: my-slot-name
- 2: my-other-slot-name - server-2: my-other-slot-name
- blade_power_states: - blade_power_states:
- server-1: on - server-1: on
- server-2: off - server-2: off
- server-3: powercycle - server-3: powercycle
However, it is possible to place the entire set of chassis configuration
data in pillar. Here's an example pillar
structure:
.. code-block:: yaml
proxy:
host: 10.27.20.18
admin_username: root
admin_password: saltstack
proxytype: fx2
chassis:
name: fx2-1
username: root
password: saltstack1
datacenter: london
location: rack-1-shelf-3
management_mode: 2
idrac_launch: 0
slot_names:
- 'server-1': blade1
- 'server-2': blade2
blades:
blade1:
idrac_password: saltstack1
ipmi_over_lan: True
ip: 172.17.17.1
subnet: 255.255.0.0
netmask: 172.17.255.255
blade2:
idrac_password: saltstack1
ipmi_over_lan: True
ip: 172.17.17.2
subnet: 255.255.0.0
netmask: 172.17.255.255
blade3:
idrac_password: saltstack1
ipmi_over_lan: True
ip: 172.17.17.2
subnet: 255.255.0.0
netmask: 172.17.255.255
blade4:
idrac_password: saltstack1
ipmi_over_lan: True
ip: 172.17.17.2
subnet: 255.255.0.0
netmask: 172.17.255.255
switches:
switch-1:
ip: 192.168.1.2
netmask: 255.255.255.0
broadcast: 192.168.1.255
snmp: nonpublic
password: saltstack1
switch-2:
ip: 192.168.1.3
netmask: 255.255.255.0
broadcast: 192.168.1.255
snmp: nonpublic
password: saltstack1
And to go with it, here's an example state that pulls the data from pillar
.. code-block:: yaml
{% set details = pillar['chassis'] with context %}
standup-step1:
dellchassis.chassis:
- name: {{ details['name'] }}
- location: {{ details['location'] }}
- mode: {{ details['management_mode'] }}
- idrac_launch: {{ details['idrac_launch'] }}
- slot_names
{% for k, v in details['chassis']['slot_names'].iteritems() %}
- {{ k }}: {{ v }}
{% endfor %}
{% for k, v in details['chassis']['switches'].iteritems() %}
standup-switches-{{ k }}:
dellchassis.dell_switch:
- name: {{ k }}
- ip: {{ v['ip'] }}
- netmask: {{ v['netmask'] }}
- gateway: {{ v['gateway'] }}
- password: {{ v['password'] }}
- snmp: {{ v['snmp'] }}
{% endfor %}
dellchassis
{% for k, v in details['chassis']['slot_names'].iteritems() %}
- {{ k }}: {{ v }}
{% endfor %}
blade_powercycle:
chassis.dell_chassis:
- blade_power_states:
- server-1: powercycle
- server-2: powercycle
- server-3: powercycle
- server-4: powercycle
''' '''
# Import python libs # Import python libs
@ -35,13 +142,13 @@ def __virtual__():
return 'chassis.cmd' in __salt__ return 'chassis.cmd' in __salt__
def blade_idrac(name, idrac_password=None, idrac_ipmi=None, def blade_idrac(idrac_password=None, idrac_ipmi=None,
idrac_ip=None, idrac_netmask=None, idrac_gateway=None, idrac_ip=None, idrac_netmask=None, idrac_gateway=None,
idrac_dnsname=None,
drac_dhcp=None): drac_dhcp=None):
''' '''
Set parameters for iDRAC in a blade. Set parameters for iDRAC in a blade.
:param name: The name of the blade to address
:param idrac_password: Password to establish for the iDRAC interface :param idrac_password: Password to establish for the iDRAC interface
:param idrac_ipmi: Enable/Disable IPMI over LAN :param idrac_ipmi: Enable/Disable IPMI over LAN
:param idrac_ip: Set IP address for iDRAC :param idrac_ip: Set IP address for iDRAC
@ -52,20 +159,58 @@ def blade_idrac(name, idrac_password=None, idrac_ipmi=None,
:return: A standard Salt changes dictionary :return: A standard Salt changes dictionary
''' '''
pass ret = {'result': True,
'changes': {},
'comment': ''}
if not idrac_password:
password = __pillar__['proxy']['admin_password']
else:
password = idrac_password
if idrac_ipmi:
if idrac_ipmi is True:
idrac_ipmi = '1'
if idrac_ipmi is False:
idrac_ipmi = '0'
current_ipmi = __salt__['dracr.get_general']('cfgIpmiLan', 'cfgIpmiLanEnable',
host=idrac_ip, admin_username='root',
admin_password=password)
if current_ipmi != idrac_ipmi:
ch = {'Old': current_ipmi, 'New': idrac_ipmi}
ret['changes']['IPMI'] = ch
if idrac_dnsname:
dnsret = __salt__['dracr.get_dns_dracname'](host=idrac_ip, admin_username='root',
admin_password=password)
current_dnsname = dnsret['Key=iDRAC.Embedded.1#NIC.1']['DNSRacName']
if current_dnsname != idrac_dnsname:
ch = {'Old': current_dnsname,
'New': idrac_dnsname}
ret['changes']['DNSRacName'] = ch
return ret
def chassis(name, location=None, mode=None, idrac_launch=None, slot_names=None, def chassis(name, chassis_name=None, password=None, datacenter=None,
blade_power_states=None): location=None, mode=None, idrac_launch=None, slot_names=None,
blade_power_states=None):
''' '''
Manage a Dell Chassis. Manage a Dell Chassis.
name chassis_name
The name of the chassis. The name of the chassis.
datacenter
The datacenter in which the chassis is located
location location
The location of the chassis. The location of the chassis.
password
Password for the chassis
mode mode
The management mode of the chassis. Viable options are: The management mode of the chassis. Viable options are:
@ -96,9 +241,10 @@ def chassis(name, location=None, mode=None, idrac_launch=None, slot_names=None,
.. code-block:: yaml .. code-block:: yaml
my-dell-chassis: my-dell-chassis:
chassis.dell: dellchassis.chassis:
- name: my-dell-chassis - name: my-dell-chassis
- location: my-location - location: my-location
- datacenter: london
- mode: 2 - mode: 2
- idrac_launch: 1 - idrac_launch: 1
- slot_names: - slot_names:
@ -109,7 +255,7 @@ def chassis(name, location=None, mode=None, idrac_launch=None, slot_names=None,
- server-2: off - server-2: off
- server-3: powercycle - server-3: powercycle
''' '''
ret = {'name': name, ret = {'chassis_name': chassis_name,
'result': True, 'result': True,
'changes': {}, 'changes': {},
'comment': ''} 'comment': ''}
@ -119,12 +265,27 @@ def chassis(name, location=None, mode=None, idrac_launch=None, slot_names=None,
mode_cmd = 'cfgRacTuneChassisMgmtAtServer' mode_cmd = 'cfgRacTuneChassisMgmtAtServer'
launch_cmd = 'cfgRacTuneIdracDNSLaunchEnable' launch_cmd = 'cfgRacTuneIdracDNSLaunchEnable'
inventory = __salt__[chassis_cmd]('inventory')
if idrac_launch:
idrac_launch = str(idrac_launch)
current_name = __salt__[chassis_cmd]('get_chassis_name') current_name = __salt__[chassis_cmd]('get_chassis_name')
if name != current_name: if chassis_name != current_name:
ret['changes'].update({'Name': ret['changes'].update({'Name':
{'Old': current_name, {'Old': current_name,
'New': name}}) 'New': chassis_name}})
current_dc = __salt__[chassis_cmd]('get_chassis_datacenter')
if datacenter and datacenter != current_dc:
ret['changes'].update({'Datacenter':
{'Old': current_dc,
'New': datacenter}})
if password:
ret['changes'].update({'Password':
{'Old': '******',
'New': '******'}})
if location: if location:
current_location = __salt__[chassis_cmd]('get_chassis_location') current_location = __salt__[chassis_cmd]('get_chassis_location')
if location != current_location: if location != current_location:
@ -147,11 +308,16 @@ def chassis(name, location=None, mode=None, idrac_launch=None, slot_names=None,
if slot_names: if slot_names:
current_slot_names = __salt__[chassis_cmd]('list_slotnames') current_slot_names = __salt__[chassis_cmd]('list_slotnames')
for key, val in slot_names: for s in slot_names:
key = s.keys()[0]
new_name = s[key]
if key.startswith('slot-'):
key = key[5:]
current_slot_name = current_slot_names.get(key).get('slotname') current_slot_name = current_slot_names.get(key).get('slotname')
if current_slot_name != val['name']: if current_slot_name != new_name:
old = {key: current_slot_name} old = {key: current_slot_name}
new = {key: val} new = {key: new_name}
if ret['changes'].get('Slot Names') is None: if ret['changes'].get('Slot Names') is None:
ret['changes'].update({'Slot Names': ret['changes'].update({'Slot Names':
{'Old': {}, {'Old': {},
@ -159,23 +325,33 @@ def chassis(name, location=None, mode=None, idrac_launch=None, slot_names=None,
ret['changes']['Slot Names']['Old'].update(old) ret['changes']['Slot Names']['Old'].update(old)
ret['changes']['Slot Names']['New'].update(new) ret['changes']['Slot Names']['New'].update(new)
# TODO: Refactor this and make DRY - can probable farm this out to a new funciton current_power_states = {}
target_power_states = {}
if blade_power_states: if blade_power_states:
# TODO: Get the power state list working for b in blade_power_states:
current_power_states = 'get a list of current power states' key = b.keys()[0]
for key, val in blade_power_states: status = __salt__[chassis_cmd]('server_powerstatus', module=key)
# TODO: Get the correct state infos current_power_states[key] = status.get('status', -1)
current_power_state = current_power_states.get(key).get('state') if b[key] == 'powerdown':
# TODO: Don't just compare values, check if True should be "on" or "off" etc if current_power_states[key] != -1 and current_power_states[key]:
if current_power_state != val: target_power_states[key] = 'powerdown'
old = {key: current_power_state} if b[key] == 'powerup':
new = {key: val} if current_power_states[key] != -1 and not current_power_states[key]:
if ret['changes'].get('Blade Power States') is None: target_power_states[key] = 'powerup'
ret['changes'].update({'Blade Power States': if b[key] == 'powercycle':
{'Old': {}, if current_power_states[key] != -1 and not current_power_states[key]:
'New': {}}}) target_power_states[key] = 'powerup'
ret['changes']['Blade Power States']['Old'].update(old) if current_power_states[key] != -1 and current_power_states[key]:
ret['changes']['Blade Power States']['New'].update(new) target_power_states[key] = 'powercycle'
for k, v in target_power_states.iteritems():
old = {k: current_power_states[k]}
new = {k: v}
if ret['changes'].get('Blade Power States') is None:
ret['changes'].update({'Blade Power States':
{'Old': {},
'New': {}}})
ret['changes']['Blade Power States']['Old'].update(old)
ret['changes']['Blade Power States']['New'].update(new)
if ret['changes'] == {}: if ret['changes'] == {}:
ret['comment'] = 'Dell chassis is already in the desired state.' ret['comment'] = 'Dell chassis is already in the desired state.'
@ -190,21 +366,50 @@ def chassis(name, location=None, mode=None, idrac_launch=None, slot_names=None,
name = __salt__[chassis_cmd]('set_chassis_name', name) name = __salt__[chassis_cmd]('set_chassis_name', name)
if location: if location:
location = __salt__[chassis_cmd]('set_chassis_location', location) location = __salt__[chassis_cmd]('set_chassis_location', location)
pw_result = True
if password:
pw_single = True
if __salt__[chassis_cmd]('change_password', username='root', uid=1,
password=password):
for blade in inventory['server'].keys():
pw_single = __salt__[chassis_cmd]('deploy_password',
username='root',
password=password,
module=blade)
if not pw_single:
pw_result = False
else:
pw_result = False
if datacenter:
datacenter_result = __salt__[chassis_cmd]('set_chassis_datacenter',
datacenter)
if mode: if mode:
mode = __salt__[chassis_cmd]('set_general', cfg_tuning, mode_cmd, mode) mode = __salt__[chassis_cmd]('set_general', cfg_tuning, mode_cmd, mode)
if idrac_launch: if idrac_launch:
idrac_launch = __salt__[chassis_cmd]('set_general', cfg_tuning, launch_cmd, idrac_launch) idrac_launch = __salt__[chassis_cmd]('set_general', cfg_tuning, launch_cmd, idrac_launch)
if slot_names: if ret['changes'].get('Slot Names') is not None:
slot_rets = [] slot_rets = []
for key, val in slot_names.iteritems(): for s in slot_names:
slot_name = val.get('slotname') key = s.keys()[0]
slot_rets.append(__salt__[chassis_cmd]('set_slotname', key, slot_name)) new_name = s[key]
if key.startswith('slot-'):
key = key[5:]
slot_rets.append(__salt__[chassis_cmd]('set_slotname', key, new_name))
if any(slot_rets) is False: if any(slot_rets) is False:
slot_names = False slot_names = False
else: else:
slot_names = True slot_names = True
if any([name, location, mode, idrac_launch, slot_names]) is False: powerchange_all_ok = True
for k, v in target_power_states.iteritems():
powerchange_ok = __salt__[chassis_cmd]('server_power', v, module=k)
if not powerchange_ok:
powerchange_all_ok = False
if any([name, location, mode, idrac_launch,
slot_names, powerchange_all_ok]) is False:
ret['result'] = False ret['result'] = False
ret['comment'] = 'There was an error setting the Dell chassis.' ret['comment'] = 'There was an error setting the Dell chassis.'
@ -212,7 +417,7 @@ def chassis(name, location=None, mode=None, idrac_launch=None, slot_names=None,
return ret return ret
def dell_switch(name, ip=None, netmask=None, gateway=None, dhcp=None, def switch(name, ip=None, netmask=None, gateway=None, dhcp=None,
password=None, snmp=None): password=None, snmp=None):
''' '''
Manage switches in a Dell Chassis. Manage switches in a Dell Chassis.
@ -245,7 +450,7 @@ def dell_switch(name, ip=None, netmask=None, gateway=None, dhcp=None,
.. code-block:: yaml .. code-block:: yaml
my-dell-chassis: my-dell-chassis:
chassis.dell_switch: dellchassis.dell_switch:
- switch: switch-1 - switch: switch-1
- ip: 192.168.1.1 - ip: 192.168.1.1
- netmask: 255.255.255.0 - netmask: 255.255.255.0

View File

@ -2,6 +2,10 @@
''' '''
Send events through Salt's event system during state runs Send events through Salt's event system during state runs
''' '''
from __future__ import absolute_import
# import salt libs
import salt.utils
def send(name, def send(name,
@ -86,5 +90,5 @@ def wait(name, sfun=None):
return {'name': name, 'changes': {}, 'result': True, 'comment': ''} return {'name': name, 'changes': {}, 'result': True, 'comment': ''}
mod_watch = send mod_watch = salt.utils.alias_function(send, 'mod_watch')
fire_master = send fire_master = salt.utils.alias_function(send, 'fire_master')

View File

@ -2486,7 +2486,7 @@ def replace(name,
pattern, pattern,
repl, repl,
count=0, count=0,
flags=0, flags=8,
bufsize=1, bufsize=1,
append_if_not_found=False, append_if_not_found=False,
prepend_if_not_found=False, prepend_if_not_found=False,
@ -2513,16 +2513,18 @@ def replace(name,
replaced, otherwise all occurrences will be replaced. replaced, otherwise all occurrences will be replaced.
flags flags
A list of flags defined in the :ref:`re module documentation <contents-of-module-re>`. A list of flags defined in the :ref:`re module documentation
Each list item should be a string that will correlate to the human-friendly flag name. <contents-of-module-re>`. Each list item should be a string that will
E.g., ``['IGNORECASE', 'MULTILINE']``. Note: multiline searches must specify ``file`` correlate to the human-friendly flag name. E.g., ``['IGNORECASE',
as the ``bufsize`` argument below. Defaults to 0 and can be a list or an int. 'MULTILINE']``. Optionally, ``flags`` may be an int, with a value
corresponding to the XOR (``|``) of all the desired flags. Defaults to
8 (which supports 'MULTILINE').
bufsize bufsize
How much of the file to buffer into memory at once. The default value ``1`` processes How much of the file to buffer into memory at once. The default value
one line at a time. The special value ``file`` may be specified which will read the ``1`` processes one line at a time. The special value ``file`` may be
entire file into memory before processing. Note: multiline searches must specify ``file`` specified which will read the entire file into memory before
buffering. Can be an int or a str. processing.
append_if_not_found append_if_not_found
If pattern is not found and set to ``True`` then, the content will be appended to the file. If pattern is not found and set to ``True`` then, the content will be appended to the file.
@ -4353,6 +4355,8 @@ def serialize(name,
'result': False 'result': False
} }
contents += '\n'
if __opts__['test']: if __opts__['test']:
ret['changes'] = __salt__['file.check_managed_changes']( ret['changes'] = __salt__['file.check_managed_changes'](
name=name, name=name,
@ -4622,10 +4626,18 @@ def mod_run_check_cmd(cmd, filename, **check_cmd_opts):
log.debug('running our check_cmd') log.debug('running our check_cmd')
_cmd = '{0} {1}'.format(cmd, filename) _cmd = '{0} {1}'.format(cmd, filename)
if __salt__['cmd.retcode'](_cmd, **check_cmd_opts) != 0: cret = __salt__['cmd.run_all'](_cmd, **check_cmd_opts)
return {'comment': 'check_cmd execution failed', if cret['retcode'] != 0:
'skip_watch': True, ret = {'comment': 'check_cmd execution failed',
'result': False} 'skip_watch': True,
'result': False}
if cret.get('stdout'):
ret['comment'] += '\n' + cret['stdout']
if cret.get('stderr'):
ret['comment'] += '\n' + cret['stderr']
return ret
# No reason to stop, return True # No reason to stop, return True
return True return True

View File

@ -11,15 +11,16 @@ masquerading, and allows ports 22/tcp and 25/tcp.
.. code-block:: yaml .. code-block:: yaml
public: public:
- name: public firewalld.present:
- block_icmp - name: public
- echo-reply - block_icmp:
- echo-request - echo-reply
- default: False - echo-request
- masquerade: True - default: False
- ports: - masquerade: True
- 22/tcp - ports:
- 25/tcp - 22/tcp
- 25/tcp
The following example applies changes to the public zone, enables The following example applies changes to the public zone, enables
masquerading and configures port forwarding TCP traffic from port 22 masquerading and configures port forwarding TCP traffic from port 22
@ -35,10 +36,14 @@ to 2222, and forwards TCP traffic from port 80 to 443 at 192.168.0.1.
- 22:2222:tcp - 22:2222:tcp
- 80:443:tcp:192.168.0.1 - 80:443:tcp:192.168.0.1
''' '''
from __future__ import absolute_import
# Import Python Libs
from __future__ import absolute_import
import logging import logging
import salt.exceptions
# Import Salt Libs
from salt.exceptions import CommandExecutionError
import salt.utils
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -61,92 +66,119 @@ def present(name,
port_fwd=None, port_fwd=None,
services=None): services=None):
''' '''
Ensure a zone has specific attributes Ensure a zone has specific attributes.
''' '''
ret = {'name': name, ret = {'name': name,
'result': True, 'result': False,
'changes': {'icmp_blocks': [], 'changes': {},
'ports': [], 'comment': ''}
'port_fwd': [],
'services': []},
'comment': {'icmp_blocks': [],
'ports': [],
'port_fwd': [],
'services': []}}
if name not in __salt__['firewalld.get_zones'](): try:
if __opts__['test']: zones = __salt__['firewalld.get_zones']()
ret['comment'][name] = '`{0}` will be created'.format(name) except CommandExecutionError as err:
else: ret['comment'] = 'Error: {0}'.format(err)
__salt__['firewalld.new_zone'](name) return ret
ret['changes'][name] = '`{0}` zone has been successfully created'.format(name)
else: if name not in zones:
ret['comment'][name] = '`{0}` zone already exists'.format(name) if not __opts__['test']:
try:
__salt__['firewalld.new_zone'](name)
except CommandExecutionError as err:
ret['comment'] = 'Error: {0}'.format(err)
return ret
ret['changes'].update({name:
{'old': zones,
'new': name}})
if block_icmp: if block_icmp:
_valid_icmp_types = __salt__['firewalld.get_icmp_types']() new_icmp_types = []
_current_icmp_blocks = __salt__['firewalld.list_icmp_block'](name) try:
_valid_icmp_types = __salt__['firewalld.get_icmp_types']()
_current_icmp_blocks = __salt__['firewalld.list_icmp_block'](name)
except CommandExecutionError as err:
ret['comment'] = 'Error: {0}'.format(err)
return ret
for icmp_type in set(block_icmp): for icmp_type in set(block_icmp):
if icmp_type in _valid_icmp_types: if icmp_type in _valid_icmp_types:
if icmp_type in _current_icmp_blocks: if icmp_type not in _current_icmp_blocks:
ret['comment']['icmp_blocks'].append( new_icmp_types.append(icmp_type)
'`{0}` already exists'.format(icmp_type) if not __opts__['test']:
) try:
else: __salt__['firewalld.block_icmp'](name, icmp_type)
if __opts__['test']: except CommandExecutionError as err:
ret['comment']['icmp_blocks'].append( ret['comment'] = 'Error: {0}'.format(err)
'`{0}` will be blocked'.format(icmp_type) return ret
)
else:
__salt__['firewalld.block_icmp'](name, icmp_type)
ret['changes']['icmp_blocks'].append(
'`{0}` has been blocked'.format(icmp_type)
)
else: else:
log.error('{0} is an invalid ICMP type'.format(icmp_type)) log.error('{0} is an invalid ICMP type'.format(icmp_type))
if new_icmp_types:
ret['changes'].update({'icmp_blocks':
{'old': _current_icmp_blocks,
'new': new_icmp_types}})
if default: if default:
if __salt__['firewalld.default_zone']() == name: try:
ret['comment']['default'] = '`{0}` is already the default zone'.format(name) default_zone = __salt__['firewalld.default_zone']()
else: except CommandExecutionError as err:
if __opts__['test']: ret['comment'] = 'Error: {0}'.format(err)
ret['comment']['default'] = '`{0}` wll be set to the default zone'.format(name) return ret
else: if name != default_zone:
__salt__['firewalld.set_default_zone'](name) if not __opts__['test']:
ret['changes']['default'] = '`{0}` has been set to the default zone'.format(name) try:
__salt__['firewalld.set_default_zone'](name)
except CommandExecutionError as err:
ret['comment'] = 'Error: {0}'.format(err)
return ret
ret['changes'].update({'default':
{'old': default_zone,
'new': name}})
if masquerade: if masquerade:
if __salt__['firewalld.get_masquerade'](name): try:
ret['comment']['masquerade'] = 'masquerading is already enabed' masquerade_ret = __salt__['firewalld.get_masquerade'](name)
else: except CommandExecutionError as err:
if __opts__['test']: ret['comment'] = 'Error: {0}'.format(err)
ret['comment']['masquerade'] = 'masquerading will be enabled' return ret
else: if not masquerade_ret:
__salt__['firewalld.add_masquerade'](name) if not __opts__['test']:
ret['changes']['masquerade'] = 'masquerading successfully set' try:
__salt__['firewalld.add_masquerade'](name)
except CommandExecutionError as err:
ret['comment'] = 'Error: {0}'.format(err)
return ret
ret['changes'].update({'masquerade':
{'old': '',
'new': 'Masquerading successfully set.'}})
if ports: if ports:
_current_ports = __salt__['firewalld.list_ports'](name) new_ports = []
try:
_current_ports = __salt__['firewalld.list_ports'](name)
except CommandExecutionError as err:
ret['comment'] = 'Error: {0}'.format(err)
return ret
for port in ports: for port in ports:
if port in _current_ports: if port not in _current_ports:
ret['comment']['ports'].append( new_ports.append(port)
'`{0}` already exists'.format(port) if not __opts__['test']:
) try:
else: __salt__['firewalld.add_port'](name, port)
if __opts__['test']: except CommandExecutionError as err:
ret['comment']['ports'].append( ret['comment'] = 'Error: {0}'.format(err)
'{0} will be added'.format(port) return ret
) if new_ports:
else: ret['changes'].update({'ports':
__salt__['firewalld.add_port'](name, port) {'old': _current_ports,
ret['changes']['ports'].append( 'new': new_ports}})
'`{0}` has been added to the firewall'.format(port)
)
if port_fwd: if port_fwd:
_current_port_fwd = __salt__['firewalld.list_port_fwd'](name) new_port_fwds = []
try:
_current_port_fwd = __salt__['firewalld.list_port_fwd'](name)
except CommandExecutionError as err:
ret['comment'] = 'Error: {0}'.format(err)
return ret
for port in port_fwd: for port in port_fwd:
dstaddr = '' dstaddr = ''
@ -157,45 +189,55 @@ def present(name,
else: else:
(src, dest, protocol) = port.split(':') (src, dest, protocol) = port.split(':')
for i in _current_port_fwd: for item in _current_port_fwd:
if (src == i['Source port'] and dest == i['Destination port'] and if (src == item['Source port'] and dest == item['Destination port'] and
protocol == i['Protocol'] and dstaddr == i['Destination address']): protocol == item['Protocol'] and dstaddr == item['Destination address']):
rule_exists = True rule_exists = True
if rule_exists: if rule_exists is False:
ret['comment']['port_fwd'].append( new_port_fwds.append(port)
'`{0}` port forwarding already exists'.format(port) if not __opts__['test']:
) try:
else: __salt__['firewalld.add_port_fwd'](name, src, dest, protocol, dstaddr)
if __opts__['test']: except CommandExecutionError as err:
ret['comment']['port_fwd'].append( ret['comment'] = 'Error: {0}'.format(err)
'`{0}` port will be added'.format(port) return ret
)
else: if new_port_fwds:
__salt__['firewalld.add_port_fwd']( ret['changes'].update({'port_fwd':
name, src, dest, protocol, dstaddr {'old': _current_port_fwd,
) 'new': new_port_fwds}})
ret['changes']['port_fwd'].append(
'`{0}` port forwarding has been added'.format(port)
)
if services: if services:
_current_services = __salt__['firewalld.list_services'](name) new_services = []
try:
_current_services = __salt__['firewalld.list_services'](name)
except CommandExecutionError as err:
ret['comment'] = 'Error: {0}'.format(err)
return ret
for service in services: for service in services:
if service in _current_services: if service not in _current_services:
ret['comment']['services'].append( new_services.append(service)
'`{0}` service already exists'.format(service) if not __opts__['test']:
) try:
else: __salt__['firewalld.add_service'](service, zone=name)
if __opts__['test']: except CommandExecutionError as err:
ret['comment']['services'].append( ret['comment'] = 'Error: {0}'.format(err)
'`{0}` service will be added'.format(service) return ret
) if new_services:
else: ret['changes'].update({'services':
__salt__['firewalld.new_service'](service) {'old': _current_services,
ret['changes']['services'].append( 'new': new_services}})
'`{0}` has been successfully added'.format(service)
)
ret['result'] = True
if ret['changes'] == {}:
ret['comment'] = '\'{0}\' is already in the desired state.'.format(name)
return ret
if __opts__['test']:
ret['result'] = None
ret['comment'] = 'Configuration for \'{0}\' will change.'.format(name)
return ret
ret['comment'] = '\'{0}\' was configured.'.format(name)
return ret return ret

View File

@ -373,6 +373,7 @@ def append(name, table='filter', family='ipv4', **kwargs):
if ignore in kwargs: if ignore in kwargs:
del kwargs[ignore] del kwargs[ignore]
kwargs['name'] = name kwargs['name'] = name
kwargs['table'] = table
rule = __salt__['iptables.build_rule'](family=family, **kwargs) rule = __salt__['iptables.build_rule'](family=family, **kwargs)
command = __salt__['iptables.build_rule'](full='True', family=family, command='A', **kwargs) command = __salt__['iptables.build_rule'](full='True', family=family, command='A', **kwargs)
if __salt__['iptables.check'](table, if __salt__['iptables.check'](table,
@ -500,6 +501,7 @@ def insert(name, table='filter', family='ipv4', **kwargs):
if ignore in kwargs: if ignore in kwargs:
del kwargs[ignore] del kwargs[ignore]
kwargs['name'] = name kwargs['name'] = name
kwargs['table'] = table
rule = __salt__['iptables.build_rule'](family=family, **kwargs) rule = __salt__['iptables.build_rule'](family=family, **kwargs)
command = __salt__['iptables.build_rule'](full=True, family=family, command='I', **kwargs) command = __salt__['iptables.build_rule'](full=True, family=family, command='I', **kwargs)
if __salt__['iptables.check'](table, if __salt__['iptables.check'](table,
@ -622,6 +624,7 @@ def delete(name, table='filter', family='ipv4', **kwargs):
if ignore in kwargs: if ignore in kwargs:
del kwargs[ignore] del kwargs[ignore]
kwargs['name'] = name kwargs['name'] = name
kwargs['table'] = table
rule = __salt__['iptables.build_rule'](family=family, **kwargs) rule = __salt__['iptables.build_rule'](family=family, **kwargs)
command = __salt__['iptables.build_rule'](full=True, family=family, command='D', **kwargs) command = __salt__['iptables.build_rule'](full=True, family=family, command='D', **kwargs)

View File

@ -127,7 +127,7 @@ def wait(name, **kwargs):
'comment': ''} 'comment': ''}
# Alias module.watch to module.wait # Alias module.watch to module.wait
watch = wait watch = salt.utils.alias_function(wait, 'watch')
def run(name, **kwargs): def run(name, **kwargs):
@ -269,4 +269,4 @@ def run(name, **kwargs):
ret['result'] = False ret['result'] = False
return ret return ret
mod_watch = run # pylint: disable=C0103 mod_watch = salt.utils.alias_function(run, 'mod_watch')

View File

@ -46,6 +46,9 @@ automatically
from __future__ import absolute_import, print_function from __future__ import absolute_import, print_function
import os import os
# Import salt libs
import salt.utils
def built( def built(
name, name,
@ -53,12 +56,13 @@ def built(
dest_dir, dest_dir,
spec, spec,
sources, sources,
template,
tgt, tgt,
template=None,
deps=None, deps=None,
env=None, env=None,
results=None, results=None,
always=False, force=False,
always=None,
saltenv='base'): saltenv='base'):
''' '''
Ensure that the named package is built and exists in the named directory Ensure that the named package is built and exists in the named directory
@ -78,12 +82,16 @@ def built(
sources sources
The list of package sources The list of package sources
template
Set to run the spec file through a templating engine
tgt tgt
The target platform to run the build on The target platform to run the build on
template
Run the spec file through a templating engine
.. versionchanged:: 2015.8.2
This argument is now optional, allowing for no templating engine to
be used if none is desired.
deps deps
Packages required to ensure that the named package is built Packages required to ensure that the named package is built
can be hosted on either the salt master server or on an HTTP can be hosted on either the salt master server or on an HTTP
@ -112,9 +120,20 @@ def built(
results results
The names of the expected rpms that will be built The names of the expected rpms that will be built
force : False
If ``True``, packages will be built even if they already exist in the
``dest_dir``. This is useful when building a package for continuous or
nightly package builds.
.. versionadded:: 2015.8.2
always always
Build with every run (good if the package is for continuous or If ``True``, packages will be built even if they already exist in the
nightly package builds) ``dest_dir``. This is useful when building a package for continuous or
nightly package builds.
.. deprecated:: 2015.8.2
Use ``force`` instead.
saltenv saltenv
The saltenv to use for files downloaded from the salt filesever The saltenv to use for files downloaded from the salt filesever
@ -123,7 +142,16 @@ def built(
'changes': {}, 'changes': {},
'comment': '', 'comment': '',
'result': True} 'result': True}
if not always:
if always is not None:
salt.utils.warn_until(
'Carbon',
'The \'always\' argument to the pkgbuild.built state has been '
'deprecated, please use \'force\' instead.'
)
force = always
if not force:
if isinstance(results, str): if isinstance(results, str):
results = results.split(',') results = results.split(',')
results = set(results) results = set(results)

View File

@ -2,10 +2,8 @@
''' '''
Management of PostgreSQL tablespace Management of PostgreSQL tablespace
=================================== ===================================
The postgres_tablespace module is used to create and manage Postgres
tablespaces.
Tablespaces can be set as either absent or present. A module used to create and manage PostgreSQL tablespaces.
.. code-block:: yaml .. code-block:: yaml
ssd-tablespace: ssd-tablespace:

View File

@ -74,4 +74,4 @@ def joined(name, host, user='rabbit', ram_node=None, runas='root'):
# Alias join to preserve backward compat # Alias join to preserve backward compat
join = joined join = salt.utils.alias_function(joined, 'join')

View File

@ -12,11 +12,14 @@ Example:
some_plugin: some_plugin:
rabbitmq_plugin.enabled: [] rabbitmq_plugin.enabled: []
''' '''
from __future__ import absolute_import
# Import python libs # Import Python Libs
from __future__ import absolute_import
import logging import logging
# Import Salt Libs
from salt.exceptions import CommandExecutionError
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -40,25 +43,33 @@ def enabled(name, runas=None):
''' '''
ret = {'name': name, 'result': True, 'comment': '', 'changes': {}} ret = {'name': name, 'result': True, 'comment': '', 'changes': {}}
result = {}
if __salt__['rabbitmq.plugin_is_enabled'](name, runas=runas): try:
ret['comment'] = 'Plugin {0} is already enabled'.format(name) plugin_enabled = __salt__['rabbitmq.plugin_is_enabled'](name, runas=runas)
except CommandExecutionError as err:
ret['result'] = False
ret['comment'] = 'Error: {0}'.format(err)
return ret return ret
if __opts__['test']: if plugin_enabled:
ret['comment'] = 'Plugin \'{0}\' is already enabled.'.format(name)
return ret
if not __opts__['test']:
try:
__salt__['rabbitmq.enable_plugin'](name, runas=runas)
except CommandExecutionError as err:
ret['result'] = False
ret['comment'] = 'Error: {0}'.format(err)
return ret
ret['changes'].update({'old': '', 'new': name})
if __opts__['test'] and ret['changes']:
ret['result'] = None ret['result'] = None
ret['comment'] = 'Plugin {0} is set to be enabled'.format(name) ret['comment'] = 'Plugin \'{0}\' is set to be enabled.'.format(name)
else: return ret
result = __salt__['rabbitmq.enable_plugin'](name, runas=runas)
if 'Error' in result:
ret['result'] = False
ret['comment'] = result['Error']
elif 'Enabled' in result:
ret['comment'] = result['Enabled']
ret['changes'] = {'old': '', 'new': name}
ret['comment'] = 'Plugin \'{0}\' was enabled.'.format(name)
return ret return ret
@ -73,23 +84,31 @@ def disabled(name, runas=None):
''' '''
ret = {'name': name, 'result': True, 'comment': '', 'changes': {}} ret = {'name': name, 'result': True, 'comment': '', 'changes': {}}
result = {}
if not __salt__['rabbitmq.plugin_is_enabled'](name, runas=runas): try:
ret['comment'] = 'Plugin {0} is not enabled'.format(name) plugin_enabled = __salt__['rabbitmq.plugin_is_enabled'](name, runas=runas)
except CommandExecutionError as err:
ret['result'] = False
ret['comment'] = 'Error: {0}'.format(err)
return ret return ret
if __opts__['test']: if not plugin_enabled:
ret['comment'] = 'Plugin \'{0}\' is already disabled.'.format(name)
return ret
if not __opts__['test']:
try:
__salt__['rabbitmq.disable_plugin'](name, runas=runas)
except CommandExecutionError as err:
ret['result'] = False
ret['comment'] = 'Error: {0}'.format(err)
return ret
ret['changes'].update({'old': name, 'new': ''})
if __opts__['test'] and ret['changes']:
ret['result'] = None ret['result'] = None
ret['comment'] = 'Plugin {0} is set to be disabled'.format(name) ret['comment'] = 'Plugin \'{0}\' is set to be disabled.'.format(name)
else: return ret
result = __salt__['rabbitmq.disable_plugin'](name, runas=runas)
if 'Error' in result:
ret['result'] = False
ret['comment'] = result['Error']
elif 'Disabled' in result:
ret['comment'] = result['Disabled']
ret['changes'] = {'new': '', 'old': name}
ret['comment'] = 'Plugin \'{0}\' was disabled.'.format(name)
return ret return ret

View File

@ -8,18 +8,18 @@ Example:
.. code-block:: yaml .. code-block:: yaml
rabbit_user: rabbit_user:
rabbitmq_user.present: rabbitmq_user.present:
- password: password - password: password
- force: True - force: True
- tags: - tags:
- monitoring - monitoring
- user - user
- perms: - perms:
- '/': - '/':
- '.*' - '.*'
- '.*' - '.*'
- '.*' - '.*'
- runas: rabbitmq - runas: rabbitmq
''' '''
# Import python libs # Import python libs
@ -28,9 +28,8 @@ import logging
# Import salt libs # Import salt libs
import salt.utils import salt.utils
# Import 3rd-party libs
import salt.ext.six as six import salt.ext.six as six
from salt.exceptions import CommandExecutionError
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -42,20 +41,25 @@ def __virtual__():
return salt.utils.which('rabbitmqctl') is not None return salt.utils.which('rabbitmqctl') is not None
def _check_perms_changes(name, newperms, runas=None): def _check_perms_changes(name, newperms, runas=None, existing=None):
''' '''
Whether Rabbitmq user's permissions need to be changed Check whether Rabbitmq user's permissions need to be changed.
''' '''
if not newperms: if not newperms:
return False return False
existing_perms = __salt__['rabbitmq.list_user_permissions'](name, runas=runas) if existing is None:
try:
existing = __salt__['rabbitmq.list_user_permissions'](name, runas=runas)
except CommandExecutionError as err:
log.error('Error: {0}'.format(err))
return False
perm_need_change = False perm_need_change = False
for vhost_perms in newperms: for vhost_perms in newperms:
for vhost, perms in vhost_perms.iteritems(): for vhost, perms in vhost_perms.iteritems():
if vhost in existing_perms: if vhost in existing:
if perms != existing_perms[vhost]: if perms != existing[vhost]:
perm_need_change = True perm_need_change = True
else: else:
perm_need_change = True perm_need_change = True
@ -63,14 +67,19 @@ def _check_perms_changes(name, newperms, runas=None):
return perm_need_change return perm_need_change
def _check_tags_changes(name, newtags, runas=None): def _check_tags_changes(name, new_tags, runas=None):
''' '''
Whether Rabbitmq user's tags need to be changed Whether Rabbitmq user's tags need to be changed
''' '''
if newtags: if new_tags:
if isinstance(newtags, str): if isinstance(new_tags, str):
newtags = newtags.split() new_tags = new_tags.split()
return __salt__['rabbitmq.list_users'](runas=runas)[name] - set(newtags) try:
users = __salt__['rabbitmq.list_users'](runas=runas)[name] - set(new_tags)
except CommandExecutionError as err:
log.error('Error: {0}'.format(err))
return []
return users
else: else:
return [] return []
@ -97,97 +106,109 @@ def present(name,
runas runas
Name of the user to run the command Name of the user to run the command
''' '''
ret = {'name': name, 'result': False, 'comment': '', 'changes': {}}
ret = {'name': name, 'result': True, 'comment': '', 'changes': {}} try:
result = {} user = __salt__['rabbitmq.user_exists'](name, runas=runas)
except CommandExecutionError as err:
user_exists = __salt__['rabbitmq.user_exists'](name, runas=runas) ret['comment'] = 'Error: {0}'.format(err)
if user_exists and not any((force, perms, tags)):
log.debug('RabbitMQ user %s exists, '
'and force is not set.', name)
ret['comment'] = 'User {0} already presents'.format(name)
return ret return ret
if user and not any((force, perms, tags)):
log.debug('RabbitMQ user \'{0}\' exists and force is not set.'.format(name))
ret['comment'] = 'User \'{0}\' is already present.'.format(name)
ret['result'] = True
return ret
if not user:
ret['changes'].update({'user':
{'old': '',
'new': name}})
if __opts__['test']:
ret['result'] = None
ret['comment'] = 'User \'{0}\' is set to be created.'.format(name)
return ret
log.debug('RabbitMQ user \'{0}\' doesn\'t exist - Creating.'.format(name))
try:
__salt__['rabbitmq.add_user'](name, password, runas=runas)
except CommandExecutionError as err:
ret['comment'] = 'Error: {0}'.format(err)
return ret
else: else:
changes = {'old': '', 'new': ''} log.debug('RabbitMQ user \'{0}\' exists'.format(name))
if force:
if not user_exists: if password is not None:
if __opts__['test']: if not __opts__['test']:
ret['result'] = None try:
ret['comment'] = 'User {0} is set to be created'.format(name) __salt__['rabbitmq.change_password'](name, password, runas=runas)
return ret except CommandExecutionError as err:
ret['comment'] = 'Error: {0}'.format(err)
log.debug("RabbitMQ user %s doesn't exist - Creating", name)
result = __salt__['rabbitmq.add_user'](
name, password, runas=runas)
else:
log.debug('RabbitMQ user %s exists', name)
if force:
if __opts__['test']:
ret['result'] = None
if password is not None:
if __opts__['test']:
ret['comment'] = ('User {0}\'s password is '
'set to be updated'.format(name))
return ret return ret
ret['changes'].update({'password':
result = __salt__['rabbitmq.change_password']( {'old': '',
name, password, runas=runas) 'new': 'Set password.'}})
changes['new'] = 'Set password.\n' else:
else: if not __opts__['test']:
log.debug('Password for %s is not set - Clearing password', log.debug('Password for {0} is not set - Clearing password.'.format(name))
name) try:
if __opts__['test']: __salt__['rabbitmq.clear_password'](name, runas=runas)
ret['comment'] = ('User {0}\'s password is ' except CommandExecutionError as err:
'set to be removed'.format(name)) ret['comment'] = 'Error: {0}'.format(err)
return ret return ret
ret['changes'].update({'password':
{'old': 'Removed password.',
'new': ''}})
result = __salt__['rabbitmq.clear_password']( new_tags = _check_tags_changes(name, tags, runas=runas)
name, runas=runas) if new_tags:
changes['old'] += 'Removed password.\n' if not __opts__['test']:
try:
if _check_tags_changes(name, tags, runas=runas): __salt__['rabbitmq.set_user_tags'](name, tags, runas=runas)
if __opts__['test']: except CommandExecutionError as err:
ret['result'] = None ret['comment'] = 'Error: {0}'.format(err)
ret['comment'] += ('Tags for user {0} '
'is set to be changed'.format(name))
return ret return ret
result.update(__salt__['rabbitmq.set_user_tags']( ret['changes'].update({'tags':
name, tags, runas=runas) {'old': tags,
) 'new': new_tags}})
changes['new'] += 'Set tags: {0}\n'.format(tags) try:
existing_perms = __salt__['rabbitmq.list_user_permissions'](name, runas=runas)[0]
if _check_perms_changes(name, perms, runas=runas): except CommandExecutionError as err:
if __opts__['test']: ret['comment'] = 'Error: {0}'.format(err)
ret['result'] = None
ret['comment'] += ('Permissions for user {0} '
'is set to be changed'.format(name))
return ret
for vhost_perm in perms:
for vhost, perm in six.iteritems(vhost_perm):
result.update(__salt__['rabbitmq.set_permissions'](
vhost, name, perm[0], perm[1], perm[2], runas=runas)
)
changes['new'] += (
'Set permissions {0} for vhost {1}'
).format(perm, vhost)
if 'Error' in result:
ret['result'] = False
ret['comment'] = result['Error']
elif 'Added' in result:
ret['comment'] = result['Added']
ret['changes'] = changes
elif 'Password Changed' in result:
ret['comment'] = result['Password Changed']
ret['changes'] = changes
elif 'Password Cleared' in result:
ret['comment'] = result['Password Cleared']
ret['changes'] = changes
return ret return ret
if _check_perms_changes(name, perms, runas=runas, existing=existing_perms):
for vhost_perm in perms:
for vhost, perm in six.iteritems(vhost_perm):
if not __opts__['test']:
try:
__salt__['rabbitmq.set_permissions'](
vhost, name, perm[0], perm[1], perm[2], runas=runas
)
except CommandExecutionError as err:
ret['comment'] = 'Error: {0}'.format(err)
return ret
new_perms = {vhost: perm}
if existing_perms != new_perms:
if ret['changes'].get('perms') is None:
ret['changes'].update({'perms':
{'old': {},
'new': {}}})
ret['changes']['perms']['old'].update(existing_perms)
ret['changes']['perms']['new'].update(new_perms)
ret['result'] = True
if ret['changes'] == {}:
ret['comment'] = '\'{0}\' is already in the desired state.'.format(name)
return ret
if __opts__['test']:
ret['result'] = None
ret['comment'] = 'Configuration for \'{0}\' will change.'.format(name)
return ret
ret['comment'] = '\'{0}\' was configured.'.format(name)
return ret
def absent(name, def absent(name,
runas=None): runas=None):
@ -199,23 +220,34 @@ def absent(name,
runas runas
User to run the command User to run the command
''' '''
ret = {'name': name, 'result': True, 'comment': '', 'changes': {}} ret = {'name': name, 'result': False, 'comment': '', 'changes': {}}
user_exists = __salt__['rabbitmq.user_exists'](name, runas=runas) try:
user_exists = __salt__['rabbitmq.user_exists'](name, runas=runas)
except CommandExecutionError as err:
ret['comment'] = 'Error: {0}'.format(err)
return ret
if not user_exists: if user_exists:
ret['comment'] = 'User {0} is not present'.format(name) if not __opts__['test']:
elif __opts__['test']: try:
ret['result'] = None __salt__['rabbitmq.delete_user'](name, runas=runas)
if user_exists: except CommandExecutionError as err:
ret['comment'] = 'Removing user {0}'.format(name) ret['comment'] = 'Error: {0}'.format(err)
return ret
ret['changes'].update({'name':
{'old': name,
'new': ''}})
else: else:
result = __salt__['rabbitmq.delete_user'](name, runas=runas) ret['result'] = True
if 'Error' in result: ret['comment'] = 'The user \'{0}\' is not present.'.format(name)
ret['result'] = False return ret
ret['comment'] = result['Error']
elif 'Deleted' in result:
ret['comment'] = 'Deleted'
ret['changes'] = {'new': '', 'old': name}
if __opts__['test'] and ret['changes']:
ret['result'] = None
ret['comment'] = 'The user \'{0}\' will be removed.'.format(name)
return ret
ret['result'] = True
ret['comment'] = 'The user \'{0}\' was removed.'.format(name)
return ret return ret

View File

@ -94,56 +94,65 @@ def _parse_key(key):
return hive, key return hive, key
def present(name, value=None, vname=None, vdata=None, vtype='REG_SZ', reflection=True): def present(name,
value=None,
vname=None,
vdata=None,
vtype='REG_SZ',
reflection=True,
use_32bit_registry=False):
''' '''
Ensure a registry key or value is present. Ensure a registry key or value is present.
:param str name: :param str name: A string value representing the full path of the key to
A string value representing the full path of the key to include the include the HIVE, Key, and all Subkeys. For example:
HIVE, Key, and all Subkeys. For example:
``HKEY_LOCAL_MACHINE\\SOFTWARE\\Salt`` ``HKEY_LOCAL_MACHINE\\SOFTWARE\\Salt``
Valid hive values include: Valid hive values include:
- HKEY_CURRENT_USER or HKCU - HKEY_CURRENT_USER or HKCU
- HKEY_LOCAL_MACHINE or HKLM - HKEY_LOCAL_MACHINE or HKLM
- HKEY_USERS or HKU - HKEY_USERS or HKU
:param str value: :param str value: Deprecated. Use vname and vdata instead. Included here for
Deprecated. Use vname and vdata instead. Included here for backwards backwards compatability.
compatability.
:param str vname: :param str vname: The name of the value you'd like to create beneath the
The name of the value you'd like to create beneath the Key. If this Key. If this parameter is not passed it will assume you want to set the
parameter is not passed it will assume you want to set the (Default) (Default) value
value
:param str vdata: :param str vdata: The value you'd like to set for the Key. If a value name
The value you'd like to set for the Key. If a value name (vname) is (vname) is passed, this will be the data for that value name. If not, this
passed, this will be the data for that value name. If not, this will be will be the (Default) value for the key.
the (Default) value for the key.
The type for the (Default) value is always REG_SZ and cannot be changed. The type for the (Default) value is always REG_SZ and cannot be changed.
This parameter is optional. If not passed, the Key will be created with. This parameter is optional. If not passed, the Key will be created with no
associated item/value pairs.
:param str vtype: :param str vtype: The value type for the data you wish to store in the
The value type for the data you wish to store in the registry. Valid registry. Valid values are:
values are:
- REG_BINARY - REG_BINARY
- REG_DWORD - REG_DWORD
- REG_EXPAND_SZ - REG_EXPAND_SZ
- REG_MULTI_SZ - REG_MULTI_SZ
- REG_SZ (Default) - REG_SZ (Default)
:param bool reflection: :param bool reflection: On 64 bit machines a duplicate value will be created
On 64 bit machines a duplicate value will be created in the in the ``Wow6432Node`` for 32bit programs. This only applies to the SOFTWARE
``Wow6432Node`` for 32bit programs. This only applies to the SOFTWARE key. This option is ignored on 32bit operating systems. This value defaults
key. This option is ignored on 32bit operating systems. This value to True. Set it to False to disable reflection.
defaults to True. Set it to False to disable reflection.
:return: .. deprecated:: 2015.8.2
Returns a dictionary showing the results of the registry operation. Use `use_32bit_registry` instead.
The parameter seems to have no effect since Windows 7 / Windows 2008R2
removed support for reflection. The parameter will be removed in Boron.
:param bool use_32bit_registry: Use the 32bit portion of the registry.
Applies only to 64bit windows. 32bit Windows will ignore this parameter.
Default if False.
:return: Returns a dictionary showing the results of the registry operation.
:rtype: dict :rtype: dict
The following example will set the ``(Default)`` value for the The following example will set the ``(Default)`` value for the
@ -199,7 +208,10 @@ def present(name, value=None, vname=None, vdata=None, vtype='REG_SZ', reflection
hive, key = _parse_key(name) hive, key = _parse_key(name)
# Determine what to do # Determine what to do
reg_current = __salt__['reg.read_value'](hive, key, vname) reg_current = __salt__['reg.read_value'](hive=hive,
key=key,
vname=vname,
use_32bit_registry=use_32bit_registry)
if vdata == reg_current['vdata'] and reg_current['success']: if vdata == reg_current['vdata'] and reg_current['success']:
ret['comment'] = '{0} in {1} is already configured'.\ ret['comment'] = '{0} in {1} is already configured'.\
@ -217,8 +229,12 @@ def present(name, value=None, vname=None, vdata=None, vtype='REG_SZ', reflection
return ret return ret
# Configure the value # Configure the value
ret['result'] = __salt__['reg.set_value'](hive, key, vname, vdata, vtype, ret['result'] = __salt__['reg.set_value'](hive=hive,
reflection) key=key,
vname=vname,
vdata=vdata,
vtype=vtype,
use_32bit_registry=use_32bit_registry)
if not ret['result']: if not ret['result']:
ret['changes'] = {} ret['changes'] = {}
@ -230,11 +246,33 @@ def present(name, value=None, vname=None, vdata=None, vtype='REG_SZ', reflection
return ret return ret
def absent(name, vname=None): def absent(name, vname=None, use_32bit_registry=False):
''' '''
Ensure a registry value is removed. To remove a key use key_absent. Ensure a registry value is removed. To remove a key use key_absent.
Example: :param str name: A string value representing the full path of the key to
include the HIVE, Key, and all Subkeys. For example:
``HKEY_LOCAL_MACHINE\\SOFTWARE\\Salt``
Valid hive values include:
- HKEY_CURRENT_USER or HKCU
- HKEY_LOCAL_MACHINE or HKLM
- HKEY_USERS or HKU
:param str vname: The name of the value you'd like to create beneath the
Key. If this parameter is not passed it will assume you want to set the
(Default) value
:param bool use_32bit_registry: Use the 32bit portion of the registry.
Applies only to 64bit windows. 32bit Windows will ignore this parameter.
Default if False.
:return: Returns a dictionary showing the results of the registry operation.
:rtype: dict
CLI Example:
.. code-block:: yaml .. code-block:: yaml
@ -242,9 +280,11 @@ def absent(name, vname=None):
reg.absent reg.absent
In the above example the path is interpreted as follows: In the above example the path is interpreted as follows:
- ``HKEY_CURRENT_USER`` is the hive - ``HKEY_CURRENT_USER`` is the hive
- ``SOFTWARE\\Salt`` is the key - ``SOFTWARE\\Salt`` is the key
- ``version`` is the value name - ``version`` is the value name
So the value ``version`` will be deleted from the ``SOFTWARE\\Salt`` key in So the value ``version`` will be deleted from the ``SOFTWARE\\Salt`` key in
the ``HKEY_CURRENT_USER`` hive. the ``HKEY_CURRENT_USER`` hive.
''' '''
@ -256,11 +296,17 @@ def absent(name, vname=None):
hive, key = _parse_key(name) hive, key = _parse_key(name)
# Determine what to do # Determine what to do
reg_check = __salt__['reg.read_value'](hive, key, vname) reg_check = __salt__['reg.read_value'](hive=hive,
key=key,
vname=vname,
use_32bit_registry=use_32bit_registry)
if not reg_check['success'] or reg_check['vdata'] == '(value not set)': if not reg_check['success'] or reg_check['vdata'] == '(value not set)':
if not vname: if not vname:
hive, key, vname = _parse_key_value(name) hive, key, vname = _parse_key_value(name)
reg_check = __salt__['reg.read_value'](hive, key, vname) reg_check = __salt__['reg.read_value'](hive=hive,
key=key,
vname=vname,
use_32bit_registry=use_32bit_registry)
if not reg_check['success'] or reg_check['vdata'] == '(value not set)': if not reg_check['success'] or reg_check['vdata'] == '(value not set)':
ret['comment'] = '{0} is already absent'.format(name) ret['comment'] = '{0} is already absent'.format(name)
return ret return ret
@ -278,7 +324,10 @@ def absent(name, vname=None):
return ret return ret
# Delete the value # Delete the value
ret['result'] = __salt__['reg.delete_value'](hive, key, vname) ret['result'] = __salt__['reg.delete_value'](hive=hive,
key=key,
vname=vname,
use_32bit_registry=use_32bit_registry)
if not ret['result']: if not ret['result']:
ret['changes'] = {} ret['changes'] = {}
ret['comment'] = r'Failed to remove {0} from {1}'.format(key, hive) ret['comment'] = r'Failed to remove {0} from {1}'.format(key, hive)
@ -289,39 +338,40 @@ def absent(name, vname=None):
return ret return ret
def key_absent(name, force=False): def key_absent(name, force=False, use_32bit_registry=False):
r''' r'''
.. versionadded:: 2015.5.4 .. versionadded:: 2015.5.4
Ensure a registry key is removed. This will remove a key and all value Ensure a registry key is removed. This will remove a key and all value
entries it contains. It will fail if the key contains subkeys. entries it contains. It will fail if the key contains subkeys.
:param str name: :param str name: A string representing the full path to the key to be
A string representing the full path to the key to be removed to include removed to include the hive and the keypath. The hive can be any of the following:
the hive and the keypath. The hive can be any of the following:
- HKEY_LOCAL_MACHINE or HKLM
- HKEY_CURRENT_USER or HKCU
- HKEY_USER or HKU
:param bool force: - HKEY_LOCAL_MACHINE or HKLM
A boolean value indicating that all subkeys should be deleted with the - HKEY_CURRENT_USER or HKCU
key. If force=False and subkeys exists beneath the key you want to - HKEY_USER or HKU
delete, key_absent will fail. Use with caution. The default is False.
:return: :param bool force: A boolean value indicating that all subkeys should be
Returns a dictionary showing the results of the registry operation. deleted with the key. If force=False and subkeys exists beneath the key you
want to delete, key_absent will fail. Use with caution. The default is False.
:return: Returns a dictionary showing the results of the registry operation.
:rtype: dict :rtype: dict
The following example will delete the ``SOFTWARE\Salt`` key and all subkeys The following example will delete the ``SOFTWARE\Salt`` key and all subkeys
under the ``HKEY_CURRENT_USER`` hive. under the ``HKEY_CURRENT_USER`` hive.
Example:: Example:
.. codeblock:: yaml
'HKEY_CURRENT_USER\SOFTWARE\Salt': 'HKEY_CURRENT_USER\SOFTWARE\Salt':
reg.key_absent: reg.key_absent:
- force: True - force: True
In the above example the path is interpreted as follows: In the above example the path is interpreted as follows:
- ``HKEY_CURRENT_USER`` is the hive - ``HKEY_CURRENT_USER`` is the hive
- ``SOFTWARE\Salt`` is the key - ``SOFTWARE\Salt`` is the key
''' '''
@ -333,7 +383,9 @@ def key_absent(name, force=False):
hive, key = _parse_key(name) hive, key = _parse_key(name)
# Determine what to do # Determine what to do
if not __salt__['reg.read_value'](hive, key)['success']: if not __salt__['reg.read_value'](hive=hive,
key=key,
use_32bit_registry=use_32bit_registry)['success']:
ret['comment'] = '{0} is already absent'.format(name) ret['comment'] = '{0} is already absent'.format(name)
return ret return ret
@ -348,8 +400,13 @@ def key_absent(name, force=False):
return ret return ret
# Delete the value # Delete the value
__salt__['reg.delete_key'](hive, key, force=force) __salt__['reg.delete_key'](hive=hive,
if __salt__['reg.read_value'](hive, key)['success']: key=key,
force=force,
use_32bit_registry=use_32bit_registry)
if __salt__['reg.read_value'](hive=hive,
key=key,
use_32bit_registry=use_32bit_registry)['success']:
ret['result'] = False ret['result'] = False
ret['changes'] = {} ret['changes'] = {}
ret['comment'] = 'Failed to remove registry key {0}'.format(name) ret['comment'] = 'Failed to remove registry key {0}'.format(name)

Some files were not shown because too many files have changed in this diff Show More