Merge branch 'develop' into add-cloud.vmware.convert_to_snapshot-feature

This commit is contained in:
Mike Place 2017-11-13 11:28:27 -07:00 committed by GitHub
commit 27e80e4627
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
644 changed files with 17255 additions and 6659 deletions

View file

@ -12,4 +12,10 @@ Remove this section if not relevant
Yes/No
### Commits signed with GPG?
Yes/No
Please review [Salt's Contributing Guide](https://docs.saltstack.com/en/latest/topics/development/contributing.html) for best practices.
See GitHub's [page on GPG signing](https://help.github.com/articles/signing-commits-using-gpg/) for more information about signing commits with GPG.

4
.github/stale.yml vendored
View file

@ -1,8 +1,8 @@
# Probot Stale configuration file
# Number of days of inactivity before an issue becomes stale
# 975 is approximately 2 years and 8 months
daysUntilStale: 975
# 890 is approximately 2 years and 5 months
daysUntilStale: 890
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7

8
.gitignore vendored
View file

@ -89,3 +89,11 @@ tests/integration/cloud/providers/logs
# Private keys from the integration tests
tests/integration/cloud/providers/pki/minions
/helpers/
# Ignore tox virtualenvs
/.tox/
# Kitchen tests files
.kitchen/
.bundle/
Gemfile.lock

187
.kitchen.yml Normal file
View file

@ -0,0 +1,187 @@
---
<% vagrant = system('which vagrant 2>/dev/null >/dev/null') %>
<% version = '2017.7.2' %>
<% platformsfile = ENV['SALT_KITCHEN_PLATFORMS'] || '.kitchen/platforms.yml' %>
<% driverfile = ENV['SALT_KITCHEN_DRIVER'] || '.kitchen/driver.yml' %>
<% if File.exists?(driverfile) %>
<%= ERB.new(File.read(driverfile)).result %>
<% else %>
driver:
name: docker
use_sudo: false
privileged: true
username: root
volume:
- /var/run/docker.sock:/docker.sock
cap_add:
- sys_admin
disable_upstart: false
provision_command:
- echo 'L /run/docker.sock - - - - /docker.sock' > /etc/tmpfiles.d/docker.conf
<% end %>
sudo: false
provisioner:
name: salt_solo
salt_install: bootstrap
salt_version: latest
salt_bootstrap_url: https://bootstrap.saltstack.com
salt_bootstrap_options: -X stable <%= version %>
log_level: info
require_chef: false
remote_states:
name: git://github.com/gtmanfred/salt-jenkins.git
branch: master
repo: git
testingdir: /testing
salt_copy_filter:
- .bundle
- .git
- .gitignore
- .kitchen
- .kitchen.yml
- Gemfile
- Gemfile.lock
- README.rst
- .travis.yml
state_top:
base:
"*":
- git.salt
- kitchen
<% if File.exists?(platformsfile) %>
<%= ERB.new(File.read(platformsfile)).result %>
<% else %>
platforms:
- name: fedora
driver_config:
image: fedora:latest
run_command: /usr/lib/systemd/systemd
provisioner:
salt_bootstrap_options: -X git v<%= version %> >/dev/null
- name: centos-7
driver_config:
run_command: /usr/lib/systemd/systemd
- name: centos-6
driver_config:
run_command: /sbin/init
provision_command:
- yum install -y upstart
provisioner:
salt_bootstrap_options: -P -y -x python2.7 -X git v<%= version %> >/dev/null
- name: ubuntu-rolling
driver_config:
image: ubuntu:rolling
run_command: /lib/systemd/systemd
provisioner:
salt_bootstrap_url: https://raw.githubusercontent.com/saltstack/salt-bootstrap/develop/bootstrap-salt.sh
- name: ubuntu-16.04
driver_config:
run_command: /lib/systemd/systemd
- name: ubuntu-14.04
driver_config:
run_command: /sbin/init
provision_command:
- rm -f /sbin/initctl
- dpkg-divert --local --rename --remove /sbin/initctl
- name: debian-8
driver_config:
run_command: /lib/systemd/systemd
provision_command:
- apt-get install -y dbus
- echo 'L /run/docker.sock - - - - /docker.sock' > /etc/tmpfiles.d/docker.conf
- name: debian-9
driver_config:
run_command: /lib/systemd/systemd
- name: arch
driver_config:
image: base/archlinux
run_command: /usr/lib/systemd/systemd
provision_command:
- pacman -Syu --noconfirm systemd
- systemctl enable sshd
- echo 'L /run/docker.sock - - - - /docker.sock' > /etc/tmpfiles.d/docker.conf
provisioner:
salt_bootstrap_options: -X git v<%= version %> >/dev/null
- name: opensuse
driver_config:
run_command: /usr/lib/systemd/systemd
provision_command:
- systemctl enable sshd.service
- echo 'L /run/docker.sock - - - - /docker.sock' > /etc/tmpfiles.d/docker.conf
provisioner:
salt_bootstrap_options: -X git v<%= version %> >/dev/null
<% if vagrant != false %>
- name: windows-2012r2
driver:
box: mwrock/Windows2012R2
communicator: winrm
name: vagrant
gui: true
username: administrator
password: Pass@word1
provisioner:
init_environment: |
Clear-Host
$AddedLocation ="c:\salt"
$Reg = "Registry::HKLM\System\CurrentControlSet\Control\Session Manager\Environment"
$OldPath = (Get-ItemProperty -Path "$Reg" -Name PATH).Path
$NewPath= $OldPath + ; + $AddedLocation
Set-ItemProperty -Path "$Reg" -Name PATH Value $NewPath
salt_bootstrap_url: https://raw.githubusercontent.com/saltstack/salt-bootstrap/develop/bootstrap-salt.ps1
salt_bootstrap_options: ''
- name: windows-2016
driver:
box: mwrock/Windows2016
communicator: winrm
name: vagrant
username: Vagrant
password: vagrant
gui: true
provisioner:
init_environment: |
Clear-Host
$AddedLocation ="c:\salt;c:\salt\bin\Scripts"
$Reg = "Registry::HKLM\System\CurrentControlSet\Control\Session Manager\Environment"
$OldPath = (Get-ItemProperty -Path "$Reg" -Name PATH).Path
$NewPath= $OldPath + ; + $AddedLocation
Set-ItemProperty -Path "$Reg" -Name PATH Value $NewPath
salt_bootstrap_url: https://raw.githubusercontent.com/saltstack/salt-bootstrap/develop/bootstrap-salt.ps1
salt_bootstrap_options: ''
<% end %>
<% end %>
suites:
- name: py2
provisioner:
pillars:
top.sls:
base:
"*":
- jenkins
jenkins.sls:
testing_dir: /tmp/kitchen/testing
clone_repo: false
salttesting_namespec: salttesting==2017.6.1
- name: py3
provisioner:
pillars:
top.sls:
base:
"*":
- jenkins
jenkins.sls:
testing_dir: /tmp/kitchen/testing
clone_repo: false
py3: true
salttesting_namespec: salttesting==2017.6.1
verifier:
name: shell
remote_exec: true
sudo: false
live_stream: {}
<% if ENV['TESTOPTS'].nil? %>
command: '$(kitchen) /tmp/kitchen/testing/tests/runtests.py --run-destructive --sysinfo --transport=zeromq --output-columns=80 --ssh --coverage-xml=/tmp/coverage.xml --xml=/tmp/xml-unittests-output'
<% else %>
command: '$(kitchen) /tmp/kitchen/testing/tests/runtests.py --run-destructive --output-columns 80 <%= ENV["TESTOPTS"] %>'
<% end %>

View file

@ -258,8 +258,8 @@ ignore-imports=no
[BASIC]
# Required attributes for module, separated by a comma
required-attributes=
# Required attributes for module, separated by a comma (will be removed in Pylint 2.0)
#required-attributes=
# List of builtins function names that should not be used, separated by a comma
bad-functions=map,filter,apply,input
@ -365,7 +365,8 @@ spelling-store-unknown-words=no
[CLASSES]
# List of interface methods to ignore, separated by a comma. This is used for
# instance to not check methods defines in Zope's Interface base class.
ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
# Will be removed in Pylint 2.0
#ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,__new__,setUp

23
Gemfile Normal file
View file

@ -0,0 +1,23 @@
# This file is only used for running the test suite with kitchen-salt.
source "https://rubygems.org"
gem "test-kitchen"
gem "kitchen-salt", :git => 'https://github.com/saltstack/kitchen-salt.git'
gem 'git'
group :docker do
gem 'kitchen-docker', :git => 'https://github.com/test-kitchen/kitchen-docker.git'
end
group :opennebula do
gem 'kitchen-opennebula', :git => 'https://github.com/gtmanfred/kitchen-opennebula.git'
gem 'xmlrpc'
end
group :windows do
gem 'vagrant-wrapper'
gem 'kitchen-vagrant'
gem 'winrm', '~>2.0'
gem 'winrm-fs', '~>1.0'
end

View file

@ -44,6 +44,11 @@ may take a few moments for someone to reply.
`<http://webchat.freenode.net/?channels=salt&uio=Mj10cnVlJjk9dHJ1ZSYxMD10cnVl83>`_
**SaltStack Slack** - Alongside IRC is our SaltStack Community Slack for the
SaltStack Working groups. Use the following link to request an invitation.
`<https://saltstackcommunity.herokuapp.com/>`_
**Mailing List** - The SaltStack community users mailing list is hosted by
Google groups. Anyone can post to ask questions about SaltStack products and
anyone can help answer. Join the conversation!

View file

@ -464,11 +464,13 @@
##### Salt-SSH Configuration #####
##########################################
# Define the default salt-ssh roster module to use
#roster: flat
# Pass in an alternative location for the salt-ssh roster file
# Pass in an alternative location for the salt-ssh `flat` roster file
#roster_file: /etc/salt/roster
# Define locations for roster files so they can be chosen when using Salt API.
# Define locations for `flat` roster files so they can be chosen when using Salt API.
# An administrator can place roster files into these locations. Then when
# calling Salt API, parameter 'roster_file' should contain a relative path to
# these locations. That is, "roster_file=/foo/roster" will be resolved as

View file

@ -438,11 +438,13 @@ syndic_user: salt
##### Salt-SSH Configuration #####
##########################################
# Define the default salt-ssh roster module to use
#roster: flat
# Pass in an alternative location for the salt-ssh roster file
# Pass in an alternative location for the salt-ssh `flat` roster file
#roster_file: /etc/salt/roster
# Define locations for roster files so they can be chosen when using Salt API.
# Define locations for `flat` roster files so they can be chosen when using Salt API.
# An administrator can place roster files into these locations. Then when
# calling Salt API, parameter 'roster_file' should contain a relative path to
# these locations. That is, "roster_file=/foo/roster" will be resolved as

Binary file not shown.

Before

Width:  |  Height:  |  Size: 790 KiB

After

Width:  |  Height:  |  Size: 438 KiB

View file

@ -29818,7 +29818,7 @@ If the master seems to be unresponsive, a SIGUSR1 can be passed to the
salt\-master threads to display what piece of code is executing. This debug
information can be invaluable in tracking down bugs.
.sp
To pass a SIGUSR1 to the master, first make sure the minion is running in the
To pass a SIGUSR1 to the master, first make sure the master is running in the
foreground. Stop the service if it is running as a daemon, and start it in the
foreground like so:
.INDENT 0.0

View file

@ -34,6 +34,7 @@ Full list of Salt Cloud modules
scaleway
softlayer
softlayer_hw
vagrant
virtualbox
vmware
vultrpy

View file

@ -1,6 +1,6 @@
===============================
==============================
salt.cloud.clouds.digitalocean
===============================
==============================
.. automodule:: salt.cloud.clouds.digitalocean
:members:

View file

@ -0,0 +1,6 @@
=========================
salt.cloud.clouds.vagrant
=========================
.. automodule:: salt.cloud.clouds.vagrant
:members:

View file

@ -718,7 +718,7 @@ Note that ping_on_rotate may cause high load on the master immediately after
the key rotation event as minions reconnect. Consider this carefully if this
salt master is managing a large number of minions.
.. code-black:: yaml
.. code-block:: yaml
ping_on_rotate: False
@ -904,7 +904,7 @@ is set to ``tcp`` by default on Windows.
ipc_mode: ipc
.. conf_master::
.. conf_master:: tcp_master_pub_port
``tcp_master_pub_port``
-----------------------
@ -963,6 +963,19 @@ The TCP port for ``mworkers`` to connect to on the master.
Salt-SSH Configuration
======================
.. conf_master:: roster
``roster``
---------------
Default: ``flat``
Define the default salt-ssh roster module to use
.. code-block:: yaml
roster: cache
.. conf_master:: roster_file
``roster_file``
@ -970,12 +983,31 @@ Salt-SSH Configuration
Default: ``/etc/salt/roster``
Pass in an alternative location for the salt-ssh roster file.
Pass in an alternative location for the salt-ssh `flat` roster file.
.. code-block:: yaml
roster_file: /root/roster
.. conf_master:: roster_file
``rosters``
---------------
Default: None
Define locations for `flat` roster files so they can be chosen when using Salt API.
An administrator can place roster files into these locations.
Then when calling Salt API, parameter 'roster_file' should contain a relative path to these locations.
That is, "roster_file=/foo/roster" will be resolved as "/etc/salt/roster.d/foo/roster" etc.
This feature prevents passing insecure custom rosters through the Salt API.
.. code-block:: yaml
rosters:
- /etc/salt/roster.d
- /opt/salt/some/more/rosters
.. conf_master:: ssh_passwd
``ssh_passwd``
@ -4205,6 +4237,7 @@ Default: ``10``
The number of workers for the runner/wheel in the reactor.
.. code-block:: yaml
reactor_worker_threads: 10
.. conf_master:: reactor_worker_hwm

View file

@ -1196,7 +1196,7 @@ be able to execute a certain module. The ``sys`` module is built into the minion
and cannot be disabled.
This setting can also tune the minion. Because all modules are loaded into system
memory, disabling modules will lover the minion's memory footprint.
memory, disabling modules will lower the minion's memory footprint.
Modules should be specified according to their file name on the system and not by
their virtual name. For example, to disable ``cmd``, use the string ``cmdmod`` which
@ -2387,6 +2387,7 @@ Default: ``10``
The number of workers for the runner/wheel in the reactor.
.. code-block:: yaml
reactor_worker_threads: 10
.. conf_minion:: reactor_worker_hwm

View file

@ -299,6 +299,7 @@ execution modules
openstack_mng
openvswitch
opkg
opsgenie
oracle
osquery
out
@ -432,6 +433,7 @@ execution modules
uptime
useradd
uwsgi
vagrant
varnish
vault
vbox_guest

View file

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

View file

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

View file

@ -46,5 +46,6 @@ returner modules
splunk
sqlite3_return
syslog_return
telegram_return
xmpp_return
zabbix_return

View file

@ -188,6 +188,7 @@ state modules
openstack_config
openvswitch_bridge
openvswitch_port
opsgenie
pagerduty
pagerduty_escalation_policy
pagerduty_schedule
@ -267,6 +268,7 @@ state modules
tuned
uptime
user
vagrant
vault
vbox_guest
victorops

View file

@ -0,0 +1,6 @@
=====================
salt.states.opsgenie
=====================
.. automodule:: salt.states.opsgenie
:members:

View file

@ -0,0 +1,6 @@
===================
salt.states.vagrant
===================
.. automodule:: salt.states.vagrant
:members:

View file

@ -6,7 +6,7 @@ Introduced in Salt version ``2017.7.0`` it is now possible to run select states
in parallel. This is accomplished very easily by adding the ``parallel: True``
option to your state declaration:
.. code_block:: yaml
.. code-block:: yaml
nginx:
service.running:
@ -24,7 +24,7 @@ state to finish.
Given this example:
.. code_block:: yaml
.. code-block:: yaml
sleep 10:
cmd.run:
@ -51,7 +51,7 @@ actually speed things up.
To run the above state much faster make sure that the ``sleep 5`` is evaluated
before the ``nginx`` state
.. code_block:: yaml
.. code-block:: yaml
sleep 10:
cmd.run:
@ -74,16 +74,16 @@ also complete.
Things to be Careful of
=======================
Parallel States does not prevent you from creating parallel conflicts on your
Parallel States do not prevent you from creating parallel conflicts on your
system. This means that if you start multiple package installs using Salt then
the package manager will block or fail. If you attempt to manage the same file
with multiple states in parallel then the result can produce an unexpected
file.
Make sure that the states you choose to run in parallel do not conflict, or
else, like in and parallel programming environment, the outcome may not be
else, like in any parallel programming environment, the outcome may not be
what you expect. Doing things like just making all states run in parallel
will almost certinly result in unexpected behavior.
will almost certainly result in unexpected behavior.
With that said, running states in parallel should be safe the vast majority
of the time and the most likely culprit for unexpected behavior is running

View file

@ -146,24 +146,24 @@ library. The following two lines set up the imports:
.. code-block:: python
from salt.cloud.libcloudfuncs import * # pylint: disable=W0614,W0401
import salt.utils
import salt.utils.functools
And then a series of declarations will make the necessary functions available
within the cloud module.
.. code-block:: python
get_size = salt.utils.namespaced_function(get_size, globals())
get_image = salt.utils.namespaced_function(get_image, globals())
avail_locations = salt.utils.namespaced_function(avail_locations, globals())
avail_images = salt.utils.namespaced_function(avail_images, globals())
avail_sizes = salt.utils.namespaced_function(avail_sizes, globals())
script = salt.utils.namespaced_function(script, globals())
destroy = salt.utils.namespaced_function(destroy, globals())
list_nodes = salt.utils.namespaced_function(list_nodes, globals())
list_nodes_full = salt.utils.namespaced_function(list_nodes_full, globals())
list_nodes_select = salt.utils.namespaced_function(list_nodes_select, globals())
show_instance = salt.utils.namespaced_function(show_instance, globals())
get_size = salt.utils.functools.namespaced_function(get_size, globals())
get_image = salt.utils.functools.namespaced_function(get_image, globals())
avail_locations = salt.utils.functools.namespaced_function(avail_locations, globals())
avail_images = salt.utils.functools.namespaced_function(avail_images, globals())
avail_sizes = salt.utils.functools.namespaced_function(avail_sizes, globals())
script = salt.utils.functools.namespaced_function(script, globals())
destroy = salt.utils.functools.namespaced_function(destroy, globals())
list_nodes = salt.utils.functools.namespaced_function(list_nodes, globals())
list_nodes_full = salt.utils.functools.namespaced_function(list_nodes_full, globals())
list_nodes_select = salt.utils.functools.namespaced_function(list_nodes_select, globals())
show_instance = salt.utils.functools.namespaced_function(show_instance, globals())
If necessary, these functions may be replaced by removing the appropriate
declaration line, and then adding the function as normal.

View file

@ -540,6 +540,17 @@ machines which are already installed, but not Salted. For more information about
this driver and for configuration examples, please see the
:ref:`Gettting Started with Saltify <getting-started-with-saltify>` documentation.
.. _config_vagrant:
Vagrant
-------
The Vagrant driver is a new, experimental driver for controlling a VagrantBox
virtual machine, and installing Salt on it. The target host machine must be a
working salt minion, which is controlled via the salt master using salt-api.
For more information, see
:ref:`Getting Started With Vagrant <getting-started-with-vagrant>`.
Extending Profiles and Cloud Providers Configuration
====================================================

View file

@ -54,6 +54,10 @@ Set up an initial profile at ``/etc/salt/cloud.profiles`` or in the
ipv6: True
create_dns_record: True
userdata_file: /etc/salt/cloud.userdata.d/setup
tags:
- tag1
- tag2
- tag3
Locations can be obtained using the ``--list-locations`` option for the ``salt-cloud``
command:

View file

@ -38,26 +38,30 @@ These are features that are available for almost every cloud host.
.. container:: scrollable
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
| |AWS |CloudStack|Digital|EC2|GoGrid|JoyEnt|Linode|OpenStack|Parallels|Rackspace|Saltify|Softlayer|Softlayer|Aliyun|
| |(Legacy)| |Ocean | | | | | | |(Legacy) | | |Hardware | |
+=======================+========+==========+=======+===+======+======+======+=========+=========+=========+=======+=========+=========+======+
|Query |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes | |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|Full Query |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes | |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|Selective Query |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes | |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|List Sizes |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes | |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|List Images |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes | |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|List Locations |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes | |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|create |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|destroy |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes | |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+-------+---------+---------+------+
| |AWS |CloudStack|Digital|EC2|GoGrid|JoyEnt|Linode|OpenStack|Parallels|Rackspace|Saltify|Vagrant|Softlayer|Softlayer|Aliyun|
| |(Legacy)| |Ocean | | | | | | |(Legacy) | | | |Hardware | |
+=======================+========+==========+=======+===+======+======+======+=========+=========+=========+=======+=======+=========+=========+======+
|Query |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |[1] |[1] |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+-------+---------+---------+------+
|Full Query |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |[1] |[1] |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+-------+---------+---------+------+
|Selective Query |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |[1] |[1] |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+-------+---------+---------+------+
|List Sizes |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |[2] |[2] |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+-------+---------+---------+------+
|List Images |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+-------+---------+---------+------+
|List Locations |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |[2] |[2] |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+-------+---------+---------+------+
|create |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |Yes |[1] |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+-------+---------+---------+------+
|destroy |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |[1] |[1] |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+-------+---------+---------+------+
[1] Yes, if salt-api is enabled.
[2] Always returns `{}`.
Actions
=======
@ -70,46 +74,46 @@ instance name to be passed in. For example:
.. container:: scrollable
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|Actions |AWS |CloudStack|Digital|EC2|GoGrid|JoyEnt|Linode|OpenStack|Parallels|Rackspace|Saltify|Softlayer|Softlayer|Aliyun|
| |(Legacy)| |Ocean | | | | | | |(Legacy) | | |Hardware | |
+=======================+========+==========+=======+===+======+======+======+=========+=========+=========+=======+=========+=========+======+
|attach_volume | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|create_attach_volumes |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|del_tags |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|delvol_on_destroy | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|detach_volume | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|disable_term_protect |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|enable_term_protect |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|get_tags |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|keepvol_on_destroy | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|list_keypairs | | |Yes | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|rename |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|set_tags |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|show_delvol_on_destroy | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|show_instance | | |Yes |Yes| | |Yes | |Yes | | |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|show_term_protect | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|start |Yes | | |Yes| |Yes |Yes | |Yes | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|stop |Yes | | |Yes| |Yes |Yes | |Yes | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|take_action | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|Actions |AWS |CloudStack|Digital|EC2|GoGrid|JoyEnt|Linode|OpenStack|Parallels|Rackspace|Saltify&|Softlayer|Softlayer|Aliyun|
| |(Legacy)| |Ocean | | | | | | |(Legacy) | Vagrant| |Hardware | |
+=======================+========+==========+=======+===+======+======+======+=========+=========+=========+========+=========+=========+======+
|attach_volume | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|create_attach_volumes |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|del_tags |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|delvol_on_destroy | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|detach_volume | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|disable_term_protect |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|enable_term_protect |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|get_tags |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|keepvol_on_destroy | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|list_keypairs | | |Yes | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|rename |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|set_tags |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|show_delvol_on_destroy | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|show_instance | | |Yes |Yes| | |Yes | |Yes | | |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|show_term_protect | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|start |Yes | | |Yes| |Yes |Yes | |Yes | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|stop |Yes | | |Yes| |Yes |Yes | |Yes | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|take_action | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
Functions
=========
@ -122,81 +126,83 @@ require the name of the provider to be passed in. For example:
.. container:: scrollable
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|Functions |AWS |CloudStack|Digital|EC2|GoGrid|JoyEnt|Linode|OpenStack|Parallels|Rackspace|Saltify|Softlayer|Softlayer|Aliyun|
| |(Legacy)| |Ocean | | | | | | |(Legacy) | | |Hardware | |
+=======================+========+==========+=======+===+======+======+======+=========+=========+=========+=======+=========+=========+======+
|block_device_mappings |Yes | | | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|create_keypair | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|create_volume | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|delete_key | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|delete_keypair | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|delete_volume | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|get_image | | |Yes | | |Yes | | |Yes | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|get_ip | |Yes | | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|get_key | |Yes | | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|get_keyid | | |Yes | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|get_keypair | |Yes | | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|get_networkid | |Yes | | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|get_node | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|get_password | |Yes | | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|get_size | | |Yes | | |Yes | | | | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|get_spot_config | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|get_subnetid | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|iam_profile |Yes | | |Yes| | | | | | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|import_key | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|key_list | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|keyname |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|list_availability_zones| | | |Yes| | | | | | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|list_custom_images | | | | | | | | | | | |Yes | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|list_keys | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|list_nodes |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|list_nodes_full |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|list_nodes_select |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|list_vlans | | | | | | | | | | | |Yes |Yes | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|rackconnect | | | | | | | |Yes | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|reboot | | | |Yes| |Yes | | | | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|reformat_node | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|securitygroup |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|securitygroupid | | | |Yes| | | | | | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|show_image | | | |Yes| | | | |Yes | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|show_key | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|show_keypair | | |Yes |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|show_volume | | | |Yes| | | | | | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|Functions |AWS |CloudStack|Digital|EC2|GoGrid|JoyEnt|Linode|OpenStack|Parallels|Rackspace|Saltify&|Softlayer|Softlayer|Aliyun|
| |(Legacy)| |Ocean | | | | | | |(Legacy) | Vagrant| |Hardware | |
+=======================+========+==========+=======+===+======+======+======+=========+=========+=========+========+=========+=========+======+
|block_device_mappings |Yes | | | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|create_keypair | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|create_volume | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|delete_key | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|delete_keypair | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|delete_volume | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|get_image | | |Yes | | |Yes | | |Yes | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|get_ip | |Yes | | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|get_key | |Yes | | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|get_keyid | | |Yes | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|get_keypair | |Yes | | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|get_networkid | |Yes | | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|get_node | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|get_password | |Yes | | | | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|get_size | | |Yes | | |Yes | | | | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|get_spot_config | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|get_subnetid | | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|iam_profile |Yes | | |Yes| | | | | | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|import_key | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|key_list | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|keyname |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|list_availability_zones| | | |Yes| | | | | | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|list_custom_images | | | | | | | | | | | |Yes | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|list_keys | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|list_nodes |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|list_nodes_full |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|list_nodes_select |Yes |Yes |Yes |Yes|Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|list_vlans | | | | | | | | | | | |Yes |Yes | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|rackconnect | | | | | | | |Yes | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|reboot | | | |Yes| |Yes | | | | |[1] | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|reformat_node | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|securitygroup |Yes | | |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|securitygroupid | | | |Yes| | | | | | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|show_image | | | |Yes| | | | |Yes | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|show_key | | | | | |Yes | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|show_keypair | | |Yes |Yes| | | | | | | | | | |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
|show_volume | | | |Yes| | | | | | | | | |Yes |
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+--------+---------+---------+------+
[1] Yes, if salt-api is enabled.

View file

@ -129,6 +129,7 @@ Cloud Provider Specifics
Getting Started With Scaleway <scaleway>
Getting Started With Saltify <saltify>
Getting Started With SoftLayer <softlayer>
Getting Started With Vagrant <vagrant>
Getting Started With Vexxhost <vexxhost>
Getting Started With Virtualbox <virtualbox>
Getting Started With VMware <vmware>

View file

@ -1,3 +1,5 @@
.. _misc-salt-cloud-options:
================================
Miscellaneous Salt Cloud Options
================================

View file

@ -4,7 +4,7 @@
Getting Started With Saltify
============================
The Saltify driver is a new, experimental driver for installing Salt on existing
The Saltify driver is a driver for installing Salt on existing
machines (virtual or bare metal).
@ -33,20 +33,29 @@ the salt-master:
However, if you wish to use the more advanced capabilities of salt-cloud, such as
rebooting, listing, and disconnecting machines, then the salt master must fill
the role usually performed by a vendor's cloud management system. In order to do
that, you must configure your salt master as a salt-api server, and supply credentials
to use it. (See ``salt-api setup`` below.)
the role usually performed by a vendor's cloud management system. The salt master
must be running on the salt-cloud machine, and created nodes must be connected to the
master.
Additional information about which configuration options apply to which actions
can be studied in the
:ref:`Saltify Module documentation <saltify-module>`
and the
:ref:`Miscellaneous Salt Cloud Options <misc-salt-cloud-options>`
document.
Profiles
========
Saltify requires a profile to be configured for each machine that needs Salt
installed. The initial profile can be set up at ``/etc/salt/cloud.profiles``
Saltify requires a separate profile to be configured for each machine that
needs Salt installed [#]_. The initial profile can be set up at
``/etc/salt/cloud.profiles``
or in the ``/etc/salt/cloud.profiles.d/`` directory. Each profile requires
both an ``ssh_host`` and an ``ssh_username`` key parameter as well as either
an ``key_filename`` or a ``password``.
.. [#] Unless you are using a map file to provide the unique parameters.
Profile configuration example:
.. code-block:: yaml
@ -68,40 +77,78 @@ The machine can now be "Salted" with the following command:
This will install salt on the machine specified by the cloud profile,
``salt-this-machine``, and will give the machine the minion id of
``my-machine``. If the command was executed on the salt-master, its Salt
key will automatically be signed on the master.
key will automatically be accepted by the master.
Once a salt-minion has been successfully installed on the instance, connectivity
to it can be verified with Salt:
.. code-block:: bash
salt my-machine test.ping
salt my-machine test.version
Destroy Options
---------------
.. versionadded:: Oxygen
For obvious reasons, the ``destroy`` action does not actually vaporize hardware.
If the salt master is connected using salt-api, it can tear down parts of
the client machines. It will remove the client's key from the salt master,
and will attempt the following options:
If the salt master is connected, it can tear down parts of the client machines.
It will remove the client's key from the salt master,
and can execute the following options:
.. code-block:: yaml
- remove_config_on_destroy: true
# default: true
# Deactivate salt-minion on reboot and
# delete the minion config and key files from its ``/etc/salt`` directory,
# NOTE: If deactivation is unsuccessful (older Ubuntu machines) then when
# delete the minion config and key files from its "/etc/salt" directory,
# NOTE: If deactivation was unsuccessful (older Ubuntu machines) then when
# salt-minion restarts it will automatically create a new, unwanted, set
# of key files. The ``force_minion_config`` option must be used in that case.
# of key files. Use the "force_minion_config" option to replace them.
- shutdown_on_destroy: false
# default: false
# send a ``shutdown`` command to the client.
# last of all, send a "shutdown" command to the client.
Wake On LAN
-----------
.. versionadded:: Oxygen
In addition to connecting a hardware machine to a Salt master,
you have the option of sending a wake-on-LAN
`magic packet`_
to start that machine running.
.. _magic packet: https://en.wikipedia.org/wiki/Wake-on-LAN
The "magic packet" must be sent by an existing salt minion which is on
the same network segment as the target machine. (Or your router
must be set up especially to route WoL packets.) Your target machine
must be set up to listen for WoL and to respond appropriatly.
You must provide the Salt node id of the machine which will send
the WoL packet \(parameter ``wol_sender_node``\), and
the hardware MAC address of the machine you intend to wake,
\(parameter ``wake_on_lan_mac``\). If both parameters are defined,
the WoL will be sent. The cloud master will then sleep a while
\(parameter ``wol_boot_wait``) to give the target machine time to
boot up before we start probing its SSH port to begin deploying
Salt to it. The default sleep time is 30 seconds.
.. code-block:: yaml
# /etc/salt/cloud.profiles.d/saltify.conf
salt-this-machine:
ssh_host: 12.34.56.78
ssh_username: root
key_filename: '/etc/salt/mysshkey.pem'
provider: my-saltify-config
wake_on_lan_mac: '00:e0:4c:70:2a:b2' # found with ifconfig
wol_sender_node: bevymaster # its on this network segment
wol_boot_wait: 45 # seconds to sleep
Using Map Files
---------------
The settings explained in the section above may also be set in a map file. An
@ -165,67 +212,3 @@ Return values:
- ``True``: Credential verification succeeded
- ``False``: Credential verification succeeded
- ``None``: Credential verification was not attempted.
Provisioning salt-api
=====================
In order to query or control minions it created, saltify needs to send commands
to the salt master. It does that using the network interface to salt-api.
The salt-api is not enabled by default. The following example will provide a
simple installation.
.. code-block:: yaml
# file /etc/salt/cloud.profiles.d/my_saltify_profiles.conf
hw_41: # a theoretical example hardware machine
ssh_host: 10.100.9.41 # the hard address of your target
ssh_username: vagrant # a user name which has passwordless sudo
password: vagrant # on your target machine
provider: my_saltify_provider
.. code-block:: yaml
# file /etc/salt/cloud.providers.d/saltify_provider.conf
my_saltify_provider:
driver: saltify
eauth: pam
username: vagrant # supply some sudo-group-member's name
password: vagrant # and password on the salt master
minion:
master: 10.100.9.5 # the hard address of the master
.. code-block:: yaml
# file /etc/salt/master.d/auth.conf
# using salt-api ... members of the 'sudo' group can do anything ...
external_auth:
pam:
sudo%:
- .*
- '@wheel'
- '@runner'
- '@jobs'
.. code-block:: yaml
# file /etc/salt/master.d/api.conf
# see https://docs.saltstack.com/en/latest/ref/netapi/all/salt.netapi.rest_cherrypy.html
rest_cherrypy:
host: localhost
port: 8000
ssl_crt: /etc/pki/tls/certs/localhost.crt
ssl_key: /etc/pki/tls/certs/localhost.key
thread_pool: 30
socket_queue_size: 10
Start your target machine as a Salt minion named "node41" by:
.. code-block:: bash
$ sudo salt-cloud -p hw_41 node41

View file

@ -40,7 +40,7 @@ Set up an initial profile at /etc/salt/cloud.profiles or in the /etc/salt/cloud.
.. code-block:: yaml
scalewa-ubuntu:
scaleway-ubuntu:
provider: my-scaleway-config
image: Ubuntu Trusty (14.04 LTS)

View file

@ -94,6 +94,8 @@ Set up an initial profile at ``/etc/salt/cloud.profiles``:
private_vlan: 396
private_network: True
private_ssh: True
# Use a dedicated host instead of cloud
dedicated_host_id: 1234
# May be used _instead_of_ image
global_identifier: 320d8be5-46c0-dead-cafe-13e3c51
@ -334,9 +336,21 @@ it can be verified with Salt:
# salt 'myserver.example.com' test.ping
Cloud Profiles
Dedicated Host
~~~~~~~~~~~~~~
Soflayer allows the creation of new VMs in a dedicated host. This means that
you can order and pay a fixed amount for a bare metal dedicated host and use
it to provision as many VMs as you can fit in there. If you want your VMs to
be launched in a dedicated host, instead of Sofltayer's cloud, set the
``dedicated_host_id`` parameter in your profile.
dedicated_host_id
-----------------
The id of the dedicated host where the VMs should be created. If not set, VMs
will be created in Softlayer's cloud instead.
Bare metal Profiles
~~~~~~~~~~~~~~~~~~~
Set up an initial profile at ``/etc/salt/cloud.profiles``:
.. code-block:: yaml

View file

@ -0,0 +1,269 @@
.. _getting-started-with-vagrant:
============================
Getting Started With Vagrant
============================
The Vagrant driver is a new, experimental driver for spinning up a VagrantBox
virtual machine, and installing Salt on it.
Dependencies
============
The Vagrant driver itself has no external dependencies.
The machine which will host the VagrantBox must be an already existing minion
of the cloud server's Salt master.
It must have Vagrant_ installed, and a Vagrant-compatible virtual machine engine,
such as VirtualBox_.
(Note: The Vagrant driver does not depend on the salt-cloud VirtualBox driver in any way.)
.. _Vagrant: https://www.vagrantup.com/
.. _VirtualBox: https://www.virtualbox.org/
\[Caution: The version of Vagrant packaged for ``apt install`` in Ubuntu 16.04 will not connect a bridged
network adapter correctly. Use a version downloaded directly from the web site.\]
Include the Vagrant guest editions plugin:
``vagrant plugin install vagrant-vbguest``.
Configuration
=============
Configuration of the client virtual machine (using VirtualBox, VMware, etc)
will be done by Vagrant as specified in the Vagrantfile on the host machine.
Salt-cloud will push the commands to install and provision a salt minion on
the virtual machine, so you need not (perhaps **should** not) provision salt
in your Vagrantfile, in most cases.
If, however, your cloud master cannot open an SSH connection to the child VM,
you may **need** to let Vagrant provision the VM with Salt, and use some other
method (such as passing a pillar dictionary to the VM) to pass the master's
IP address to the VM. The VM can then attempt to reach the salt master in the
usual way for non-cloud minions. Specify the profile configuration argument
as ``deploy: False`` to prevent the cloud master from trying.
.. code-block:: yaml
# Note: This example is for /etc/salt/cloud.providers file or any file in
# the /etc/salt/cloud.providers.d/ directory.
my-vagrant-config:
minion:
master: 111.222.333.444
provider: vagrant
Because the Vagrant driver needs a place to store the mapping between the
node name you use for Salt commands and the Vagrantfile which controls the VM,
you must configure your salt minion as a Salt smb server.
(See `host provisioning example`_ below.)
Profiles
========
Vagrant requires a profile to be configured for each machine that needs Salt
installed. The initial profile can be set up at ``/etc/salt/cloud.profiles``
or in the ``/etc/salt/cloud.profiles.d/`` directory.
Each profile requires a ``vagrantfile`` parameter. If the Vagrantfile has
definitions for `multiple machines`_ then you need a ``machine`` parameter,
.. _`multiple machines`: https://www.vagrantup.com/docs/multi-machine/
Salt-cloud uses SSH to provision the minion. There must be a routable path
from the cloud master to the VM. Usually, you will want to use
a bridged network adapter for SSH. The address may not be known until
DHCP assigns it. If ``ssh_host`` is not defined, and ``target_network``
is defined, the driver will attempt to read the address from the output
of an ``ifconfig`` command. Lacking either setting,
the driver will try to use the value Vagrant returns as its ``ssh_host``,
which will work only if the cloud master is running somewhere on the same host.
The ``target_network`` setting should be used
to identify the IP network your bridged adapter is expected to appear on.
Use CIDR notation, like ``target_network: '2001:DB8::/32'``
or ``target_network: '192.0.2.0/24'``.
Profile configuration example:
.. code-block:: yaml
# /etc/salt/cloud.profiles.d/vagrant.conf
vagrant-machine:
host: my-vhost # the Salt id of the virtual machine's host computer.
provider: my-vagrant-config
cwd: /srv/machines # the path to your Virtualbox file.
vagrant_runas: my-username # the username who defined the Vagrantbox on the host
# vagrant_up_timeout: 300 # (seconds) timeout for cmd.run of the "vagrant up" command
# vagrant_provider: '' # option for "vagrant up" like: "--provider vmware_fusion"
# ssh_host: None # "None" means try to find the routable IP address from "ifconfig"
# ssh_username: '' # also required when ssh_host is used.
# target_network: None # Expected CIDR address range of your bridged network
# force_minion_config: false # Set "true" to re-purpose an existing VM
The machine can now be created and configured with the following command:
.. code-block:: bash
salt-cloud -p vagrant-machine my-id
This will create the machine specified by the cloud profile
``vagrant-machine``, and will give the machine the minion id of
``my-id``. If the cloud master is also the salt-master, its Salt
key will automatically be accepted on the master.
Once a salt-minion has been successfully installed on the instance, connectivity
to it can be verified with Salt:
.. code-block:: bash
salt my-id test.ping
.. _host provisioning example:
Provisioning a Vagrant cloud host (example)
===========================================
In order to query or control minions it created, each host
minion needs to track the Salt node names associated with
any guest virtual machines on it.
It does that using a Salt sdb database.
The Salt sdb is not configured by default. The following example shows a
simple installation.
This example assumes:
- you are on a large network using the 10.x.x.x IP address space
- your Salt master's Salt id is "bevymaster"
- it will also be your salt-cloud controller
- it is at hardware address 10.124.30.7
- it is running a recent Debian family Linux (raspbian)
- your workstation is a Salt minion of bevymaster
- your workstation's minion id is "my_laptop"
- VirtualBox has been installed on "my_laptop" (apt install is okay)
- Vagrant was installed from vagrantup.com. (not the 16.04 Ubuntu apt)
- "my_laptop" has done "vagrant plugin install vagrant-vbguest"
- the VM you want to start is on "my_laptop" at "/home/my_username/Vagrantfile"
.. code-block:: yaml
# file /etc/salt/minion.d/vagrant_sdb.conf on host computer "my_laptop"
# -- this sdb database is required by the Vagrant module --
vagrant_sdb_data: # The sdb database must have this name.
driver: sqlite3 # Let's use SQLite to store the data ...
database: /var/cache/salt/vagrant.sqlite # ... in this file ...
table: sdb # ... using this table name.
create_table: True # if not present
Remember to re-start your minion after changing its configuration files...
``sudo systemctl restart salt-minion``
.. code-block:: ruby
# -*- mode: ruby -*-
# file /home/my_username/Vagrantfile on host computer "my_laptop"
BEVY = "bevy1"
DOMAIN = BEVY + ".test" # .test is an ICANN reserved non-public TLD
# must supply a list of names to avoid Vagrant asking for interactive input
def get_good_ifc() # try to find a working Ubuntu network adapter name
addr_infos = Socket.getifaddrs
addr_infos.each do |info|
a = info.addr
if a and a.ip? and not a.ip_address.start_with?("127.")
return info.name
end
end
return "eth0" # fall back to an old reliable name
end
Vagrant.configure(2) do |config|
config.ssh.forward_agent = true # so you can use git ssh://...
# add a bridged network interface. (try to detect name, then guess MacOS names, too)
interface_guesses = [get_good_ifc(), 'en0: Ethernet', 'en1: Wi-Fi (AirPort)']
config.vm.network "public_network", bridge: interface_guesses
if ARGV[0] == "up"
puts "Trying bridge network using interfaces: #{interface_guesses}"
end
config.vm.provision "shell", inline: "ip address", run: "always" # make user feel good
# . . . . . . . . . . . . Define machine QUAIL1 . . . . . . . . . . . . . .
config.vm.define "quail1", primary: true do |quail_config|
quail_config.vm.box = "boxesio/xenial64-standard" # a public VMware & Virtualbox box
quail_config.vm.hostname = "quail1." + DOMAIN # supply a name in our bevy
quail_config.vm.provider "virtualbox" do |v|
v.memory = 1024 # limit memory for the virtual box
v.cpus = 1
v.linked_clone = true # make a soft copy of the base Vagrant box
v.customize ["modifyvm", :id, "--natnet1", "192.168.128.0/24"] # do not use 10.x network for NAT
end
end
end
.. code-block:: yaml
# file /etc/salt/cloud.profiles.d/my_vagrant_profiles.conf on bevymaster
q1:
host: my_laptop # the Salt id of your virtual machine host
machine: quail1 # a machine name in the Vagrantfile (if not primary)
vagrant_runas: my_username # owner of Vagrant box files on "my_laptop"
cwd: '/home/my_username' # the path (on "my_laptop") of the Vagrantfile
provider: my_vagrant_provider # name of entry in provider.conf file
target_network: '10.0.0.0/8' # VM external address will be somewhere here
.. code-block:: yaml
# file /etc/salt/cloud.providers.d/vagrant_provider.conf on bevymaster
my_vagrant_provider:
driver: vagrant
minion:
master: 10.124.30.7 # the hard address of the master
Create and use your new Salt minion
-----------------------------------
- Typing on the Salt master computer ``bevymaster``, tell it to create a new minion named ``v1`` using profile ``q1``...
.. code-block:: bash
sudo salt-cloud -p q1 v1
sudo salt v1 network.ip_addrs
[ you get a list of IP addresses, including the bridged one ]
- logged in to your laptop (or some other computer known to GitHub)...
\[NOTE:\] if you are using MacOS, you need to type ``ssh-add -K`` after each boot,
unless you use one of the methods in `this gist`_.
.. _this gist: https://github.com/jirsbek/SSH-keys-in-macOS-Sierra-keychain
.. code-block:: bash
ssh -A vagrant@< the bridged network address >
# [ or, if you are at /home/my_username/ on my_laptop ]
vagrant ssh quail1
- then typing on your new node "v1" (a.k.a. quail1.bevy1.test)...
.. code-block:: bash
password: vagrant
# [ stuff types out ... ]
ls -al /vagrant
# [ should be shared /home/my_username from my_laptop ]
# you can access other network facilities using the ssh authorization
# as recorded in your ~.ssh/ directory on my_laptop ...
sudo apt update
sudo apt install git
git clone ssh://git@github.com/yourID/your_project
# etc...

View file

@ -283,6 +283,10 @@ Set up an initial profile at ``/etc/salt/cloud.profiles`` or
thin_provision
Specifies whether the disk should be thin provisioned or not. Default is ``thin_provision: False``.
.. versionadded:: 2016.3.0
eagerly_scrub
Specifies whether the disk should be rewrite with zeros during thick provisioning or not.
Default is ``eagerly_scrub: False``.
.. versionadded:: Oxygen
controller
Specify the SCSI controller label to which this disk should be attached.
This should be specified only when creating both the specified SCSI

View file

@ -68,8 +68,8 @@ Each salt minion establishes a connection to the master Publisher.
EventPublisher
--------------
The EventPublisher publishes events onto the event bus. It is bound to the
following:
The EventPublisher publishes master events out to any event listeners. It is
bound to the following:
* IPC: master_event_pull.ipc
* IPC: master_event_pub.ipc
@ -110,48 +110,37 @@ The typical lifecycle of a salt job from the perspective of the master
might be as follows:
1) A command is issued on the CLI. For example, 'salt my_minion test.ping'.
2) The 'salt' command uses LocalClient to generate a request to the salt master
by connecting to the ReqServer on TCP:4506 and issuing the job.
3) The salt-master ReqServer sees the request and passes it to an available
MWorker over workers.ipc.
4) A worker picks up the request and handles it. First, it checks to ensure
that the requested user has permissions to issue the command. Then, it sends
the publish command to all connected minions. For the curious, this happens
in ClearFuncs.publish().
5) The worker announces on the master event bus that it is about to publish
a job to connected minions. This happens by placing the event on the master
event bus (master_event_pull.ipc) where the EventPublisher picks it up and
distributes it to all connected event listeners on master_event_pub.ipc.
6) The message to the minions is encrypted and sent to the Publisher via IPC
on publish_pull.ipc.
7) Connected minions have a TCP session established with the Publisher on TCP
port 4505 where they await commands. When the Publisher receives the job over
publish_pull, it sends the jobs across the wire to the minions for processing.
8) After the minions receive the request, they decrypt it and perform any
requested work, if they determine that they are targeted to do so.
9) When the minion is ready to respond, it publishes the result of its job back
to the master by sending the encrypted result back to the master on TCP 4506
where it is again picked up by the ReqServer and forwarded to an available
MWorker for processing. (Again, this happens by passing this message across
workers.ipc to an available worker.)
10) When the MWorker receives the job it decrypts it and fires an event onto
the master event bus (master_event_pull.ipc). (Again for the curious, this
happens in AESFuncs._return().
11) The EventPublisher sees this event and re-publishes it on the bus to all
connected listeners of the master event bus (on master_event_pub.ipc). This
is where the LocalClient has been waiting, listening to the event bus for
minion replies. It gathers the job and stores the result.
12) When all targeted minions have replied or the timeout has been exceeded,
the salt client displays the results of the job to the user on the CLI.
@ -167,8 +156,8 @@ Salt. It can either operate as a stand-alone daemon which accepts commands
locally via 'salt-call' or it can connect back to a master and receive commands
remotely.
When starting up, salt minions connect _back_ to a master defined in the minion
config file. The connect to two ports on the master:
When starting up, salt minions connect *back* to a master defined in the minion
config file. They connect to two ports on the master:
* TCP: 4505
This is the connection to the master Publisher. It is on this port that
@ -196,8 +185,8 @@ permissions can read or write to the bus as a common interface with the salt
minion.
Job Flow
--------
Minion Job Flow
---------------
When a salt minion starts up, it attempts to connect to the Publisher and the
ReqServer on the salt master. It then attempts to authenticate and once the
@ -206,28 +195,22 @@ minion has successfully authenticated, it simply listens for jobs.
Jobs normally come either come from the 'salt-call' script run by a local user
on the salt minion or they can come directly from a master.
Master Job Flow
---------------
The job flow on a minion, coming from the master via a 'salt' command is as
follows:
1) A master publishes a job that is received by a minion as outlined by the
master's job flow above.
2) The minion is polling its receive socket that's connected to the master
Publisher (TCP 4505 on master). When it detects an incoming message, it picks it
up from the socket and decrypts it.
3) A new minion process or thread is created and provided with the contents of the
decrypted message. The _thread_return() method is provided with the contents of
the received message.
4) The new minion thread is created. The _thread_return() function starts up
and actually calls out to the requested function contained in the job.
5) The requested function runs and returns a result. [Still in thread.]
6) The result of the function that's run is encrypted and returned to the
master's ReqServer (TCP 4506 on master). [Still in thread.]
7) Thread exits. Because the main thread was only blocked for the time that it
took to initialize the worker thread, many other requests could have been
received and processed during this time.
@ -241,6 +224,5 @@ clear and when they are passed using encryption. There are two rules governing
this behaviour:
1) ClearFuncs is used for intra-master communication and during the initial
authentication handshake between a minion and master during the key exhange.
authentication handshake between a minion and master during the key exchange.
2) AESFuncs is used everywhere else.

View file

@ -137,11 +137,11 @@ The second return value will be a string with two possible values:
Both before and after the installing the target(s), you should run
:strong:`list_pkgs` to obtain a list of the installed packages. You should then
return the output of ``salt.utils.compare_dicts()``
return the output of ``salt.utils.data.compare_dicts()``:
.. code-block:: python
return salt.utils.compare_dicts(old, new)
return salt.utils.data.compare_dicts(old, new)
remove

View file

@ -95,19 +95,19 @@ globally available or passed in through function arguments, file data, etc.
Mocking Loader Modules
----------------------
Salt loader modules use a series of globally available dunder variables,
``__salt__``, ``__opts__``, ``__pillar__``, etc. To facilitate testing these
modules a mixin class was created, ``LoaderModuleMockMixin`` which can be found
in ``tests/support/mixins.py``. The reason for the exitance of this class is
because, historycally, and because it was easier, one would add these dunder
variables directly on the imported module. This however, introduces unexpected
behavior when running the full test suite since those attributes would not be
removed once we were done testing the module and would therefor leak to other
modules being tested with unpredictable results. This is the kind of work that
should be defered to mock, and that's exactly what this mixin class does.
Salt loader modules use a series of globally available dunder variables,
``__salt__``, ``__opts__``, ``__pillar__``, etc. To facilitate testing these
modules a mixin class was created, ``LoaderModuleMockMixin`` which can be found
in ``tests/support/mixins.py``. The reason for the existance of this class is
because historiclly and because it was easier, one would add these dunder
variables directly on the imported module. This however, introduces unexpected
behavior when running the full test suite since those attributes would not be
removed once we were done testing the module and would therefore leak to other
modules being tested with unpredictable results. This is the kind of work that
should be deferred to mock, and that's exactly what this mixin class does.
As an example, if one needs to specify some options which should be available
to the module being tests one should do:
As an example, if one needs to specify some options which should be available
to the module being tested one should do:
.. code-block:: python
@ -122,8 +122,8 @@ to the module being tests one should do:
}
}
Consider this more extensive example from
``tests/unit/modules/test_libcloud_dns.py``::
Consider this more extensive example from
``tests/unit/modules/test_libcloud_dns.py``:
.. code-block:: python
@ -173,10 +173,10 @@ Consider this more extensive example from
return {libcloud_dns: module_globals}
What happens on the above example is that, we mock a call to
`__salt__['config.option']` to return the configuration needed for the
execution of the tests. Additionally, if the ``libcloud`` library is not
available, since that's not actually part of whats being tested, we mocked that
What happens in the above example is we mock a call to
`__salt__['config.option']` to return the configuration needed for the
execution of the tests. Additionally, if the ``libcloud`` library is not
available, since that's not actually part of what's being tested, we mocked that
import by patching ``sys.modules`` when tests are running.
@ -245,7 +245,7 @@ To understand how one might integrate Mock into writing a unit test for Salt,
let's imagine a scenario in which we're testing an execution module that's
designed to operate on a database. Furthermore, let's imagine two separate
methods, here presented in pseduo-code in an imaginary execution module called
'db.py.
'db.py'.
.. code-block:: python

View file

@ -246,6 +246,7 @@ Server configuration values and their defaults:
# Bind to LDAP anonymously to determine group membership
# Active Directory does not allow anonymous binds without special configuration
# In addition, if auth.ldap.anonymous is True, empty bind passwords are not permitted.
auth.ldap.anonymous: False
# FOR TESTING ONLY, this is a VERY insecure setting.
@ -285,7 +286,11 @@ and groups, it re-authenticates as the user running the Salt commands.
If you are already aware of the structure of your DNs and permissions in your LDAP store are set such that
users can look up their own group memberships, then the first and second users can be the same. To tell Salt this is
the case, omit the ``auth.ldap.bindpw`` parameter. You can template the ``binddn`` like this:
the case, omit the ``auth.ldap.bindpw`` parameter. Note this is not the same thing as using an anonymous bind.
Most LDAP servers will not permit anonymous bind, and as mentioned above, if `auth.ldap.anonymous` is False you
cannot use an empty password.
You can template the ``binddn`` like this:
.. code-block:: yaml

View file

@ -4,12 +4,25 @@ Event System
The Salt Event System is used to fire off events enabling third party
applications or external processes to react to behavior within Salt.
The event system uses a publish-subscribe pattern, otherwise know as pub/sub.
The event system is comprised of a two primary components:
Event Bus
=========
The event system is comprised of a two primary components, which make up the
concept of an Event Bus:
* The event sockets which publishes events.
* The event library which can listen to events and send events into the salt system.
Events are published onto the event bus and event bus subscribers listen for the
published events.
The event bus is used for both inter-process communication as well as network transport
in Salt. Inter-process communication is provided through UNIX domain sockets (UDX).
The Salt Master and each Salt Minion has their own event bus.
Event types
===========
@ -21,7 +34,7 @@ Event types
Listening for Events
====================
Salt's Event Bus is used heavily within Salt and it is also written to
Salt's event system is used heavily within Salt and it is also written to
integrate heavily with existing tooling and scripts. There is a variety of
ways to consume it.

View file

@ -45,11 +45,27 @@ but leave any existing config, cache, and PKI information.
Salt Minion Installation
========================
If the system is missing the appropriate version of the Visual C++
Redistributable (vcredist) the user will be prompted to install it. Click ``OK``
to install the vcredist. Click ``Cancel`` to abort the installation without
making modifications to the system.
If Salt is already installed on the system the user will be prompted to remove
the previous installation. Click ``OK`` to uninstall Salt without removing the
configuration, PKI information, or cached files. Click ``Cancel`` to abort the
installation before making any modifications to the system.
After the Welcome and the License Agreement, the installer asks for two bits of
information to configure the minion; the master hostname and the minion name.
The installer will update the minion config with these options. If the installer
finds an existing minion config file, these fields will be populated with values
from the existing config.
The installer will update the minion config with these options.
If the installer finds an existing minion config file, these fields will be
populated with values from the existing config, but they will be grayed out.
There will also be a checkbox to use the existing config. If you continue, the
existing config will be used. If the checkbox is unchecked, default values are
displayed and can be changed. If you continue, the existing config file in
``c:\salt\conf`` will be removed along with the ``c:\salt\conf\minion.d`
directory. The values entered will be used with the default config.
The final page allows you to start the minion service and optionally change its
startup type. By default, the minion is set to ``Automatic``. You can change the
@ -71,11 +87,6 @@ be managed there or from the command line like any other Windows service.
sc start salt-minion
net start salt-minion
.. note::
If the minion won't start, you may need to install the Microsoft Visual C++
2008 x64 SP1 redistributable. Allow all Windows updates to run salt-minion
smoothly.
Installation Prerequisites
--------------------------
@ -96,15 +107,29 @@ Minion silently:
========================= =====================================================
Option Description
========================= =====================================================
``/minion-name=`` A string value to set the minion name. Default is
'hostname'
``/master=`` A string value to set the IP address or host name of
the master. Default value is 'salt'
the master. Default value is 'salt'. You can pass a
single master or a comma-separated list of masters.
Setting the master will replace existing config with
the default config. Cannot be used in conjunction
with ``/use-existing-config``
``/minion-name=`` A string value to set the minion name. Default is
'hostname'. Setting the minion name will replace
existing config with the default config. Cannot be
used in conjunction with ``/use-existing-config``
``/start-minion=`` Either a 1 or 0. '1' will start the salt-minion
service, '0' will not. Default is to start the
service after installation.
service after installation
``/start-minion-delayed`` Set the minion start type to
``Automatic (Delayed Start)``
``/use-existing-config`` Either a 1 or 0. '1' will use the existing config if
present. '0' will replace existing config with the
default config. Default is '1'. If this is set to '1'
values passed in ``/master`` and ``/minion-name``
will be ignored
``/S`` Runs the installation silently. Uses the above
settings or the defaults
``/?`` Displays command line help
========================= =====================================================
.. note::

View file

@ -1727,7 +1727,7 @@ in the current Jinja context.
.. code-block:: jinja
Context is: {{ show_full_context() }}
Context is: {{ show_full_context()|yaml(False) }}
.. jinja_ref:: logs

View file

@ -4,9 +4,21 @@ Salt 2016.11.8 Release Notes
Version 2016.11.8 is a bugfix release for :ref:`2016.11.0 <release-2016-11-0>`.]
Anonymous Binds and LDAP/Active Directory
-----------------------------------------
When auth.ldap.anonymous is set to False, the bind password can no longer be empty.
Changes for v2016.11.7..v2016.11.8
----------------------------------
Security Fix
============
CVE-2017-14695 Directory traversal vulnerability in minion id validation in SaltStack. Allows remote minions with incorrect credentials to authenticate to a master via a crafted minion ID. Credit for discovering the security flaw goes to: Julian Brost (julian@0x4a42.net)
CVE-2017-14696 Remote Denial of Service with a specially crafted authentication request. Credit for discovering the security flaw goes to: Julian Brost (julian@0x4a42.net)
Extended changelog courtesy of Todd Stansell (https://github.com/tjstansell/salt-changelogs):
*Generated at: 2017-09-11T14:52:27Z*

View file

@ -0,0 +1,6 @@
============================
Salt 2016.11.9 Release Notes
============================
Version 2016.11.9 is a bugfix release for :ref:`2016.11.0 <release-2016-11-0>`.]

View file

@ -7,23 +7,9 @@ Version 2016.3.8 is a bugfix release for :ref:`2016.3.0 <release-2016-3-0>`.
Changes for v2016.3.7..v2016.3.8
--------------------------------
New master configuration option `allow_minion_key_revoke`, defaults to True. This option
controls whether a minion can request that the master revoke its key. When True, a minion
can request a key revocation and the master will comply. If it is False, the key will not
be revoked by the msater.
Security Fix
============
New master configuration option `require_minion_sign_messages`
This requires that minions cryptographically sign the messages they
publish to the master. If minions are not signing, then log this information
at loglevel 'INFO' and drop the message without acting on it.
CVE-2017-14695 Directory traversal vulnerability in minion id validation in SaltStack. Allows remote minions with incorrect credentials to authenticate to a master via a crafted minion ID. Credit for discovering the security flaw goes to: Julian Brost (julian@0x4a42.net)
New master configuration option `drop_messages_signature_fail`
Drop messages from minions when their signatures do not validate.
Note that when this option is False but `require_minion_sign_messages` is True
minions MUST sign their messages but the validity of their signatures
is ignored.
New minion configuration option `minion_sign_messages`
Causes the minion to cryptographically sign the payload of messages it places
on the event bus for the master. The payloads are signed with the minion's
private key so the master can verify the signature with its public key.
CVE-2017-14696 Remote Denial of Service with a specially crafted authentication request. Credit for discovering the security flaw goes to: Julian Brost (julian@0x4a42.net)

View file

@ -0,0 +1,29 @@
===========================
Salt 2016.3.9 Release Notes
===========================
Version 2016.3.9 is a bugfix release for :ref:`2016.3.0 <release-2016-3-0>`.
Changes for v2016.3.7..v2016.3.9
--------------------------------
New master configuration option `allow_minion_key_revoke`, defaults to True. This option
controls whether a minion can request that the master revoke its key. When True, a minion
can request a key revocation and the master will comply. If it is False, the key will not
be revoked by the msater.
New master configuration option `require_minion_sign_messages`
This requires that minions cryptographically sign the messages they
publish to the master. If minions are not signing, then log this information
at loglevel 'INFO' and drop the message without acting on it.
New master configuration option `drop_messages_signature_fail`
Drop messages from minions when their signatures do not validate.
Note that when this option is False but `require_minion_sign_messages` is True
minions MUST sign their messages but the validity of their signatures
is ignored.
New minion configuration option `minion_sign_messages`
Causes the minion to cryptographically sign the payload of messages it places
on the event bus for the master. The payloads are signed with the minion's
private key so the master can verify the signature with its public key.

View file

@ -7,18 +7,40 @@ Version 2017.7.2 is a bugfix release for :ref:`2017.7.0 <release-2017-7-0>`.
Changes for v2017.7.1..v2017.7.2
--------------------------------
Security Fix
============
CVE-2017-14695 Directory traversal vulnerability in minion id validation in SaltStack. Allows remote minions with incorrect credentials to authenticate to a master via a crafted minion ID. Credit for discovering the security flaw goes to: Julian Brost (julian@0x4a42.net)
CVE-2017-14696 Remote Denial of Service with a specially crafted authentication request. Credit for discovering the security flaw goes to: Julian Brost (julian@0x4a42.net)
Known Issues
============
On 2017.7.2 when using salt-api and cherrypy version 5.6.0, issue `#43581`_ will occur when starting the salt-api service. We have patched the cherry-py packages for python-cherrypy-5.6.0-2 from repo.saltstack.com. If you are using python-cherrypy-5.6.0-1 please ensure to run `yum install python-cherrypy` to install the new patched version.
Extended changelog courtesy of Todd Stansell (https://github.com/tjstansell/salt-changelogs):
*Generated at: 2017-09-26T21:06:19Z*
*Generated at: 2017-10-02T21:10:14Z*
Statistics:
Statistics
==========
- Total Merges: **326**
- Total Issue references: **133**
- Total PR references: **389**
- Total Merges: **328**
- Total Issue references: **134**
- Total PR references: **391**
Changes:
Changes
=======
- **PR** `#43868`_: (*rallytime*) Back-port `#43847`_ to 2017.7.2
* Fix to module.run
- **PR** `#43756`_: (*gtmanfred*) split build and install for pkg osx
@ *2017-09-26T20:51:28Z*
* 88414d5 Merge pull request `#43756`_ from gtmanfred/2017.7.2
* f7df41f split build and install for pkg osx
- **PR** `#43585`_: (*rallytime*) Back-port `#43330`_ to 2017.7.2
@ *2017-09-19T17:33:34Z*
@ -3097,6 +3119,13 @@ Changes:
.. _`#475`: https://github.com/saltstack/salt/issues/475
.. _`#480`: https://github.com/saltstack/salt/issues/480
.. _`#495`: https://github.com/saltstack/salt/issues/495
.. _`#43581`: https://github.com/saltstack/salt/issues/43581
.. _`#43756`: https://github.com/saltstack/salt/pull/43756
.. _`#43847`: https://github.com/saltstack/salt/pull/43847
.. _`#43868`: https://github.com/saltstack/salt/pull/43868
.. _`#475`: https://github.com/saltstack/salt/issues/475
.. _`#480`: https://github.com/saltstack/salt/issues/480
.. _`#495`: https://github.com/saltstack/salt/issues/495
.. _`bp-37424`: https://github.com/saltstack/salt/pull/37424
.. _`bp-39366`: https://github.com/saltstack/salt/pull/39366
.. _`bp-41543`: https://github.com/saltstack/salt/pull/41543

View file

@ -0,0 +1,6 @@
============================
Salt 2017.7.3 Release Notes
============================
Version 2017.7.3 is a bugfix release for :ref:`2017.7.0 <release-2017-7-0>`.

View file

@ -55,6 +55,13 @@ The new grains added are:
* ``fc_wwn``: Show all fibre channel world wide port names for a host
* ``iscsi_iqn``: Show the iSCSI IQN name for a host
* ``swap_total``: Show the configured swap_total for Linux, *BSD, OS X and Solaris/SunOS
Grains Changes
--------------
* The ``virtual`` grain identifies reports KVM and VMM hypervisors when running
an OpenBSD guest
New Modules
-----------
@ -110,6 +117,31 @@ The ``state_output`` parameter now supports ``full_id``, ``changes_id`` and ``te
Just like ``mixed_id``, these use the state ID as name in the highstate output.
For more information on these output modes, see the docs for the :mod:`Highstate Outputter <salt.output.highstate>`.
Windows Installer: Changes to existing config handling
------------------------------------------------------
Behavior with existing configuration has changed. With previous installers the
existing config was used and the master and minion id could be modified via the
installer. It was problematic in that it didn't account for configuration that
may be defined in the ``minion.d`` directory. This change gives you the option
via a checkbox to either use the existing config with out changes or the default
config using values you pass to the installer. If you choose to use the existing
config then no changes are made. If not, the existing config is deleted, to
include the ``minion.d`` directory, and the default config is used. A
command-line switch (``/use-existing-config``) has also been added to control
this behavior.
Windows Installer: Multi-master configuration
---------------------------------------------
The installer now has the ability to apply a multi-master configuration either
from the gui or the command line. The ``master`` field in the gui can accept
either a single master or a comma-separated list of masters. The command-line
switch (``/master=``) can accept the same.
Windows Installer: Command-line help
------------------------------------
The Windows installer will now display command-line help when a help switch
(``/?``) is passed.
Salt Cloud Features
-------------------
@ -132,6 +164,58 @@ file. For example:
These commands will run in sequence **before** the bootstrap script is executed.
New salt-cloud Grains
=====================
When salt cloud creates a new minon, it will now add grain information
to the minion configuration file, identifying the resources originally used
to create it.
The generated grain information will appear similar to:
.. code-block:: yaml
grains:
salt-cloud:
driver: ec2
provider: my_ec2:ec2
profile: ec2-web
The generation of salt-cloud grains can be surpressed by the
option ``enable_cloud_grains: 'False'`` in the cloud configuration file.
Upgraded Saltify Driver
=======================
The salt-cloud Saltify driver is used to provision machines which
are not controlled by a dedicated cloud supervisor (such as typical hardware
machines) by pushing a salt-bootstrap command to them and accepting them on
the salt master. Creation of a node has been its only function and no other
salt-cloud commands were implemented.
With this upgrade, it can use the salt-api to provide advanced control,
such as rebooting a machine, querying it along with conventional cloud minions,
and, ultimately, disconnecting it from its master.
After disconnection from ("destroying" on) one master, a machine can be
re-purposed by connecting to ("creating" on) a subsequent master.
New Vagrant Driver
==================
The salt-cloud Vagrant driver brings virtual machines running in a limited
environment, such as a programmer's workstation, under salt-cloud control.
This can be useful for experimentation, instruction, or testing salt configurations.
Using salt-api on the master, and a salt-minion running on the host computer,
the Vagrant driver can create (``vagrant up``), restart (``vagrant reload``),
and destroy (``vagrant destroy``) VMs, as controlled by salt-cloud profiles
which designate a ``Vagrantfile`` on the host machine.
The master can be a very limited machine, such as a Raspberry Pi, or a small
VagrantBox VM.
New pillar/master_tops module called saltclass
----------------------------------------------
@ -329,7 +413,7 @@ signed certificates. :ref:`Here<new-pywinrm>` for more information.
DigitalOcean
------------
The DigitalOcean driver has been renamed to conform to the companies name. The
The DigitalOcean driver has been renamed to conform to the company name. The
new driver name is ``digitalocean``. The old name ``digital_ocean`` and a
short one ``do`` will still be supported through virtual aliases, this is mostly
cosmetic.
@ -338,7 +422,7 @@ Solaris Logical Domains In Virtual Grain
----------------------------------------
Support has been added to the ``virtual`` grain for detecting Solaris LDOMs
running on T-Series SPARC hardware. The ``virtual_subtype`` grain is
running on T-Series SPARC hardware. The ``virtual_subtype`` grain is
populated as a list of domain roles.
Lists of comments in state returns
@ -353,7 +437,7 @@ Beacon configuration changes
In order to remain consistent and to align with other Salt components such as states,
support for configuring beacons using dictionary based configuration has been deprecated
in favor of list based configuration. All beacons have a validation function which will
in favor of list based configuration. All beacons have a validation function which will
check the configuration for the correct format and only load if the validation passes.
- ``avahi_announce`` beacon
@ -1014,3 +1098,10 @@ The ``version.py`` file had the following changes:
Warnings for moving away from the ``env`` option were removed. ``saltenv`` should be
used instead. The removal of these warnings does not have a behavior change. Only
the warning text was removed.
Sentry Log Handler
------------------
Configuring sentry raven python client via ``project``, ``servers``, ``public_key
and ``secret_key`` is deprecated and won't work with sentry clients > 3.0.
Instead, the ``dsn`` config param must be used.

View file

@ -29,6 +29,7 @@ the name of the repository, and the link to the repository:
For HTTP/HTTPS Basic authorization you can define credentials:
.. code-block:: yaml
my_repo:
url: https://spm.example.com/
username: user

View file

@ -164,7 +164,7 @@ states are evaluated before ``tgt`` states.
Each of these sections needs to be evaluated as text, rather than as YAML.
Consider the following block:
.. code-block::
.. code-block:: text
pre_local_state: >
echo test > /tmp/spmtest:
@ -187,7 +187,7 @@ a minion.
the ``>`` marker to denote that the state is evaluated as text, not a data
structure.
.. code-block::
.. code-block:: text
pre_local_state: >
echo test > /tmp/spmtest:
@ -203,7 +203,7 @@ the ``spm`` command is running on is a master.
Because ``tgt`` states require that a target be specified, their code blocks
are a little different. Consider the following state:
.. code-block::
.. code-block:: text
pre_tgt_state:
tgt: '*'
@ -229,7 +229,7 @@ This means that you can use Jinja or any other supported renderer inside of
Salt. All formula variables are available to the renderer, so you can reference
``FORMULA`` data inside your state if you need to:
.. code-block::
.. code-block:: text
pre_tgt_state:
tgt: '*'

View file

@ -34,7 +34,7 @@ passing on a single socket.
TLS Support
===========
.. version_added:: 2016.11.1
.. versionadded:: 2016.11.1
The TCP transport allows for the master/minion communication to be optionally
wrapped in a TLS connection. Enabling this is simple, the master and minion need

View file

@ -141,7 +141,7 @@ If the master seems to be unresponsive, a SIGUSR1 can be passed to the
salt-master threads to display what piece of code is executing. This debug
information can be invaluable in tracking down bugs.
To pass a SIGUSR1 to the master, first make sure the minion is running in the
To pass a SIGUSR1 to the master, first make sure the master is running in the
foreground. Stop the service if it is running as a daemon, and start it in the
foreground like so:

View file

@ -27,7 +27,7 @@ Installing Dependencies
=======================
Both pygit2_ and GitPython_ are supported Python interfaces to git. If
compatible versions of both are installed, pygit2_ will preferred. In these
compatible versions of both are installed, pygit2_ will be preferred. In these
cases, GitPython_ can be forced using the :conf_master:`gitfs_provider`
parameter in the master config file.

View file

@ -33,3 +33,5 @@ Tutorials Index
* :ref:`SaltStack Walk-through <tutorial-salt-walk-through>`
* :ref:`Writing Salt Tests <tutorial-salt-testing>`
* :ref:`Multi-cloud orchestration with Apache Libcloud <tutorial-libcloud>`
* :ref:`Running Salt States and Commands in Docker Containers <docker-sls>`
* :ref:`Preseed Minion with Accepted Key <tutorial-preseed-key>`

View file

@ -260,14 +260,11 @@ the retention time defined by
250 jobs/day * 2000 minions returns = 500,000 files a day
If no job history is needed, the job cache can be disabled:
Use and External Job Cache
~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: yaml
job_cache: False
If the job cache is necessary there are (currently) 2 options:
An external job cache allows for job storage to be placed on an external
system, such as a database.
- ext_job_cache: this will have the minions store their return data directly
into a returner (not sent through the Master)
@ -287,3 +284,20 @@ for up to sixty seconds by default.
To enable the master key cache, set `key_cache: 'sched'` in the master
configuration file.
Disable The Job Cache
~~~~~~~~~~~~~~~~~~~~~
The job cache is a central component of the Salt Master and many aspects of
the Salt Master will not function correctly without a running job cache.
Disabling the job cache is **STRONGLY DISCOURAGED** and should not be done
unless the master is being used to execute routines that require no history
or reliable feedback!
The job cache can be disabled:
.. code-block:: yaml
job_cache: False

View file

@ -23,7 +23,7 @@ Supported Operating Systems
.. note::
In the event you do not see your distribution or version available please
review the develop branch on GitHub as it main contain updates that are
review the develop branch on GitHub as it may contain updates that are
not present in the stable release:
https://github.com/saltstack/salt-bootstrap/tree/develop

View file

@ -88,7 +88,8 @@ sudo $PKGRESOURCES/build_env.sh $PYVER
echo -n -e "\033]0;Build: Install Salt\007"
sudo rm -rf $SRCDIR/build
sudo rm -rf $SRCDIR/dist
sudo $PYTHON $SRCDIR/setup.py build -e "$PYTHON -E -s" install
sudo $PYTHON $SRCDIR/setup.py build -e "$PYTHON -E -s"
sudo $PYTHON $SRCDIR/setup.py install
############################################################################
# Build Package

View file

@ -11,6 +11,7 @@
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
!define PRODUCT_UNINST_KEY_OTHER "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME_OTHER}"
!define PRODUCT_UNINST_ROOT_KEY "HKLM"
!define OUTFILE "Salt-Minion-${PRODUCT_VERSION}-Py${PYTHON_VERSION}-${CPUARCH}-Setup.exe"
# Import Libraries
!include "MUI2.nsh"
@ -52,6 +53,15 @@ ${StrStrAdv}
Pop "${ResultVar}"
!macroend
# Part of the Explode function for Strings
!define Explode "!insertmacro Explode"
!macro Explode Length Separator String
Push `${Separator}`
Push `${String}`
Call Explode
Pop `${Length}`
!macroend
###############################################################################
# Configure Pages, Ordering, and Configuration
@ -92,10 +102,17 @@ Var Dialog
Var Label
Var CheckBox_Minion_Start
Var CheckBox_Minion_Start_Delayed
Var ConfigMasterHost
Var MasterHost
Var MasterHost_State
Var ConfigMinionName
Var MinionName
Var MinionName_State
Var ExistingConfigFound
Var UseExistingConfig
Var UseExistingConfig_State
Var WarningExistingConfig
Var WarningDefaultConfig
Var StartMinion
Var StartMinionDelayed
Var DeleteInstallDir
@ -115,27 +132,105 @@ Function pageMinionConfig
Abort
${EndIf}
# Master IP or Hostname Dialog Control
${NSD_CreateLabel} 0 0 100% 12u "Master IP or Hostname:"
Pop $Label
${NSD_CreateText} 0 13u 100% 12u $MasterHost_State
Pop $MasterHost
# Minion ID Dialog Control
${NSD_CreateLabel} 0 30u 100% 12u "Minion Name:"
Pop $Label
${NSD_CreateText} 0 43u 100% 12u $MinionName_State
Pop $MinionName
# Use Existing Config Checkbox
${NSD_CreateCheckBox} 0 65u 100% 12u "&Use Existing Config"
Pop $UseExistingConfig
${NSD_OnClick} $UseExistingConfig pageMinionConfig_OnClick
# Add Existing Config Warning Label
${NSD_CreateLabel} 0 80u 100% 60u "The values above are taken from an \
existing configuration found in `c:\salt\conf\minion`. Configuration \
settings defined in the `minion.d` directories, if they exist, are not \
shown here.$\r$\n\
$\r$\n\
Clicking `Install` will leave the existing config unchanged."
Pop $WarningExistingConfig
CreateFont $0 "Arial" 10 500 /ITALIC
SendMessage $WarningExistingConfig ${WM_SETFONT} $0 1
SetCtlColors $WarningExistingConfig 0xBB0000 transparent
# Add Default Config Warning Label
${NSD_CreateLabel} 0 80u 100% 60u "Clicking `Install` will remove the \
the existing minion config file and remove the minion.d directories. \
The values above will be used in the new default config."
Pop $WarningDefaultConfig
CreateFont $0 "Arial" 10 500 /ITALIC
SendMessage $WarningDefaultConfig ${WM_SETFONT} $0 1
SetCtlColors $WarningDefaultConfig 0xBB0000 transparent
# If no existing config found, disable the checkbox and stuff
# Set UseExistingConfig_State to 0
${If} $ExistingConfigFound == 0
StrCpy $UseExistingConfig_State 0
ShowWindow $UseExistingConfig ${SW_HIDE}
ShowWindow $WarningExistingConfig ${SW_HIDE}
ShowWindow $WarningDefaultConfig ${SW_HIDE}
${Endif}
${NSD_SetState} $UseExistingConfig $UseExistingConfig_State
Call pageMinionConfig_OnClick
nsDialogs::Show
FunctionEnd
Function pageMinionConfig_OnClick
# You have to pop the top handle to keep the stack clean
Pop $R0
# Assign the current checkbox state to the variable
${NSD_GetState} $UseExistingConfig $UseExistingConfig_State
# Validate the checkboxes
${If} $UseExistingConfig_State == ${BST_CHECKED}
# Use Existing Config is checked, show warning
ShowWindow $WarningExistingConfig ${SW_SHOW}
EnableWindow $MasterHost 0
EnableWindow $MinionName 0
${NSD_SetText} $MasterHost $ConfigMasterHost
${NSD_SetText} $MinionName $ConfigMinionName
${If} $ExistingConfigFound == 1
ShowWindow $WarningDefaultConfig ${SW_HIDE}
${Endif}
${Else}
# Use Existing Config is not checked, hide the warning
ShowWindow $WarningExistingConfig ${SW_HIDE}
EnableWindow $MasterHost 1
EnableWindow $MinionName 1
${NSD_SetText} $MasterHost $MasterHost_State
${NSD_SetText} $MinionName $MinionName_State
${If} $ExistingConfigFound == 1
ShowWindow $WarningDefaultConfig ${SW_SHOW}
${Endif}
${EndIf}
FunctionEnd
Function pageMinionConfig_Leave
${NSD_GetText} $MasterHost $MasterHost_State
${NSD_GetText} $MinionName $MinionName_State
${NSD_GetState} $UseExistingConfig $UseExistingConfig_State
Call RemoveExistingConfig
FunctionEnd
@ -194,7 +289,7 @@ FunctionEnd
!else
Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
!endif
OutFile "Salt-Minion-${PRODUCT_VERSION}-Py${PYTHON_VERSION}-${CPUARCH}-Setup.exe"
OutFile "${OutFile}"
InstallDir "c:\salt"
InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" ""
ShowInstDetails show
@ -311,8 +406,6 @@ SectionEnd
Function .onInit
Call getMinionConfig
Call parseCommandLineSwitches
# Check for existing installation
@ -364,6 +457,23 @@ Function .onInit
skipUninstall:
Call getMinionConfig
IfSilent 0 +2
Call RemoveExistingConfig
FunctionEnd
Function RemoveExistingConfig
${If} $ExistingConfigFound == 1
${AndIf} $UseExistingConfig_State == 0
# Wipe out the Existing Config
Delete "$INSTDIR\conf\minion"
RMDir /r "$INSTDIR\conf\minion.d"
${EndIf}
FunctionEnd
@ -407,7 +517,9 @@ Section -Post
nsExec::Exec "nssm.exe set salt-minion AppStopMethodConsole 24000"
nsExec::Exec "nssm.exe set salt-minion AppStopMethodWindow 2000"
Call updateMinionConfig
${If} $UseExistingConfig_State == 0
Call updateMinionConfig
${EndIf}
Push "C:\salt"
Call AddToPath
@ -534,18 +646,32 @@ FunctionEnd
# Helper Functions
###############################################################################
Function MsiQueryProductState
# Used for detecting VCRedist Installation
!define INSTALLSTATE_DEFAULT "5"
!define INSTALLSTATE_DEFAULT "5"
Pop $R0
StrCpy $NeedVcRedist "False"
System::Call "msi::MsiQueryProductStateA(t '$R0') i.r0"
StrCmp $0 ${INSTALLSTATE_DEFAULT} +2 0
StrCpy $NeedVcRedist "True"
Pop $R0
StrCpy $NeedVcRedist "False"
System::Call "msi::MsiQueryProductStateA(t '$R0') i.r0"
StrCmp $0 ${INSTALLSTATE_DEFAULT} +2 0
StrCpy $NeedVcRedist "True"
FunctionEnd
#------------------------------------------------------------------------------
# Trim Function
# - Trim whitespace from the beginning and end of a string
# - Trims spaces, \r, \n, \t
#
# Usage:
# Push " some string " ; String to Trim
# Call Trim
# Pop $0 ; Trimmed String: "some string"
#
# or
#
# ${Trim} $0 $1 ; Trimmed String, String to Trim
#------------------------------------------------------------------------------
Function Trim
Exch $R1 # Original string
@ -580,6 +706,95 @@ Function Trim
FunctionEnd
#------------------------------------------------------------------------------
# Explode Function
# - Splits a string based off the passed separator
# - Each item in the string is pushed to the stack
# - The last item pushed to the stack is the length of the array
#
# Usage:
# Push "," ; Separator
# Push "string,to,separate" ; String to explode
# Call Explode
# Pop $0 ; Number of items in the array
#
# or
#
# ${Explode} $0 $1 $2 ; Length, Separator, String
#------------------------------------------------------------------------------
Function Explode
# Initialize variables
Var /GLOBAL explString
Var /GLOBAL explSeparator
Var /GLOBAL explStrLen
Var /GLOBAL explSepLen
Var /GLOBAL explOffset
Var /GLOBAL explTmp
Var /GLOBAL explTmp2
Var /GLOBAL explTmp3
Var /GLOBAL explArrCount
# Get input from user
Pop $explString
Pop $explSeparator
# Calculates initial values
StrLen $explStrLen $explString
StrLen $explSepLen $explSeparator
StrCpy $explArrCount 1
${If} $explStrLen <= 1 # If we got a single character
${OrIf} $explSepLen > $explStrLen # or separator is larger than the string,
Push $explString # then we return initial string with no change
Push 1 # and set array's length to 1
Return
${EndIf}
# Set offset to the last symbol of the string
StrCpy $explOffset $explStrLen
IntOp $explOffset $explOffset - 1
# Clear temp string to exclude the possibility of appearance of occasional data
StrCpy $explTmp ""
StrCpy $explTmp2 ""
StrCpy $explTmp3 ""
# Loop until the offset becomes negative
${Do}
# If offset becomes negative, it is time to leave the function
${IfThen} $explOffset == -1 ${|} ${ExitDo} ${|}
# Remove everything before and after the searched part ("TempStr")
StrCpy $explTmp $explString $explSepLen $explOffset
${If} $explTmp == $explSeparator
# Calculating offset to start copy from
IntOp $explTmp2 $explOffset + $explSepLen # Offset equals to the current offset plus length of separator
StrCpy $explTmp3 $explString "" $explTmp2
Push $explTmp3 # Throwing array item to the stack
IntOp $explArrCount $explArrCount + 1 # Increasing array's counter
StrCpy $explString $explString $explOffset 0 # Cutting all characters beginning with the separator entry
StrLen $explStrLen $explString
${EndIf}
${If} $explOffset = 0 # If the beginning of the line met and there is no separator,
# copying the rest of the string
${If} $explSeparator == "" # Fix for the empty separator
IntOp $explArrCount $explArrCount - 1
${Else}
Push $explString
${EndIf}
${EndIf}
IntOp $explOffset $explOffset - 1
${Loop}
Push $explArrCount
FunctionEnd
#------------------------------------------------------------------------------
# StrStr Function
# - find substring in a string
@ -816,6 +1031,9 @@ FunctionEnd
###############################################################################
Function getMinionConfig
# Set Config Found Default Value
StrCpy $ExistingConfigFound 0
confFind:
IfFileExists "$INSTDIR\conf\minion" confFound confNotFound
@ -828,24 +1046,42 @@ Function getMinionConfig
${EndIf}
confFound:
StrCpy $ExistingConfigFound 1
FileOpen $0 "$INSTDIR\conf\minion" r
ClearErrors
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
ClearErrors # Clear Errors
FileRead $0 $1 # Read the next line
IfErrors EndOfFile # Error is probably EOF
${StrLoc} $2 $1 "master:" ">" # Find `master:` starting at the beginning
${If} $2 == 0 # If it found it in the first position, then it is defined
${StrStrAdv} $2 $1 "master: " ">" ">" "0" "0" "0" # Read everything after `master: `
${Trim} $2 $2 # Trim white space
${If} $2 == "" # If it's empty, it's probably a list
masterLoop:
ClearErrors # Clear Errors
FileRead $0 $1 # Read the next line
IfErrors EndOfFile # Error is probably EOF
${StrStrAdv} $2 $1 "- " ">" ">" "0" "0" "0" # Read everything after `- `
${Trim} $2 $2 # Trim white space
${IfNot} $2 == "" # If it's not empty, we found something
${If} $ConfigMasterHost == "" # Is the default `salt` there
StrCpy $ConfigMasterHost $2 # If so, make the first item the new entry
${Else}
StrCpy $ConfigMasterHost "$ConfigMasterHost,$2" # Append the new master, comma separated
${EndIf}
Goto masterLoop # Check the next one
${EndIf}
${Else}
StrCpy $ConfigMasterHost $2 # A single master entry
${EndIf}
${EndIf}
${StrLoc} $2 $1 "id:" ">"
${If} $2 == 0
${StrStrAdv} $2 $1 "id: " ">" ">" "0" "0" "0"
${Trim} $2 $2
StrCpy $MinionName_State $2
StrCpy $ConfigMinionName $2
${EndIf}
Goto confLoop
@ -855,6 +1091,14 @@ Function getMinionConfig
confReallyNotFound:
# Set Default Config Values if not found
${If} $ConfigMasterHost == ""
StrCpy $ConfigMasterHost "salt"
${EndIf}
${If} $ConfigMinionName == ""
StrCpy $ConfigMinionName "hostname"
${EndIf}
FunctionEnd
@ -874,7 +1118,22 @@ Function updateMinionConfig
${StrLoc} $3 $2 "master:" ">" # where is 'master:' in this line
${If} $3 == 0 # is it in the first...
${OrIf} $3 == 1 # or second position (account for comments)
StrCpy $2 "master: $MasterHost_State$\r$\n" # write the master
${Explode} $9 "," $MasterHost_state # Split the hostname on commas, $9 is the number of items found
${If} $9 == 1 # 1 means only a single master was passed
StrCpy $2 "master: $MasterHost_State$\r$\n" # write the master
${Else} # Make a multi-master entry
StrCpy $2 "master:" # Make the first line "master:"
loop_explode: # Start a loop to go through the list in the config
pop $8 # Pop the next item off the stack
${Trim} $8 $8 # Trim any whitespace
StrCpy $2 "$2$\r$\n - $8" # Add it to the master variable ($2)
IntOp $9 $9 - 1 # Decrement the list count
${If} $9 >= 1 # If it's not 0
Goto loop_explode # Do it again
${EndIf} # close if statement
${EndIf} # close if statement
${EndIf} # close if statement
${EndIf} # close if statement
@ -905,6 +1164,67 @@ Function parseCommandLineSwitches
# Load the parameters
${GetParameters} $R0
# Display Help
ClearErrors
${GetOptions} $R0 "/?" $R1
IfErrors display_help_not_found
System::Call 'kernel32::GetStdHandle(i -11)i.r0'
System::Call 'kernel32::AttachConsole(i -1)i.r1'
${If} $0 = 0
${OrIf} $1 = 0
System::Call 'kernel32::AllocConsole()'
System::Call 'kernel32::GetStdHandle(i -11)i.r0'
${EndIf}
FileWrite $0 "$\n"
FileWrite $0 "$\n"
FileWrite $0 "Help for Salt Minion installation$\n"
FileWrite $0 "===============================================================================$\n"
FileWrite $0 "$\n"
FileWrite $0 "/minion-name=$\t$\tA string value to set the minion name. Default is$\n"
FileWrite $0 "$\t$\t$\t'hostname'. Setting the minion name will replace$\n"
FileWrite $0 "$\t$\t$\texisting config with a default config. Cannot be$\n"
FileWrite $0 "$\t$\t$\tused in conjunction with /use-existing-config=1$\n"
FileWrite $0 "$\n"
FileWrite $0 "/master=$\t$\tA string value to set the IP address or hostname of$\n"
FileWrite $0 "$\t$\t$\tthe master. Default value is 'salt'. You may pass a$\n"
FileWrite $0 "$\t$\t$\tsingle master, or a comma separated list of masters.$\n"
FileWrite $0 "$\t$\t$\tSetting the master will replace existing config with$\n"
FileWrite $0 "$\t$\t$\ta default config. Cannot be used in conjunction with$\n"
FileWrite $0 "$\t$\t$\t/use-existing-config=1$\n"
FileWrite $0 "$\n"
FileWrite $0 "/start-minion=$\t$\t1 will start the service, 0 will not. Default is 1$\n"
FileWrite $0 "$\n"
FileWrite $0 "/start-minion-delayed$\tSet the minion start type to 'Automatic (Delayed Start)'$\n"
FileWrite $0 "$\n"
FileWrite $0 "/use-existing-config=$\t1 will use the existing config if present, 0 will$\n"
FileWrite $0 "$\t$\t$\treplace existing config with a default config. Default$\n"
FileWrite $0 "$\t$\t$\tis 1. If this is set to 1, values passed in$\n"
FileWrite $0 "$\t$\t$\t/minion-name and /master will be ignored$\n"
FileWrite $0 "$\n"
FileWrite $0 "/S$\t$\t$\tInstall Salt silently$\n"
FileWrite $0 "$\n"
FileWrite $0 "/?$\t$\t$\tDisplay this help screen$\n"
FileWrite $0 "$\n"
FileWrite $0 "-------------------------------------------------------------------------------$\n"
FileWrite $0 "$\n"
FileWrite $0 "Examples:$\n"
FileWrite $0 "$\n"
FileWrite $0 "${OutFile} /S$\n"
FileWrite $0 "$\n"
FileWrite $0 "${OutFile} /S /minion-name=myminion /master=master.mydomain.com /start-minion-delayed$\n"
FileWrite $0 "$\n"
FileWrite $0 "===============================================================================$\n"
FileWrite $0 "Press Enter to continue..."
System::Free $0
System::Free $1
System::Call 'kernel32::FreeConsole()'
Abort
display_help_not_found:
# Set default value for Use Existing Config
StrCpy $UseExistingConfig_State 1
# Check for start-minion switches
# /start-service is to be deprecated, so we must check for both
${GetOptions} $R0 "/start-service=" $R1
@ -930,19 +1250,31 @@ Function parseCommandLineSwitches
start_minion_delayed_not_found:
# Minion Config: Master IP/Name
# If setting master, we don't want to use existing config
${GetOptions} $R0 "/master=" $R1
${IfNot} $R1 == ""
StrCpy $MasterHost_State $R1
StrCpy $UseExistingConfig_State 0
${ElseIf} $MasterHost_State == ""
StrCpy $MasterHost_State "salt"
${EndIf}
# Minion Config: Minion ID
# If setting minion id, we don't want to use existing config
${GetOptions} $R0 "/minion-name=" $R1
${IfNot} $R1 == ""
StrCpy $MinionName_State $R1
StrCpy $UseExistingConfig_State 0
${ElseIf} $MinionName_State == ""
StrCpy $MinionName_State "hostname"
${EndIf}
# Use Existing Config
# Overrides above settings with user passed settings
${GetOptions} $R0 "/use-existing-config=" $R1
${IfNot} $R1 == ""
# Use Existing Config was passed something, set it
StrCpy $UseExistingConfig_State $R1
${EndIf}
FunctionEnd

View file

@ -9,3 +9,4 @@ SaltPyLint>=v2017.3.6
pytest
git+https://github.com/eisensheng/pytest-catchlog.git@develop#egg=Pytest-catchlog
git+https://github.com/saltstack/pytest-salt.git@master#egg=pytest-salt
testinfra>=1.7.0

View file

@ -13,3 +13,5 @@ httpretty
SaltPyLint>=v2017.2.29
pytest
git+https://github.com/saltstack/pytest-salt.git@master#egg=pytest-salt
git+https://github.com/eisensheng/pytest-catchlog.git@develop#egg=Pytest-catchlog
testinfra>=1.7.0

View file

@ -12,7 +12,7 @@ found by reading the salt documentation:
from __future__ import absolute_import
# Import salt libs
import salt.utils
import salt.utils.stringutils
# Import 3rd-party libs
from salt.ext import six
@ -31,13 +31,13 @@ class PublisherACL(object):
Takes a username as a string and returns a boolean. True indicates that
the provided user has been blacklisted
'''
return not salt.utils.check_whitelist_blacklist(user, blacklist=self.blacklist.get('users', []))
return not salt.utils.stringutils.check_whitelist_blacklist(user, blacklist=self.blacklist.get('users', []))
def cmd_is_blacklisted(self, cmd):
# If this is a regular command, it is a single function
if isinstance(cmd, six.string_types):
cmd = [cmd]
for fun in cmd:
if not salt.utils.check_whitelist_blacklist(fun, blacklist=self.blacklist.get('modules', [])):
if not salt.utils.stringutils.check_whitelist_blacklist(fun, blacklist=self.blacklist.get('modules', [])):
return True
return False

View file

@ -6,8 +6,6 @@ This system allows for authentication to be managed in a module pluggable way
so that any external authentication system can be used inside of Salt
'''
from __future__ import absolute_import
# 1. Create auth loader instance
# 2. Accept arguments as a dict
# 3. Verify with function introspection
@ -16,7 +14,7 @@ from __future__ import absolute_import
# 6. Interface to verify tokens
# Import python libs
from __future__ import print_function
from __future__ import absolute_import, print_function
import collections
import time
import logging
@ -28,12 +26,13 @@ from salt.ext.six.moves import input
import salt.config
import salt.loader
import salt.transport.client
import salt.utils
import salt.utils.args
import salt.utils.dictupdate
import salt.utils.files
import salt.utils.minions
import salt.utils.versions
import salt.utils.user
import salt.utils.versions
import salt.utils.zeromq
import salt.payload
log = logging.getLogger(__name__)
@ -88,9 +87,10 @@ class LoadAuth(object):
fstr = '{0}.auth'.format(load['eauth'])
if fstr not in self.auth:
return False
fcall = salt.utils.format_call(self.auth[fstr],
load,
expected_extra_kws=AUTH_INTERNAL_KEYWORDS)
fcall = salt.utils.args.format_call(
self.auth[fstr],
load,
expected_extra_kws=AUTH_INTERNAL_KEYWORDS)
try:
if 'kwargs' in fcall:
return self.auth[fstr](*fcall['args'], **fcall['kwargs'])
@ -134,9 +134,10 @@ class LoadAuth(object):
fstr = '{0}.acl'.format(mod)
if fstr not in self.auth:
return None
fcall = salt.utils.format_call(self.auth[fstr],
load,
expected_extra_kws=AUTH_INTERNAL_KEYWORDS)
fcall = salt.utils.args.format_call(
self.auth[fstr],
load,
expected_extra_kws=AUTH_INTERNAL_KEYWORDS)
try:
return self.auth[fstr](*fcall['args'], **fcall['kwargs'])
except Exception as e:
@ -169,9 +170,10 @@ class LoadAuth(object):
fstr = '{0}.groups'.format(load['eauth'])
if fstr not in self.auth:
return False
fcall = salt.utils.format_call(self.auth[fstr],
load,
expected_extra_kws=AUTH_INTERNAL_KEYWORDS)
fcall = salt.utils.args.format_call(
self.auth[fstr],
load,
expected_extra_kws=AUTH_INTERNAL_KEYWORDS)
try:
return self.auth[fstr](*fcall['args'], **fcall['kwargs'])
except IndexError:
@ -426,13 +428,28 @@ class LoadAuth(object):
auth_list = self.get_auth_list(load)
elif auth_type == 'user':
if not self.authenticate_key(load, key):
auth_ret = self.authenticate_key(load, key)
msg = 'Authentication failure of type "user" occurred'
if not auth_ret: # auth_ret can be a boolean or the effective user id
if show_username:
msg = 'Authentication failure of type "user" occurred for user {0}.'.format(username)
else:
msg = 'Authentication failure of type "user" occurred'
msg = '{0} for user {1}.'.format(msg, username)
ret['error'] = {'name': 'UserAuthenticationError', 'message': msg}
return ret
# Verify that the caller has root on master
if auth_ret is not True:
if AuthUser(load['user']).is_sudo():
if not self.opts['sudo_acl'] or not self.opts['publisher_acl']:
auth_ret = True
if auth_ret is not True:
# Avoid a circular import
import salt.utils.master
auth_list = salt.utils.master.get_values_of_matching_keys(
self.opts['publisher_acl'], auth_ret)
if not auth_list:
ret['error'] = {'name': 'UserAuthenticationError', 'message': msg}
return ret
else:
ret['error'] = {'name': 'SaltInvocationError',
'message': 'Authentication type not supported.'}
@ -653,7 +670,7 @@ class Resolver(object):
def _send_token_request(self, load):
if self.opts['transport'] in ('zeromq', 'tcp'):
master_uri = 'tcp://' + salt.utils.ip_bracket(self.opts['interface']) + \
master_uri = 'tcp://' + salt.utils.zeromq.ip_bracket(self.opts['interface']) + \
':' + str(self.opts['ret_port'])
channel = salt.transport.client.ReqChannel.factory(self.opts,
crypt='clear',

View file

@ -110,6 +110,10 @@ class _LDAPConnection(object):
self.ldap.set_option(ldap.OPT_REFERRALS, 0) # Needed for AD
if not anonymous:
if self.bindpw is None or len(self.bindpw) < 1:
raise CommandExecutionError(
'LDAP bind password is not set: password cannot be empty if auth.ldap.anonymous is False'
)
self.ldap.simple_bind_s(self.binddn, self.bindpw)
except Exception as ldap_error:
raise CommandExecutionError(

View file

@ -10,7 +10,7 @@ import re
# Import Salt libs
import salt.loader
import salt.utils
import salt.utils.event
import salt.utils.minion
from salt.ext.six.moves import map
from salt.exceptions import CommandExecutionError
@ -199,13 +199,42 @@ class Beacon(object):
else:
self.opts['beacons'][name].append({'enabled': enabled_value})
def list_beacons(self):
def _get_beacons(self,
include_opts=True,
include_pillar=True):
'''
Return the beacons data structure
'''
beacons = {}
if include_pillar:
pillar_beacons = self.opts.get('pillar', {}).get('beacons', {})
if not isinstance(pillar_beacons, dict):
raise ValueError('Beacons must be of type dict.')
beacons.update(pillar_beacons)
if include_opts:
opts_beacons = self.opts.get('beacons', {})
if not isinstance(opts_beacons, dict):
raise ValueError('Beacons must be of type dict.')
beacons.update(opts_beacons)
return beacons
def list_beacons(self,
include_pillar=True,
include_opts=True):
'''
List the beacon items
include_pillar: Whether to include beacons that are
configured in pillar, default is True.
include_opts: Whether to include beacons that are
configured in opts, default is True.
'''
beacons = self._get_beacons(include_pillar, include_opts)
# Fire the complete event back along with the list of beacons
evt = salt.utils.event.get_event('minion', opts=self.opts)
evt.fire_event({'complete': True, 'beacons': self.opts['beacons']},
evt.fire_event({'complete': True, 'beacons': beacons},
tag='/salt/minion/minion_beacons_list_complete')
return True
@ -236,8 +265,8 @@ class Beacon(object):
del beacon_data['enabled']
valid, vcomment = self.beacons[validate_str](beacon_data)
else:
log.info('Beacon %s does not have a validate'
' function, skipping validation.', name)
vcomment = 'Beacon {0} does not have a validate' \
' function, skipping validation.'.format(name)
valid = True
# Fire the complete event back along with the list of beacons
@ -257,16 +286,23 @@ class Beacon(object):
data = {}
data[name] = beacon_data
if name in self.opts['beacons']:
log.info('Updating settings for beacon '
'item: %s', name)
if name in self._get_beacons(include_opts=False):
comment = 'Cannot update beacon item {0}, ' \
'because it is configured in pillar.'.format(name)
complete = False
else:
log.info('Added new beacon item %s', name)
self.opts['beacons'].update(data)
if name in self.opts['beacons']:
comment = 'Updating settings for beacon ' \
'item: {0}'.format(name)
else:
comment = 'Added new beacon item: {0}'.format(name)
complete = True
self.opts['beacons'].update(data)
# Fire the complete event back along with updated list of beacons
evt = salt.utils.event.get_event('minion', opts=self.opts)
evt.fire_event({'complete': True, 'beacons': self.opts['beacons']},
evt.fire_event({'complete': complete, 'comment': comment,
'beacons': self.opts['beacons']},
tag='/salt/minion/minion_beacon_add_complete')
return True
@ -279,13 +315,20 @@ class Beacon(object):
data = {}
data[name] = beacon_data
log.info('Updating settings for beacon '
'item: %s', name)
self.opts['beacons'].update(data)
if name in self._get_beacons(include_opts=False):
comment = 'Cannot modify beacon item {0}, ' \
'it is configured in pillar.'.format(name)
complete = False
else:
comment = 'Updating settings for beacon ' \
'item: {0}'.format(name)
complete = True
self.opts['beacons'].update(data)
# Fire the complete event back along with updated list of beacons
evt = salt.utils.event.get_event('minion', opts=self.opts)
evt.fire_event({'complete': True, 'beacons': self.opts['beacons']},
evt.fire_event({'complete': complete, 'comment': comment,
'beacons': self.opts['beacons']},
tag='/salt/minion/minion_beacon_modify_complete')
return True
@ -295,13 +338,22 @@ class Beacon(object):
Delete a beacon item
'''
if name in self.opts['beacons']:
log.info('Deleting beacon item %s', name)
del self.opts['beacons'][name]
if name in self._get_beacons(include_opts=False):
comment = 'Cannot delete beacon item {0}, ' \
'it is configured in pillar.'.format(name)
complete = False
else:
if name in self.opts['beacons']:
del self.opts['beacons'][name]
comment = 'Deleting beacon item: {0}'.format(name)
else:
comment = 'Beacon item {0} not found.'.format(name)
complete = True
# Fire the complete event back along with updated list of beacons
evt = salt.utils.event.get_event('minion', opts=self.opts)
evt.fire_event({'complete': True, 'beacons': self.opts['beacons']},
evt.fire_event({'complete': complete, 'comment': comment,
'beacons': self.opts['beacons']},
tag='/salt/minion/minion_beacon_delete_complete')
return True
@ -339,11 +391,19 @@ class Beacon(object):
Enable a beacon
'''
self._update_enabled(name, True)
if name in self._get_beacons(include_opts=False):
comment = 'Cannot enable beacon item {0}, ' \
'it is configured in pillar.'.format(name)
complete = False
else:
self._update_enabled(name, True)
comment = 'Enabling beacon item {0}'.format(name)
complete = True
# Fire the complete event back along with updated list of beacons
evt = salt.utils.event.get_event('minion', opts=self.opts)
evt.fire_event({'complete': True, 'beacons': self.opts['beacons']},
evt.fire_event({'complete': complete, 'comment': comment,
'beacons': self.opts['beacons']},
tag='/salt/minion/minion_beacon_enabled_complete')
return True
@ -353,11 +413,19 @@ class Beacon(object):
Disable a beacon
'''
self._update_enabled(name, False)
if name in self._get_beacons(include_opts=False):
comment = 'Cannot disable beacon item {0}, ' \
'it is configured in pillar.'.format(name)
complete = False
else:
self._update_enabled(name, False)
comment = 'Disabling beacon item {0}'.format(name)
complete = True
# Fire the complete event back along with updated list of beacons
evt = salt.utils.event.get_event('minion', opts=self.opts)
evt.fire_event({'complete': True, 'beacons': self.opts['beacons']},
evt.fire_event({'complete': complete, 'comment': comment,
'beacons': self.opts['beacons']},
tag='/salt/minion/minion_beacon_disabled_complete')
return True

View file

@ -7,7 +7,7 @@ A simple beacon to watch journald for specific entries
from __future__ import absolute_import
# Import salt libs
import salt.utils
import salt.utils.data
import salt.utils.locales
import salt.ext.six
from salt.ext.six.moves import map
@ -99,7 +99,7 @@ def beacon(config):
n_flag += 1
if n_flag == len(_config['services'][name]):
# Match!
sub = salt.utils.simple_types_filter(cur)
sub = salt.utils.data.simple_types_filter(cur)
sub.update({'tag': name})
ret.append(sub)
return ret

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
'''
Send events covering service status
Send events covering process status
'''
# Import Python Libs

View file

@ -3,6 +3,8 @@
Beacon to monitor temperature, humidity and pressure using the SenseHat
of a Raspberry Pi.
.. versionadded:: 2017.7.0
:maintainer: Benedikt Werner <1benediktwerner@gmail.com>
:maturity: new
:depends: sense_hat Python module

View file

@ -8,7 +8,6 @@ from __future__ import absolute_import
import time
# Import salt libs
import salt.utils
import salt.utils.path
import salt.utils.vt

View file

@ -18,7 +18,6 @@ import shutil
import tempfile
from salt.exceptions import SaltCacheError
import salt.utils
import salt.utils.atomicfile
import salt.utils.files

View file

@ -11,7 +11,7 @@ import copy
from datetime import datetime, timedelta
# Import salt libs
import salt.utils # Can be removed once print_cli is moved
import salt.utils.stringutils
import salt.client
import salt.output
import salt.exceptions
@ -73,7 +73,7 @@ class Batch(object):
m = next(six.iterkeys(ret))
except StopIteration:
if not self.quiet:
salt.utils.print_cli('No minions matched the target.')
salt.utils.stringutils.print_cli('No minions matched the target.')
break
if m is not None:
fret.add(m)
@ -95,7 +95,7 @@ class Batch(object):
return int(self.opts['batch'])
except ValueError:
if not self.quiet:
salt.utils.print_cli('Invalid batch data sent: {0}\nData must be in the '
salt.utils.stringutils.print_cli('Invalid batch data sent: {0}\nData must be in the '
'form of %10, 10% or 3'.format(self.opts['batch']))
def __update_wait(self, wait):
@ -147,7 +147,7 @@ class Batch(object):
# We already know some minions didn't respond to the ping, so inform
# the user we won't be attempting to run a job on them
for down_minion in self.down_minions:
salt.utils.print_cli('Minion {0} did not respond. No job will be sent.'.format(down_minion))
salt.utils.stringutils.print_cli('Minion {0} did not respond. No job will be sent.'.format(down_minion))
# Iterate while we still have things to execute
while len(ret) < len(self.minions):
@ -172,7 +172,7 @@ class Batch(object):
if next_:
if not self.quiet:
salt.utils.print_cli('\nExecuting run on {0}\n'.format(sorted(next_)))
salt.utils.stringutils.print_cli('\nExecuting run on {0}\n'.format(sorted(next_)))
# create a new iterator for this batch of minions
new_iter = self.local.cmd_iter_no_block(
*args,
@ -219,14 +219,14 @@ class Batch(object):
if part['data']['id'] in minion_tracker[queue]['minions']:
minion_tracker[queue]['minions'].remove(part['data']['id'])
else:
salt.utils.print_cli('minion {0} was already deleted from tracker, probably a duplicate key'.format(part['id']))
salt.utils.stringutils.print_cli('minion {0} was already deleted from tracker, probably a duplicate key'.format(part['id']))
else:
parts.update(part)
for id in part:
if id in minion_tracker[queue]['minions']:
minion_tracker[queue]['minions'].remove(id)
else:
salt.utils.print_cli('minion {0} was already deleted from tracker, probably a duplicate key'.format(id))
salt.utils.stringutils.print_cli('minion {0} was already deleted from tracker, probably a duplicate key'.format(id))
except StopIteration:
# if a iterator is done:
# - set it to inactive

View file

@ -20,12 +20,13 @@ import salt.minion
import salt.output
import salt.payload
import salt.transport
import salt.utils # Can be removed once print_cli, activate_profile, and output_profile are moved
import salt.utils.args
import salt.utils.files
import salt.utils.jid
import salt.utils.kinds as kinds
import salt.utils.minion
import salt.utils.profile
import salt.utils.stringutils
import salt.defaults.exitcodes
from salt.cli import daemons
from salt.log import LOG_LEVELS
@ -113,7 +114,7 @@ class BaseCaller(object):
docs[name] = func.__doc__
for name in sorted(docs):
if name.startswith(self.opts.get('fun', '')):
salt.utils.print_cli('{0}:\n{1}\n'.format(name, docs[name]))
salt.utils.stringutils.print_cli('{0}:\n{1}\n'.format(name, docs[name]))
def print_grains(self):
'''
@ -128,11 +129,11 @@ class BaseCaller(object):
'''
profiling_enabled = self.opts.get('profiling_enabled', False)
try:
pr = salt.utils.activate_profile(profiling_enabled)
pr = salt.utils.profile.activate_profile(profiling_enabled)
try:
ret = self.call()
finally:
salt.utils.output_profile(
salt.utils.profile.output_profile(
pr,
stats_path=self.opts.get('profiling_path', '/tmp/stats'),
stop=True)
@ -209,7 +210,7 @@ class BaseCaller(object):
ret['return'] = func(*args, **kwargs)
except TypeError as exc:
sys.stderr.write('\nPassed invalid arguments: {0}.\n\nUsage:\n'.format(exc))
salt.utils.print_cli(func.__doc__)
salt.utils.stringutils.print_cli(func.__doc__)
active_level = LOG_LEVELS.get(
self.opts['log_level'].lower(), logging.ERROR)
if active_level <= logging.DEBUG:

View file

@ -19,7 +19,6 @@ import sys
# Import salt libs
import salt.client
import salt.output
import salt.utils
import salt.utils.files
import salt.utils.gzip_util
import salt.utils.itertools
@ -127,9 +126,10 @@ class SaltCP(object):
if os.path.isfile(fn_):
files.update(self._file_dict(fn_))
elif os.path.isdir(fn_):
salt.utils.print_cli(fn_ + ' is a directory, only files are supported '
'in non-chunked mode. Use "--chunked" command '
'line argument.')
salt.utils.stringutils.print_cli(
fn_ + ' is a directory, only files are supported '
'in non-chunked mode. Use "--chunked" command '
'line argument.')
sys.exit(1)
return files

View file

@ -44,7 +44,7 @@ from salt.utils import migrations
import salt.utils.kinds as kinds
try:
from salt.utils import ip_bracket
from salt.utils.zeromq import ip_bracket
import salt.utils.parsers
from salt.utils.verify import check_user, verify_env, verify_socket
except ImportError as exc:

View file

@ -2,8 +2,8 @@
from __future__ import print_function
from __future__ import absolute_import
import salt.utils # Can be removed once activate_profile and output_profile are moved
import salt.utils.parsers
import salt.utils.profile
from salt.utils.verify import check_user, verify_log
from salt.exceptions import SaltClientError
import salt.defaults.exitcodes # pylint: disable=W0611
@ -35,7 +35,7 @@ class SaltRun(salt.utils.parsers.SaltRunOptionParser):
# someone tries to use the runners via the python API
try:
if check_user(self.config['user']):
pr = salt.utils.activate_profile(profiling_enabled)
pr = salt.utils.profile.activate_profile(profiling_enabled)
try:
ret = runner.run()
# In older versions ret['data']['retcode'] was used
@ -49,7 +49,7 @@ class SaltRun(salt.utils.parsers.SaltRunOptionParser):
elif isinstance(ret, dict) and 'retcode' in ret.get('data', {}):
self.exit(ret['data']['retcode'])
finally:
salt.utils.output_profile(
salt.utils.profile.output_profile(
pr,
stats_path=self.options.profiling_path,
stop=True)

View file

@ -7,15 +7,18 @@ sys.modules['pkg_resources'] = None
import os
# Import Salt libs
import salt.utils # Can be removed once print_cli is moved
import salt.utils.job
import salt.utils.parsers
import salt.utils.stringutils
from salt.utils.args import yamlify_arg
from salt.utils.verify import verify_log
from salt.exceptions import (
SaltClientError,
SaltInvocationError,
EauthAuthenticationError
)
EauthAuthenticationError,
LoaderError,
SaltClientError,
SaltInvocationError,
SaltSystemExit
)
# Import 3rd-party libs
from salt.ext import six
@ -93,7 +96,7 @@ class SaltCMD(salt.utils.parsers.SaltCMDOptionParser):
# potentially switch to batch execution
if self.options.batch_safe_limit > 1:
if len(self._preview_target()) >= self.options.batch_safe_limit:
salt.utils.print_cli('\nNOTICE: Too many minions targeted, switching to batch execution.')
salt.utils.stringutils.print_cli('\nNOTICE: Too many minions targeted, switching to batch execution.')
self.options.batch = self.options.batch_safe_size
self._run_batch()
return
@ -140,7 +143,7 @@ class SaltCMD(salt.utils.parsers.SaltCMDOptionParser):
if self.config['async']:
jid = self.local_client.cmd_async(**kwargs)
salt.utils.print_cli('Executed command with job ID: {0}'.format(jid))
salt.utils.stringutils.print_cli('Executed command with job ID: {0}'.format(jid))
return
# local will be None when there was an error
@ -166,8 +169,8 @@ class SaltCMD(salt.utils.parsers.SaltCMDOptionParser):
out = 'progress'
try:
self._progress_ret(progress, out)
except salt.exceptions.LoaderError as exc:
raise salt.exceptions.SaltSystemExit(exc)
except LoaderError as exc:
raise SaltSystemExit(exc)
if 'return_count' not in progress:
ret.update(progress)
self._progress_end(out)
@ -250,7 +253,7 @@ class SaltCMD(salt.utils.parsers.SaltCMDOptionParser):
try:
batch = salt.cli.batch.Batch(self.config, eauth=eauth, quiet=True)
except salt.exceptions.SaltClientError as exc:
except SaltClientError:
sys.exit(2)
ret = {}
@ -264,7 +267,7 @@ class SaltCMD(salt.utils.parsers.SaltCMDOptionParser):
try:
self.config['batch'] = self.options.batch
batch = salt.cli.batch.Batch(self.config, eauth=eauth, parser=self.options)
except salt.exceptions.SaltClientError as exc:
except SaltClientError:
# We will print errors to the console further down the stack
sys.exit(1)
# Printing the output is already taken care of in run() itself
@ -279,12 +282,12 @@ class SaltCMD(salt.utils.parsers.SaltCMDOptionParser):
def _print_errors_summary(self, errors):
if errors:
salt.utils.print_cli('\n')
salt.utils.print_cli('---------------------------')
salt.utils.print_cli('Errors')
salt.utils.print_cli('---------------------------')
salt.utils.stringutils.print_cli('\n')
salt.utils.stringutils.print_cli('---------------------------')
salt.utils.stringutils.print_cli('Errors')
salt.utils.stringutils.print_cli('---------------------------')
for error in errors:
salt.utils.print_cli(self._format_error(error))
salt.utils.stringutils.print_cli(self._format_error(error))
def _print_returns_summary(self, ret):
'''
@ -314,22 +317,22 @@ class SaltCMD(salt.utils.parsers.SaltCMDOptionParser):
return_counter += 1
if self._get_retcode(ret[each_minion]):
failed_minions.append(each_minion)
salt.utils.print_cli('\n')
salt.utils.print_cli('-------------------------------------------')
salt.utils.print_cli('Summary')
salt.utils.print_cli('-------------------------------------------')
salt.utils.print_cli('# of minions targeted: {0}'.format(return_counter + not_return_counter))
salt.utils.print_cli('# of minions returned: {0}'.format(return_counter))
salt.utils.print_cli('# of minions that did not return: {0}'.format(not_return_counter))
salt.utils.print_cli('# of minions with errors: {0}'.format(len(failed_minions)))
salt.utils.stringutils.print_cli('\n')
salt.utils.stringutils.print_cli('-------------------------------------------')
salt.utils.stringutils.print_cli('Summary')
salt.utils.stringutils.print_cli('-------------------------------------------')
salt.utils.stringutils.print_cli('# of minions targeted: {0}'.format(return_counter + not_return_counter))
salt.utils.stringutils.print_cli('# of minions returned: {0}'.format(return_counter))
salt.utils.stringutils.print_cli('# of minions that did not return: {0}'.format(not_return_counter))
salt.utils.stringutils.print_cli('# of minions with errors: {0}'.format(len(failed_minions)))
if self.options.verbose:
if not_connected_minions:
salt.utils.print_cli('Minions not connected: {0}'.format(" ".join(not_connected_minions)))
salt.utils.stringutils.print_cli('Minions not connected: {0}'.format(" ".join(not_connected_minions)))
if not_response_minions:
salt.utils.print_cli('Minions not responding: {0}'.format(" ".join(not_response_minions)))
salt.utils.stringutils.print_cli('Minions not responding: {0}'.format(" ".join(not_response_minions)))
if failed_minions:
salt.utils.print_cli('Minions with failures: {0}'.format(" ".join(failed_minions)))
salt.utils.print_cli('-------------------------------------------')
salt.utils.stringutils.print_cli('Minions with failures: {0}'.format(" ".join(failed_minions)))
salt.utils.stringutils.print_cli('-------------------------------------------')
def _progress_end(self, out):
import salt.output
@ -344,9 +347,9 @@ class SaltCMD(salt.utils.parsers.SaltCMDOptionParser):
if not hasattr(self, 'progress_bar'):
try:
self.progress_bar = salt.output.get_progress(self.config, out, progress)
except Exception as exc:
raise salt.exceptions.LoaderError('\nWARNING: Install the `progressbar` python package. '
'Requested job was still run but output cannot be displayed.\n')
except Exception:
raise LoaderError('\nWARNING: Install the `progressbar` python package. '
'Requested job was still run but output cannot be displayed.\n')
salt.output.update_progress(self.config, progress, self.progress_bar, out)
def _output_ret(self, ret, out):
@ -421,6 +424,6 @@ class SaltCMD(salt.utils.parsers.SaltCMDOptionParser):
salt.output.display_output({fun: docs[fun]}, 'nested', self.config)
else:
for fun in sorted(docs):
salt.utils.print_cli('{0}:'.format(fun))
salt.utils.print_cli(docs[fun])
salt.utils.print_cli('')
salt.utils.stringutils.print_cli('{0}:'.format(fun))
salt.utils.stringutils.print_cli(docs[fun])
salt.utils.stringutils.print_cli('')

View file

@ -32,16 +32,16 @@ import salt.cache
import salt.payload
import salt.transport
import salt.loader
import salt.utils # Can be removed once ip_bracket is moved
import salt.utils.args
import salt.utils.event
import salt.utils.files
import salt.utils.jid
import salt.utils.minions
import salt.utils.platform
import salt.utils.user
import salt.utils.verify
import salt.utils.versions
import salt.utils.jid
import salt.utils.zeromq
import salt.syspaths as syspaths
from salt.exceptions import (
EauthAuthenticationError, SaltInvocationError, SaltReqTimeoutError,
@ -1595,7 +1595,10 @@ class LocalClient(object):
timeout=timeout,
tgt=tgt,
tgt_type=tgt_type,
expect_minions=(verbose or show_timeout),
# (gtmanfred) expect_minions is popped here incase it is passed from a client
# call. If this is not popped, then it would be passed twice to
# get_iter_returns.
expect_minions=(kwargs.pop('expect_minions', False) or verbose or show_timeout),
**kwargs
):
log.debug(u'return event: %s', ret)
@ -1791,7 +1794,7 @@ class LocalClient(object):
timeout,
**kwargs)
master_uri = u'tcp://' + salt.utils.ip_bracket(self.opts[u'interface']) + \
master_uri = u'tcp://' + salt.utils.zeromq.ip_bracket(self.opts[u'interface']) + \
u':' + str(self.opts[u'ret_port'])
channel = salt.transport.Channel.factory(self.opts,
crypt=u'clear',
@ -1899,7 +1902,7 @@ class LocalClient(object):
timeout,
**kwargs)
master_uri = u'tcp://' + salt.utils.ip_bracket(self.opts[u'interface']) + \
master_uri = u'tcp://' + salt.utils.zeromq.ip_bracket(self.opts[u'interface']) + \
u':' + str(self.opts[u'ret_port'])
channel = salt.transport.client.AsyncReqChannel.factory(self.opts,
io_loop=io_loop,

View file

@ -16,7 +16,6 @@ import copy as pycopy
# Import Salt libs
import salt.exceptions
import salt.minion
import salt.utils # Can be removed once daemonize, format_call are moved
import salt.utils.args
import salt.utils.doc
import salt.utils.error
@ -371,7 +370,7 @@ class SyncClientMixin(object):
args = low[u'arg']
kwargs = low[u'kwarg']
else:
f_call = salt.utils.format_call(
f_call = salt.utils.args.format_call(
self.functions[fun],
low,
expected_extra_kws=CLIENT_INTERNAL_KEYWORDS
@ -469,7 +468,7 @@ class AsyncClientMixin(object):
# Shutdown the multiprocessing before daemonizing
salt.log.setup.shutdown_multiprocessing_logging()
salt.utils.daemonize()
salt.utils.process.daemonize()
# Reconfigure multiprocessing logging after daemonizing
salt.log.setup.setup_multiprocessing_logging()

View file

@ -36,11 +36,12 @@ import salt.minion
import salt.roster
import salt.serializers.yaml
import salt.state
import salt.utils
import salt.utils.args
import salt.utils.atomicfile
import salt.utils.event
import salt.utils.files
import salt.utils.hashutils
import salt.utils.json
import salt.utils.network
import salt.utils.path
import salt.utils.stringutils
@ -496,7 +497,7 @@ class SSH(object):
**target)
stdout, stderr, retcode = single.cmd_block()
try:
data = salt.utils.find_json(stdout)
data = salt.utils.json.find_json(stdout)
return {host: data.get(u'local', data)}
except Exception:
if stderr:
@ -524,7 +525,7 @@ class SSH(object):
stdout, stderr, retcode = single.run()
# This job is done, yield
try:
data = salt.utils.find_json(stdout)
data = salt.utils.json.find_json(stdout)
if len(data) < 2 and u'local' in data:
ret[u'ret'] = data[u'local']
else:
@ -1507,7 +1508,7 @@ def mod_data(fsclient):
if not os.path.isfile(mod_path):
continue
mods_data[os.path.basename(fn_)] = mod_path
chunk = salt.utils.get_hash(mod_path)
chunk = salt.utils.hashutils.get_hash(mod_path)
ver_base += chunk
if mods_data:
if ref in ret:

View file

@ -15,7 +15,6 @@ import subprocess
# Import salt libs
import salt.defaults.exitcodes
import salt.utils
import salt.utils.nb_popen
import salt.utils.vt

View file

@ -137,7 +137,7 @@ def need_deployment():
sys.exit(EX_THIN_DEPLOY)
# Adapted from salt.utils.get_hash()
# Adapted from salt.utils.hashutils.get_hash()
def get_hash(path, form=u'sha1', chunk_size=4096):
'''
Generate a hash digest string for a file.

View file

@ -13,7 +13,7 @@ import copy
# Import salt libs
import salt.loader
import salt.utils
import salt.utils.data
import salt.client.ssh
# Import 3rd-party libs
@ -121,7 +121,7 @@ class FunctionWrapper(object):
u'stderr': stderr,
u'retcode': retcode}
try:
ret = json.loads(stdout, object_hook=salt.utils.decode_dict)
ret = json.loads(stdout, object_hook=salt.utils.data.decode_dict)
if len(ret) < 2 and u'local' in ret:
ret = ret[u'local']
ret = ret.get(u'return', {})

View file

@ -9,7 +9,8 @@ import re
import os
# Import salt libs
import salt.utils
import salt.utils.data
import salt.utils.files
import salt.syspaths as syspaths
# Import 3rd-party libs
@ -81,7 +82,7 @@ def manage_mode(mode):
# config.manage_mode should no longer be invoked from the __salt__ dunder
# in Salt code, this function is only being left here for backwards
# compatibility.
return salt.utils.normalize_mode(mode)
return salt.utils.files.normalize_mode(mode)
def valid_fileproto(uri):
@ -215,16 +216,16 @@ def get(key, default=u''):
salt '*' config.get pkg:apache
'''
ret = salt.utils.traverse_dict_and_list(__opts__, key, u'_|-')
ret = salt.utils.data.traverse_dict_and_list(__opts__, key, u'_|-')
if ret != u'_|-':
return ret
ret = salt.utils.traverse_dict_and_list(__grains__, key, u'_|-')
ret = salt.utils.data.traverse_dict_and_list(__grains__, key, u'_|-')
if ret != u'_|-':
return ret
ret = salt.utils.traverse_dict_and_list(__pillar__, key, u'_|-')
ret = salt.utils.data.traverse_dict_and_list(__pillar__, key, u'_|-')
if ret != u'_|-':
return ret
ret = salt.utils.traverse_dict_and_list(__pillar__.get(u'master', {}), key, u'_|-')
ret = salt.utils.data.traverse_dict_and_list(__pillar__.get(u'master', {}), key, u'_|-')
if ret != u'_|-':
return ret
return default

View file

@ -11,7 +11,7 @@ import math
import json
# Import salt libs
import salt.utils
import salt.utils.data
import salt.utils.dictupdate
from salt.defaults import DEFAULT_TARGET_DELIM
from salt.exceptions import SaltException
@ -75,10 +75,11 @@ def get(key, default=u'', delimiter=DEFAULT_TARGET_DELIM, ordered=True):
grains = __grains__
else:
grains = json.loads(json.dumps(__grains__))
return salt.utils.traverse_dict_and_list(__grains__,
key,
default,
delimiter)
return salt.utils.data.traverse_dict_and_list(
__grains__,
key,
default,
delimiter)
def has_value(key):
@ -99,7 +100,9 @@ def has_value(key):
salt '*' grains.has_value pkg:apache
'''
return True if salt.utils.traverse_dict_and_list(__grains__, key, False) else False
return True \
if salt.utils.data.traverse_dict_and_list(__grains__, key, False) \
else False
def items(sanitize=False):
@ -118,7 +121,7 @@ def items(sanitize=False):
salt '*' grains.items sanitize=True
'''
if salt.utils.is_true(sanitize):
if salt.utils.data.is_true(sanitize):
out = dict(__grains__)
for key, func in six.iteritems(_SANITIZERS):
if key in out:
@ -151,7 +154,7 @@ def item(*args, **kwargs):
ret[arg] = __grains__[arg]
except KeyError:
pass
if salt.utils.is_true(kwargs.get(u'sanitize')):
if salt.utils.data.is_true(kwargs.get(u'sanitize')):
for arg, func in six.iteritems(_SANITIZERS):
if arg in ret:
ret[arg] = func(ret[arg])

View file

@ -9,7 +9,8 @@ import collections
# Import salt libs
import salt.pillar
import salt.utils
import salt.utils.data
import salt.utils.dictupdate
from salt.defaults import DEFAULT_TARGET_DELIM
@ -51,15 +52,16 @@ def get(key, default=u'', merge=False, delimiter=DEFAULT_TARGET_DELIM):
salt '*' pillar.get pkg:apache
'''
if merge:
ret = salt.utils.traverse_dict_and_list(__pillar__, key, {}, delimiter)
ret = salt.utils.data.traverse_dict_and_list(__pillar__, key, {}, delimiter)
if isinstance(ret, collections.Mapping) and \
isinstance(default, collections.Mapping):
return salt.utils.dictupdate.update(default, ret)
return salt.utils.traverse_dict_and_list(__pillar__,
key,
default,
delimiter)
return salt.utils.data.traverse_dict_and_list(
__pillar__,
key,
default,
delimiter)
def item(*args):
@ -126,7 +128,7 @@ def keys(key, delimiter=DEFAULT_TARGET_DELIM):
salt '*' pillar.keys web:sites
'''
ret = salt.utils.traverse_dict_and_list(
ret = salt.utils.data.traverse_dict_and_list(
__pillar__, key, KeyError, delimiter)
if ret is KeyError:

View file

@ -13,7 +13,9 @@ import logging
# Import salt libs
import salt.client.ssh.shell
import salt.client.ssh.state
import salt.utils
import salt.utils.args
import salt.utils.data
import salt.utils.hashutils
import salt.utils.thin
import salt.roster
import salt.state
@ -100,7 +102,7 @@ def sls(mods, saltenv=u'base', test=None, exclude=None, **kwargs):
__pillar__,
st_kwargs[u'id_'],
roster_grains)
trans_tar_sum = salt.utils.get_hash(trans_tar, __opts__[u'hash_type'])
trans_tar_sum = salt.utils.hashutils.get_hash(trans_tar, __opts__[u'hash_type'])
cmd = u'state.pkg {0}/salt_state.tgz test={1} pkg_sum={2} hash_type={3}'.format(
__opts__[u'thin_dir'],
test,
@ -125,7 +127,7 @@ def sls(mods, saltenv=u'base', test=None, exclude=None, **kwargs):
# Read in the JSON data and return the data structure
try:
return json.loads(stdout, object_hook=salt.utils.decode_dict)
return json.loads(stdout, object_hook=salt.utils.data.decode_dict)
except Exception as e:
log.error(u"JSON Render failed for: %s\n%s", stdout, stderr)
log.error(str(e))
@ -177,7 +179,7 @@ def low(data, **kwargs):
__pillar__,
st_kwargs[u'id_'],
roster_grains)
trans_tar_sum = salt.utils.get_hash(trans_tar, __opts__[u'hash_type'])
trans_tar_sum = salt.utils.hashutils.get_hash(trans_tar, __opts__[u'hash_type'])
cmd = u'state.pkg {0}/salt_state.tgz pkg_sum={1} hash_type={2}'.format(
__opts__[u'thin_dir'],
trans_tar_sum,
@ -201,7 +203,7 @@ def low(data, **kwargs):
# Read in the JSON data and return the data structure
try:
return json.loads(stdout, object_hook=salt.utils.decode_dict)
return json.loads(stdout, object_hook=salt.utils.data.decode_dict)
except Exception as e:
log.error(u"JSON Render failed for: %s\n%s", stdout, stderr)
log.error(str(e))
@ -250,7 +252,7 @@ def high(data, **kwargs):
__pillar__,
st_kwargs[u'id_'],
roster_grains)
trans_tar_sum = salt.utils.get_hash(trans_tar, __opts__[u'hash_type'])
trans_tar_sum = salt.utils.hashutils.get_hash(trans_tar, __opts__[u'hash_type'])
cmd = u'state.pkg {0}/salt_state.tgz pkg_sum={1} hash_type={2}'.format(
__opts__[u'thin_dir'],
trans_tar_sum,
@ -274,7 +276,7 @@ def high(data, **kwargs):
# Read in the JSON data and return the data structure
try:
return json.loads(stdout, object_hook=salt.utils.decode_dict)
return json.loads(stdout, object_hook=salt.utils.data.decode_dict)
except Exception as e:
log.error(u"JSON Render failed for: %s\n%s", stdout, stderr)
log.error(str(e))
@ -353,7 +355,7 @@ def highstate(test=None, **kwargs):
__pillar__,
st_kwargs[u'id_'],
roster_grains)
trans_tar_sum = salt.utils.get_hash(trans_tar, __opts__[u'hash_type'])
trans_tar_sum = salt.utils.hashutils.get_hash(trans_tar, __opts__[u'hash_type'])
cmd = u'state.pkg {0}/salt_state.tgz test={1} pkg_sum={2} hash_type={3}'.format(
__opts__[u'thin_dir'],
test,
@ -378,7 +380,7 @@ def highstate(test=None, **kwargs):
# Read in the JSON data and return the data structure
try:
return json.loads(stdout, object_hook=salt.utils.decode_dict)
return json.loads(stdout, object_hook=salt.utils.data.decode_dict)
except Exception as e:
log.error(u"JSON Render failed for: %s\n%s", stdout, stderr)
log.error(str(e))
@ -402,7 +404,7 @@ def top(topfn, test=None, **kwargs):
__pillar__.update(kwargs.get(u'pillar', {}))
st_kwargs = __salt__.kwargs
__opts__[u'grains'] = __grains__
if salt.utils.test_mode(test=test, **kwargs):
if salt.utils.args.test_mode(test=test, **kwargs):
__opts__[u'test'] = True
else:
__opts__[u'test'] = __opts__.get(u'test', None)
@ -433,7 +435,7 @@ def top(topfn, test=None, **kwargs):
__pillar__,
st_kwargs[u'id_'],
roster_grains)
trans_tar_sum = salt.utils.get_hash(trans_tar, __opts__[u'hash_type'])
trans_tar_sum = salt.utils.hashutils.get_hash(trans_tar, __opts__[u'hash_type'])
cmd = u'state.pkg {0}/salt_state.tgz test={1} pkg_sum={2} hash_type={3}'.format(
__opts__[u'thin_dir'],
test,
@ -458,7 +460,7 @@ def top(topfn, test=None, **kwargs):
# Read in the JSON data and return the data structure
try:
return json.loads(stdout, object_hook=salt.utils.decode_dict)
return json.loads(stdout, object_hook=salt.utils.data.decode_dict)
except Exception as e:
log.error(u"JSON Render failed for: %s\n%s", stdout, stderr)
log.error(str(e))
@ -519,7 +521,7 @@ def show_sls(mods, saltenv=u'base', test=None, **kwargs):
__pillar__.update(kwargs.get(u'pillar', {}))
__opts__[u'grains'] = __grains__
opts = copy.copy(__opts__)
if salt.utils.test_mode(test=test, **kwargs):
if salt.utils.args.test_mode(test=test, **kwargs):
opts[u'test'] = True
else:
opts[u'test'] = __opts__.get(u'test', None)
@ -562,7 +564,7 @@ def show_low_sls(mods, saltenv=u'base', test=None, **kwargs):
__opts__[u'grains'] = __grains__
opts = copy.copy(__opts__)
if salt.utils.test_mode(test=test, **kwargs):
if salt.utils.args.test_mode(test=test, **kwargs):
opts[u'test'] = True
else:
opts[u'test'] = __opts__.get(u'test', None)
@ -651,7 +653,7 @@ def single(fun, name, test=None, **kwargs):
opts = copy.deepcopy(__opts__)
# Set test mode
if salt.utils.test_mode(test=test, **kwargs):
if salt.utils.args.test_mode(test=test, **kwargs):
opts[u'test'] = True
else:
opts[u'test'] = __opts__.get(u'test', None)
@ -695,7 +697,7 @@ def single(fun, name, test=None, **kwargs):
roster_grains)
# Create a hash so we can verify the tar on the target system
trans_tar_sum = salt.utils.get_hash(trans_tar, __opts__[u'hash_type'])
trans_tar_sum = salt.utils.hashutils.get_hash(trans_tar, __opts__[u'hash_type'])
# We use state.pkg to execute the "state package"
cmd = u'state.pkg {0}/salt_state.tgz test={1} pkg_sum={2} hash_type={3}'.format(
@ -728,7 +730,7 @@ def single(fun, name, test=None, **kwargs):
# Read in the JSON data and return the data structure
try:
return json.loads(stdout, object_hook=salt.utils.decode_dict)
return json.loads(stdout, object_hook=salt.utils.data.decode_dict)
except Exception as e:
log.error(u"JSON Render failed for: %s\n%s", stdout, stderr)
log.error(str(e))

View file

@ -29,10 +29,11 @@ from salt.exceptions import (
import salt.config
import salt.client
import salt.loader
import salt.utils
import salt.utils.args
import salt.utils.cloud
import salt.utils.context
import salt.utils.crypt
import salt.utils.data
import salt.utils.dictupdate
import salt.utils.files
import salt.syspaths
@ -233,7 +234,7 @@ class CloudClient(object):
if a.get('provider', '')]
if providers:
_providers = opts.get('providers', {})
for provider in list(_providers):
for provider in list(_providers).copy():
if provider not in providers:
_providers.pop(provider)
return opts
@ -243,7 +244,7 @@ class CloudClient(object):
Pass the cloud function and low data structure to run
'''
l_fun = getattr(self, fun)
f_call = salt.utils.format_call(l_fun, low)
f_call = salt.utils.args.format_call(l_fun, low)
return l_fun(*f_call.get('args', ()), **f_call.get('kwargs', {}))
def list_sizes(self, provider=None):
@ -251,7 +252,7 @@ class CloudClient(object):
List all available sizes in configured cloud systems
'''
mapper = salt.cloud.Map(self._opts_defaults())
return salt.utils.simple_types_filter(
return salt.utils.data.simple_types_filter(
mapper.size_list(provider)
)
@ -260,7 +261,7 @@ class CloudClient(object):
List all available images in configured cloud systems
'''
mapper = salt.cloud.Map(self._opts_defaults())
return salt.utils.simple_types_filter(
return salt.utils.data.simple_types_filter(
mapper.image_list(provider)
)
@ -269,7 +270,7 @@ class CloudClient(object):
List all available locations in configured cloud systems
'''
mapper = salt.cloud.Map(self._opts_defaults())
return salt.utils.simple_types_filter(
return salt.utils.data.simple_types_filter(
mapper.location_list(provider)
)
@ -343,7 +344,7 @@ class CloudClient(object):
mapper = salt.cloud.Map(self._opts_defaults(**kwargs))
if isinstance(names, six.string_types):
names = names.split(',')
return salt.utils.simple_types_filter(
return salt.utils.data.simple_types_filter(
mapper.run_profile(profile, names, vm_overrides=vm_overrides)
)
@ -357,7 +358,7 @@ class CloudClient(object):
kwarg.update(kwargs)
mapper = salt.cloud.Map(self._opts_defaults(**kwarg))
dmap = mapper.map_data()
return salt.utils.simple_types_filter(
return salt.utils.data.simple_types_filter(
mapper.run_map(dmap)
)
@ -368,7 +369,7 @@ class CloudClient(object):
mapper = salt.cloud.Map(self._opts_defaults(destroy=True))
if isinstance(names, six.string_types):
names = names.split(',')
return salt.utils.simple_types_filter(
return salt.utils.data.simple_types_filter(
mapper.destroy(names)
)
@ -407,7 +408,7 @@ class CloudClient(object):
vm_['profile'] = None
vm_['provider'] = provider
ret[name] = salt.utils.simple_types_filter(
ret[name] = salt.utils.data.simple_types_filter(
mapper.create(vm_))
return ret
@ -442,7 +443,7 @@ class CloudClient(object):
extra_['provider'] = provider
extra_['profile'] = None
extra_['action'] = action
ret[name] = salt.utils.simple_types_filter(
ret[name] = salt.utils.data.simple_types_filter(
mapper.extras(extra_)
)
return ret
@ -1416,7 +1417,7 @@ class Cloud(object):
if name in vms:
prov = vms[name]['provider']
driv = vms[name]['driver']
msg = six.u('{0} already exists under {1}:{2}').format(
msg = u'{0} already exists under {1}:{2}'.format(
name, prov, driv
)
log.error(msg)
@ -2098,7 +2099,7 @@ class Map(Cloud):
master_temp_pub = salt.utils.files.mkstemp()
with salt.utils.files.fopen(master_temp_pub, 'w') as mtp:
mtp.write(pub)
master_finger = salt.utils.pem_finger(master_temp_pub, sum_type=self.opts['hash_type'])
master_finger = salt.utils.crypt.pem_finger(master_temp_pub, sum_type=self.opts['hash_type'])
os.unlink(master_temp_pub)
if master_profile.get('make_minion', True) is True:
@ -2183,7 +2184,7 @@ class Map(Cloud):
# mitigate man-in-the-middle attacks
master_pub = os.path.join(self.opts['pki_dir'], 'master.pub')
if os.path.isfile(master_pub):
master_finger = salt.utils.pem_finger(master_pub, sum_type=self.opts['hash_type'])
master_finger = salt.utils.crypt.pem_finger(master_pub, sum_type=self.opts['hash_type'])
opts = self.opts.copy()
if self.opts['parallel']:
@ -2300,7 +2301,7 @@ def create_multiprocessing(parallel_data, queue=None):
This function will be called from another process when running a map in
parallel mode. The result from the create is always a json object.
'''
salt.utils.reinit_crypto()
salt.utils.crypt.reinit_crypto()
parallel_data['opts']['output'] = 'json'
cloud = Cloud(parallel_data['opts'])
@ -2323,7 +2324,7 @@ def create_multiprocessing(parallel_data, queue=None):
output.pop('deploy_kwargs', None)
return {
parallel_data['name']: salt.utils.simple_types_filter(output)
parallel_data['name']: salt.utils.data.simple_types_filter(output)
}
@ -2332,7 +2333,7 @@ def destroy_multiprocessing(parallel_data, queue=None):
This function will be called from another process when running a map in
parallel mode. The result from the destroy is always a json object.
'''
salt.utils.reinit_crypto()
salt.utils.crypt.reinit_crypto()
parallel_data['opts']['output'] = 'json'
clouds = salt.loader.clouds(parallel_data['opts'])
@ -2359,7 +2360,7 @@ def destroy_multiprocessing(parallel_data, queue=None):
return {parallel_data['name']: {'Error': str(exc)}}
return {
parallel_data['name']: salt.utils.simple_types_filter(output)
parallel_data['name']: salt.utils.data.simple_types_filter(output)
}
@ -2368,7 +2369,7 @@ def run_parallel_map_providers_query(data, queue=None):
This function will be called from another process when building the
providers map.
'''
salt.utils.reinit_crypto()
salt.utils.crypt.reinit_crypto()
cloud = Cloud(data['opts'])
try:
@ -2382,7 +2383,7 @@ def run_parallel_map_providers_query(data, queue=None):
return (
data['alias'],
data['driver'],
salt.utils.simple_types_filter(
salt.utils.data.simple_types_filter(
cloud.clouds[data['fun']]()
)
)

View file

@ -42,6 +42,7 @@ from salt.ext.six.moves.urllib.parse import quote as _quote # pylint: disable=i
# Import salt cloud libs
import salt.utils.cloud
import salt.utils.data
import salt.config as config
from salt.exceptions import (
SaltCloudNotFound,
@ -823,7 +824,7 @@ def query(params=None):
content = request.text
result = json.loads(content, object_hook=salt.utils.decode_dict)
result = json.loads(content, object_hook=salt.utils.data.decode_dict)
if 'Code' in result:
raise SaltCloudSystemExit(
pprint.pformat(result.get('Message', {}))

View file

@ -10,6 +10,7 @@ The Azure cloud module is used to control access to Microsoft Azure
:depends:
* `Microsoft Azure SDK for Python <https://pypi.python.org/pypi/azure>`_ >= 2.0rc5
* `Microsoft Azure Storage SDK for Python <https://pypi.python.org/pypi/azure-storage>`_ >= 0.32
* `Microsoft Azure CLI <https://pypi.python.org/pypi/azure-cli>` >= 2.0.12
:configuration:
Required provider parameters:
@ -62,8 +63,8 @@ import yaml
import collections
import salt.cache
import salt.config as config
import salt.utils
import salt.utils.cloud
import salt.utils.data
import salt.utils.files
from salt.utils.versions import LooseVersion
from salt.ext import six
@ -146,7 +147,13 @@ def __virtual__():
return False
if get_dependencies() is False:
return False
return (
False,
'The following dependencies are required to use the AzureARM driver: '
'Microsoft Azure SDK for Python >= 2.0rc5, '
'Microsoft Azure Storage SDK for Python >= 0.32, '
'Microsoft Azure CLI >= 2.0.12'
)
global cache # pylint: disable=global-statement,invalid-name
cache = salt.cache.Cache(__opts__)
@ -568,7 +575,7 @@ def show_instance(name, resource_group=None, call=None): # pylint: disable=unus
data['resource_group'] = resource_group
__utils__['cloud.cache_node'](
salt.utils.simple_types_filter(data),
salt.utils.data.simple_types_filter(data),
__active_provider_name__,
__opts__
)
@ -1453,7 +1460,7 @@ def make_safe(data):
'''
Turn object data into something serializable
'''
return salt.utils.simple_types_filter(object_to_dict(data))
return salt.utils.data.simple_types_filter(object_to_dict(data))
def create_security_group(call=None, kwargs=None): # pylint: disable=unused-argument

371
salt/cloud/clouds/clc.py Normal file
View file

@ -0,0 +1,371 @@
# -*- coding: utf-8 -*-
'''
CenturyLink Cloud Module
===================
.. versionadded:: 0yxgen
The CLC cloud module allows you to manage CLC Via the CLC SDK.
:codeauthor: Stephan Looney <slooney@stephanlooney.com>
Dependencies
============
- clc-sdk Python Module
- flask
CLC SDK
-------
clc-sdk can be installed via pip:
.. code-block:: bash
pip install clc-sdk
.. note::
For sdk reference see: https://github.com/CenturyLinkCloud/clc-python-sdk
Flask
-------
flask can be installed via pip:
.. code-block:: bash
pip install flask
Configuration
=============
To use this module: set up the clc-sdk, user, password, key in the
cloud configuration at
``/etc/salt/cloud.providers`` or ``/etc/salt/cloud.providers.d/clc.conf``:
.. code-block:: yaml
my-clc-config:
driver: clc
user: 'web-user'
password: 'verybadpass'
token: ''
token_pass:''
accountalias: 'ACT'
.. note::
The ``provider`` parameter in cloud provider configuration was renamed to ``driver``.
This change was made to avoid confusion with the ``provider`` parameter that is
used in cloud profile configuration. Cloud provider configuration now uses ``driver``
to refer to the salt-cloud driver that provides the underlying functionality to
connect to a cloud provider, while cloud profile configuration continues to use
``provider`` to refer to the cloud provider configuration that you define.
'''
# Import python libs
from __future__ import absolute_import
import logging
import time
import json
# Import salt libs
import importlib
from salt.exceptions import SaltCloudSystemExit
# Import salt cloud libs
import salt.config as config
# Get logging started
log = logging.getLogger(__name__)
# Attempt to import clc-sdk lib
try:
#when running this in linode's Ubuntu 16.x version the following line is required to get the clc sdk libraries to load
importlib.import_module('clc')
import clc
HAS_CLC = True
except ImportError:
HAS_CLC = False
# Disable InsecureRequestWarning generated on python > 2.6
try:
from requests.packages.urllib3 import disable_warnings # pylint: disable=no-name-in-module
disable_warnings()
except Exception:
pass
__virtualname__ = 'clc'
# Only load in this module if the CLC configurations are in place
def __virtual__():
'''
Check for CLC configuration and if required libs are available.
'''
if get_configured_provider() is False or get_dependencies() is False:
return False
return __virtualname__
def get_configured_provider():
return config.is_provider_configured(
__opts__,
__active_provider_name__ or __virtualname__,
('token', 'token_pass', 'user', 'password', )
)
def get_dependencies():
'''
Warn if dependencies aren't met.
'''
deps = {
'clc': HAS_CLC,
}
return config.check_driver_dependencies(
__virtualname__,
deps
)
def get_creds():
user = config.get_cloud_config_value(
'user', get_configured_provider(), __opts__, search_global=False
)
password = config.get_cloud_config_value(
'password', get_configured_provider(), __opts__, search_global=False
)
accountalias = config.get_cloud_config_value(
'accountalias', get_configured_provider(), __opts__, search_global=False
)
token = config.get_cloud_config_value(
'token', get_configured_provider(), __opts__, search_global=False
)
token_pass = config.get_cloud_config_value(
'token_pass', get_configured_provider(), __opts__, search_global=False
)
creds = {'user': user, 'password': password, 'token': token, 'token_pass': token_pass, 'accountalias': accountalias}
return creds
def list_nodes_full(call=None, for_output=True):
'''
Return a list of the VMs that are on the provider
'''
if call == 'action':
raise SaltCloudSystemExit(
'The list_nodes_full function must be called with -f or --function.'
)
creds = get_creds()
clc.v1.SetCredentials(creds["token"], creds["token_pass"])
servers_raw = clc.v1.Server.GetServers(location=None)
servers_raw = json.dumps(servers_raw)
servers = json.loads(servers_raw)
return servers
def get_queue_data(call=None, for_output=True):
creds = get_creds()
clc.v1.SetCredentials(creds["token"], creds["token_pass"])
cl_queue = clc.v1.Queue.List()
return cl_queue
def get_monthly_estimate(call=None, for_output=True):
'''
Return a list of the VMs that are on the provider
'''
creds = get_creds()
clc.v1.SetCredentials(creds["token"], creds["token_pass"])
if call == 'action':
raise SaltCloudSystemExit(
'The list_nodes_full function must be called with -f or --function.'
)
try:
billing_raw = clc.v1.Billing.GetAccountSummary(alias=creds["accountalias"])
billing_raw = json.dumps(billing_raw)
billing = json.loads(billing_raw)
billing = round(billing["MonthlyEstimate"], 2)
return {"Monthly Estimate": billing}
except RuntimeError:
return {"Monthly Estimate": 0}
def get_month_to_date(call=None, for_output=True):
'''
Return a list of the VMs that are on the provider
'''
creds = get_creds()
clc.v1.SetCredentials(creds["token"], creds["token_pass"])
if call == 'action':
raise SaltCloudSystemExit(
'The list_nodes_full function must be called with -f or --function.'
)
try:
billing_raw = clc.v1.Billing.GetAccountSummary(alias=creds["accountalias"])
billing_raw = json.dumps(billing_raw)
billing = json.loads(billing_raw)
billing = round(billing["MonthToDateTotal"], 2)
return {"Month To Date": billing}
except RuntimeError:
return 0
def get_server_alerts(call=None, for_output=True, **kwargs):
'''
Return a list of alerts from CLC as reported by their infra
'''
for key, value in kwargs.items():
servername = ""
if key == "servername":
servername = value
creds = get_creds()
clc.v2.SetCredentials(creds["user"], creds["password"])
alerts = clc.v2.Server(servername).Alerts()
return alerts
def get_group_estimate(call=None, for_output=True, **kwargs):
'''
Return a list of the VMs that are on the provider
usage: "salt-cloud -f get_group_estimate clc group=Dev location=VA1"
'''
for key, value in kwargs.items():
group = ""
location = ""
if key == "group":
group = value
if key == "location":
location = value
creds = get_creds()
clc.v1.SetCredentials(creds["token"], creds["token_pass"])
if call == 'action':
raise SaltCloudSystemExit(
'The list_nodes_full function must be called with -f or --function.'
)
try:
billing_raw = clc.v1.Billing.GetGroupEstimate(group=group, alias=creds["accountalias"], location=location)
billing_raw = json.dumps(billing_raw)
billing = json.loads(billing_raw)
estimate = round(billing["MonthlyEstimate"], 2)
month_to_date = round(billing["MonthToDate"], 2)
return {"Monthly Estimate": estimate, "Month to Date": month_to_date}
except RuntimeError:
return 0
def avail_images(call=None):
'''
returns a list of images available to you
'''
all_servers = list_nodes_full()
templates = {}
for server in all_servers:
if server["IsTemplate"]:
templates.update({"Template Name": server["Name"]})
return templates
def avail_locations(call=None):
'''
returns a list of locations available to you
'''
creds = get_creds()
clc.v1.SetCredentials(creds["token"], creds["token_pass"])
locations = clc.v1.Account.GetLocations()
return locations
def avail_sizes(call=None):
'''
use templates for this
'''
return {"Sizes": "Sizes are built into templates. Choose appropriate template"}
def get_build_status(req_id, nodename):
'''
get the build status from CLC to make sure we dont return to early
'''
counter = 0
req_id = str(req_id)
while counter < 10:
queue = clc.v1.Blueprint.GetStatus(request_id=(req_id))
if queue["PercentComplete"] == 100:
server_name = queue["Servers"][0]
creds = get_creds()
clc.v2.SetCredentials(creds["user"], creds["password"])
ip_addresses = clc.v2.Server(server_name).ip_addresses
internal_ip_address = ip_addresses[0]["internal"]
return internal_ip_address
else:
counter = counter + 1
log.info("Creating Cloud VM " + nodename + " Time out in " + str(10 - counter) + " minutes")
time.sleep(60)
def create(vm_):
'''
get the system build going
'''
creds = get_creds()
clc.v1.SetCredentials(creds["token"], creds["token_pass"])
cloud_profile = config.is_provider_configured(
__opts__,
__active_provider_name__ or __virtualname__,
('token',)
)
group = config.get_cloud_config_value(
'group', vm_, __opts__, search_global=False, default=None,
)
name = vm_['name']
description = config.get_cloud_config_value(
'description', vm_, __opts__, search_global=False, default=None,
)
ram = config.get_cloud_config_value(
'ram', vm_, __opts__, search_global=False, default=None,
)
backup_level = config.get_cloud_config_value(
'backup_level', vm_, __opts__, search_global=False, default=None,
)
template = config.get_cloud_config_value(
'template', vm_, __opts__, search_global=False, default=None,
)
password = config.get_cloud_config_value(
'password', vm_, __opts__, search_global=False, default=None,
)
cpu = config.get_cloud_config_value(
'cpu', vm_, __opts__, search_global=False, default=None,
)
network = config.get_cloud_config_value(
'network', vm_, __opts__, search_global=False, default=None,
)
location = config.get_cloud_config_value(
'location', vm_, __opts__, search_global=False, default=None,
)
if len(name) > 6:
name = name[0:6]
if len(password) < 9:
password = ''
clc_return = clc.v1.Server.Create(alias=None, location=(location), name=(name), template=(template), cpu=(cpu), ram=(ram), backup_level=(backup_level), group=(group), network=(network), description=(description), password=(password))
req_id = clc_return["RequestID"]
vm_['ssh_host'] = get_build_status(req_id, name)
__utils__['cloud.fire_event'](
'event',
'waiting for ssh',
'salt/cloud/{0}/waiting_for_ssh'.format(name),
sock_dir=__opts__['sock_dir'],
args={'ip_address': vm_['ssh_host']},
transport=__opts__['transport']
)
# Bootstrap!
ret = __utils__['cloud.bootstrap'](vm_, __opts__)
return_message = {"Server Name": name, "IP Address": vm_['ssh_host']}
ret.update(return_message)
return return_message
def destroy(name, call=None):
'''
destroy the vm
'''
return {"status": "destroying must be done via https://control.ctl.io at this time"}

View file

@ -33,7 +33,7 @@ import salt.config as config
import salt.utils.cloud
import salt.utils.event
from salt.cloud.libcloudfuncs import * # pylint: disable=redefined-builtin,wildcard-import,unused-wildcard-import
from salt.utils import namespaced_function
from salt.utils.functools import namespaced_function
from salt.exceptions import SaltCloudSystemExit
from salt.utils.versions import LooseVersion as _LooseVersion

View file

@ -298,7 +298,8 @@ def create(vm_):
'size': get_size(vm_),
'image': get_image(vm_),
'region': get_location(vm_),
'ssh_keys': []
'ssh_keys': [],
'tags': []
}
# backwards compat
@ -379,6 +380,10 @@ def create(vm_):
raise SaltCloudConfigError("'ipv6' should be a boolean value.")
kwargs['ipv6'] = ipv6
kwargs['tags'] = config.get_cloud_config_value(
'tags', vm_, __opts__, search_global=False, default=False
)
userdata_file = config.get_cloud_config_value(
'userdata_file', vm_, __opts__, search_global=False, default=None
)

View file

@ -55,12 +55,9 @@ except ImportError:
# Import generic libcloud functions
# from salt.cloud.libcloudfuncs import *
# Import salt libs
import salt.utils
# Import salt.cloud libs
from salt.cloud.libcloudfuncs import * # pylint: disable=redefined-builtin,wildcard-import,unused-wildcard-import
from salt.utils import namespaced_function
from salt.utils.functools import namespaced_function
import salt.utils.cloud
import salt.config as config
from salt.exceptions import (

View file

@ -82,7 +82,7 @@ except ImportError:
# pylint: enable=import-error
# Import salt libs
from salt.utils import namespaced_function
from salt.utils.functools import namespaced_function
from salt.ext import six
import salt.utils.cloud
import salt.utils.files
@ -2080,6 +2080,7 @@ def attach_disk(name=None, kwargs=None, call=None):
disk_name = kwargs['disk_name']
mode = kwargs.get('mode', 'READ_WRITE').upper()
boot = kwargs.get('boot', False)
auto_delete = kwargs.get('auto_delete', False)
if boot and boot.lower() in ['true', 'yes', 'enabled']:
boot = True
else:
@ -2109,7 +2110,8 @@ def attach_disk(name=None, kwargs=None, call=None):
transport=__opts__['transport']
)
result = conn.attach_volume(node, disk, ex_mode=mode, ex_boot=boot)
result = conn.attach_volume(node, disk, ex_mode=mode, ex_boot=boot,
ex_auto_delete=auto_delete)
__utils__['cloud.fire_event'](
'event',
@ -2389,6 +2391,8 @@ def create_attach_volumes(name, kwargs, call=None):
'type': The disk type, either pd-standard or pd-ssd. Optional, defaults to pd-standard.
'image': An image to use for this new disk. Optional.
'snapshot': A snapshot to use for this new disk. Optional.
'auto_delete': An option(bool) to keep or remove the disk upon
instance deletion. Optional, defaults to False.
Volumes are attached in the order in which they are given, thus on a new
node the first volume will be /dev/sdb, the second /dev/sdc, and so on.
@ -2401,9 +2405,10 @@ def create_attach_volumes(name, kwargs, call=None):
'-a or --action.'
)
volumes = kwargs['volumes']
volumes = literal_eval(kwargs['volumes'])
node = kwargs['node']
node_data = _expand_node(node)
conn = get_conn()
node_data = _expand_node(conn.ex_get_node(node))
letter = ord('a') - 1
for idx, volume in enumerate(volumes):
@ -2413,9 +2418,10 @@ def create_attach_volumes(name, kwargs, call=None):
'disk_name': volume_name,
'location': node_data['extra']['zone']['name'],
'size': volume['size'],
'type': volume['type'],
'image': volume['image'],
'snapshot': volume['snapshot']
'type': volume.get('type', 'pd-standard'),
'image': volume.get('image', None),
'snapshot': volume.get('snapshot', None),
'auto_delete': volume.get('auto_delete', False)
}
create_disk(volume_dict, 'function')
@ -2581,7 +2587,10 @@ def create(vm_=None, call=None):
ssh_user, ssh_key = __get_ssh_credentials(vm_)
vm_['ssh_host'] = __get_host(node_data, vm_)
vm_['key_filename'] = ssh_key
__utils__['cloud.bootstrap'](vm_, __opts__)
ret = __utils__['cloud.bootstrap'](vm_, __opts__)
ret.update(node_dict)
log.info('Created Cloud VM \'{0[name]}\''.format(vm_))
log.trace(
@ -2599,7 +2608,7 @@ def create(vm_=None, call=None):
transport=__opts__['transport']
)
return node_dict
return ret
def update_pricing(kwargs=None, call=None):

View file

@ -74,7 +74,6 @@ except ImportError:
# Import salt libs
import salt.config as config
import salt.utils
import salt.utils.cloud
from salt.exceptions import (
SaltCloudConfigError,
@ -466,18 +465,54 @@ def create(vm_):
return ret
except Exception as e: # pylint: disable=broad-except
# Try to clean up in as much cases as possible
log.info('Cleaning up after exception clean up items: {0}'.format(cleanup))
for leftover in cleanup:
what = leftover['what']
item = leftover['item']
if what == 'domain':
destroy_domain(conn, item)
if what == 'volume':
item.delete()
do_cleanup(cleanup)
# throw the root cause after cleanup
raise e
def do_cleanup(cleanup):
'''
Clean up clone domain leftovers as much as possible.
Extra robust clean up in order to deal with some small changes in libvirt
behavior over time. Passed in volumes and domains are deleted, any errors
are ignored. Used when cloning/provisioning a domain fails.
:param cleanup: list containing dictonaries with two keys: 'what' and 'item'.
If 'what' is domain the 'item' is a libvirt domain object.
If 'what' is volume then the item is a libvirt volume object.
Returns:
none
.. versionadded: 2017.7.3
'''
log.info('Cleaning up after exception')
for leftover in cleanup:
what = leftover['what']
item = leftover['item']
if what == 'domain':
log.info('Cleaning up {0} {1}'.format(what, item.name()))
try:
item.destroy()
log.debug('{0} {1} forced off'.format(what, item.name()))
except libvirtError:
pass
try:
item.undefineFlags(libvirt.VIR_DOMAIN_UNDEFINE_MANAGED_SAVE+
libvirt.VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA+
libvirt.VIR_DOMAIN_UNDEFINE_NVRAM)
log.debug('{0} {1} undefined'.format(what, item.name()))
except libvirtError:
pass
if what == 'volume':
try:
item.delete()
log.debug('{0} {1} cleaned up'.format(what, item.name()))
except libvirtError:
pass
def destroy(name, call=None):
"""
This function irreversibly destroys a virtual machine on the cloud provider.

View file

@ -17,9 +17,6 @@ import copy
import time
from pprint import pformat
# Import salt libs
import salt.utils
# Import salt cloud libs
import salt.utils.cloud
import salt.config as config

View file

@ -223,7 +223,7 @@ except ImportError as exc:
# Import Salt Cloud Libs
from salt.cloud.libcloudfuncs import * # pylint: disable=W0614,W0401
import salt.config as config
from salt.utils import namespaced_function
from salt.utils.functools import namespaced_function
from salt.exceptions import (
SaltCloudConfigError,
SaltCloudNotFound,

View file

@ -76,7 +76,7 @@ from salt.exceptions import (
SaltCloudNotFound,
SaltCloudSystemExit
)
import salt.utils
import salt.utils.data
import salt.utils.files
# Import Third Party Libs
@ -1575,7 +1575,7 @@ def image_persistent(call=None, kwargs=None):
server, user, password = _get_xml_rpc()
auth = ':'.join([user, password])
response = server.one.image.persistent(auth, int(image_id), salt.utils.is_true(persist))
response = server.one.image.persistent(auth, int(image_id), salt.utils.data.is_true(persist))
data = {
'action': 'image.persistent',
@ -2794,7 +2794,7 @@ def vm_allocate(call=None, kwargs=None):
server, user, password = _get_xml_rpc()
auth = ':'.join([user, password])
response = server.one.vm.allocate(auth, data, salt.utils.is_true(hold))
response = server.one.vm.allocate(auth, data, salt.utils.data.is_true(hold))
ret = {
'action': 'vm.allocate',
@ -3026,7 +3026,7 @@ def vm_deploy(name, kwargs=None, call=None):
response = server.one.vm.deploy(auth,
int(vm_id),
int(host_id),
salt.utils.is_true(capacity_maintained),
salt.utils.data.is_true(capacity_maintained),
int(datastore_id))
data = {
@ -3495,8 +3495,8 @@ def vm_migrate(name, kwargs=None, call=None):
response = server.one.vm.migrate(auth,
vm_id,
int(host_id),
salt.utils.is_true(live_migration),
salt.utils.is_true(capacity_maintained),
salt.utils.data.is_true(live_migration),
salt.utils.data.is_true(capacity_maintained),
int(datastore_id))
data = {
@ -3615,7 +3615,7 @@ def vm_resize(name, kwargs=None, call=None):
server, user, password = _get_xml_rpc()
auth = ':'.join([user, password])
vm_id = int(get_vm_id(kwargs={'name': name}))
response = server.one.vm.resize(auth, vm_id, data, salt.utils.is_true(capacity_maintained))
response = server.one.vm.resize(auth, vm_id, data, salt.utils.data.is_true(capacity_maintained))
ret = {
'action': 'vm.resize',
@ -4572,7 +4572,8 @@ def _list_nodes(full=False):
pass
vms[name]['id'] = vm.find('ID').text
vms[name]['image'] = vm.find('TEMPLATE').find('TEMPLATE_ID').text
if vm.find('TEMPLATE').find('TEMPLATE_ID'):
vms[name]['image'] = vm.find('TEMPLATE').find('TEMPLATE_ID').text
vms[name]['name'] = name
vms[name]['size'] = {'cpu': cpu_size, 'memory': memory_size}
vms[name]['state'] = vm.find('STATE').text

View file

@ -185,7 +185,6 @@ except Exception:
from salt.cloud.libcloudfuncs import * # pylint: disable=W0614,W0401
# Import salt libs
import salt.utils # Can be removed once namespaced_function has been moved
import salt.utils.cloud
import salt.utils.files
import salt.utils.pycrypto
@ -197,6 +196,7 @@ from salt.exceptions import (
SaltCloudExecutionFailure,
SaltCloudExecutionTimeout
)
from salt.utils.functools import namespaced_function
# Import netaddr IP matching
try:
@ -214,19 +214,19 @@ __virtualname__ = 'openstack'
# Some of the libcloud functions need to be in the same namespace as the
# functions defined in the module, so we create new function objects inside
# this module namespace
get_size = salt.utils.namespaced_function(get_size, globals())
get_image = salt.utils.namespaced_function(get_image, globals())
avail_locations = salt.utils.namespaced_function(avail_locations, globals())
avail_images = salt.utils.namespaced_function(avail_images, globals())
avail_sizes = salt.utils.namespaced_function(avail_sizes, globals())
script = salt.utils.namespaced_function(script, globals())
destroy = salt.utils.namespaced_function(destroy, globals())
reboot = salt.utils.namespaced_function(reboot, globals())
list_nodes = salt.utils.namespaced_function(list_nodes, globals())
list_nodes_full = salt.utils.namespaced_function(list_nodes_full, globals())
list_nodes_select = salt.utils.namespaced_function(list_nodes_select, globals())
show_instance = salt.utils.namespaced_function(show_instance, globals())
get_node = salt.utils.namespaced_function(get_node, globals())
get_size = namespaced_function(get_size, globals())
get_image = namespaced_function(get_image, globals())
avail_locations = namespaced_function(avail_locations, globals())
avail_images = namespaced_function(avail_images, globals())
avail_sizes = namespaced_function(avail_sizes, globals())
script = namespaced_function(script, globals())
destroy = namespaced_function(destroy, globals())
reboot = namespaced_function(reboot, globals())
list_nodes = namespaced_function(list_nodes, globals())
list_nodes_full = namespaced_function(list_nodes_full, globals())
list_nodes_select = namespaced_function(list_nodes_select, globals())
show_instance = namespaced_function(show_instance, globals())
get_node = namespaced_function(get_node, globals())
# Only load in this module is the OPENSTACK configurations are in place

View file

@ -75,7 +75,7 @@ from salt.exceptions import (
import salt.utils.cloud
from salt.cloud.libcloudfuncs import get_size, get_image, script, show_instance
from salt.utils import namespaced_function
from salt.utils.functools import namespaced_function
get_size = namespaced_function(get_size, globals())
get_image = namespaced_function(get_image, globals())

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