mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 17:09:03 +00:00
Merge pull request #26189 from basepi/merge-forward-develop
Merge forward from 2015.8 to develop
This commit is contained in:
commit
fd70187176
@ -3,13 +3,13 @@
|
||||
# directory is identical.
|
||||
|
||||
#my-digitalocean-config:
|
||||
# provider: digital_ocean
|
||||
# driver: digital_ocean
|
||||
# client_key: wFGEwgregeqw3435gDger
|
||||
# api_key: GDE43t43REGTrkilg43934t34qT43t4dgegerGEgg
|
||||
# location: New York 1
|
||||
|
||||
#my-aws-quick-start:
|
||||
# provider: ec2
|
||||
# driver: ec2
|
||||
# id: HJGRYCILJLKJYG
|
||||
# key: 'kdjgfsgm;woormgl/aserigjksjdhasdfgn'
|
||||
# keyname: test
|
||||
@ -17,7 +17,7 @@
|
||||
# private_key: /root/test.pem
|
||||
|
||||
#my-aws-default:
|
||||
# provider: ec2
|
||||
# driver: ec2
|
||||
# id: HJGRYCILJLKJYG
|
||||
# key: 'kdjgfsgm;woormgl/aserigjksjdhasdfgn'
|
||||
# keyname: test
|
||||
@ -25,12 +25,12 @@
|
||||
# private_key: /root/test.pem
|
||||
|
||||
#my-gogrid-config:
|
||||
# provider: gogrid
|
||||
# driver: gogrid
|
||||
# apikey: asdff7896asdh789
|
||||
# sharedsecret: saltybacon
|
||||
|
||||
#my-openstack-hp-config:
|
||||
# provider: openstack
|
||||
# driver: openstack
|
||||
# identity_url: 'https://region-a.geo-1.identity.hpcloudsvc.com:35357/v2.0/'
|
||||
# compute_name: Compute
|
||||
# compute_region: 'az-1.region-a.geo-1'
|
||||
@ -41,7 +41,7 @@
|
||||
# password: mypass
|
||||
|
||||
#my-ibmsce-config:
|
||||
# provider: ibmsce
|
||||
# driver: ibmsce
|
||||
# user: myuser@mycorp.com
|
||||
# password: mypass
|
||||
# ssh_key_name: mykey
|
||||
@ -49,30 +49,30 @@
|
||||
# location: Raleigh
|
||||
|
||||
#my-joyent-config:
|
||||
# provider: joyent
|
||||
# driver: joyent
|
||||
# user: fred
|
||||
# password: saltybacon
|
||||
# private_key: /root/joyent.pem
|
||||
|
||||
#my-linode-config:
|
||||
# provider: linode
|
||||
# driver: linode
|
||||
# apikey: asldkgfakl;sdfjsjaslfjaklsdjf;askldjfaaklsjdfhasldsadfghdkf
|
||||
# password: F00barbaz
|
||||
|
||||
#my-parallels-config:
|
||||
# provider: parallels
|
||||
# driver: parallels
|
||||
# user: myuser
|
||||
# password: xyzzy
|
||||
# url: https://api.cloud.xmission.com:4465/paci/v1.0/
|
||||
|
||||
#my-proxmox-config:
|
||||
# provider: proxmox
|
||||
# driver: proxmox
|
||||
# user: saltcloud@pve
|
||||
# password: xyzzy
|
||||
# url: your.proxmox.host
|
||||
|
||||
#my-openstack-rackspace-config:
|
||||
# provider: openstack
|
||||
# driver: openstack
|
||||
# identity_url: 'https://identity.api.rackspacecloud.com/v2.0/tokens'
|
||||
# compute_name: cloudServersOpenStack
|
||||
# protocol: ipv4
|
||||
@ -83,4 +83,4 @@
|
||||
# apikey: 901d3f579h23c8v73q9
|
||||
|
||||
#my-saltify-config:
|
||||
# provider: saltify
|
||||
# driver: saltify
|
||||
|
@ -1,5 +1,5 @@
|
||||
#my-digitalocean-config:
|
||||
# provider: digital_ocean
|
||||
# driver: digital_ocean
|
||||
# client_key: wFGEwgregeqw3435gDger
|
||||
# api_key: GDE43t43REGTrkilg43934t34qT43t4dgegerGEgg
|
||||
# location: New York 1
|
||||
|
@ -1,5 +1,5 @@
|
||||
#my-aws-quick-start:
|
||||
# provider: ec2
|
||||
# driver: ec2
|
||||
# id: HJGRYCILJLKJYG
|
||||
# key: 'kdjgfsgm;woormgl/aserigjksjdhasdfgn'
|
||||
# keyname: test
|
||||
@ -7,7 +7,7 @@
|
||||
# private_key: /root/test.pem
|
||||
|
||||
#my-aws-default:
|
||||
# provider: ec2
|
||||
# driver: ec2
|
||||
# id: HJGRYCILJLKJYG
|
||||
# key: 'kdjgfsgm;woormgl/aserigjksjdhasdfgn'
|
||||
# keyname: test
|
||||
|
@ -1,4 +1,4 @@
|
||||
#my-gogrid-config:
|
||||
# provider: gogrid
|
||||
# driver: gogrid
|
||||
# apikey: asdff7896asdh789
|
||||
# sharedsecret: saltybacon
|
||||
|
@ -1,5 +1,5 @@
|
||||
#my-openstack-hp-config:
|
||||
# provider: openstack
|
||||
# driver: openstack
|
||||
# identity_url: 'https://region-a.geo-1.identity.hpcloudsvc.com:35357/v2.0/'
|
||||
# compute_name: Compute
|
||||
# compute_region: 'az-1.region-a.geo-1'
|
||||
|
@ -1,5 +1,5 @@
|
||||
#my-ibmsce-config:
|
||||
# provider: ibmsce
|
||||
# driver: ibmsce
|
||||
# user: myuser@mycorp.com
|
||||
# password: mypass
|
||||
# ssh_key_name: mykey
|
||||
|
@ -1,5 +1,5 @@
|
||||
#my-joyent-config:
|
||||
# provider: joyent
|
||||
# driver: joyent
|
||||
# user: fred
|
||||
# password: saltybacon
|
||||
# private_key: /root/joyent.pem
|
||||
|
@ -1,4 +1,4 @@
|
||||
#my-linode-config:
|
||||
# provider: linode
|
||||
# driver: linode
|
||||
# apikey: asldkgfakl;sdfjsjaslfjaklsdjf;askldjfaaklsjdfhasldsadfghdkf
|
||||
# password: F00barbaz
|
||||
|
@ -1,5 +1,5 @@
|
||||
#my-parallels-config:
|
||||
# provider: parallels
|
||||
# driver: parallels
|
||||
# user: myuser
|
||||
# password: xyzzy
|
||||
# url: https://api.cloud.xmission.com:4465/paci/v1.0/
|
||||
|
@ -1,6 +1,5 @@
|
||||
#my-proxmox-config:
|
||||
# provider: proxmox
|
||||
# driver: proxmox
|
||||
# user: saltcloud@pve
|
||||
# password: xyzzy
|
||||
# url: your.proxmox.host
|
||||
|
@ -1,5 +1,5 @@
|
||||
#my-openstack-rackspace-config:
|
||||
# provider: openstack
|
||||
# driver: openstack
|
||||
# identity_url: 'https://identity.api.rackspacecloud.com/v2.0/tokens'
|
||||
# compute_name: cloudServersOpenStack
|
||||
# protocol: ipv4
|
||||
|
@ -1,2 +1,2 @@
|
||||
#my-saltify-config:
|
||||
# provider: saltify
|
||||
# driver: saltify
|
||||
|
@ -1,5 +1,5 @@
|
||||
#my-vsphere-config:
|
||||
# provider: vsphere
|
||||
# driver: vsphere
|
||||
# user: myuser
|
||||
# password: verybadpass
|
||||
# url: 'https://10.1.1.1:443'
|
||||
|
@ -1140,14 +1140,12 @@ Walkthrough <gitfs-per-remote-config>`.
|
||||
|
||||
.. versionadded:: 2014.7.0
|
||||
|
||||
Specify the provider to be used for gitfs. More information can be found in the
|
||||
:ref:`GitFS Walkthrough <gitfs-dependencies>`.
|
||||
Optional parameter used to specify the provider to be used for gitfs. More
|
||||
information can be found in the :ref:`GitFS Walkthrough <gitfs-dependencies>`.
|
||||
|
||||
Specify one value among valid values: ``gitpython``, ``pygit2``, ``dulwich``
|
||||
|
||||
.. _pygit2: https://github.com/libgit2/pygit2
|
||||
.. _GitPython: https://github.com/gitpython-developers/GitPython
|
||||
.. _dulwich: https://www.samba.org/~jelmer/dulwich/
|
||||
Must be one of the following: ``pygit2``, ``gitpython``, or ``dulwich``. If
|
||||
unset, then each will be tried in that same order, and the first one with a
|
||||
compatible version installed will be the provider that is used.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
@ -1160,11 +1158,11 @@ Specify one value among valid values: ``gitpython``, ``pygit2``, ``dulwich``
|
||||
|
||||
Default: ``True``
|
||||
|
||||
The ``gitfs_ssl_verify`` option specifies whether to ignore SSL certificate
|
||||
errors when contacting the gitfs backend. You might want to set this to
|
||||
``False`` if you're using a git backend that uses a self-signed certificate but
|
||||
keep in mind that setting this flag to anything other than the default of
|
||||
``True`` is a security concern, you may want to try using the ssh transport.
|
||||
Specifies whether or not to ignore SSL certificate errors when contacting the
|
||||
remote repository. You might want to set this to ``False`` if you're using a
|
||||
git repo that uses a self-signed certificate. However, keep in mind that
|
||||
setting this to anything other ``True`` is a considered insecure, and using an
|
||||
SSH-based transport (if available) may be a better option.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
@ -1942,11 +1940,27 @@ ext_pillar.
|
||||
|
||||
ext_pillar_first: False
|
||||
|
||||
.. _git-pillar-config-opts:
|
||||
.. _git_pillar-config-opts:
|
||||
|
||||
Git External Pillar (git_pillar) Configuration Options
|
||||
------------------------------------------------------
|
||||
|
||||
.. conf_master:: git_pillar_provider
|
||||
|
||||
``git_pillar_provider``
|
||||
***********************
|
||||
|
||||
.. versionadded:: 2015.8.0
|
||||
|
||||
Specify the provider to be used for git_pillar. Must be either ``pygit2`` or
|
||||
``gitpython``. If unset, then both will be tried in that same order, and the
|
||||
first one with a compatible version installed will be the provider that is
|
||||
used.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
git_pillar_provider: gitpython
|
||||
|
||||
.. conf_master:: git_pillar_base
|
||||
|
||||
``git_pillar_base``
|
||||
@ -2030,7 +2044,7 @@ environment irrespective of the branch/tag being used.
|
||||
.. conf_master:: git_pillar_root
|
||||
|
||||
``git_pillar_root``
|
||||
********************
|
||||
*******************
|
||||
|
||||
.. versionadded:: 2015.8.0
|
||||
|
||||
@ -2077,23 +2091,23 @@ files would be looked for in a subdirectory called ``pillar``.
|
||||
Default: ``True``
|
||||
|
||||
Specifies whether or not to ignore SSL certificate errors when contacting the
|
||||
git_pillar remote repository. You might want to set this to ``False`` if you're
|
||||
using a git backend that uses a self-signed certificate but keep in mind that
|
||||
setting this flag to anything other than the default of ``True`` is a security
|
||||
concern, you may want to try using the ssh transport.
|
||||
remote repository. You might want to set this to ``False`` if you're using a
|
||||
git repo that uses a self-signed certificate. However, keep in mind that
|
||||
setting this to anything other ``True`` is a considered insecure, and using an
|
||||
SSH-based transport (if available) may be a better option.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
git_pillar_ssl_verify: True
|
||||
|
||||
git_pillar Authentication Options
|
||||
*********************************
|
||||
Git External Pillar Authentication Options
|
||||
******************************************
|
||||
|
||||
These parameters only currently apply to the pygit2 gitfs provider.
|
||||
Authentication works the same as it does in gitfs, as outlined in the
|
||||
:ref:`GitFS Walkthrough <gitfs-authentication>`, though the global
|
||||
configuration options are named differently to reflect that they are for
|
||||
git_pillar instead of gitfs.
|
||||
These parameters only currently apply to the ``pygit2``
|
||||
:conf_master:`git_pillar_provider`. Authentication works the same as it does
|
||||
in gitfs, as outlined in the :ref:`GitFS Walkthrough <gitfs-authentication>`,
|
||||
though the global configuration options are named differently to reflect that
|
||||
they are for git_pillar instead of gitfs.
|
||||
|
||||
.. conf_master:: git_pillar_user
|
||||
|
||||
@ -2700,57 +2714,238 @@ option then the master will log a warning message.
|
||||
- master.d/*
|
||||
- /etc/roles/webserver
|
||||
|
||||
.. _winrepo-config-opts:
|
||||
|
||||
Windows Software Repo Settings
|
||||
==============================
|
||||
|
||||
.. conf_master:: winrepo_provider
|
||||
|
||||
``winrepo_provider``
|
||||
--------------------
|
||||
|
||||
.. versionadded:: 2015.8.0
|
||||
|
||||
Specify the provider to be used for winrepo. Must be either ``pygit2`` or
|
||||
``gitpython``. If unset, then both will be tried in that same order, and the
|
||||
first one with a compatible version installed will be the provider that is
|
||||
used.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
winrepo_provider: gitpython
|
||||
|
||||
.. conf_master:: winrepo_dir
|
||||
.. conf_master:: win_repo
|
||||
|
||||
``win_repo``
|
||||
------------
|
||||
``winrepo_dir``
|
||||
---------------
|
||||
|
||||
.. versionchanged:: 2015.8.0
|
||||
Renamed from ``win_repo`` to ``winrepo_dir``
|
||||
|
||||
Default: ``/srv/salt/win/repo``
|
||||
|
||||
Location of the repo on the master
|
||||
|
||||
Location on the master where the :conf_master:`winrepo_remotes` are checked
|
||||
out.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
win_repo: '/srv/salt/win/repo'
|
||||
winrepo_dir: /srv/salt/win/repo
|
||||
|
||||
.. conf_master:: winrepo_cachefile
|
||||
.. conf_master:: win_repo_mastercachefile
|
||||
|
||||
``win_repo_mastercachefile``
|
||||
----------------------------
|
||||
``winrepo_cachefile``
|
||||
---------------------
|
||||
|
||||
Default: ``/srv/salt/win/repo/winrepo.p``
|
||||
.. versionchanged:: 2015.8.0
|
||||
Renamed from ``win_repo_mastercachefile`` to ``winrepo_cachefile``
|
||||
|
||||
Default: ``winrepo.p``
|
||||
|
||||
Path relative to :conf_master:`winrepo_dir` where the winrepo cache should be
|
||||
created.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
win_repo_mastercachefile: '/srv/salt/win/repo/winrepo.p'
|
||||
winrepo_cachefile: winrepo.p
|
||||
|
||||
.. conf_master:: winrepo_remotes
|
||||
.. conf_master:: win_gitrepos
|
||||
|
||||
``win_gitrepos``
|
||||
----------------
|
||||
``winrepo_remotes``
|
||||
-------------------
|
||||
|
||||
.. versionchanged:: 2015.8.0
|
||||
Renamed from ``win_gitrepos`` to ``winrepo_remotes``
|
||||
|
||||
Default: ``['https://github.com/saltstack/salt-winrepo.git']``
|
||||
|
||||
List of git repositories to checkout and include in the winrepo
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
winrepo_remotes:
|
||||
- https://github.com/saltstack/salt-winrepo.git
|
||||
|
||||
To specify a specific revision of the repository, prepend a commit ID to the
|
||||
URL of the the repository:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
winrepo_remotes:
|
||||
- '<commit_id> https://github.com/saltstack/salt-winrepo.git'
|
||||
|
||||
Replace ``<commit_id>`` with the SHA1 hash of a commit ID. Specifying a commit
|
||||
ID is useful in that it allows one to revert back to a previous version in the
|
||||
event that an error is introduced in the latest revision of the repo.
|
||||
|
||||
.. conf_master:: winrepo_branch
|
||||
|
||||
``winrepo_branch``
|
||||
------------------
|
||||
|
||||
.. versionadded:: 2015.8.0
|
||||
|
||||
Default: ``master``
|
||||
|
||||
If the branch is omitted from a winrepo remote, then this branch will be
|
||||
used instead. For example, in the configuration below, the first two remotes
|
||||
would use the ``winrepo`` branch/tag, while the third would use the ``foo``
|
||||
branch/tag.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
winrepo_branch: winrepo
|
||||
|
||||
ext_pillar:
|
||||
- git:
|
||||
- https://mygitserver/winrepo1.git
|
||||
- https://mygitserver/winrepo2.git:
|
||||
- foo https://mygitserver/winrepo3.git
|
||||
|
||||
.. conf_master:: winrepo_ssl_verify
|
||||
|
||||
``winrepo_ssl_verify``
|
||||
----------------------
|
||||
|
||||
.. versionadded:: 2015.8.0
|
||||
|
||||
Default: ``True``
|
||||
|
||||
Specifies whether or not to ignore SSL certificate errors when contacting the
|
||||
remote repository. You might want to set this to ``False`` if you're using a
|
||||
git repo that uses a self-signed certificate. However, keep in mind that
|
||||
setting this to anything other ``True`` is a considered insecure, and using an
|
||||
SSH-based transport (if available) may be a better option.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
winrepo_ssl_verify: True
|
||||
|
||||
Winrepo Authentication Options
|
||||
------------------------------
|
||||
|
||||
These parameters only currently apply to the ``pygit2``
|
||||
:conf_master:`winrepo_provider`. Authentication works the same as it does in
|
||||
gitfs, as outlined in the :ref:`GitFS Walkthrough <gitfs-authentication>`,
|
||||
though the global configuration options are named differently to reflect that
|
||||
they are for winrepo instead of gitfs.
|
||||
|
||||
.. conf_master:: winrepo_user
|
||||
|
||||
``winrepo_user``
|
||||
****************
|
||||
|
||||
.. versionadded:: 2015.8.0
|
||||
|
||||
Default: ``''``
|
||||
|
||||
List of git repositories to include with the local repo.
|
||||
Along with :conf_master:`winrepo_password`, is used to authenticate to HTTPS
|
||||
remotes.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
win_gitrepos:
|
||||
- 'https://github.com/saltstack/salt-winrepo.git'
|
||||
winrepo_user: git
|
||||
|
||||
To specify a specific revision of the repository, preface the
|
||||
repository location with a commit ID:
|
||||
.. conf_master:: winrepo_password
|
||||
|
||||
``winrepo_password``
|
||||
********************
|
||||
|
||||
.. versionadded:: 2015.8.0
|
||||
|
||||
Default: ``''``
|
||||
|
||||
Along with :conf_master:`winrepo_user`, is used to authenticate to HTTPS
|
||||
remotes. This parameter is not required if the repository does not use
|
||||
authentication.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
win_gitrepos:
|
||||
- '<commit_id> https://github.com/saltstack/salt-winrepo.git'
|
||||
winrepo_password: mypassword
|
||||
|
||||
Replacing ``<commit_id>`` with the ID from GitHub. Specifying a commit
|
||||
ID is useful if you need to revert to a previous version if an error
|
||||
is introduced in the latest version.
|
||||
.. conf_master:: winrepo_insecure_auth
|
||||
|
||||
``winrepo_insecure_auth``
|
||||
*************************
|
||||
|
||||
.. versionadded:: 2015.8.0
|
||||
|
||||
Default: ``False``
|
||||
|
||||
By default, Salt will not authenticate to an HTTP (non-HTTPS) remote. This
|
||||
parameter enables authentication over HTTP. **Enable this at your own risk.**
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
winrepo_insecure_auth: True
|
||||
|
||||
.. conf_master:: winrepo_pubkey
|
||||
|
||||
``winrepo_pubkey``
|
||||
******************
|
||||
|
||||
.. versionadded:: 2015.8.0
|
||||
|
||||
Default: ``''``
|
||||
|
||||
Along with :conf_master:`winrepo_privkey` (and optionally
|
||||
:conf_master:`winrepo_passphrase`), is used to authenticate to SSH remotes.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
winrepo_pubkey: /path/to/key.pub
|
||||
|
||||
.. conf_master:: winrepo_privkey
|
||||
|
||||
``winrepo_privkey``
|
||||
*******************
|
||||
|
||||
.. versionadded:: 2015.8.0
|
||||
|
||||
Default: ``''``
|
||||
|
||||
Along with :conf_master:`winrepo_pubkey` (and optionally
|
||||
:conf_master:`winrepo_passphrase`), is used to authenticate to SSH remotes.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
winrepo_privkey: /path/to/key
|
||||
|
||||
.. conf_master:: winrepo_passphrase
|
||||
|
||||
``winrepo_passphrase``
|
||||
**********************
|
||||
|
||||
.. versionadded:: 2015.8.0
|
||||
|
||||
Default: ``''``
|
||||
|
||||
This parameter is optional, required only when the SSH key being used to
|
||||
authenticate is protected by a passphrase.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
winrepo_passphrase: mypassphrase
|
||||
|
@ -1207,3 +1207,75 @@ have other services that need to go with it.
|
||||
.. code-block:: yaml
|
||||
|
||||
update_restart_services: ['salt-minion']
|
||||
|
||||
|
||||
Windows Software Repo Settings
|
||||
==============================
|
||||
|
||||
.. important::
|
||||
To use these config options, the minion must be running in masterless mode
|
||||
(set :conf_minion:`file_client` to ``local``).
|
||||
|
||||
.. conf_minion:: winrepo_dir
|
||||
.. conf_minion:: win_repo
|
||||
|
||||
``winrepo_dir``
|
||||
---------------
|
||||
|
||||
.. versionchanged:: 2015.8.0
|
||||
Renamed from ``win_repo`` to ``winrepo_dir``
|
||||
|
||||
Default: ``c:\\salt\\file_roots\\winrepo``
|
||||
|
||||
Location on the minion where the :conf_minion:`winrepo_remotes` are checked
|
||||
out.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
winrepo_dir: /srv/salt/win/repo
|
||||
|
||||
.. conf_minion:: winrepo_cachefile
|
||||
|
||||
``winrepo_cachefile``
|
||||
---------------------
|
||||
|
||||
.. versionchanged:: 2015.8.0
|
||||
Renamed from ``win_repo_mastercachefile`` to ``winrepo_cachefile``
|
||||
|
||||
Default: ``winrepo.p``
|
||||
|
||||
Path relative to :conf_minion:`winrepo_dir` where the winrepo cache should be
|
||||
created.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
winrepo_cachefile: winrepo.p
|
||||
|
||||
.. conf_minion:: winrepo_remotes
|
||||
.. conf_minion:: win_gitrepos
|
||||
|
||||
``winrepo_remotes``
|
||||
-------------------
|
||||
|
||||
.. versionadded:: 2015.8.0
|
||||
|
||||
Default: ``['https://github.com/saltstack/salt-winrepo.git']``
|
||||
|
||||
List of git repositories to checkout and include in the winrepo
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
winrepo_remotes:
|
||||
- https://github.com/saltstack/salt-winrepo.git
|
||||
|
||||
To specify a specific revision of the repository, prepend a commit ID to the
|
||||
URL of the the repository:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
winrepo_remotes:
|
||||
- '<commit_id> https://github.com/saltstack/salt-winrepo.git'
|
||||
|
||||
Replace ``<commit_id>`` with the SHA1 hash of a commit ID. Specifying a commit
|
||||
ID is useful in that it allows one to revert back to a previous version in the
|
||||
event that an error is introduced in the latest revision of the repo.
|
||||
|
@ -93,8 +93,25 @@ A State Module must return a dict containing the following keys/values:
|
||||
containing the old/new values. For example, the pkg state's **changes** dict
|
||||
has one key for each package changed, with the "old" and "new" keys in its
|
||||
sub-dict containing the old and new versions of the package.
|
||||
- **result:** A boolean value. *True* if the action was successful, otherwise
|
||||
*False*.
|
||||
- **result:** A tristate value. ``True`` if the action was successful,
|
||||
``False`` if it was not, or ``None`` if the state was run in test mode,
|
||||
``test=True``, and changes would have been made if the state was not run in
|
||||
test mode.
|
||||
|
||||
+--------------------+-----------+-----------+
|
||||
| | live mode | test mode |
|
||||
+====================+===========+===========+
|
||||
| no changes | ``True`` | ``True`` |
|
||||
+--------------------+-----------+-----------+
|
||||
| successful changes | ``True`` | ``None`` |
|
||||
+--------------------+-----------+-----------+
|
||||
| failed changes | ``False`` | ``None`` |
|
||||
+--------------------+-----------+-----------+
|
||||
|
||||
.. note::
|
||||
|
||||
Test mode does not predict if the changes will be successful or not.
|
||||
|
||||
- **comment:** A string containing a summary of the result.
|
||||
|
||||
The return data can also, include the **pchanges** key, this statnds for
|
||||
|
@ -3,7 +3,7 @@ Getting Started With Aliyun ECS
|
||||
===============================
|
||||
|
||||
The Aliyun ECS (Elastic Computer Service) is one of the most popular public
|
||||
cloud providers in China. This cloud provider can be used to manage aliyun
|
||||
cloud hosts in China. This cloud host can be used to manage aliyun
|
||||
instance using salt-cloud.
|
||||
|
||||
http://www.aliyun.com/
|
||||
@ -34,6 +34,14 @@ under "My Service" tab.
|
||||
location: cn-qingdao
|
||||
driver: aliyun
|
||||
|
||||
.. note::
|
||||
.. versionchanged:: 2015.8.0
|
||||
|
||||
The ``provider`` parameter in cloud provider definitions was renamed to ``driver``. This
|
||||
change was made to avoid confusion with the ``provider`` parameter that is used in cloud profile
|
||||
definitions. Cloud provider definitions now use ``driver`` to refer to the Salt cloud module that
|
||||
provides the underlying functionality to connect to a cloud host, while cloud profiles continue
|
||||
to use ``provider`` to refer to provider configurations that you define.
|
||||
|
||||
Profiles
|
||||
========
|
||||
@ -46,7 +54,7 @@ Set up an initial profile at ``/etc/salt/cloud.profiles`` or in the
|
||||
.. code-block:: yaml
|
||||
|
||||
aliyun_centos:
|
||||
driver: my-aliyun-config
|
||||
provider: my-aliyun-config
|
||||
size: ecs.t1.small
|
||||
location: cn-qingdao
|
||||
securitygroup: G1989096784427999
|
||||
@ -161,4 +169,4 @@ for the ``salt-cloud`` command:
|
||||
|
||||
.. note::
|
||||
|
||||
Aliyun ECS REST API documentation is available from `Aliyun ECS API <http://help.aliyun.com/list/11113464.html?spm=5176.7224429.1997282881.55.J9XhVL>`_.
|
||||
Aliyun ECS REST API documentation is available from `Aliyun ECS API <http://help.aliyun.com/list/11113464.html?spm=5176.7224429.1997282881.55.J9XhVL>`_.
|
||||
|
@ -5,9 +5,9 @@ Getting Started With AWS EC2
|
||||
Amazon EC2 is a very widely used public cloud platform and one of the core
|
||||
platforms Salt Cloud has been built to support.
|
||||
|
||||
Previously, the suggested provider for AWS EC2 was the ``aws`` provider. This
|
||||
has been deprecated in favor of the ``ec2`` provider. Configuration using the
|
||||
old ``aws`` provider will still function, but that driver is no longer in
|
||||
Previously, the suggested driver for AWS EC2 was the ``aws`` driver. This
|
||||
has been deprecated in favor of the ``ec2`` driver. Configuration using the
|
||||
old ``aws`` driver will still function, but that driver is no longer in
|
||||
active development.
|
||||
|
||||
|
||||
@ -146,6 +146,14 @@ parameters are discussed in more detail below.
|
||||
|
||||
driver: ec2
|
||||
|
||||
.. note::
|
||||
.. versionchanged:: 2015.8.0
|
||||
|
||||
The ``provider`` parameter in cloud provider definitions was renamed to ``driver``. This
|
||||
change was made to avoid confusion with the ``provider`` parameter that is used in cloud profile
|
||||
definitions. Cloud provider definitions now use ``driver`` to refer to the Salt cloud module that
|
||||
provides the underlying functionality to connect to a cloud host, while cloud profiles continue
|
||||
to use ``provider`` to refer to provider configurations that you define.
|
||||
|
||||
Access Credentials
|
||||
==================
|
||||
|
@ -65,6 +65,14 @@ tab within the "Settings" section of the management portal.
|
||||
|
||||
Optionally, a ``management_host`` may be configured, if necessary for the region.
|
||||
|
||||
.. note::
|
||||
.. versionchanged:: 2015.8.0
|
||||
|
||||
The ``provider`` parameter in cloud provider definitions was renamed to ``driver``. This
|
||||
change was made to avoid confusion with the ``provider`` parameter that is used in cloud profile
|
||||
definitions. Cloud provider definitions now use ``driver`` to refer to the Salt cloud module that
|
||||
provides the underlying functionality to connect to a cloud host, while cloud profiles continue
|
||||
to use ``provider`` to refer to provider configurations that you define.
|
||||
|
||||
Cloud Profiles
|
||||
==============
|
||||
|
@ -19,7 +19,7 @@ Assuming there is a profile configured as following:
|
||||
.. code-block:: bash
|
||||
|
||||
fedora_rackspace:
|
||||
provider: rackspace
|
||||
provider: my-rackspace-config
|
||||
image: Fedora 17
|
||||
size: 256 server
|
||||
script: bootstrap-salt
|
||||
@ -43,4 +43,4 @@ For example, to delete the VM created on above example, use:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-cloud -d fedora_http_01
|
||||
salt-cloud -d fedora_http_01
|
||||
|
@ -1,24 +1,24 @@
|
||||
==============================
|
||||
Writing Cloud Provider Modules
|
||||
==============================
|
||||
============================
|
||||
Writing Cloud Driver Modules
|
||||
============================
|
||||
|
||||
Salt Cloud runs on a module system similar to the main Salt project. The
|
||||
modules inside saltcloud exist in the ``salt/cloud/clouds`` directory of the
|
||||
salt source.
|
||||
|
||||
There are two basic types of cloud modules. If a cloud provider is supported by
|
||||
There are two basic types of cloud modules. If a cloud host is supported by
|
||||
libcloud, then using it is the fastest route to getting a module written. The
|
||||
Apache Libcloud project is located at:
|
||||
|
||||
http://libcloud.apache.org/
|
||||
|
||||
Not every cloud provider is supported by libcloud. Additionally, not every
|
||||
feature in a supported cloud provider is necessary supported by libcloud. In
|
||||
Not every cloud host is supported by libcloud. Additionally, not every
|
||||
feature in a supported cloud host is necessarily supported by libcloud. In
|
||||
either of these cases, a module can be created which does not rely on libcloud.
|
||||
|
||||
All Modules
|
||||
===========
|
||||
The following functions are required by all modules, whether or not they are
|
||||
All Driver Modules
|
||||
==================
|
||||
The following functions are required by all driver modules, whether or not they are
|
||||
based on libcloud.
|
||||
|
||||
The __virtual__() Function
|
||||
@ -51,17 +51,17 @@ The create() Function
|
||||
---------------------
|
||||
The most important function that does need to be manually written is the
|
||||
``create()`` function. This is what is used to request a virtual machine to be
|
||||
created by the cloud provider, wait for it to become available, and then
|
||||
created by the cloud host, wait for it to become available, and then
|
||||
(optionally) log in and install Salt on it.
|
||||
|
||||
A good example to follow for writing a cloud provider module based on libcloud
|
||||
A good example to follow for writing a cloud driver module based on libcloud
|
||||
is the module provided for Linode:
|
||||
|
||||
https://github.com/saltstack/salt/tree/develop/salt/cloud/clouds/linode.py
|
||||
|
||||
The basic flow of a ``create()`` function is as follows:
|
||||
|
||||
* Send a request to the cloud provider to create a virtual machine.
|
||||
* Send a request to the cloud host to create a virtual machine.
|
||||
* Wait for the virtual machine to become available.
|
||||
* Generate kwargs to be used to deploy Salt.
|
||||
* Log into the virtual machine and deploy Salt.
|
||||
@ -80,20 +80,20 @@ configuration and environment variables.
|
||||
The first thing the ``create()`` function must do is fire an event stating that
|
||||
it has started the create process. This event is tagged
|
||||
``salt/cloud/<vm name>/creating``. The payload contains the names of the VM,
|
||||
profile and provider.
|
||||
profile, and provider.
|
||||
|
||||
A set of kwargs is then usually created, to describe the parameters required
|
||||
by the cloud provider to request the virtual machine.
|
||||
by the cloud host to request the virtual machine.
|
||||
|
||||
An event is then fired to state that a virtual machine is about to be requested.
|
||||
It is tagged as ``salt/cloud/<vm name>/requesting``. The payload contains most
|
||||
or all of the parameters that will be sent to the cloud provider. Any private
|
||||
or all of the parameters that will be sent to the cloud host. Any private
|
||||
information (such as passwords) should not be sent in the event.
|
||||
|
||||
After a request is made, a set of deploy kwargs will be generated. These will
|
||||
be used to install Salt on the target machine. Windows options are supported
|
||||
at this point, and should be generated, even if the cloud provider does not
|
||||
currently support Windows. This will save time in the future if the provider
|
||||
at this point, and should be generated, even if the cloud host does not
|
||||
currently support Windows. This will save time in the future if the host
|
||||
does eventually decide to support Windows.
|
||||
|
||||
An event is then fired to state that the deploy process is about to begin. This
|
||||
@ -118,12 +118,12 @@ manager. These do not need to be handled by the developer in the cloud module.
|
||||
|
||||
The ``salt.utils.cloud.validate_windows_cred()`` function has been extended to
|
||||
take the number of retries and retry_delay parameters in case a specific cloud
|
||||
provider has a delay between providing the Windows credentials and the
|
||||
host has a delay between providing the Windows credentials and the
|
||||
credentials being available for use. In their ``create()`` function, or as a
|
||||
a sub-function called during the creation process, developers should use the
|
||||
``win_deploy_auth_retries`` and ``win_deploy_auth_retry_delay`` parameters from
|
||||
the provider configuration to allow the end-user the ability to customize the
|
||||
number of tries and delay between tries for their particular provider.
|
||||
number of tries and delay between tries for their particular host.
|
||||
|
||||
After the appropriate deploy function completes, a final event is fired
|
||||
which describes the virtual machine that has just been created. This event is
|
||||
@ -133,13 +133,13 @@ VM, profile, and provider.
|
||||
Finally, a dict (queried from the provider) which describes the new virtual
|
||||
machine is returned to the user. Because this data is not fired on the event
|
||||
bus it can, and should, return any passwords that were returned by the cloud
|
||||
provider. In some cases (for example, Rackspace), this is the only time that
|
||||
host. In some cases (for example, Rackspace), this is the only time that
|
||||
the password can be queried by the user; post-creation queries may not contain
|
||||
password information (depending upon the provider).
|
||||
password information (depending upon the host).
|
||||
|
||||
The libcloudfuncs Functions
|
||||
---------------------------
|
||||
A number of other functions are required for all cloud providers. However, with
|
||||
A number of other functions are required for all cloud hosts. However, with
|
||||
libcloud-based modules, these are all provided for free by the libcloudfuncs
|
||||
library. The following two lines set up the imports:
|
||||
|
||||
@ -181,7 +181,7 @@ required by the developer. When this is the case, some or all of the functions
|
||||
in ``libcloudfuncs`` may be replaced. If they are all replaced, the libcloud
|
||||
imports should be absent from the Salt Cloud module.
|
||||
|
||||
A good example of a non-libcloud provider is the DigitalOcean module:
|
||||
A good example of a non-libcloud driver is the DigitalOcean driver:
|
||||
|
||||
https://github.com/saltstack/salt/tree/develop/salt/cloud/clouds/digital_ocean.py
|
||||
|
||||
@ -202,8 +202,8 @@ to exist otherwise.
|
||||
|
||||
The avail_locations() Function
|
||||
------------------------------
|
||||
This function returns a list of locations available, if the cloud provider uses
|
||||
multiple data centers. It is not necessary if the cloud provider only uses one
|
||||
This function returns a list of locations available, if the cloud host uses
|
||||
multiple data centers. It is not necessary if the cloud host uses only one
|
||||
data center. It is normally called using the ``--list-locations`` option.
|
||||
|
||||
.. code-block:: bash
|
||||
|
@ -45,7 +45,7 @@ Cloud Configuration Syntax
|
||||
|
||||
The data specific to interacting with public clouds is set up here.
|
||||
|
||||
Cloud provider configuration syntax can live in several places. The first is in
|
||||
Cloud provider configuration settings can live in several places. The first is in
|
||||
``/etc/salt/cloud``:
|
||||
|
||||
.. code-block:: yaml
|
||||
@ -171,13 +171,13 @@ minion. In your pillar file, you would use something like this:
|
||||
|
||||
profiles:
|
||||
ubuntu-nova:
|
||||
driver: my-nova
|
||||
provider: my-nova
|
||||
size: performance1-8
|
||||
image: bb02b1a3-bc77-4d17-ab5b-421d89850fca
|
||||
script_args: git develop
|
||||
|
||||
ubuntu-openstack:
|
||||
driver: my-openstack
|
||||
provider: my-openstack
|
||||
size: performance1-8
|
||||
image: bb02b1a3-bc77-4d17-ab5b-421d89850fca
|
||||
script_args: git develop
|
||||
@ -217,7 +217,7 @@ Rackspace cloud requires two configuration options; a ``user`` and an ``apikey``
|
||||
my-rackspace-config:
|
||||
user: example_user
|
||||
apikey: 123984bjjas87034
|
||||
driver: rackspace-config
|
||||
driver: rackspace
|
||||
|
||||
.. note::
|
||||
|
||||
@ -444,7 +444,7 @@ Proxmox
|
||||
-------
|
||||
|
||||
Using Salt with Proxmox requires a ``user``, ``password``, and ``URL``. These can be
|
||||
obtained from your cloud provider. Both PAM and PVE users can be used.
|
||||
obtained from your cloud host. Both PAM and PVE users can be used.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
@ -478,7 +478,7 @@ And in the map file:
|
||||
.. code-block:: yaml
|
||||
|
||||
devhost10-lxc:
|
||||
driver: devhost10-lxc
|
||||
provider: devhost10-lxc
|
||||
from_container: ubuntu
|
||||
backing: lvm
|
||||
sudo: True
|
||||
|
@ -75,7 +75,7 @@ test.ping. This is configured in the main cloud config file:
|
||||
|
||||
|
||||
This is currently considered to be experimental functionality, and may not work
|
||||
well with all providers. If you experience problems with Salt Cloud hanging
|
||||
well with all cloud hosts. If you experience problems with Salt Cloud hanging
|
||||
after Salt is deployed, consider using Startup States instead:
|
||||
|
||||
http://docs.saltstack.com/ref/states/startup.html
|
||||
@ -114,7 +114,7 @@ Or even on the VM's profile settings:
|
||||
.. code-block:: yaml
|
||||
|
||||
ubuntu_aws:
|
||||
provider: ec2
|
||||
provider: my-ec2-config
|
||||
image: ami-7e2da54e
|
||||
size: t1.micro
|
||||
deploy: False
|
||||
@ -174,7 +174,7 @@ to pass arguments to the deploy script:
|
||||
.. code-block:: yaml
|
||||
|
||||
aws-amazon:
|
||||
provider: ec2
|
||||
provider: my-ec2-config
|
||||
image: ami-1624987f
|
||||
size: t1.micro
|
||||
ssh_username: ec2-user
|
||||
@ -186,4 +186,4 @@ This has also been tested to work with pipes, if needed:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
script_args: | head
|
||||
script_args: | head
|
||||
|
@ -2,7 +2,7 @@
|
||||
Getting Started With DigitalOcean
|
||||
=================================
|
||||
|
||||
DigitalOcean is a public cloud provider that specializes in Linux instances.
|
||||
DigitalOcean is a public cloud host that specializes in Linux instances.
|
||||
|
||||
|
||||
Configuration
|
||||
@ -25,6 +25,14 @@ under the "SSH Keys" section.
|
||||
ssh_key_names: my-key-name,my-key-name-2
|
||||
location: New York 1
|
||||
|
||||
.. note::
|
||||
.. versionchanged:: 2015.8.0
|
||||
|
||||
The ``provider`` parameter in cloud provider definitions was renamed to ``driver``. This
|
||||
change was made to avoid confusion with the ``provider`` parameter that is used in cloud profile
|
||||
definitions. Cloud provider definitions now use ``driver`` to refer to the Salt cloud module that
|
||||
provides the underlying functionality to connect to a cloud host, while cloud profiles continue
|
||||
to use ``provider`` to refer to provider configurations that you define.
|
||||
|
||||
Profiles
|
||||
========
|
||||
|
@ -4,23 +4,23 @@
|
||||
Feature Matrix
|
||||
==============
|
||||
|
||||
A number of features are available in most cloud providers, but not all are
|
||||
A number of features are available in most cloud hosts, but not all are
|
||||
available everywhere. This may be because the feature isn't supported by the
|
||||
cloud provider itself, or it may only be that the feature has not yet been
|
||||
cloud host itself, or it may only be that the feature has not yet been
|
||||
added to Salt Cloud. In a handful of cases, it is because the feature does not
|
||||
make sense for a particular cloud provider (Saltify, for instance).
|
||||
|
||||
This matrix shows which features are available in which cloud providers, as far
|
||||
This matrix shows which features are available in which cloud hosts, as far
|
||||
as Salt Cloud is concerned. This is not a comprehensive list of all features
|
||||
available in all cloud providers, and should not be used to make business
|
||||
decisions concerning choosing a cloud provider. In most cases, adding support
|
||||
available in all cloud hosts, and should not be used to make business
|
||||
decisions concerning choosing a cloud host. In most cases, adding support
|
||||
for a feature to Salt Cloud requires only a little effort.
|
||||
|
||||
Legacy Drivers
|
||||
==============
|
||||
Both AWS and Rackspace are listed as "Legacy". This is because those drivers
|
||||
have been replaced by other drivers, which are generally the preferred method
|
||||
for working with those providers.
|
||||
for working with those hosts.
|
||||
|
||||
The EC2 driver should be used instead of the AWS driver, when possible. The
|
||||
OpenStack driver should be used instead of the Rackspace driver, unless the user
|
||||
@ -28,13 +28,13 @@ is dealing with instances in "the old cloud" in Rackspace.
|
||||
|
||||
Note for Developers
|
||||
===================
|
||||
When adding new features to a particular cloud provider, please make sure to
|
||||
When adding new features to a particular cloud host, please make sure to
|
||||
add the feature to this table. Additionally, if you notice a feature that is not
|
||||
properly listed here, pull requests to fix them is appreciated.
|
||||
|
||||
Standard Features
|
||||
=================
|
||||
These are features that are available for almost every provider.
|
||||
These are features that are available for almost every cloud host.
|
||||
|
||||
.. container:: scrollable
|
||||
|
||||
@ -199,4 +199,4 @@ require the name of the provider to be passed in. For example:
|
||||
|show_keypair | | |Yes |Yes| | | | | | | | | | |
|
||||
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|
||||
|show_volume | | | |Yes| | | | | | | | | |Yes |
|
||||
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|
||||
+-----------------------+--------+----------+-------+---+------+------+------+---------+---------+---------+-------+---------+---------+------+
|
||||
|
@ -113,6 +113,14 @@ Set up the cloud config at ``/etc/salt/cloud``:
|
||||
The value provided for ``project`` must not contain underscores or spaces and
|
||||
is labeled as "Project ID" on the Google Developers Console.
|
||||
|
||||
.. note::
|
||||
.. versionchanged:: 2015.8.0
|
||||
|
||||
The ``provider`` parameter in cloud provider definitions was renamed to ``driver``. This
|
||||
change was made to avoid confusion with the ``provider`` parameter that is used in cloud profile
|
||||
definitions. Cloud provider definitions now use ``driver`` to refer to the Salt cloud module that
|
||||
provides the underlying functionality to connect to a cloud host, while cloud profiles continue
|
||||
to use ``provider`` to refer to provider configurations that you define.
|
||||
|
||||
Cloud Profiles
|
||||
==============
|
||||
|
@ -2,7 +2,7 @@
|
||||
Getting Started With GoGrid
|
||||
===========================
|
||||
|
||||
GoGrid is a public cloud provider supporting Linux and Windows.
|
||||
GoGrid is a public cloud host that supports Linux and Windows.
|
||||
|
||||
|
||||
Configuration
|
||||
@ -32,6 +32,14 @@ in the configuration file to enable interfacing with GoGrid:
|
||||
with the GoGrid driver. Map files will work with GoGrid, but the ``-P``
|
||||
argument should not be used on maps referencing GoGrid instances.
|
||||
|
||||
.. note::
|
||||
.. versionchanged:: 2015.8.0
|
||||
|
||||
The ``provider`` parameter in cloud provider definitions was renamed to ``driver``. This
|
||||
change was made to avoid confusion with the ``provider`` parameter that is used in cloud profile
|
||||
definitions. Cloud provider definitions now use ``driver`` to refer to the Salt cloud module that
|
||||
provides the underlying functionality to connect to a cloud host, while cloud profiles continue
|
||||
to use ``provider`` to refer to provider configurations that you define.
|
||||
|
||||
Profiles
|
||||
========
|
||||
|
@ -50,6 +50,14 @@ provider configuration file as in the example shown below:
|
||||
|
||||
The subsequent example that follows is using the openstack driver.
|
||||
|
||||
.. note::
|
||||
.. versionchanged:: 2015.8.0
|
||||
|
||||
The ``provider`` parameter in cloud provider definitions was renamed to ``driver``. This
|
||||
change was made to avoid confusion with the ``provider`` parameter that is used in cloud profile
|
||||
definitions. Cloud provider definitions now use ``driver`` to refer to the Salt cloud module that
|
||||
provides the underlying functionality to connect to a cloud host, while cloud profiles continue
|
||||
to use ``provider`` to refer to provider configurations that you define.
|
||||
|
||||
Compute Region
|
||||
==============
|
||||
@ -164,4 +172,4 @@ The example below is a modified version of the previous example. Note the use of
|
||||
ssh_username: ubuntu
|
||||
ssh_interface: private_ips
|
||||
|
||||
With this setup, salt-cloud will use the private IP address to ssh into the instance and set up the salt-minion
|
||||
With this setup, salt-cloud will use the private IP address to ssh into the instance and set up the salt-minion
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
<row class="intro-row">
|
||||
<div class="col-sm-4">
|
||||
<div class="intro-text">Provision systems on cloud providers / hypervisors and immediately bring them under management.</div>
|
||||
<div class="intro-text">Provision systems on cloud hosts / hypervisors and immediately bring them under management.</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-8">
|
||||
|
@ -15,9 +15,9 @@ Salt Cloud is built-in to Salt and is configured on and executed from your Salt
|
||||
Define a Provider
|
||||
-----------------
|
||||
|
||||
The first step is to add the credentials for your cloud provider. Credentials
|
||||
and provider settings are stored in provider configuration files.
|
||||
Provider configurations contain the details needed to connect to a cloud provider such as EC2, GCE, Rackspace, etc.,
|
||||
The first step is to add the credentials for your cloud host. Credentials
|
||||
and other settings provided by the cloud host are stored in provider configuration files.
|
||||
Provider configurations contain the details needed to connect to a cloud host such as EC2, GCE, Rackspace, etc.,
|
||||
and any global options that you want set on your cloud minions (such as the location of your Salt Master).
|
||||
|
||||
On your Salt Master, browse to ``/etc/salt/cloud.providers.d/`` and create a file called ``<provider>.provider.conf``,
|
||||
@ -25,7 +25,7 @@ replacing ``<provider>`` with ``ec2``, ``softlayer``, and so on. The name helps
|
||||
important as long as the file ends in ``.conf``.
|
||||
|
||||
Next, browse to the :ref:`Provider specifics <cloud-provider-specifics>` and add any required settings for your
|
||||
provider to this file. Here is an example for Amazon EC2:
|
||||
cloud host to this file. Here is an example for Amazon EC2:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
@ -45,7 +45,7 @@ provider to this file. Here is an example for Amazon EC2:
|
||||
minion:
|
||||
master: saltmaster.example.com
|
||||
|
||||
The required configuration varies between providers so make sure you read the provider specifics.
|
||||
The required configuration varies between cloud hosts so make sure you read the provider specifics.
|
||||
|
||||
List Cloud Provider Options
|
||||
---------------------------
|
||||
|
@ -2,7 +2,7 @@
|
||||
Getting Started With Joyent
|
||||
===========================
|
||||
|
||||
Joyent is a public cloud provider supporting SmartOS, Linux, FreeBSD, and
|
||||
Joyent is a public cloud host that supports SmartOS, Linux, FreeBSD, and
|
||||
Windows.
|
||||
|
||||
|
||||
@ -30,6 +30,14 @@ send the provisioning commands up to the freshly created virtual machine.
|
||||
private_key: /root/mykey.pem
|
||||
keyname: mykey
|
||||
|
||||
.. note::
|
||||
.. versionchanged:: 2015.8.0
|
||||
|
||||
The ``provider`` parameter in cloud provider definitions was renamed to ``driver``. This
|
||||
change was made to avoid confusion with the ``provider`` parameter that is used in cloud profile
|
||||
definitions. Cloud provider definitions now use ``driver`` to refer to the Salt cloud module that
|
||||
provides the underlying functionality to connect to a cloud host, while cloud profiles continue
|
||||
to use ``provider`` to refer to provider configurations that you define.
|
||||
|
||||
Profiles
|
||||
========
|
||||
|
@ -2,7 +2,7 @@
|
||||
Getting Started With Linode
|
||||
===========================
|
||||
|
||||
Linode is a public cloud provider with a focus on Linux instances.
|
||||
Linode is a public cloud host with a focus on Linux instances.
|
||||
|
||||
Starting with the 2015.8.0 release of Salt, the Linode driver uses Linode's
|
||||
native REST API. There are no external dependencies required to use the
|
||||
@ -28,6 +28,15 @@ instances also needs to be set:
|
||||
The password needs to be 8 characters and contain lowercase, uppercase, and
|
||||
numbers.
|
||||
|
||||
.. note::
|
||||
.. versionchanged:: 2015.8.0
|
||||
|
||||
The ``provider`` parameter in cloud provider definitions was renamed to ``driver``. This
|
||||
change was made to avoid confusion with the ``provider`` parameter that is used in cloud profile
|
||||
definitions. Cloud provider definitions now use ``driver`` to refer to the Salt cloud module that
|
||||
provides the underlying functionality to connect to a cloud host, while cloud profiles continue
|
||||
to use ``provider`` to refer to provider configurations that you define.
|
||||
|
||||
Profiles
|
||||
========
|
||||
|
||||
|
@ -23,10 +23,6 @@ Limitations
|
||||
- Listing images must be targeted to a particular LXC provider (nothing will be
|
||||
outputted with ``all``)
|
||||
|
||||
.. warning::
|
||||
|
||||
On pre **2015.5.2**, you need to specify explitly the network bridge
|
||||
|
||||
Operation
|
||||
---------
|
||||
|
||||
@ -62,6 +58,15 @@ Here is a simple provider configuration:
|
||||
target: devhost10
|
||||
driver: lxc
|
||||
|
||||
.. note::
|
||||
.. versionchanged:: 2015.8.0
|
||||
|
||||
The ``provider`` parameter in cloud provider definitions was renamed to ``driver``. This
|
||||
change was made to avoid confusion with the ``provider`` parameter that is used in cloud profile
|
||||
definitions. Cloud provider definitions now use ``driver`` to refer to the Salt cloud module that
|
||||
provides the underlying functionality to connect to a cloud host, while cloud profiles continue
|
||||
to use ``provider`` to refer to provider configurations that you define.
|
||||
|
||||
Profile configuration
|
||||
---------------------
|
||||
|
||||
|
@ -14,7 +14,7 @@ to pass arguments to the deploy script:
|
||||
.. code-block:: yaml
|
||||
|
||||
ec2-amazon:
|
||||
provider: ec2
|
||||
provider: my-ec2-config
|
||||
image: ami-1624987f
|
||||
size: t1.micro
|
||||
ssh_username: ec2-user
|
||||
@ -95,7 +95,7 @@ Delete SSH Keys
|
||||
===============
|
||||
When Salt Cloud deploys an instance, the SSH pub key for the instance is added
|
||||
to the known_hosts file for the user that ran the salt-cloud command. When an
|
||||
instance is deployed, a cloud provider generally recycles the IP address for
|
||||
instance is deployed, a cloud host generally recycles the IP address for
|
||||
the instance. When Salt Cloud attempts to deploy an instance using a recycled
|
||||
IP address that has previously been accessed from the same machine, the old key
|
||||
in the known_hosts file will cause a conflict.
|
||||
@ -161,7 +161,7 @@ wait_for_ip_timeout
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The amount of time Salt Cloud should wait for a VM to start and get an IP back
|
||||
from the cloud provider.
|
||||
from the cloud host.
|
||||
Default: varies by cloud provider ( between 5 and 25 minutes)
|
||||
|
||||
|
||||
@ -232,7 +232,7 @@ diff_cache_events
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
When the cloud cachedir is being managed, if differences are encountered
|
||||
between the data that is returned live from the cloud provider and the data in
|
||||
between the data that is returned live from the cloud host and the data in
|
||||
the cache, fire events which describe the changes. This setting can be True or
|
||||
False.
|
||||
|
||||
@ -251,20 +251,20 @@ The following are events that can be fired based on this data.
|
||||
|
||||
salt/cloud/minionid/cache_node_new
|
||||
**********************************
|
||||
A new node was found on the cloud provider which was not listed in the cloud
|
||||
A new node was found on the cloud host which was not listed in the cloud
|
||||
cachedir. A dict describing the new node will be contained in the event.
|
||||
|
||||
|
||||
salt/cloud/minionid/cache_node_missing
|
||||
**************************************
|
||||
A node that was previously listed in the cloud cachedir is no longer available
|
||||
on the cloud provider.
|
||||
on the cloud host.
|
||||
|
||||
|
||||
salt/cloud/minionid/cache_node_diff
|
||||
***********************************
|
||||
One or more pieces of data in the cloud cachedir has changed on the cloud
|
||||
provider. A dict containing both the old and the new data will be contained in
|
||||
host. A dict containing both the old and the new data will be contained in
|
||||
the event.
|
||||
|
||||
|
||||
|
@ -46,6 +46,14 @@ Configuration
|
||||
# skip SSL certificate validation (default false)
|
||||
insecure: false
|
||||
|
||||
.. note::
|
||||
.. versionchanged:: 2015.8.0
|
||||
|
||||
The ``provider`` parameter in cloud provider definitions was renamed to ``driver``. This
|
||||
change was made to avoid confusion with the ``provider`` parameter that is used in cloud profile
|
||||
definitions. Cloud provider definitions now use ``driver`` to refer to the Salt cloud module that
|
||||
provides the underlying functionality to connect to a cloud host, while cloud profiles continue
|
||||
to use ``provider`` to refer to provider configurations that you define.
|
||||
|
||||
Using nova client to get information from OpenStack
|
||||
===================================================
|
||||
|
@ -4,7 +4,7 @@ Getting Started With Parallels
|
||||
|
||||
Parallels Cloud Server is a product by Parallels that delivers a cloud hosting
|
||||
solution. The PARALLELS module for Salt Cloud enables you to manage instances
|
||||
hosted by a provider using PCS. Further information can be found at:
|
||||
hosted using PCS. Further information can be found at:
|
||||
|
||||
http://www.parallels.com/products/pcs/
|
||||
|
||||
@ -22,7 +22,7 @@ http://www.parallels.com/products/pcs/
|
||||
PARALLELS.user: myuser
|
||||
PARALLELS.password: badpass
|
||||
|
||||
# Set the access URL for your PARALLELS provider
|
||||
# Set the access URL for your PARALLELS host
|
||||
#
|
||||
PARALLELS.url: https://api.cloud.xmission.com:4465/paci/v1.0/
|
||||
|
||||
@ -49,12 +49,19 @@ http://www.parallels.com/products/pcs/
|
||||
url: https://api.cloud.xmission.com:4465/paci/v1.0/
|
||||
driver: parallels
|
||||
|
||||
.. note::
|
||||
.. versionchanged:: 2015.8.0
|
||||
|
||||
The ``provider`` parameter in cloud provider definitions was renamed to ``driver``. This
|
||||
change was made to avoid confusion with the ``provider`` parameter that is used in cloud profile
|
||||
definitions. Cloud provider definitions now use ``driver`` to refer to the Salt cloud module that
|
||||
provides the underlying functionality to connect to a cloud host, while cloud profiles continue
|
||||
to use ``provider`` to refer to provider configurations that you define.
|
||||
|
||||
Access Credentials
|
||||
==================
|
||||
The ``user``, ``password``, and ``url`` will be provided to you by your cloud
|
||||
provider. These are all required in order for the PARALLELS driver to work.
|
||||
host. These are all required in order for the PARALLELS driver to work.
|
||||
|
||||
|
||||
Cloud Profiles
|
||||
@ -62,34 +69,19 @@ Cloud Profiles
|
||||
Set up an initial profile at ``/etc/salt/cloud.profiles`` or
|
||||
``/etc/salt/cloud.profiles.d/parallels.conf``:
|
||||
|
||||
|
||||
* Using the old cloud configuration format:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
parallels-ubuntu:
|
||||
provider: parallels
|
||||
image: ubuntu-12.04-x86_64
|
||||
|
||||
|
||||
* Using the new cloud configuration format and the cloud configuration example
|
||||
from above:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
parallels-ubuntu:
|
||||
provider: my-parallels-config
|
||||
image: ubuntu-12.04-x86_64
|
||||
|
||||
|
||||
|
||||
The profile can be realized now with a salt command:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# salt-cloud -p parallels-ubuntu myubuntu
|
||||
|
||||
This will create an instance named ``myubuntu`` on the cloud provider. The
|
||||
This will create an instance named ``myubuntu`` on the cloud host. The
|
||||
minion that is installed on this instance will have an ``id`` of ``myubuntu``.
|
||||
If the command was executed on the salt-master, its Salt key will automatically
|
||||
be signed on the master.
|
||||
@ -131,8 +123,8 @@ Optional Settings
|
||||
=================
|
||||
Unlike other cloud providers in Salt Cloud, Parallels does not utilize a
|
||||
``size`` setting. This is because Parallels allows the end-user to specify a
|
||||
more detailed configuration for their instances, than is allowed by many other
|
||||
cloud providers. The following options are available to be used in a profile,
|
||||
more detailed configuration for their instances than is allowed by many other
|
||||
cloud hosts. The following options are available to be used in a profile,
|
||||
with their default settings listed.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
@ -8,7 +8,7 @@ a yaml configuration. The syntax for declaring profiles is simple:
|
||||
.. code-block:: yaml
|
||||
|
||||
fedora_rackspace:
|
||||
provider: rackspace
|
||||
provider: my-rackspace-config
|
||||
image: Fedora 17
|
||||
size: 256 server
|
||||
script: bootstrap-salt
|
||||
@ -18,12 +18,12 @@ and does not normally need to be specified. Further examples in this document
|
||||
will not show the ``script`` option.
|
||||
|
||||
A few key pieces of information need to be declared and can change based on the
|
||||
public cloud provider. A number of additional parameters can also be inserted:
|
||||
cloud provider. A number of additional parameters can also be inserted:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
centos_rackspace:
|
||||
driver: rackspace
|
||||
provider: my-rackspace-config
|
||||
image: CentOS 6.2
|
||||
size: 1024 server
|
||||
minion:
|
||||
@ -66,44 +66,44 @@ Larger Example
|
||||
.. code-block:: yaml
|
||||
|
||||
rhel_ec2:
|
||||
provider: ec2
|
||||
provider: my-ec2-config
|
||||
image: ami-e565ba8c
|
||||
size: t1.micro
|
||||
minion:
|
||||
cheese: edam
|
||||
|
||||
ubuntu_ec2:
|
||||
provider: ec2
|
||||
provider: my-ec2-config
|
||||
image: ami-7e2da54e
|
||||
size: t1.micro
|
||||
minion:
|
||||
cheese: edam
|
||||
|
||||
ubuntu_rackspace:
|
||||
provider: rackspace
|
||||
provider: my-rackspace-config
|
||||
image: Ubuntu 12.04 LTS
|
||||
size: 256 server
|
||||
minion:
|
||||
cheese: edam
|
||||
|
||||
fedora_rackspace:
|
||||
provider: rackspace
|
||||
provider: my-rackspace-config
|
||||
image: Fedora 17
|
||||
size: 256 server
|
||||
minion:
|
||||
cheese: edam
|
||||
|
||||
cent_linode:
|
||||
provider: linode
|
||||
provider: my-linode-config
|
||||
image: CentOS 6.2 64bit
|
||||
size: Linode 512
|
||||
|
||||
cent_gogrid:
|
||||
provider: gogrid
|
||||
provider: my-gogrid-config
|
||||
image: 12834
|
||||
size: 512MB
|
||||
|
||||
cent_joyent:
|
||||
provider: joyent
|
||||
provider: my-joyent-config
|
||||
image: centos-6
|
||||
size: Small 1GB
|
||||
size: Small 1GB
|
||||
|
@ -34,17 +34,24 @@ done when the VM is an OpenVZ container rather than a KVM virtual machine.
|
||||
user: myuser@pve
|
||||
password: badpass
|
||||
|
||||
# Set the access URL for your PROXMOX provider
|
||||
# Set the access URL for your PROXMOX host
|
||||
#
|
||||
url: your.proxmox.host
|
||||
driver: proxmox
|
||||
|
||||
.. note::
|
||||
.. versionchanged:: 2015.8.0
|
||||
|
||||
The ``provider`` parameter in cloud provider definitions was renamed to ``driver``. This
|
||||
change was made to avoid confusion with the ``provider`` parameter that is used in cloud profile
|
||||
definitions. Cloud provider definitions now use ``driver`` to refer to the Salt cloud module that
|
||||
provides the underlying functionality to connect to a cloud host, while cloud profiles continue
|
||||
to use ``provider`` to refer to provider configurations that you define.
|
||||
|
||||
Access Credentials
|
||||
==================
|
||||
The ``user``, ``password``, and ``url`` will be provided to you by your cloud
|
||||
provider. These are all required in order for the PROXMOX driver to work.
|
||||
host. These are all required in order for the PROXMOX driver to work.
|
||||
|
||||
|
||||
Cloud Profiles
|
||||
@ -57,7 +64,7 @@ Set up an initial profile at ``/etc/salt/cloud.profiles`` or
|
||||
.. code-block:: yaml
|
||||
|
||||
proxmox-ubuntu:
|
||||
provider: proxmox
|
||||
provider: my-proxmox-config
|
||||
image: local:vztmpl/ubuntu-12.04-standard_12.04-1_amd64.tar.gz
|
||||
technology: openvz
|
||||
host: myvmhost
|
||||
@ -71,7 +78,7 @@ The profile can be realized now with a salt command:
|
||||
|
||||
# salt-cloud -p proxmox-ubuntu myubuntu
|
||||
|
||||
This will create an instance named ``myubuntu`` on the cloud provider. The
|
||||
This will create an instance named ``myubuntu`` on the cloud host. The
|
||||
minion that is installed on this instance will have a ``hostname`` of ``myubuntu``.
|
||||
If the command was executed on the salt-master, its Salt key will automatically
|
||||
be signed on the master.
|
||||
|
@ -5,7 +5,7 @@ Getting Started With Rackspace
|
||||
Rackspace is a major public cloud platform which may be configured using either
|
||||
the `rackspace` or the `openstack` driver, depending on your needs.
|
||||
|
||||
Please note that the `rackspace` driver is only intended for 1st gen instances,
|
||||
Please note that the `rackspace` driver is intended only for 1st gen instances,
|
||||
aka, "the old cloud" at Rackspace. It is required for 1st gen instances, but
|
||||
will *not* work with OpenStack-based instances. Unless you explicitly have a
|
||||
reason to use it, it is highly recommended that you use the `openstack` driver
|
||||
@ -66,6 +66,14 @@ To use the `rackspace` driver, set up the cloud configuration at
|
||||
The settings that follow are for using Rackspace with the `openstack` driver,
|
||||
and will not work with the `rackspace` driver.
|
||||
|
||||
.. note::
|
||||
.. versionchanged:: 2015.8.0
|
||||
|
||||
The ``provider`` parameter in cloud provider definitions was renamed to ``driver``. This
|
||||
change was made to avoid confusion with the ``provider`` parameter that is used in cloud profile
|
||||
definitions. Cloud provider definitions now use ``driver`` to refer to the Salt cloud module that
|
||||
provides the underlying functionality to connect to a cloud host, while cloud profiles continue
|
||||
to use ``provider`` to refer to provider configurations that you define.
|
||||
|
||||
Compute Region
|
||||
==============
|
||||
@ -172,10 +180,10 @@ configuration please add:
|
||||
force_first_gen: True
|
||||
|
||||
Private Subnets
|
||||
--------------------------------
|
||||
By default salt-cloud will not add Rackspace private networks to new servers. To enable
|
||||
---------------
|
||||
By default salt-cloud will not add Rackspace private networks to new servers. To enable
|
||||
a private network to a server instantiated by salt cloud, add the following section
|
||||
to the provider file (typically ``/etc/salt/cloud.providers.d/rackspace.conf``)
|
||||
to the provider file (typically ``/etc/salt/cloud.providers.d/rackspace.conf``)
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
|
@ -34,8 +34,7 @@ using the ``ec2-config`` provider, the payload for this tag would look like:
|
||||
|
||||
{'name': 'web1',
|
||||
'profile': 'ec2-centos',
|
||||
'provider': 'ec2-config'}
|
||||
|
||||
'provider': 'ec2-config:ec2'}
|
||||
|
||||
Available Events
|
||||
================
|
||||
@ -206,11 +205,11 @@ options that can be specified is ``startup_states``, which is commonly set to
|
||||
``highstate``. This will tell the minion to immediately apply a highstate, as
|
||||
soon as it is able to do so.
|
||||
|
||||
This can present a problem with some system images on some cloud providers. For
|
||||
This can present a problem with some system images on some cloud hosts. For
|
||||
instance, Salt Cloud can be configured to log in as either the ``root`` user, or
|
||||
a user with ``sudo`` access. While some providers commonly use images that
|
||||
a user with ``sudo`` access. While some hosts commonly use images that
|
||||
lock out remote ``root`` access and require a user with ``sudo`` privileges to
|
||||
log in (notably EC2, with their ``ec2-user`` login), most cloud providers fall
|
||||
log in (notably EC2, with their ``ec2-user`` login), most cloud hosts fall
|
||||
back to ``root`` as the default login on all images, including for operating
|
||||
systems (such as Ubuntu) which normally disallow remote ``root`` login.
|
||||
|
||||
@ -245,4 +244,4 @@ Because this event will not be fired until Salt Cloud has cleaned up after
|
||||
itself, the highstate run will not step on Salt Cloud's toes. And because every
|
||||
file on the minion is configurable, including ``/etc/salt/minion``, the
|
||||
``startup_states`` can still be configured for future minion restarts, if
|
||||
desired.
|
||||
desired.
|
||||
|
@ -238,7 +238,7 @@ presence of the instance will be managed statefully.
|
||||
|
||||
my-instance-name:
|
||||
cloud.present:
|
||||
- driver: my-ec2-config
|
||||
- provider: my-ec2-config
|
||||
- image: ami-1624987f
|
||||
- size: 't1.micro'
|
||||
- ssh_username: ec2-user
|
||||
|
@ -2,7 +2,7 @@
|
||||
Getting Started With Scaleway
|
||||
=============================
|
||||
|
||||
Scaleway is the first IaaS provider worldwide to offer an ARM based cloud. It’s the ideal platform for horizontal scaling with BareMetal SSD servers. The solution provides on demand resources: it comes with on-demand SSD storage, movable IPs , images, security group and an Object Storage solution. https://scaleway.com
|
||||
Scaleway is the first IaaS host worldwide to offer an ARM based cloud. It’s the ideal platform for horizontal scaling with BareMetal SSD servers. The solution provides on demand resources: it comes with on-demand SSD storage, movable IPs , images, security group and an Object Storage solution. https://scaleway.com
|
||||
|
||||
Configuration
|
||||
=============
|
||||
@ -21,6 +21,15 @@ If you do not have API token you can create one by clicking the "Create New Toke
|
||||
token: a7347ec8-5de1-4024-a5e3-24b77d1ba91d
|
||||
driver: scaleway
|
||||
|
||||
.. note::
|
||||
.. versionchanged:: 2015.8.0
|
||||
|
||||
The ``provider`` parameter in cloud provider definitions was renamed to ``driver``. This
|
||||
change was made to avoid confusion with the ``provider`` parameter that is used in cloud profile
|
||||
definitions. Cloud provider definitions now use ``driver`` to refer to the Salt cloud module that
|
||||
provides the underlying functionality to connect to a cloud host, while cloud profiles continue
|
||||
to use ``provider`` to refer to provider configurations that you define.
|
||||
|
||||
Profiles
|
||||
========
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
Getting Started With SoftLayer
|
||||
==============================
|
||||
|
||||
SoftLayer is a public cloud provider, and baremetal hardware hosting provider.
|
||||
SoftLayer is a public cloud host, and baremetal hardware hosting service.
|
||||
|
||||
Dependencies
|
||||
============
|
||||
@ -50,6 +50,14 @@ Set up the cloud config at ``/etc/salt/cloud.providers``:
|
||||
|
||||
driver: softlayer_hw
|
||||
|
||||
.. note::
|
||||
.. versionchanged:: 2015.8.0
|
||||
|
||||
The ``provider`` parameter in cloud provider definitions was renamed to ``driver``. This
|
||||
change was made to avoid confusion with the ``provider`` parameter that is used in cloud profile
|
||||
definitions. Cloud provider definitions now use ``driver`` to refer to the Salt cloud module that
|
||||
provides the underlying functionality to connect to a cloud host, while cloud profiles continue
|
||||
to use ``provider`` to refer to provider configurations that you define.
|
||||
|
||||
Access Credentials
|
||||
==================
|
||||
@ -384,7 +392,7 @@ The `globalIdentifier` returned in this list is necessary for the
|
||||
|
||||
Optional Products for SoftLayer HW
|
||||
==================================
|
||||
The softlayer_hw provider supports the ability to add optional products, which
|
||||
The softlayer_hw driver supports the ability to add optional products, which
|
||||
are supported by SoftLayer's API. These products each have an ID associated with
|
||||
them, that can be passed into Salt Cloud with the `optional_products` option:
|
||||
|
||||
|
@ -83,7 +83,7 @@ By default, Salt Cloud will create a directory on the target instance called
|
||||
``/tmp/.saltcloud/``. This directory should be owned by the user that is to
|
||||
execute the deploy script, and should have permissions of ``0700``.
|
||||
|
||||
Most cloud providers are configured to use ``root`` as the default initial user
|
||||
Most cloud hosts are configured to use ``root`` as the default initial user
|
||||
for deployment, and as such, this directory and all files in it should be owned
|
||||
by the ``root`` user.
|
||||
|
||||
@ -101,14 +101,14 @@ The ``/tmp/.saltcloud/`` directory should the following files:
|
||||
|
||||
Unprivileged Primary Users
|
||||
--------------------------
|
||||
Some providers, most notably EC2, are configured with a different primary user.
|
||||
Some cloud hosts, most notably EC2, are configured with a different primary user.
|
||||
Some common examples are ``ec2-user``, ``ubuntu``, ``fedora``, and ``bitnami``.
|
||||
In these cases, the ``/tmp/.saltcloud/`` directory and all files in it should
|
||||
be owned by this user.
|
||||
|
||||
Some providers, such as EC2, are configured to not require these users to
|
||||
Some cloud hosts, such as EC2, are configured to not require these users to
|
||||
provide a password when using the ``sudo`` command. Because it is more secure
|
||||
to require ``sudo`` users to provide a password, other providers are configured
|
||||
to require ``sudo`` users to provide a password, other hosts are configured
|
||||
that way.
|
||||
|
||||
If this instance is required to provide a password, it needs to be configured
|
||||
@ -123,7 +123,7 @@ configuration or the profile configuration:
|
||||
``/tmp/`` is Mounted as ``noexec``
|
||||
----------------------------------
|
||||
It is more secure to mount the ``/tmp/`` directory with a ``noexec`` option.
|
||||
This is uncommon on most cloud providers, but very common in private
|
||||
This is uncommon on most cloud hosts, but very common in private
|
||||
environments. To see if the ``/tmp/`` directory is mounted this way, run the
|
||||
following command:
|
||||
|
||||
|
@ -2,13 +2,13 @@
|
||||
Getting Started with VEXXHOST
|
||||
=============================
|
||||
|
||||
`VEXXHOST <http://vexxhost.com>`_ is an cloud computing provider which provides
|
||||
`VEXXHOST <http://vexxhost.com>`_ is a cloud computing host which provides
|
||||
`Canadian cloud computing <http://vexxhost.com/cloud-computing>`_ services
|
||||
which are based in Monteral and uses the libcloud OpenStack driver. VEXXHOST
|
||||
which are based in Monteral and use the libcloud OpenStack driver. VEXXHOST
|
||||
currently runs the Havana release of OpenStack. When provisioning new
|
||||
instances, they automatically get a public IP and private IP address.
|
||||
Therefore, you do not need to assign a floating IP to access your instance
|
||||
once it's booted.
|
||||
after it's booted.
|
||||
|
||||
|
||||
Cloud Provider Configuration
|
||||
@ -24,7 +24,7 @@ driver.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
vexxhost:
|
||||
my-vexxhost-config:
|
||||
# Set the location of the salt-master
|
||||
#
|
||||
minion:
|
||||
@ -52,6 +52,14 @@ driver.
|
||||
|
||||
driver: openstack
|
||||
|
||||
.. note::
|
||||
.. versionchanged:: 2015.8.0
|
||||
|
||||
The ``provider`` parameter in cloud provider definitions was renamed to ``driver``. This
|
||||
change was made to avoid confusion with the ``provider`` parameter that is used in cloud profile
|
||||
definitions. Cloud provider definitions now use ``driver`` to refer to the Salt cloud module that
|
||||
provides the underlying functionality to connect to a cloud host, while cloud profiles continue
|
||||
to use ``provider`` to refer to provider configurations that you define.
|
||||
|
||||
Authentication
|
||||
==============
|
||||
@ -80,7 +88,7 @@ profile will build an Ubuntu 12.04 LTS `nb.2G` instance.
|
||||
.. code-block:: yaml
|
||||
|
||||
vh_ubuntu1204_2G:
|
||||
provider: vexxhost
|
||||
provider: my-vexxhost-config
|
||||
image: 4051139f-750d-4d72-8ef0-074f2ccc7e5a
|
||||
size: nb.2G
|
||||
|
||||
@ -106,4 +114,4 @@ the following command:
|
||||
# salt vh_instance1 test.ping
|
||||
|
||||
You can now continue to provision new instances and they will all automatically
|
||||
be set up as minions of the master you've defined in the configuration file.
|
||||
be set up as minions of the master you've defined in the configuration file.
|
||||
|
@ -60,6 +60,15 @@ set up in the cloud configuration at
|
||||
server is not using the defaults. Default is ``protocol: https`` and
|
||||
``port: 443``.
|
||||
|
||||
.. note::
|
||||
.. versionchanged:: 2015.8.0
|
||||
|
||||
The ``provider`` parameter in cloud provider definitions was renamed to ``driver``. This
|
||||
change was made to avoid confusion with the ``provider`` parameter that is used in cloud profile
|
||||
definitions. Cloud provider definitions now use ``driver`` to refer to the Salt cloud module that
|
||||
provides the underlying functionality to connect to a cloud host, while cloud profiles continue
|
||||
to use ``provider`` to refer to provider configurations that you define.
|
||||
|
||||
.. _vmware-cloud-profile:
|
||||
|
||||
Profiles
|
||||
|
@ -46,6 +46,14 @@ Set up the cloud config at ``/etc/salt/cloud.providers`` or in the
|
||||
# Set the URL of your vSphere server
|
||||
url: 'vsphere.example.com'
|
||||
|
||||
.. note::
|
||||
.. versionchanged:: 2015.8.0
|
||||
|
||||
The ``provider`` parameter in cloud provider definitions was renamed to ``driver``. This
|
||||
change was made to avoid confusion with the ``provider`` parameter that is used in cloud profile
|
||||
definitions. Cloud provider definitions now use ``driver`` to refer to the Salt cloud module that
|
||||
provides the underlying functionality to connect to a cloud host, while cloud profiles continue
|
||||
to use ``provider`` to refer to provider configurations that you define.
|
||||
|
||||
Profiles
|
||||
========
|
||||
|
@ -261,7 +261,7 @@ the tests pass and the pull request can be merged.
|
||||
``Tests Passed``
|
||||
The pull request has passed all tests even though some test results are negative. Sometimes the automated testing
|
||||
infrastructure will encounter internal errors unrelated to the code change in the pull request that cause test runs
|
||||
to fail. These errors can be caused by cloud provider and network issues and also Jenkins issues like erroneously
|
||||
to fail. These errors can be caused by cloud host and network issues and also Jenkins issues like erroneously
|
||||
accumulating workspace artifacts, resource exhaustion, and bugs that arise from long running Jenkins processes.
|
||||
|
||||
Other
|
||||
|
@ -108,7 +108,7 @@ the default cloud provider configuration file for DigitalOcean looks like this:
|
||||
.. code-block:: yaml
|
||||
|
||||
digitalocean-config:
|
||||
provider: digital_ocean
|
||||
driver: digital_ocean
|
||||
client_key: ''
|
||||
api_key: ''
|
||||
location: New York 1
|
||||
@ -119,7 +119,7 @@ must be provided:
|
||||
.. code-block:: yaml
|
||||
|
||||
digitalocean-config:
|
||||
provider: digital_ocean
|
||||
driver: digital_ocean
|
||||
client_key: wFGEwgregeqw3435gDger
|
||||
api_key: GDE43t43REGTrkilg43934t34qT43t4dgegerGEgg
|
||||
location: New York 1
|
||||
|
@ -318,7 +318,7 @@ Ocean, located at: ``tests/integration/files/conf/cloud.providers.d/digital_ocea
|
||||
.. code-block:: yaml
|
||||
|
||||
digitalocean-config:
|
||||
provider: digital_ocean
|
||||
driver: digital_ocean
|
||||
client_key: ''
|
||||
api_key: ''
|
||||
location: New York 1
|
||||
|
@ -42,21 +42,27 @@ functionality.
|
||||
Windows Software Repo Changes
|
||||
=============================
|
||||
|
||||
The :mod:`winrepo.update_git_repos <salt.runners.winrepo.update_git_repos>`
|
||||
runner has been updated to use either GitPython_ or pygit2_ to checkout the git
|
||||
repositories containing repo data. Existing winrepo git checkouts should be
|
||||
removed before starting up the salt-master after upgrading, if GitPython_ or
|
||||
pygit2_ is installed, to allow them to be checked out again.
|
||||
Several config options have been renamed to make the naming more consistent.
|
||||
For a list of the winrepo config options, see :ref:`here
|
||||
<winrepo-config-opts>`.
|
||||
|
||||
This enhancement also brings new functionality, see the :mod:`winrepo runner
|
||||
<salt.runners.winrepo>` documentation for more information.
|
||||
The :mod:`winrepo.update_git_repos <salt.runners.winrepo.update_git_repos>`
|
||||
runner has been updated to use either pygit2_ or GitPython_ to checkout the git
|
||||
repositories containing repo data. If pygit2_ or GitPython_ is installed,
|
||||
existing winrepo git checkouts should be removed after upgrading to 2015.8.0,
|
||||
to allow them to be checked out again by running
|
||||
:py:func:`winrepo.update_git_repos <salt.runners.winrepo.update_git_repos>`.
|
||||
|
||||
This enhancement also brings new functionality, see the :ref:`Windows Software
|
||||
Repository <2015-8-0-winrepo-changes>` documentation for more information.
|
||||
|
||||
If neither GitPython_ nor pygit2_ are installed, then Salt will fall back to
|
||||
the pre-existing behavior for :mod:`winrepo.update_git_repos
|
||||
<salt.runners.winrepo.update_git_repos>`.
|
||||
<salt.runners.winrepo.update_git_repos>`, and a warning will be logged in the
|
||||
master log.
|
||||
|
||||
.. _GitPython: https://github.com/gitpython-developers/GitPython
|
||||
.. _pygit2: https://github.com/libgit2/pygit2
|
||||
.. _GitPython: https://github.com/gitpython-developers/GitPython
|
||||
|
||||
JBoss 7 State
|
||||
=============
|
||||
|
@ -1,7 +1,13 @@
|
||||
.. _windows-package-manager:
|
||||
===========================
|
||||
Windows Software Repository
|
||||
===========================
|
||||
|
||||
.. note::
|
||||
Git repository management for the Windows Software Repository has changed
|
||||
in version 2015.8.0. Please see :ref:`below <2015-8-0-winrepo-changes>` for
|
||||
important details if upgrading from an earlier Salt release.
|
||||
|
||||
The Salt Windows Software Repository provides a package manager and software
|
||||
repository similar to what is provided by yum and apt on Linux.
|
||||
|
||||
@ -48,12 +54,13 @@ between the pre and post ``pkg.list_pkgs`` results.
|
||||
Usage
|
||||
=====
|
||||
|
||||
By default, the Windows software repository is found at ``/srv/salt/win/repo``
|
||||
This can be changed in the master config file (default location is
|
||||
``/etc/salt/master``) by modifying the ``win_repo`` variable, but this must
|
||||
reside somewhere inside the master's `file_roots`. Each piece of software
|
||||
should have its own directory which contains the installers and a package
|
||||
definition file. This package definition file is a YAML file named
|
||||
By default, the Windows software repository is found at ``/srv/salt/win/repo``.
|
||||
This can be changed in the master config file by setting the
|
||||
:conf_master:`winrepo_dir` option (**NOTE:** this option was called
|
||||
``win_repo`` in Salt versions prior to 2015.8.0). However, this path must
|
||||
reside somewhere inside the master's :conf_master:`file_roots`. Each piece of
|
||||
software should have its own directory which contains the installers and a
|
||||
package definition file. This package definition file is a YAML file named
|
||||
``init.sls``.
|
||||
|
||||
The package definition file should look similar to this example for Firefox:
|
||||
@ -197,7 +204,8 @@ Alternatively the ``uninstaller`` can also simply repeat the URL of the msi file
|
||||
Generate Repo Cache File
|
||||
========================
|
||||
|
||||
Once the sls file has been created, generate the repository cache file with the winrepo runner:
|
||||
Once the sls file has been created, generate the repository cache file with the
|
||||
winrepo runner:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
@ -247,9 +255,9 @@ The above line will install the latest version of Firefox.
|
||||
|
||||
The above line will install version 16.0.2 of Firefox.
|
||||
|
||||
If a different version of the package is already installed it will
|
||||
be replaced with the version in winrepo (only if the package itself supports
|
||||
live updating).
|
||||
If a different version of the package is already installed it will be replaced
|
||||
with the version in the winrepo (only if the package itself supports live
|
||||
updating).
|
||||
|
||||
You can also specify the full name:
|
||||
|
||||
@ -274,33 +282,44 @@ future ``pkg.purge`` may direct the installer to remove all configs and
|
||||
settings for software packages that support that option.
|
||||
|
||||
|
||||
|
||||
Standalone Minion Salt Windows Repo Module
|
||||
==========================================
|
||||
|
||||
In order to facilitate managing a Salt Windows software repo with Salt on a
|
||||
Standalone Minion on Windows, a new module named winrepo has been added to
|
||||
Salt. winrepo matches what is available in the salt runner and allows you to
|
||||
manage the Windows software repo contents. Example: ``salt '*'
|
||||
winrepo.genrepo``
|
||||
Standalone Minion on Windows, a :mod:`winrepo execution module
|
||||
<salt.modules.win_repo>` is available. This execution module matches what is
|
||||
available in the :mod:`winrepo runner <salt.runners.winrepo>` and allows for
|
||||
Windows software repo contents to be managed on a standalone Windows minion.
|
||||
For example, to generate the winrepo cache, ``salt-call winrepo.genrepo`` would
|
||||
be run.
|
||||
|
||||
.. note::
|
||||
The :mod:`winrepo execution module <salt.modules.win_repo>` does not
|
||||
support the :ref:`new features <2015-8-0-winrepo-changes>` added in
|
||||
version 2015.8.0.
|
||||
|
||||
|
||||
Git Hosted Repo
|
||||
===============
|
||||
|
||||
Windows software package definitions can also be hosted in one or more git
|
||||
repositories. The default repo is one hosted on GitHub.com by SaltStack,Inc., which
|
||||
includes package definitions for open source software. This repo points to the
|
||||
HTTP or ftp locations of the installer files. Anyone is welcome to send a pull
|
||||
request to this repo to add new package definitions. Browse the repo
|
||||
here: `https://github.com/saltstack/salt-winrepo
|
||||
<https://github.com/saltstack/salt-winrepo>`_ .
|
||||
repositories. The default repo is one hosted on GitHub.com by SaltStack, Inc.,
|
||||
which includes package definitions for open source software. This repo points
|
||||
to the HTTP or ftp locations of the installer files. Anyone is welcome to send
|
||||
a pull request to this repo to add new package definitions. Browse the repo
|
||||
here: `https://github.com/saltstack/salt-winrepo.git
|
||||
<https://github.com/saltstack/salt-winrepo.git>`_ .
|
||||
|
||||
Configure which git repos the master can search for package definitions by
|
||||
modifying or extending the ``win_gitrepos`` configuration option list in the
|
||||
master config.
|
||||
Configure which git repositories the master can search for package definitions
|
||||
by modifying or extending the :conf_master:`winrepo_remotes` option (**NOTE:**
|
||||
this option was called ``win_gitrepos`` in Salt versions prior to 2015.8.0).
|
||||
|
||||
Checkout each git repo in ``win_gitrepos``, compile your package repository
|
||||
cache and then refresh each minion's package cache:
|
||||
Use the :py:func:`winrepo.update_git_repos
|
||||
<salt.runners.winrepo.update_git_repos>` runner to clone/update the configured
|
||||
reops, then use :py:func:`winrepo.genrepo <salt.runners.winrepo.genrepo>`
|
||||
runner to compile the repository cache. Finally, use :py:func:`pkg.refresh_db
|
||||
<salt.modules.win_pkg.refresh_db>` on each minion to have them update their
|
||||
copy of the repository cache. Command examples are as follows:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
@ -310,12 +329,82 @@ cache and then refresh each minion's package cache:
|
||||
|
||||
.. _wiki: http://wpkg.org/Category:Silent_Installers
|
||||
|
||||
.. _2015-8-0-winrepo-changes:
|
||||
|
||||
Changes in Version 2015.8.0
|
||||
===========================
|
||||
|
||||
Many of the winrepo configuration parameters have changed in version 2015.8.0
|
||||
to make the naming more consistent. The old parameter names will still work,
|
||||
but a warning will be logged indicating that the old name is deprecated. For a
|
||||
list of the winrepo config options, see :ref:`here <winrepo-config-opts>`.
|
||||
|
||||
Starting in version 2015.8.0, the :py:func:`winrepo.update_git_repos
|
||||
<salt.runners.winrepo.update_git_repos>` runner now makes use of the same
|
||||
underlying code used by the :ref:`Git Fileserver Backend <tutorial-gitfs>` and
|
||||
:ref:`Git External Pillar <tutorial-git_pillar>` to maintain and update its
|
||||
local clones of git repositories. If a compatible version of either pygit2_
|
||||
(0.20.3 and later) or GitPython_ (0.3.0 or later) is installed, then Salt will
|
||||
use it instead of the old method (which invokes the :py:func:`git.latest
|
||||
<salt.states.git.latest>` state).
|
||||
|
||||
.. note::
|
||||
If compatible versions of both pygit2_ and GitPython_ are installed, then
|
||||
Salt will prefer pygit2_, to override this behavior use the
|
||||
:conf_master:`winrepo_provider` configuration parameter:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
winrepo_provider: gitpython
|
||||
|
||||
.. _pygit2: https://github.com/libgit2/pygit2
|
||||
.. _GitPython: https://github.com/gitpython-developers/GitPython
|
||||
|
||||
One important change this brings is the the fact that each repo configured
|
||||
under the :conf_master:`winrepo_remotes` option (``win_gitrepos`` in Salt
|
||||
versions prior to 2015.8.0) will have its URL hashed and and the files will be
|
||||
checked out into a subdirectory containing that hashed name (for example,
|
||||
``/srv/salt/win/repo/f42c3382aeeaa8733908e5c256dba1ca/myprogram.sls``). There
|
||||
is no functional reason for the hashed name, it just comes from using the same
|
||||
back-end code that gitfs and git_pillar are using.
|
||||
|
||||
To minimize potential issues, it is a good idea to remove any winrepo git
|
||||
repositories that were checked out by the old (pre-2015.8.0) winrepo code when
|
||||
upgrading the master to 2015.8.0 or later, and run
|
||||
:py:func:`winrepo.update_git_repos <salt.runners.winrepo.update_git_repos>` to
|
||||
clone them anew after the master is started.
|
||||
|
||||
Additional added features include the ability to access authenticated git
|
||||
repositories (**NOTE:** pygit2_ only), and to set per-remote config settings. An
|
||||
example of this would be the following:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
winrepo_remotes:
|
||||
- https://github.com/saltstack/salt-winrepo.git
|
||||
- git@github.com:myuser/myrepo.git:
|
||||
- pubkey: /path/to/key.pub
|
||||
- privkey: /path/to/key
|
||||
- passphrase: myaw3s0m3pa$$phr4$3
|
||||
- https://github.com/myuser/privaterepo.git:
|
||||
- user: mygithubuser
|
||||
- password: correcthorsebatterystaple
|
||||
|
||||
.. note::
|
||||
Per-remote configuration settings work in the same fashion as they do in
|
||||
gitfs, with global parameters being overridden by their per-remote
|
||||
counterparts (for instance, setting :conf_master:`winrepo_passphrase` would
|
||||
set a global passphrase for winrepo that would apply to all SSH-based
|
||||
remotes, unless overridden by a ``passphrase`` per-remote parameter).
|
||||
|
||||
See :ref:`here <gitfs-per-remote-config>` for more a more in-depth
|
||||
explanation of how per-remote configuration works in gitfs, the same
|
||||
principles apply to winrepo.
|
||||
|
||||
|
||||
Troubleshooting
|
||||
===============
|
||||
|
||||
|
||||
Incorrect name/version
|
||||
----------------------
|
||||
|
||||
|
@ -923,7 +923,7 @@ class LocalClient(object):
|
||||
if raw is None:
|
||||
break
|
||||
if gather_errors:
|
||||
if raw['tag'] == '_salt_error':
|
||||
if raw['tag'] == '_salt_error' and 'id' in raw['data']:
|
||||
ret = {raw['data']['id']: raw['data']['data']}
|
||||
yield ret
|
||||
if 'minions' in raw.get('data', {}):
|
||||
|
@ -17,7 +17,7 @@
|
||||
# CREATED: 10/15/2012 09:49:37 PM WEST
|
||||
#======================================================================================================================
|
||||
set -o nounset # Treat unset variables as an error
|
||||
__ScriptVersion="2015.07.22"
|
||||
__ScriptVersion="2015.08.06"
|
||||
__ScriptName="bootstrap-salt.sh"
|
||||
|
||||
#======================================================================================================================
|
||||
@ -282,7 +282,7 @@ usage() {
|
||||
'install_<distro>_check_services' checks. You can also do this by
|
||||
touching /tmp/disable_salt_checks on the target host. Defaults \${BS_FALSE}
|
||||
-H Use the specified http proxy for the installation
|
||||
-Z Enable external software source for newer ZeroMQ(Only available for RHEL/CentOS/Fedora based distributions)
|
||||
-Z Enable external software source for newer ZeroMQ(Only available for RHEL/CentOS/Fedora/Ubuntu based distributions)
|
||||
|
||||
EOT
|
||||
} # ---------- end of function usage ----------
|
||||
@ -504,6 +504,7 @@ __exit_cleanup() {
|
||||
if [ $_KEEP_TEMP_FILES -eq $BS_FALSE ]; then
|
||||
# Clean up the checked out repository
|
||||
echodebug "Cleaning up the Salt Temporary Git Repository"
|
||||
cd "${__SALT_GIT_CHECKOUT_PARENT_DIR}"
|
||||
rm -rf "${__SALT_GIT_CHECKOUT_DIR}"
|
||||
else
|
||||
echowarn "Not cleaning up the Salt Temporary git repository on request"
|
||||
@ -1326,14 +1327,8 @@ __check_end_of_life_versions() {
|
||||
ubuntu)
|
||||
# Ubuntu versions not supported
|
||||
#
|
||||
# < 10
|
||||
# = 10.10
|
||||
# = 11.04
|
||||
# = 11.10
|
||||
if ([ "$DISTRO_MAJOR_VERSION" -eq 10 ] && [ "$DISTRO_MINOR_VERSION" -eq 10 ]) || \
|
||||
([ "$DISTRO_MAJOR_VERSION" -eq 11 ] && [ "$DISTRO_MINOR_VERSION" -eq 04 ]) || \
|
||||
([ "$DISTRO_MAJOR_VERSION" -eq 11 ] && [ "$DISTRO_MINOR_VERSION" -eq 10 ]) || \
|
||||
[ "$DISTRO_MAJOR_VERSION" -lt 10 ]; then
|
||||
# < 12.04
|
||||
if [ "$DISTRO_MAJOR_VERSION" -lt 12 ]; then
|
||||
echoerror "End of life distributions are not supported."
|
||||
echoerror "Please consider upgrading to the next stable. See:"
|
||||
echoerror " https://wiki.ubuntu.com/Releases"
|
||||
@ -1766,14 +1761,20 @@ install_ubuntu_deps() {
|
||||
# Need python-apt for managing packages via Salt
|
||||
__PACKAGES="${__PACKAGES} python-apt"
|
||||
|
||||
echoinfo "Installing Python Requests/Chardet from Chris Lea's PPA repository"
|
||||
if [ "$DISTRO_MAJOR_VERSION" -gt 11 ] || ([ "$DISTRO_MAJOR_VERSION" -eq 11 ] && [ "$DISTRO_MINOR_VERSION" -gt 04 ]); then
|
||||
# Above Ubuntu 11.04 add a -y flag
|
||||
add-apt-repository -y "ppa:chris-lea/python-requests" || return 1
|
||||
add-apt-repository -y "ppa:chris-lea/python-chardet" || return 1
|
||||
else
|
||||
add-apt-repository "ppa:chris-lea/python-requests" || return 1
|
||||
add-apt-repository "ppa:chris-lea/python-chardet" || return 1
|
||||
if [ "$DISTRO_MAJOR_VERSION" -lt 14 ]; then
|
||||
echoinfo "Installing Python Requests/Chardet from Chris Lea's PPA repository"
|
||||
if [ "$DISTRO_MAJOR_VERSION" -gt 11 ] || ([ "$DISTRO_MAJOR_VERSION" -eq 11 ] && [ "$DISTRO_MINOR_VERSION" -gt 04 ]); then
|
||||
# Above Ubuntu 11.04 add a -y flag
|
||||
add-apt-repository -y "ppa:chris-lea/python-requests" || return 1
|
||||
add-apt-repository -y "ppa:chris-lea/python-chardet" || return 1
|
||||
add-apt-repository -y "ppa:chris-lea/python-urllib3" || return 1
|
||||
add-apt-repository -y "ppa:chris-lea/python-crypto" || return 1
|
||||
else
|
||||
add-apt-repository "ppa:chris-lea/python-requests" || return 1
|
||||
add-apt-repository "ppa:chris-lea/python-chardet" || return 1
|
||||
add-apt-repository "ppa:chris-lea/python-urllib3" || return 1
|
||||
add-apt-repository "ppa:chris-lea/python-crypto" || return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
__PACKAGES="${__PACKAGES} python-requests"
|
||||
@ -1839,13 +1840,17 @@ install_ubuntu_stable_deps() {
|
||||
add-apt-repository "ppa:$STABLE_PPA" || return 1
|
||||
fi
|
||||
|
||||
__PACKAGES=""
|
||||
if [ ! "$(echo "$STABLE_REV" | egrep '^(2015\.8|latest)$')" = "" ]; then
|
||||
# We need a recent tornado package
|
||||
__REQUIRED_TORNADO="tornado >= 4.0"
|
||||
check_pip_allowed "You need to allow pip based installations (-P) in order to install the python package '${__REQUIRED_TORNADO}'"
|
||||
if [ "$(which pip)" = "" ]; then
|
||||
__apt_get_install_noinput python-setuptools python-pip
|
||||
__PACKAGES="${__PACKAGES} python-setuptools python-pip"
|
||||
fi
|
||||
__PACKAGES="${__PACKAGES} python-dev"
|
||||
# shellcheck disable=SC2086
|
||||
__apt_get_install_noinput $__PACKAGES
|
||||
pip install -U "${__REQUIRED_TORNADO}"
|
||||
fi
|
||||
|
||||
@ -1887,14 +1892,18 @@ install_ubuntu_git_deps() {
|
||||
|
||||
__git_clone_and_checkout || return 1
|
||||
|
||||
__PACKAGES=""
|
||||
if [ -f "${__SALT_GIT_CHECKOUT_DIR}/requirements/base.txt" ]; then
|
||||
# We're on the develop branch, install whichever tornado is on the requirements file
|
||||
__REQUIRED_TORNADO="$(grep tornado "${__SALT_GIT_CHECKOUT_DIR}/requirements/base.txt")"
|
||||
if [ "${__REQUIRED_TORNADO}" != "" ]; then
|
||||
__PACKAGES="${__PACKAGES} python-dev"
|
||||
check_pip_allowed "You need to allow pip based installations (-P) in order to install the python package '${__REQUIRED_TORNADO}'"
|
||||
if [ "$(which pip)" = "" ]; then
|
||||
__apt_get_install_noinput python-setuptools python-pip
|
||||
__PACKAGES="${__PACKAGES} python-setuptools python-pip"
|
||||
fi
|
||||
# shellcheck disable=SC2086
|
||||
__apt_get_install_noinput $__PACKAGES
|
||||
pip install -U "${__REQUIRED_TORNADO}"
|
||||
fi
|
||||
fi
|
||||
@ -2389,6 +2398,7 @@ install_debian_git_deps() {
|
||||
__REQUIRED_TORNADO="$(grep tornado "${__SALT_GIT_CHECKOUT_DIR}/requirements/base.txt")"
|
||||
if [ "${__REQUIRED_TORNADO}" != "" ]; then
|
||||
check_pip_allowed "You need to allow pip based installations (-P) in order to install the python package '${__REQUIRED_TORNADO}'"
|
||||
__apt_get_install_noinput python-dev
|
||||
pip install -U "${__REQUIRED_TORNADO}" || return 1
|
||||
fi
|
||||
fi
|
||||
@ -3026,10 +3036,10 @@ install_centos_git() {
|
||||
_PYEXE=python2
|
||||
fi
|
||||
if [ -f "${__SALT_GIT_CHECKOUT_DIR}/salt/syspaths.py" ]; then
|
||||
$_PYEXE setup.py install --salt-config-dir="$_SALT_ETC_DIR" || \
|
||||
$_PYEXE setup.py --salt-config-dir="$_SALT_ETC_DIR" install || return 1
|
||||
$_PYEXE setup.py install --prefix=/usr --salt-config-dir="$_SALT_ETC_DIR" || \
|
||||
$_PYEXE setup.py --prefix=/usr --salt-config-dir="$_SALT_ETC_DIR" install || return 1
|
||||
else
|
||||
$_PYEXE setup.py install || return 1
|
||||
$_PYEXE setup.py install --prefix=/usr || return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
@ -381,9 +381,6 @@ VALID_OPTS = {
|
||||
# Events matching a tag in this list should never be sent to an event returner.
|
||||
'event_return_blacklist': list,
|
||||
|
||||
# The source location for the winrepo sls files
|
||||
'win_repo_source_dir': str,
|
||||
|
||||
# This pidfile to write out to when a deamon starts
|
||||
'pidfile': str,
|
||||
|
||||
@ -570,9 +567,21 @@ VALID_OPTS = {
|
||||
# The logfile location for salt-key
|
||||
'key_logfile': str,
|
||||
|
||||
'win_repo': str,
|
||||
'win_repo_mastercachefile': str,
|
||||
'win_gitrepos': list,
|
||||
# The source location for the winrepo sls files
|
||||
# (used by win_pkg.py, minion only)
|
||||
'winrepo_source_dir': str,
|
||||
|
||||
'winrepo_dir': str,
|
||||
'winrepo_cachefile': str,
|
||||
'winrepo_remotes': list,
|
||||
'winrepo_branch': str,
|
||||
'winrepo_ssl_verify': bool,
|
||||
'winrepo_user': str,
|
||||
'winrepo_password': str,
|
||||
'winrepo_insecure_auth': bool,
|
||||
'winrepo_privkey': str,
|
||||
'winrepo_pubkey': str,
|
||||
'winrepo_passphrase': str,
|
||||
|
||||
# Set a hard limit for the amount of memory modules can consume on a minion.
|
||||
'modules_max_memory': int,
|
||||
@ -843,7 +852,10 @@ DEFAULT_MINION_OPTS = {
|
||||
'syndic_log_file': os.path.join(salt.syspaths.LOGS_DIR, 'syndic'),
|
||||
'syndic_pidfile': os.path.join(salt.syspaths.PIDFILE_DIR, 'salt-syndic.pid'),
|
||||
'random_reauth_delay': 10,
|
||||
'win_repo_source_dir': 'salt://win/repo/',
|
||||
'winrepo_source_dir': 'salt://win/repo/',
|
||||
'winrepo_dir': 'c:\\salt\\file_roots\\winrepo',
|
||||
'winrepo_cachefile': 'winrepo.p',
|
||||
'winrepo_remotes': ['https://github.com/saltstack/salt-winrepo.git'],
|
||||
'pidfile': os.path.join(salt.syspaths.PIDFILE_DIR, 'salt-minion.pid'),
|
||||
'range_server': 'range:80',
|
||||
'tcp_keepalive': True,
|
||||
@ -1042,10 +1054,17 @@ DEFAULT_MASTER_OPTS = {
|
||||
'verify_env': True,
|
||||
'permissive_pki_access': False,
|
||||
'default_include': 'master.d/*.conf',
|
||||
'win_repo': os.path.join(salt.syspaths.BASE_FILE_ROOTS_DIR, 'win', 'repo'),
|
||||
'win_repo_mastercachefile': os.path.join(salt.syspaths.BASE_FILE_ROOTS_DIR,
|
||||
'win', 'repo', 'winrepo.p'),
|
||||
'win_gitrepos': ['https://github.com/saltstack/salt-winrepo.git'],
|
||||
'winrepo_dir': os.path.join(salt.syspaths.BASE_FILE_ROOTS_DIR, 'win', 'repo'),
|
||||
'winrepo_cachefile': 'winrepo.p',
|
||||
'winrepo_remotes': ['https://github.com/saltstack/salt-winrepo.git'],
|
||||
'winrepo_branch': 'master',
|
||||
'winrepo_ssl_verify': False,
|
||||
'winrepo_user': '',
|
||||
'winrepo_password': '',
|
||||
'winrepo_insecure_auth': False,
|
||||
'winrepo_privkey': '',
|
||||
'winrepo_pubkey': '',
|
||||
'winrepo_passphrase': '',
|
||||
'syndic_wait': 5,
|
||||
'jinja_lstrip_blocks': False,
|
||||
'jinja_trim_blocks': False,
|
||||
|
@ -102,10 +102,10 @@ class Client(object):
|
||||
# Backwards compatibility
|
||||
saltenv = env
|
||||
|
||||
dest = os.path.join(self.opts['cachedir'],
|
||||
'files',
|
||||
saltenv,
|
||||
path)
|
||||
dest = salt.utils.path_join(self.opts['cachedir'],
|
||||
'files',
|
||||
saltenv,
|
||||
path)
|
||||
destdir = os.path.dirname(dest)
|
||||
cumask = os.umask(63)
|
||||
if not os.path.isdir(destdir):
|
||||
|
@ -778,7 +778,12 @@ def version(name, check_remote=False, source=None, pre_versions=False):
|
||||
log.error(err)
|
||||
raise CommandExecutionError(err)
|
||||
|
||||
cmd = [choc_path, 'version', name]
|
||||
if _LooseVersion(chocolatey_version()) >= _LooseVersion('0.9.9'):
|
||||
choco_cmd = "list"
|
||||
else:
|
||||
choco_cmd = "version"
|
||||
|
||||
cmd = [choc_path, choco_cmd, name]
|
||||
if not salt.utils.is_true(check_remote):
|
||||
cmd.append('-LocalOnly')
|
||||
if salt.utils.is_true(pre_versions):
|
||||
@ -800,13 +805,13 @@ def version(name, check_remote=False, source=None, pre_versions=False):
|
||||
# pairs is shown in rows...
|
||||
if not salt.utils.is_true(check_remote):
|
||||
ver_re = re.compile(r'(\S+)\s+(.+)')
|
||||
for line in result['stdout'].split('\n'):
|
||||
for line in result['stdout'].split('\n')[:-1]:
|
||||
for name, ver in ver_re.findall(line):
|
||||
ret['name'] = name
|
||||
ret['found'] = ver
|
||||
else:
|
||||
ver_re = re.compile(r'(\S+)\s+:\s*(.*)')
|
||||
for line in result['stdout'].split('\n'):
|
||||
for line in result['stdout'].split('\n')[:-1]:
|
||||
for key, value in ver_re.findall(line):
|
||||
ret[key] = value
|
||||
|
||||
|
@ -1089,7 +1089,7 @@ def comment_line(path,
|
||||
regex.lstrip('^').rstrip('$'),
|
||||
'$' if regex.endswith('$') else '')
|
||||
else:
|
||||
regex = '^{0}({1}){2}'.format(
|
||||
regex = r'^{0}\s*({1}){2}'.format(
|
||||
char,
|
||||
regex.lstrip('^').rstrip('$'),
|
||||
'$' if regex.endswith('$') else '')
|
||||
|
@ -47,7 +47,7 @@ def add(overlay):
|
||||
ret = list()
|
||||
old_overlays = list_local()
|
||||
cmd = 'layman --quietness=0 --add {0}'.format(overlay)
|
||||
add_attempt = __salt__['cmd.run_all'](cmd, python_shell=False)
|
||||
add_attempt = __salt__['cmd.run_all'](cmd, python_shell=False, stdin='y')
|
||||
if add_attempt['retcode'] != 0:
|
||||
raise salt.exceptions.CommandExecutionError(add_attempt['stdout'])
|
||||
new_overlays = list_local()
|
||||
|
@ -135,8 +135,8 @@ def read_key(hkey, path, key=None):
|
||||
'success': True}
|
||||
|
||||
if key: # This if statement will be removed in Boron
|
||||
salt.utils.warn_until('Boron', 'Use reg.read_value to read a registry'
|
||||
'value. This functionality will be'
|
||||
salt.utils.warn_until('Boron', 'Use reg.read_value to read a registry '
|
||||
'value. This functionality will be '
|
||||
'removed in Salt Boron')
|
||||
return read_value(hive=hkey,
|
||||
key=path,
|
||||
@ -248,8 +248,8 @@ def set_key(hkey, path, value, key=None, vtype='REG_DWORD', reflection=True):
|
||||
'''
|
||||
|
||||
if key: # This if statement will be removed in Boron
|
||||
salt.utils.warn_until('Boron', 'Use reg.set_value to set a registry'
|
||||
'value. This functionality will be'
|
||||
salt.utils.warn_until('Boron', 'Use reg.set_value to set a registry '
|
||||
'value. This functionality will be '
|
||||
'removed in Salt Boron')
|
||||
return set_value(hive=hkey,
|
||||
key=path,
|
||||
@ -353,8 +353,8 @@ def create_key(hkey, path, key=None, value=None, reflection=True):
|
||||
salt '*' reg.create_key HKEY_CURRENT_USER 'SOFTWARE\\Salt' 'version' '0.97'
|
||||
'''
|
||||
if key: # This if statement will be removed in Boron
|
||||
salt.utils.warn_until('Boron', 'Use reg.set_value to set a registry'
|
||||
'value. This functionality will be'
|
||||
salt.utils.warn_until('Boron', 'Use reg.set_value to set a registry '
|
||||
'value. This functionality will be '
|
||||
'removed in Salt Boron')
|
||||
return set_value(hive=hkey,
|
||||
key=path,
|
||||
@ -406,8 +406,8 @@ def delete_key(hkey, path, key=None, reflection=True):
|
||||
'''
|
||||
|
||||
if key: # This if statement will be removed in Boron
|
||||
salt.utils.warn_until('Boron', 'Use reg.set_value to set a registry'
|
||||
'value. This functionality will be'
|
||||
salt.utils.warn_until('Boron', 'Use reg.set_value to set a registry '
|
||||
'value. This functionality will be '
|
||||
'removed in Salt Boron')
|
||||
return delete_value(hive=hkey,
|
||||
key=path,
|
||||
|
@ -965,7 +965,7 @@ def build_routes(iface, **settings):
|
||||
'''
|
||||
|
||||
template = 'rh6_route_eth.jinja'
|
||||
if float(__grains__['osrelease']) < 6:
|
||||
if __grains__['osrelease'][0] < 6:
|
||||
template = 'route_eth.jinja'
|
||||
log.debug('Template name: ' + template)
|
||||
|
||||
|
@ -6,6 +6,7 @@ from __future__ import absolute_import
|
||||
|
||||
# Import Python libs
|
||||
import logging
|
||||
import json
|
||||
|
||||
# Import Salt libs
|
||||
import salt.utils
|
||||
@ -13,6 +14,13 @@ import salt.utils.decorators as decorators
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
# Function aliases
|
||||
__func_alias__ = {
|
||||
'list_installed': 'list',
|
||||
'update_installed': 'update',
|
||||
'import_image': 'import'
|
||||
}
|
||||
|
||||
# Define the module's virtual name
|
||||
__virtualname__ = 'imgadm'
|
||||
|
||||
@ -36,6 +44,27 @@ def _exit_status(retcode):
|
||||
return ret
|
||||
|
||||
|
||||
def _parse_image_meta(image=None, detail=False):
|
||||
if not image:
|
||||
return {}
|
||||
|
||||
if detail:
|
||||
return {
|
||||
'name': image['manifest']['name'],
|
||||
'version': image['manifest']['version'],
|
||||
'os': image['manifest']['os'],
|
||||
'description': image['manifest']['description'],
|
||||
'published': image['manifest']['published_at'],
|
||||
'source': image['source']
|
||||
}
|
||||
else:
|
||||
return '{name}@{version} [{date}]'.format(
|
||||
name=image['manifest']['name'],
|
||||
version=image['manifest']['version'],
|
||||
date=image['manifest']['published_at'],
|
||||
)
|
||||
|
||||
|
||||
def __virtual__():
|
||||
'''
|
||||
Provides imgadm only on SmartOS
|
||||
@ -63,70 +92,90 @@ def version():
|
||||
return ret[-1]
|
||||
|
||||
|
||||
def update_installed():
|
||||
def update_installed(uuid=''):
|
||||
'''
|
||||
Gather info on unknown images (locally installed)
|
||||
Gather info on unknown image(s) (locally installed)
|
||||
|
||||
uuid : string
|
||||
Specifies uuid of image
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' imgadm.update_installed()
|
||||
salt '*' imgadm.update [uuid]
|
||||
'''
|
||||
imgadm = _check_imgadm()
|
||||
if imgadm:
|
||||
cmd = '{0} update'.format(imgadm)
|
||||
cmd = '{0} update {1}'.format(imgadm, uuid).rstrip()
|
||||
__salt__['cmd.run'](cmd)
|
||||
return {}
|
||||
|
||||
|
||||
def avail(search=None):
|
||||
def avail(search=None, verbose=False):
|
||||
'''
|
||||
Return a list of available images
|
||||
|
||||
search : string
|
||||
Specifies search keyword
|
||||
verbose : boolean (False)
|
||||
Specifies verbose output
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' imgadm.avail [percona]
|
||||
salt '*' imgadm.avail verbose=True
|
||||
'''
|
||||
ret = {}
|
||||
imgadm = _check_imgadm()
|
||||
cmd = '{0} avail'.format(imgadm)
|
||||
cmd = '{0} avail -j'.format(imgadm)
|
||||
res = __salt__['cmd.run_all'](cmd)
|
||||
retcode = res['retcode']
|
||||
result = {}
|
||||
if retcode != 0:
|
||||
ret['Error'] = _exit_status(retcode)
|
||||
return ret
|
||||
if search:
|
||||
for line in res['stdout'].splitlines():
|
||||
if search in line:
|
||||
ret = line
|
||||
else:
|
||||
ret = res['stdout'].splitlines()
|
||||
return ret
|
||||
|
||||
for image in json.loads(res['stdout']):
|
||||
if image['manifest']['disabled'] or not image['manifest']['public']:
|
||||
continue
|
||||
if search and search not in image['manifest']['name']:
|
||||
# we skip if we are searching but don't have a match
|
||||
continue
|
||||
result[image['manifest']['uuid']] = _parse_image_meta(image, verbose)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def list_installed():
|
||||
def list_installed(verbose=False):
|
||||
'''
|
||||
Return a list of installed images
|
||||
|
||||
verbose : boolean (False)
|
||||
Specifies verbose output
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' imgadm.list_installed
|
||||
salt '*' imgadm.list [verbose=True]
|
||||
'''
|
||||
ret = {}
|
||||
imgadm = _check_imgadm()
|
||||
cmd = '{0} list'.format(imgadm)
|
||||
cmd = '{0} list -j'.format(imgadm)
|
||||
res = __salt__['cmd.run_all'](cmd)
|
||||
retcode = res['retcode']
|
||||
result = {}
|
||||
if retcode != 0:
|
||||
ret['Error'] = _exit_status(retcode)
|
||||
return ret
|
||||
ret = res['stdout'].splitlines()
|
||||
return ret
|
||||
|
||||
for image in json.loads(res['stdout']):
|
||||
result[image['manifest']['uuid']] = _parse_image_meta(image, verbose)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def show(uuid=None):
|
||||
@ -150,7 +199,7 @@ def show(uuid=None):
|
||||
if retcode != 0:
|
||||
ret['Error'] = _exit_status(retcode)
|
||||
return ret
|
||||
ret[uuid] = res['stdout'].splitlines()
|
||||
ret = json.loads(res['stdout'])
|
||||
return ret
|
||||
|
||||
|
||||
@ -175,19 +224,24 @@ def get(uuid=None):
|
||||
if retcode != 0:
|
||||
ret['Error'] = _exit_status(retcode)
|
||||
return ret
|
||||
ret[uuid] = res['stdout'].splitlines()
|
||||
ret = json.loads(res['stdout'])
|
||||
return ret
|
||||
|
||||
|
||||
def import_image(uuid=None):
|
||||
def import_image(uuid=None, verbose=False):
|
||||
'''
|
||||
Import an image from the repository
|
||||
|
||||
uuid : string
|
||||
Specifies uuid to import
|
||||
verbose : boolean (False)
|
||||
Specifies verbose output
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' imgadm.import_image e42f8c84-bbea-11e2-b920-078fab2aab1f
|
||||
salt '*' imgadm.import e42f8c84-bbea-11e2-b920-078fab2aab1f [verbose=True]
|
||||
'''
|
||||
ret = {}
|
||||
if not uuid:
|
||||
@ -200,14 +254,17 @@ def import_image(uuid=None):
|
||||
if retcode != 0:
|
||||
ret['Error'] = _exit_status(retcode)
|
||||
return ret
|
||||
ret[uuid] = res['stdout'].splitlines()
|
||||
return ret
|
||||
|
||||
return {uuid: _parse_image_meta(get(uuid), verbose)}
|
||||
|
||||
|
||||
def delete(uuid=None):
|
||||
'''
|
||||
Remove an installed image
|
||||
|
||||
uuid : string
|
||||
Specifies uuid to import
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
@ -225,8 +282,48 @@ def delete(uuid=None):
|
||||
if retcode != 0:
|
||||
ret['Error'] = _exit_status(retcode)
|
||||
return ret
|
||||
ret[uuid] = res['stdout'].splitlines()
|
||||
return ret
|
||||
# output: Deleted image d5b3865c-0804-11e5-be21-dbc4ce844ddc
|
||||
result = []
|
||||
for image in res['stdout'].splitlines():
|
||||
image = [var for var in image.split(" ") if var]
|
||||
result.append(image[2])
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def vacuum(verbose=False):
|
||||
'''
|
||||
Remove unused images
|
||||
|
||||
verbose : boolean (False)
|
||||
Specifies verbose output
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' imgadm.vacuum [verbose=True]
|
||||
'''
|
||||
ret = {}
|
||||
imgadm = _check_imgadm()
|
||||
cmd = '{0} vacuum -f'.format(imgadm)
|
||||
res = __salt__['cmd.run_all'](cmd)
|
||||
retcode = res['retcode']
|
||||
if retcode != 0:
|
||||
ret['Error'] = _exit_status(retcode)
|
||||
return ret
|
||||
# output: Deleted image d5b3865c-0804-11e5-be21-dbc4ce844ddc (lx-centos-6@20150601)
|
||||
result = {}
|
||||
for image in res['stdout'].splitlines():
|
||||
image = [var for var in image.split(" ") if var]
|
||||
result[image[2]] = {
|
||||
'name': image[3][1:image[3].index('@')],
|
||||
'version': image[3][image[3].index('@')+1:-1]
|
||||
}
|
||||
if verbose:
|
||||
return result
|
||||
else:
|
||||
return list(result.keys())
|
||||
|
||||
|
||||
# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
|
@ -109,6 +109,12 @@ def set_zone(timezone):
|
||||
|
||||
salt '*' timezone.set_zone 'America/Denver'
|
||||
'''
|
||||
if salt.utils.which('timedatectl'):
|
||||
try:
|
||||
__salt__['cmd.run']('timedatectl set-timezone {0}'.format(timezone))
|
||||
except CommandExecutionError:
|
||||
pass
|
||||
|
||||
if 'Solaris' in __grains__['os_family']:
|
||||
zonepath = '/usr/share/lib/zoneinfo/{0}'.format(timezone)
|
||||
else:
|
||||
|
@ -389,7 +389,11 @@ def chfullname(name, fullname):
|
||||
|
||||
salt '*' user.chfullname foo "Foo Bar"
|
||||
'''
|
||||
fullname = str(fullname)
|
||||
if fullname is None:
|
||||
fullname = ''
|
||||
else:
|
||||
fullname = str(fullname)
|
||||
|
||||
pre_info = _get_gecos(name)
|
||||
if not pre_info:
|
||||
return False
|
||||
@ -415,7 +419,11 @@ def chroomnumber(name, roomnumber):
|
||||
|
||||
salt '*' user.chroomnumber foo 123
|
||||
'''
|
||||
roomnumber = str(roomnumber)
|
||||
if roomnumber is None:
|
||||
roomnumber = ''
|
||||
else:
|
||||
roomnumber = str(roomnumber)
|
||||
|
||||
pre_info = _get_gecos(name)
|
||||
if not pre_info:
|
||||
return False
|
||||
@ -441,7 +449,11 @@ def chworkphone(name, workphone):
|
||||
|
||||
salt '*' user.chworkphone foo "7735550123"
|
||||
'''
|
||||
workphone = str(workphone)
|
||||
if workphone is None:
|
||||
workphone = ''
|
||||
else:
|
||||
workphone = str(workphone)
|
||||
|
||||
pre_info = _get_gecos(name)
|
||||
if not pre_info:
|
||||
return False
|
||||
@ -467,7 +479,11 @@ def chhomephone(name, homephone):
|
||||
|
||||
salt '*' user.chhomephone foo "7735551234"
|
||||
'''
|
||||
homephone = str(homephone)
|
||||
if homephone is None:
|
||||
homephone = ''
|
||||
else:
|
||||
homephone = str(homephone)
|
||||
|
||||
pre_info = _get_gecos(name)
|
||||
if not pre_info:
|
||||
return False
|
||||
|
@ -6,13 +6,17 @@ from __future__ import absolute_import
|
||||
|
||||
# Import python libs
|
||||
import re
|
||||
import logging
|
||||
|
||||
# Import salt libs
|
||||
import salt.utils
|
||||
from salt.ext import six
|
||||
|
||||
# Define the module's virtual name
|
||||
__virtualname__ = 'firewall'
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def __virtual__():
|
||||
'''
|
||||
@ -119,11 +123,18 @@ def add_rule(name, localport, protocol='tcp', action='allow', dir='in'):
|
||||
'dir={0}'.format(dir),
|
||||
'localport={0}'.format(localport),
|
||||
'action={0}'.format(action)]
|
||||
return __salt__['cmd.run'](cmd, python_shell=False) == 'Ok.'
|
||||
ret = __salt__['cmd.run'](cmd, python_shell=False)
|
||||
if isinstance(ret, six.string_types):
|
||||
return ret.strip() == 'Ok.'
|
||||
else:
|
||||
log.error('firewall.add_rule failed: {0}'.format(ret))
|
||||
return False
|
||||
|
||||
|
||||
def delete_rule(name, localport, protocol='tcp', dir='in'):
|
||||
'''
|
||||
.. versionadded:: 2015.8.0
|
||||
|
||||
Delete an existing firewall rule
|
||||
|
||||
CLI Example:
|
||||
@ -137,4 +148,9 @@ def delete_rule(name, localport, protocol='tcp', dir='in'):
|
||||
'protocol={0}'.format(protocol),
|
||||
'dir={0}'.format(dir),
|
||||
'localport={0}'.format(localport)]
|
||||
return __salt__['cmd.run'](cmd, python_shell=False) == 'Ok.'
|
||||
ret = __salt__['cmd.run'](cmd, python_shell=False)
|
||||
if isinstance(ret, six.string_types):
|
||||
return ret.endswith('Ok.')
|
||||
else:
|
||||
log.error('firewall.delete_rule failed: {0}'.format(ret))
|
||||
return False
|
||||
|
@ -93,9 +93,9 @@ def latest_version(*names, **kwargs):
|
||||
latest_installed = sorted(installed_pkgs[name], cmp=_reverse_cmp_pkg_versions).pop()
|
||||
log.debug('Latest installed version of package {0} is {1}'.format(name, latest_installed))
|
||||
|
||||
# get latest available (from win_repo) version of package
|
||||
# get latest available (from winrepo_dir) version of package
|
||||
pkg_info = _get_package_info(name)
|
||||
log.trace('Raw win_repo pkg_info for {0} is {1}'.format(name, pkg_info))
|
||||
log.trace('Raw winrepo pkg_info for {0} is {1}'.format(name, pkg_info))
|
||||
latest_available = _get_latest_pkg_version(pkg_info)
|
||||
if latest_available:
|
||||
log.debug('Latest available version of package {0} is {1}'.format(name, latest_available))
|
||||
@ -371,25 +371,47 @@ def refresh_db(saltenv='base'):
|
||||
salt '*' pkg.refresh_db
|
||||
'''
|
||||
__context__.pop('winrepo.data', None)
|
||||
repo = __opts__['win_repo_source_dir']
|
||||
cached_files = __salt__['cp.cache_dir'](repo, saltenv, include_pat='*.sls')
|
||||
if 'win_repo_source_dir' in __opts__:
|
||||
salt.utils.warn_until(
|
||||
'Nitrogen',
|
||||
'The \'win_repo_source_dir\' config option is deprecated, please '
|
||||
'use \'winrepo_source_dir\' instead.'
|
||||
)
|
||||
winrepo_source_dir = __opts__['win_repo_source_dir']
|
||||
else:
|
||||
winrepo_source_dir = __opts__['winrepo_source_dir']
|
||||
|
||||
cached_files = __salt__['cp.cache_dir'](
|
||||
winrepo_source_dir,
|
||||
saltenv,
|
||||
include_pat='*.sls'
|
||||
)
|
||||
genrepo(saltenv=saltenv)
|
||||
return cached_files
|
||||
|
||||
|
||||
def _get_local_repo_dir(saltenv='base'):
|
||||
master_repo_src = __opts__['win_repo_source_dir']
|
||||
if 'win_repo_source_dir' in __opts__:
|
||||
salt.utils.warn_until(
|
||||
'Nitrogen',
|
||||
'The \'win_repo_source_dir\' config option is deprecated, please '
|
||||
'use \'winrepo_source_dir\' instead.'
|
||||
)
|
||||
winrepo_source_dir = __opts__['win_repo_source_dir']
|
||||
else:
|
||||
winrepo_source_dir = __opts__['winrepo_source_dir']
|
||||
|
||||
dirs = []
|
||||
dirs.append(salt.syspaths.CACHE_DIR)
|
||||
dirs.extend(['minion', 'files'])
|
||||
dirs.append(saltenv)
|
||||
dirs.extend(master_repo_src[7:].strip('/').split('/'))
|
||||
dirs.extend(winrepo_source_dir[7:].strip('/').split('/'))
|
||||
return os.sep.join(dirs)
|
||||
|
||||
|
||||
def genrepo(saltenv='base'):
|
||||
'''
|
||||
Generate win_repo_cachefile based on sls files in the win_repo
|
||||
Generate winrepo_cachefile based on sls files in the winrepo
|
||||
|
||||
CLI Example:
|
||||
|
||||
@ -626,7 +648,10 @@ def remove(name=None, pkgs=None, version=None, extra_uninstall_flags=None, **kwa
|
||||
uninstaller = pkginfo[version].get('installer')
|
||||
if not uninstaller:
|
||||
return 'Error: No installer or uninstaller configured for package {0}'.format(name)
|
||||
if uninstaller.startswith('salt:'):
|
||||
if uninstaller.startswith('salt:') \
|
||||
or uninstaller.startswith('http:') \
|
||||
or uninstaller.startswith('https:') \
|
||||
or uninstaller.startswith('ftp:'):
|
||||
cached_pkg = \
|
||||
__salt__['cp.is_cached'](uninstaller)
|
||||
if not cached_pkg:
|
||||
|
@ -2,10 +2,11 @@
|
||||
r'''
|
||||
Module to manage Windows software repo on a Standalone Minion
|
||||
|
||||
The following options must be set in the Minion config:
|
||||
file_client: local
|
||||
win_repo_cachefile: c:\salt\file_roots\winrepo\winrepo.p
|
||||
win_repo: c:\salt\file_roots\winrepo
|
||||
``file_client: local`` must be set in the minion config file. Other config
|
||||
options of interest include:
|
||||
|
||||
* :conf_minion:`winrepo_dir`
|
||||
* :conf_minion:`winrepo_cachefile`
|
||||
|
||||
Place all Windows package files in the 'win_repo' directory.
|
||||
'''
|
||||
@ -46,7 +47,7 @@ def __virtual__():
|
||||
|
||||
def genrepo():
|
||||
r'''
|
||||
Generate win_repo_cachefile based on sls files in the win_repo
|
||||
Generate winrepo_cachefile based on sls files in the win_repo
|
||||
|
||||
CLI Example:
|
||||
|
||||
@ -54,13 +55,31 @@ def genrepo():
|
||||
|
||||
salt-call winrepo.genrepo -c c:\salt\conf
|
||||
'''
|
||||
if 'win_repo' in __opts__:
|
||||
salt.utils.warn_until(
|
||||
'Nitrogen',
|
||||
'The \'win_repo\' config option is deprecated, please use '
|
||||
'\'winrepo_dir\' instead.'
|
||||
)
|
||||
winrepo_dir = __opts__['win_repo']
|
||||
else:
|
||||
winrepo_dir = __opts__['winrepo_dir']
|
||||
|
||||
if 'win_repo_cachefile' in __opts__:
|
||||
salt.utils.warn_until(
|
||||
'Nitrogen',
|
||||
'The \'win_repo_cachefile\' config option is deprecated, please '
|
||||
'use \'winrepo_cachefile\' instead.'
|
||||
)
|
||||
winrepo_cachefile = __opts__['win_repo_cachefile']
|
||||
else:
|
||||
winrepo_cachefile = __opts__['winrepo_cachefile']
|
||||
|
||||
ret = {}
|
||||
repo = __opts__['win_repo']
|
||||
if not os.path.exists(repo):
|
||||
os.makedirs(repo)
|
||||
winrepo = __opts__['win_repo_cachefile']
|
||||
if not os.path.exists(winrepo_dir):
|
||||
os.makedirs(winrepo_dir)
|
||||
renderers = salt.loader.render(__opts__, __salt__)
|
||||
for root, dirs, files in os.walk(repo):
|
||||
for root, dirs, files in os.walk(winrepo_dir):
|
||||
for name in files:
|
||||
if name.endswith('.sls'):
|
||||
config = salt.template.compile_template(
|
||||
@ -77,7 +96,8 @@ def genrepo():
|
||||
revmap[repodata['full_name']] = pkgname
|
||||
ret.setdefault('repo', {}).update(config)
|
||||
ret.setdefault('name_map', {}).update(revmap)
|
||||
with salt.utils.fopen(os.path.join(repo, winrepo), 'w+b') as repo:
|
||||
with salt.utils.fopen(
|
||||
os.path.join(winrepo_dir, winrepo_cachefile), 'w+b') as repo:
|
||||
repo.write(msgpack.dumps(ret))
|
||||
salt.output.display_output(ret, 'pprint', __opts__)
|
||||
return ret
|
||||
@ -91,25 +111,43 @@ def update_git_repos():
|
||||
|
||||
This function will not work unless git is installed and the git module
|
||||
is further updated to work on Windows. In the meantime just place all
|
||||
Windows package files in the ``win_repo`` directory.
|
||||
Windows package files in the :conf_minion:`winrepo_dir` directory.
|
||||
'''
|
||||
if 'win_repo' in __opts__:
|
||||
salt.utils.warn_until(
|
||||
'Nitrogen',
|
||||
'The \'win_repo\' config option is deprecated, please use '
|
||||
'\'winrepo_dir\' instead.'
|
||||
)
|
||||
winrepo_dir = __opts__['win_repo']
|
||||
else:
|
||||
winrepo_dir = __opts__['winrepo_dir']
|
||||
|
||||
if 'win_gitrepos' in __opts__:
|
||||
salt.utils.warn_until(
|
||||
'Nitrogen',
|
||||
'The \'win_gitrepos\' config option is deprecated, please use '
|
||||
'\'winrepo_remotes\' instead.'
|
||||
)
|
||||
winrepo_remotes = __opts__['win_gitrepos']
|
||||
else:
|
||||
winrepo_remotes = __opts__['winrepo_remotes']
|
||||
|
||||
ret = {}
|
||||
#mminion = salt.minion.MasterMinion(__opts__)
|
||||
repo = __opts__['win_repo']
|
||||
gitrepos = __opts__['win_gitrepos']
|
||||
for gitrepo in gitrepos:
|
||||
#if '/' in gitrepo:
|
||||
#targetname = gitrepo.split('/')[-1]
|
||||
for remote in winrepo_remotes:
|
||||
#if '/' in remote:
|
||||
#targetname = remote.split('/')[-1]
|
||||
#else:
|
||||
#targetname = gitrepo
|
||||
targetname = gitrepo
|
||||
#targetname = remote
|
||||
targetname = remote
|
||||
rev = None
|
||||
# If a revision is specified, use it.
|
||||
if len(gitrepo.strip().split(' ')) > 1:
|
||||
rev, gitrepo = gitrepo.strip().split(' ')
|
||||
gittarget = os.path.join(repo, targetname)
|
||||
#result = mminion.states['git.latest'](gitrepo,
|
||||
result = __salt__['git.latest'](gitrepo,
|
||||
if len(remote.strip().split(' ')) > 1:
|
||||
rev, remote = remote.strip().split(' ')
|
||||
gittarget = os.path.join(winrepo_dir, targetname)
|
||||
#result = mminion.states['git.latest'](remote,
|
||||
result = __salt__['git.latest'](remote,
|
||||
rev=rev,
|
||||
target=gittarget,
|
||||
force=True)
|
||||
|
@ -1,22 +1,33 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Module for managing windows systems.
|
||||
|
||||
:depends:
|
||||
- win32net
|
||||
|
||||
Support for reboot, shutdown, etc
|
||||
'''
|
||||
from __future__ import absolute_import
|
||||
|
||||
# Import python libs
|
||||
import logging
|
||||
import re
|
||||
import datetime
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
||||
# Import 3rd Party Libs
|
||||
try:
|
||||
from shlex import quote as _cmd_quote # pylint: disable=E0611
|
||||
import win32net
|
||||
import win32api
|
||||
import pywintypes
|
||||
from ctypes import windll
|
||||
HAS_WIN32NET_MODS = True
|
||||
except ImportError:
|
||||
from pipes import quote as _cmd_quote
|
||||
HAS_WIN32NET_MODS = False
|
||||
|
||||
# Import salt libs
|
||||
import salt.utils
|
||||
import salt.utils.locales
|
||||
from salt.modules.reg import read_value
|
||||
|
||||
# Set up logging
|
||||
log = logging.getLogger(__name__)
|
||||
@ -27,11 +38,11 @@ __virtualname__ = 'system'
|
||||
|
||||
def __virtual__():
|
||||
'''
|
||||
This only supports Windows
|
||||
Set the system module of the kernel is Windows
|
||||
'''
|
||||
if not salt.utils.is_windows():
|
||||
return False
|
||||
return __virtualname__
|
||||
if HAS_WIN32NET_MODS and salt.utils.is_windows():
|
||||
return __virtualname__
|
||||
return False
|
||||
|
||||
|
||||
def _convert_minutes_seconds(timeout, in_seconds=False):
|
||||
@ -43,7 +54,14 @@ def _convert_minutes_seconds(timeout, in_seconds=False):
|
||||
|
||||
def halt(timeout=5, in_seconds=False):
|
||||
'''
|
||||
Halt a running system
|
||||
Halt a running system.
|
||||
|
||||
:param int timeout:
|
||||
Number of seconds before halting the system.
|
||||
Default is 5 seconds.
|
||||
|
||||
:return: True is successful.
|
||||
:rtype: bool
|
||||
|
||||
timeout
|
||||
The wait time before the system will be shutdown.
|
||||
@ -59,7 +77,7 @@ def halt(timeout=5, in_seconds=False):
|
||||
|
||||
salt '*' system.halt 5
|
||||
'''
|
||||
return shutdown(timeout, in_seconds)
|
||||
return shutdown(timeout=timeout, in_seconds=in_seconds)
|
||||
|
||||
|
||||
def init(runlevel):
|
||||
@ -84,7 +102,14 @@ def init(runlevel):
|
||||
|
||||
def poweroff(timeout=5, in_seconds=False):
|
||||
'''
|
||||
Poweroff a running system
|
||||
Power off a running system.
|
||||
|
||||
:param int timeout:
|
||||
Number of seconds before powering off the system.
|
||||
Default is 5 seconds.
|
||||
|
||||
:return: True if successful
|
||||
:rtype: bool
|
||||
|
||||
timeout
|
||||
The wait time before the system will be shutdown.
|
||||
@ -100,12 +125,19 @@ def poweroff(timeout=5, in_seconds=False):
|
||||
|
||||
salt '*' system.poweroff 5
|
||||
'''
|
||||
return shutdown(timeout, in_seconds)
|
||||
return shutdown(timeout=timeout, in_seconds=in_seconds)
|
||||
|
||||
|
||||
def reboot(timeout=5, in_seconds=False, wait_for_reboot=False):
|
||||
'''
|
||||
Reboot the system
|
||||
Reboot a running system.
|
||||
|
||||
:param int timeout:
|
||||
Number of seconds before rebooting the system.
|
||||
Default is 5 seconds.
|
||||
|
||||
:return: True if successful
|
||||
:rtype: bool
|
||||
|
||||
timeout
|
||||
The wait time before the system will be shutdown.
|
||||
@ -133,28 +165,57 @@ def reboot(timeout=5, in_seconds=False, wait_for_reboot=False):
|
||||
salt '*' system.reboot 5
|
||||
salt '*' system.reboot 5 True
|
||||
'''
|
||||
seconds = _convert_minutes_seconds(timeout, in_seconds)
|
||||
cmd = ['shutdown', '/r', '/t', '{0}'.format(seconds)]
|
||||
ret = __salt__['cmd.run'](cmd, python_shell=False)
|
||||
|
||||
ret = shutdown(timeout=timeout, reboot=True, in_seconds=in_seconds)
|
||||
|
||||
if wait_for_reboot:
|
||||
seconds = _convert_minutes_seconds(timeout, in_seconds)
|
||||
time.sleep(seconds + 30)
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def shutdown(timeout=5, in_seconds=False):
|
||||
def shutdown(message=None, timeout=5, force_close=True, reboot=False, in_seconds=False):
|
||||
'''
|
||||
Shutdown a running system
|
||||
Shutdown a running system.
|
||||
|
||||
timeout
|
||||
The wait time before the system will be shutdown.
|
||||
:param str message:
|
||||
A message to display to the user before shutting down.
|
||||
|
||||
in_seconds
|
||||
:param int timeout:
|
||||
The length of time that the shutdown dialog box should be displayed, in
|
||||
seconds. While this dialog box is displayed, the shutdown can be stopped
|
||||
by the shutdown_abort function.
|
||||
|
||||
If dwTimeout is not zero, InitiateSystemShutdown displays a dialog box
|
||||
on the specified computer. The dialog box displays the name of the user
|
||||
who called the function, displays the message specified by the lpMessage
|
||||
parameter, and prompts the user to log off. The dialog box beeps when it
|
||||
is created and remains on top of other windows in the system. The dialog
|
||||
box can be moved but not closed. A timer counts down the remaining time
|
||||
before a forced shutdown.
|
||||
|
||||
If dwTimeout is zero, the computer shuts down without displaying the
|
||||
dialog box, and the shutdown cannot be stopped by shutdown_abort.
|
||||
|
||||
Default is 5
|
||||
|
||||
:param bool in_seconds:
|
||||
Whether to treat timeout as seconds or minutes.
|
||||
|
||||
.. versionadded:: 2015.8.0
|
||||
|
||||
:param bool force_close:
|
||||
True to force close all open applications. False displays a dialog box
|
||||
instructing the user to close the applications.
|
||||
|
||||
:param bool reboot:
|
||||
True restarts the computer immediately after shutdown.
|
||||
False caches to disk and safely powers down the system.
|
||||
|
||||
:return: True if successful
|
||||
:rtype: bool
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
@ -162,14 +223,32 @@ def shutdown(timeout=5, in_seconds=False):
|
||||
salt '*' system.shutdown 5
|
||||
'''
|
||||
seconds = _convert_minutes_seconds(timeout, in_seconds)
|
||||
cmd = ['shutdown', '/s', '/t', '{0}'.format(seconds)]
|
||||
ret = __salt__['cmd.run'](cmd, python_shell=False)
|
||||
return ret
|
||||
|
||||
if message:
|
||||
message = message.decode('utf-8')
|
||||
try:
|
||||
win32api.InitiateSystemShutdown('127.0.0.1', message, timeout,
|
||||
force_close, reboot)
|
||||
return True
|
||||
except pywintypes.error as exc:
|
||||
(number, context, message) = exc
|
||||
log.error('Failed to shutdown the system')
|
||||
log.error('nbr: {0}'.format(number))
|
||||
log.error('ctx: {0}'.format(context))
|
||||
log.error('msg: {0}'.format(message))
|
||||
return False
|
||||
|
||||
|
||||
def shutdown_hard():
|
||||
'''
|
||||
Shutdown a running system with no timeout or warning
|
||||
Shutdown a running system with no timeout or warning.
|
||||
|
||||
:param int timeout:
|
||||
Number of seconds before shutting down the system.
|
||||
Default is 5 seconds.
|
||||
|
||||
:return: True if successful
|
||||
:rtype: bool
|
||||
|
||||
CLI Example:
|
||||
|
||||
@ -177,27 +256,61 @@ def shutdown_hard():
|
||||
|
||||
salt '*' system.shutdown_hard
|
||||
'''
|
||||
cmd = ['shutdown', '/p', '/f']
|
||||
ret = __salt__['cmd.run'](cmd, python_shell=False)
|
||||
return ret
|
||||
return shutdown(timeout=0)
|
||||
|
||||
|
||||
def shutdown_abort():
|
||||
'''
|
||||
Abort a shutdown. Only available while the dialog box is being
|
||||
displayed to the user. Once the shutdown has initiated, it cannot be aborted
|
||||
|
||||
:return: True if successful
|
||||
:rtype: bool
|
||||
'''
|
||||
try:
|
||||
win32api.AbortSystemShutdown('127.0.0.1')
|
||||
return True
|
||||
except pywintypes.error as exc:
|
||||
(number, context, message) = exc
|
||||
log.error('Failed to abort system shutdown')
|
||||
log.error('nbr: {0}'.format(number))
|
||||
log.error('ctx: {0}'.format(context))
|
||||
log.error('msg: {0}'.format(message))
|
||||
return False
|
||||
|
||||
|
||||
def lock():
|
||||
'''
|
||||
Lock the workstation.
|
||||
|
||||
:return: True if successful
|
||||
:rtype: bool
|
||||
'''
|
||||
return windll.user32.LockWorkStation()
|
||||
|
||||
|
||||
def set_computer_name(name):
|
||||
'''
|
||||
Set the Windows computer name
|
||||
|
||||
:param str name:
|
||||
The new name to give the computer. Requires a reboot to take effect.
|
||||
|
||||
:return:
|
||||
Returns a dictionary containing the old and new names if successful.
|
||||
False if not.
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'minion-id' system.set_computer_name 'DavesComputer'
|
||||
'''
|
||||
cmd = ('wmic computersystem where name="%COMPUTERNAME%"'
|
||||
' call rename name="{0}"'.format(name))
|
||||
log.debug('Attempting to change computer name. Cmd is: {0}'.format(cmd))
|
||||
ret = __salt__['cmd.run'](cmd, python_shell=True)
|
||||
if 'ReturnValue = 0;' in ret:
|
||||
ret = {'Computer Name': {'Current': get_computer_name()}}
|
||||
if name:
|
||||
name = name.decode('utf-8')
|
||||
|
||||
if windll.kernel32.SetComputerNameW(name):
|
||||
ret = {'Computer Name': {'Current': get_system_info()['name']}}
|
||||
pending = get_pending_computer_name()
|
||||
if pending not in (None, False):
|
||||
ret['Computer Name']['Pending'] = pending
|
||||
@ -213,6 +326,10 @@ def get_pending_computer_name():
|
||||
retrieving the pending computer name, ``False`` will be returned, and an
|
||||
error message will be logged to the minion log.
|
||||
|
||||
:return:
|
||||
Returns the pending name if pending restart. Returns none if not pending
|
||||
restart.
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
@ -220,26 +337,11 @@ def get_pending_computer_name():
|
||||
salt 'minion-id' system.get_pending_computer_name
|
||||
'''
|
||||
current = get_computer_name()
|
||||
cmd = ['reg', 'query',
|
||||
'HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ComputerName',
|
||||
'/v', 'ComputerName']
|
||||
output = __salt__['cmd.run'](cmd, python_shell=False)
|
||||
pending = None
|
||||
for line in output.splitlines():
|
||||
try:
|
||||
pending = re.search(
|
||||
r'ComputerName\s+REG_SZ\s+(\S+)',
|
||||
line
|
||||
).group(1)
|
||||
break
|
||||
except AttributeError:
|
||||
continue
|
||||
|
||||
if pending is not None:
|
||||
pending = read_value('HKLM',
|
||||
r'SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName',
|
||||
'ComputerName')['vdata']
|
||||
if pending:
|
||||
return pending if pending != current else None
|
||||
|
||||
log.error('Unable to retrieve pending computer name using the '
|
||||
'following command: {0}'.format(cmd))
|
||||
return False
|
||||
|
||||
|
||||
@ -247,58 +349,90 @@ def get_computer_name():
|
||||
'''
|
||||
Get the Windows computer name
|
||||
|
||||
:return:
|
||||
Returns the computer name if found. Otherwise returns False
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'minion-id' system.get_computer_name
|
||||
'''
|
||||
cmd = ['net', 'config', 'server']
|
||||
lines = __salt__['cmd.run'](cmd, python_shell=False).splitlines()
|
||||
for line in lines:
|
||||
if 'Server Name' in line:
|
||||
_, srv_name = line.split('Server Name', 1)
|
||||
return srv_name.strip().lstrip('\\')
|
||||
return False
|
||||
name = get_system_info()['name']
|
||||
return name if name else False
|
||||
|
||||
|
||||
def set_computer_desc(desc):
|
||||
def set_computer_desc(desc=None):
|
||||
'''
|
||||
Set the Windows computer description
|
||||
|
||||
:param str desc:
|
||||
The computer description
|
||||
|
||||
:return: False if it fails. Description if successful.
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'minion-id' system.set_computer_desc 'This computer belongs to Dave!'
|
||||
'''
|
||||
cmd = ['net',
|
||||
'config',
|
||||
'server',
|
||||
u'/srvcomment:{0}'.format(salt.utils.locales.sdecode(desc))]
|
||||
__salt__['cmd.run'](cmd, python_shell=False)
|
||||
# Make sure the system exists
|
||||
# Return an object containing current information array for the computer
|
||||
system_info = win32net.NetServerGetInfo(None, 101)
|
||||
|
||||
# If desc is passed, decode it for unicode
|
||||
if desc:
|
||||
system_info['comment'] = desc.decode('utf-8')
|
||||
else:
|
||||
return False
|
||||
|
||||
# Apply new settings
|
||||
try:
|
||||
win32net.NetServerSetInfo(None, 101, system_info)
|
||||
except win32net.error as exc:
|
||||
(number, context, message) = exc
|
||||
log.error('Failed to update system')
|
||||
log.error('nbr: {0}'.format(number))
|
||||
log.error('ctx: {0}'.format(context))
|
||||
log.error('msg: {0}'.format(message))
|
||||
return False
|
||||
|
||||
return {'Computer Description': get_computer_desc()}
|
||||
|
||||
|
||||
set_computer_description = set_computer_desc
|
||||
|
||||
|
||||
def get_system_info():
|
||||
'''
|
||||
Get system information.
|
||||
|
||||
:return:
|
||||
Returns a Dictionary containing information about the system to include
|
||||
name, description, version, etc...
|
||||
:rtype: dict
|
||||
'''
|
||||
system_info = win32net.NetServerGetInfo(None, 101)
|
||||
return system_info
|
||||
|
||||
|
||||
def get_computer_desc():
|
||||
'''
|
||||
Get the Windows computer description
|
||||
|
||||
:return:
|
||||
Returns the computer description if found. Otherwise returns False
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'minion-id' system.get_computer_desc
|
||||
'''
|
||||
cmd = ['net', 'config', 'server']
|
||||
lines = __salt__['cmd.run'](cmd, python_shell=False).splitlines()
|
||||
for line in lines:
|
||||
if 'Server Comment' in line:
|
||||
_, desc = line.split('Server Comment', 1)
|
||||
return desc.strip()
|
||||
return False
|
||||
desc = get_system_info()['comment']
|
||||
return desc if desc else False
|
||||
|
||||
|
||||
get_computer_description = get_computer_desc
|
||||
|
||||
@ -308,29 +442,28 @@ def join_domain(
|
||||
username=None,
|
||||
password=None,
|
||||
account_ou=None,
|
||||
account_exists=False
|
||||
):
|
||||
account_exists=False):
|
||||
'''
|
||||
Join a computer to an Active Directory domain
|
||||
|
||||
domain
|
||||
:param str domain:
|
||||
The domain to which the computer should be joined, e.g.
|
||||
``my-company.com``
|
||||
|
||||
username
|
||||
:param str username:
|
||||
Username of an account which is authorized to join computers to the
|
||||
specified domain. Need to be either fully qualified like
|
||||
``user@domain.tld`` or simply ``user``
|
||||
|
||||
password
|
||||
:param str password:
|
||||
Password of the specified user
|
||||
|
||||
account_ou : None
|
||||
:param str account_ou:
|
||||
The DN of the OU below which the account for this computer should be
|
||||
created when joining the domain, e.g.
|
||||
``ou=computers,ou=departm_432,dc=my-company,dc=com``
|
||||
|
||||
account_exists : False
|
||||
:param bool account_exists:
|
||||
Needs to be set to ``True`` to allow re-using an existing account
|
||||
|
||||
CLI Example:
|
||||
@ -354,27 +487,20 @@ def join_domain(
|
||||
join_options = 3
|
||||
if account_exists:
|
||||
join_options = 1
|
||||
cmd = ('wmic /interactive:off ComputerSystem Where '
|
||||
'name="%computername%" call JoinDomainOrWorkgroup FJoinOptions={0} '
|
||||
'Name={1} UserName={2} Password="{3}"'
|
||||
).format(
|
||||
join_options,
|
||||
_cmd_quote(domain),
|
||||
_cmd_quote(username),
|
||||
password)
|
||||
if account_ou:
|
||||
# contrary to RFC#2253, 2.1, 'wmic' requires a ; as a RDN separator
|
||||
# for the DN
|
||||
account_ou = account_ou.replace(',', ';')
|
||||
add_ou = ' AccountOU="{0}"'.format(account_ou)
|
||||
cmd = cmd + add_ou
|
||||
|
||||
ret = __salt__['cmd.run'](cmd, python_shell=True)
|
||||
if 'ReturnValue = 0;' in ret:
|
||||
ret = windll.netapi32.NetJoinDomain(None,
|
||||
domain,
|
||||
account_ou,
|
||||
username,
|
||||
password,
|
||||
join_options)
|
||||
if ret == 0:
|
||||
return {'Domain': domain}
|
||||
|
||||
return_values = {
|
||||
2: 'Invalid OU or specifying OU is not supported',
|
||||
5: 'Access is denied',
|
||||
53: 'The network path was not found',
|
||||
87: 'The parameter is incorrect',
|
||||
110: 'The system cannot open the specified object',
|
||||
1323: 'Unable to update the password',
|
||||
@ -384,115 +510,249 @@ def join_domain(
|
||||
2691: 'The machine is already joined to the domain',
|
||||
2692: 'The machine is not currently joined to a domain',
|
||||
}
|
||||
for value in return_values:
|
||||
if 'ReturnValue = {0};'.format(value) in ret:
|
||||
log.error(return_values[value])
|
||||
log.error(return_values[ret])
|
||||
return False
|
||||
|
||||
|
||||
def _validate_datetime(newdatetime, valid_formats):
|
||||
def unjoin_domain(username=None, password=None, disable=False):
|
||||
'''
|
||||
Validate `newdatetime` against list of date/time formats understood by
|
||||
windows.
|
||||
Unjoin a computer from an Active Directory Domain
|
||||
|
||||
:param username:
|
||||
Username of an account which is authorized to join computers to the
|
||||
specified domain. Need to be either fully qualified like
|
||||
``user@domain.tld`` or simply ``user``
|
||||
|
||||
:param str password:
|
||||
Password of the specified user
|
||||
|
||||
:param bool disable:
|
||||
Disable the user account in Active Directory. True to disable.
|
||||
|
||||
:return: True if successful. False if not. Log contains error code.
|
||||
:rtype: bool
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'minion-id' system.unjoin_domain username='unjoinuser' \\
|
||||
password='unjoinpassword' disable=True
|
||||
'''
|
||||
unjoin_options = 0
|
||||
if disable:
|
||||
unjoin_options = 2
|
||||
|
||||
ret = windll.netapi32.NetUnjoinDomain(None,
|
||||
username,
|
||||
password,
|
||||
unjoin_options)
|
||||
if ret == 0:
|
||||
return True
|
||||
|
||||
return_values = {
|
||||
2: 'Invalid OU or specifying OU is not supported',
|
||||
5: 'Access is denied',
|
||||
53: 'The network path was not found',
|
||||
87: 'The parameter is incorrect',
|
||||
110: 'The system cannot open the specified object',
|
||||
1323: 'Unable to update the password',
|
||||
1326: 'Logon failure: unknown username or bad password',
|
||||
1355: 'The specified domain either does not exist or could not be contacted',
|
||||
2224: 'The account already exists',
|
||||
2691: 'The machine is already joined to the domain',
|
||||
2692: 'The machine is not currently joined to a domain',
|
||||
}
|
||||
log.error(return_values[ret])
|
||||
return False
|
||||
|
||||
|
||||
def _get_date_time_format(dt_string):
|
||||
'''
|
||||
Function that detects the date/time format for the string passed.
|
||||
|
||||
:param str dt_string:
|
||||
A date/time string
|
||||
|
||||
:return: The format of the passed dt_string
|
||||
:rtype: str
|
||||
'''
|
||||
valid_formats = [
|
||||
'%I:%M:%S %p',
|
||||
'%I:%M %p',
|
||||
'%H:%M:%S',
|
||||
'%H:%M',
|
||||
'%Y-%m-%d',
|
||||
'%m-%d-%y',
|
||||
'%m-%d-%Y',
|
||||
'%m/%d/%y',
|
||||
'%m/%d/%Y',
|
||||
'%Y/%m/%d'
|
||||
]
|
||||
for dt_format in valid_formats:
|
||||
try:
|
||||
datetime.datetime.strptime(newdatetime, dt_format)
|
||||
return True
|
||||
datetime.strptime(dt_string, dt_format)
|
||||
return dt_format
|
||||
except ValueError:
|
||||
continue
|
||||
return False
|
||||
|
||||
|
||||
def _validate_time(newtime):
|
||||
'''
|
||||
Validate `newtime` against list of time formats understood by windows.
|
||||
'''
|
||||
valid_time_formats = [
|
||||
'%I:%M:%S %p',
|
||||
'%I:%M %p',
|
||||
'%H:%M:%S',
|
||||
'%H:%M'
|
||||
]
|
||||
return _validate_datetime(newtime, valid_time_formats)
|
||||
|
||||
|
||||
def _validate_date(newdate):
|
||||
'''
|
||||
Validate `newdate` against list of date formats understood by windows.
|
||||
'''
|
||||
valid_date_formats = [
|
||||
'%Y-%m-%d',
|
||||
'%m/%d/%y',
|
||||
'%y/%m/%d'
|
||||
]
|
||||
return _validate_datetime(newdate, valid_date_formats)
|
||||
|
||||
|
||||
def get_system_time():
|
||||
'''
|
||||
Get the Windows system time
|
||||
Get the system time.
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' system.get_system_time
|
||||
:return: Returns the system time in HH:MM AM/PM format.
|
||||
:rtype: str
|
||||
'''
|
||||
cmd = 'time /T'
|
||||
return __salt__['cmd.run'](cmd, python_shell=True)
|
||||
return datetime.strftime(datetime.now(), "%I:%M %p")
|
||||
|
||||
|
||||
def set_system_time(newtime):
|
||||
'''
|
||||
Set the Windows system time
|
||||
Set the system time.
|
||||
|
||||
:param str newtime:
|
||||
The time to set. Can be any of the following formats.
|
||||
- HH:MM:SS AM/PM
|
||||
- HH:MM AM/PM
|
||||
- HH:MM:SS (24 hour)
|
||||
- HH:MM (24 hour)
|
||||
|
||||
:return: Returns True if successful. Otherwise False.
|
||||
:rtype: bool
|
||||
'''
|
||||
# Parse time values from new time
|
||||
time_format = _get_date_time_format(newtime)
|
||||
dt_obj = datetime.strptime(newtime, time_format)
|
||||
|
||||
# Set time using set_system_date_time()
|
||||
return set_system_date_time(hours=int(dt_obj.strftime('%H')),
|
||||
minutes=int(dt_obj.strftime('%M')),
|
||||
seconds=int(dt_obj.strftime('%S')))
|
||||
|
||||
|
||||
def set_system_date_time(years=None,
|
||||
months=None,
|
||||
days=None,
|
||||
hours=None,
|
||||
minutes=None,
|
||||
seconds=None):
|
||||
'''
|
||||
Set the system date and time. Each argument is an element of the date, but
|
||||
not required. If an element is not passed, the current system value for that
|
||||
element will be used. For example, if you don't pass the year, the current
|
||||
system year will be used. (Used by set_system_date and set_system_time)
|
||||
|
||||
:param int years: Years digit, ie: 2015
|
||||
:param int months: Months digit: 1 - 12
|
||||
:param int days: Days digit: 1 - 31
|
||||
:param int hours: Hours digit: 0 - 23
|
||||
:param int minutes: Minutes digit: 0 - 59
|
||||
:param int seconds: Seconds digit: 0 - 59
|
||||
|
||||
:return: True if successful. Otherwise False.
|
||||
:rtype: bool
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' system.set_system_time '11:31:15 AM'
|
||||
salt '*' system.set_system_date_ time 2015 5 12 11 37 53
|
||||
'''
|
||||
if not _validate_time(newtime):
|
||||
# Get the current date/time
|
||||
try:
|
||||
date_time = win32api.GetLocalTime()
|
||||
except win32api.error as exc:
|
||||
(number, context, message) = exc
|
||||
log.error('Failed to get local time')
|
||||
log.error('nbr: {0}'.format(number))
|
||||
log.error('ctx: {0}'.format(context))
|
||||
log.error('msg: {0}'.format(message))
|
||||
return False
|
||||
cmd = 'time {0}'.format(newtime)
|
||||
return not __salt__['cmd.retcode'](cmd, python_shell=True)
|
||||
|
||||
# Check for passed values. If not passed, use current values
|
||||
if not years:
|
||||
years = date_time[0]
|
||||
if not months:
|
||||
months = date_time[1]
|
||||
if not days:
|
||||
days = date_time[3]
|
||||
if not hours:
|
||||
hours = date_time[4]
|
||||
if not minutes:
|
||||
minutes = date_time[5]
|
||||
if not seconds:
|
||||
seconds = date_time[6]
|
||||
|
||||
# Create the time tuple to be passed to SetLocalTime, including day_of_week
|
||||
time_tuple = (years, months, days, hours, minutes, seconds, 0)
|
||||
|
||||
try:
|
||||
win32api.SetLocalTime(time_tuple)
|
||||
except win32api.error as exc:
|
||||
(number, context, message) = exc
|
||||
log.error('Failed to set local time')
|
||||
log.error('nbr: {0}'.format(number))
|
||||
log.error('ctx: {0}'.format(context))
|
||||
log.error('msg: {0}'.format(message))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def get_system_date():
|
||||
'''
|
||||
Get the Windows system date
|
||||
|
||||
:return: Returns the system date.
|
||||
:rtype: str
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' system.get_system_date
|
||||
'''
|
||||
cmd = 'date /T'
|
||||
return __salt__['cmd.run'](cmd, python_shell=True)
|
||||
return datetime.strftime(datetime.now(), "%a %m/%d/%Y")
|
||||
|
||||
|
||||
def set_system_date(newdate):
|
||||
'''
|
||||
Set the Windows system date. Use <mm-dd-yy> format for the date.
|
||||
|
||||
:param str newdate:
|
||||
The date to set. Can be any of the following formats
|
||||
- YYYY-MM-DD
|
||||
- MM-DD-YYYY
|
||||
- MM-DD-YY
|
||||
- MM/DD/YYYY
|
||||
- MM/DD/YY
|
||||
- YYYY/MM/DD
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' system.set_system_date '03-28-13'
|
||||
'''
|
||||
if not _validate_date(newdate):
|
||||
return False
|
||||
cmd = 'date {0}'.format(newdate)
|
||||
return not __salt__['cmd.retcode'](cmd, python_shell=True)
|
||||
# Parse time values from new time
|
||||
date_format = _get_date_time_format(newdate)
|
||||
dt_obj = datetime.strptime(newdate, date_format)
|
||||
|
||||
# Set time using set_system_date_time()
|
||||
return set_system_date_time(years=int(dt_obj.strftime('%Y')),
|
||||
months=int(dt_obj.strftime('%m')),
|
||||
days=int(dt_obj.strftime('%d')))
|
||||
|
||||
|
||||
def start_time_service():
|
||||
'''
|
||||
Start the Windows time service
|
||||
|
||||
:return: True if successful. Otherwise False
|
||||
:rtype: bool
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
@ -506,6 +766,9 @@ def stop_time_service():
|
||||
'''
|
||||
Stop the Windows time service
|
||||
|
||||
:return: True if successful. Otherwise False
|
||||
:rtype: bool
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
@ -135,7 +135,7 @@ authenication parameter names prefixed with ``git_pillar`` instead of ``gitfs``
|
||||
:conf_master:`git_pillar_passphrase`, etc.).
|
||||
|
||||
A full list of the git_pillar configuration options can be found :ref:`here
|
||||
<git-pillar-config-opts>`.
|
||||
<git_pillar-config-opts>`.
|
||||
|
||||
.. _GitPython: https://github.com/gitpython-developers/GitPython
|
||||
.. _pygit2: https://github.com/libgit2/pygit2
|
||||
|
@ -177,6 +177,17 @@ def save_load(jid, clear_load):
|
||||
|
||||
serial = salt.payload.Serial(__opts__)
|
||||
|
||||
# Save the invocation information
|
||||
try:
|
||||
if not os.path.exists(jid_dir):
|
||||
os.makedirs(jid_dir)
|
||||
serial.dump(
|
||||
clear_load,
|
||||
salt.utils.fopen(os.path.join(jid_dir, LOAD_P), 'w+b')
|
||||
)
|
||||
except IOError as exc:
|
||||
log.warning('Could not write job invocation cache file: {0}'.format(exc))
|
||||
|
||||
# if you have a tgt, save that for the UI etc
|
||||
if 'tgt' in clear_load:
|
||||
ckminions = salt.utils.minions.CkMinions(__opts__)
|
||||
@ -191,19 +202,9 @@ def save_load(jid, clear_load):
|
||||
minions,
|
||||
salt.utils.fopen(os.path.join(jid_dir, MINIONS_P), 'w+b')
|
||||
)
|
||||
except IOError:
|
||||
except IOError as exc:
|
||||
log.warning('Could not write job cache file for minions: {0}'.format(minions))
|
||||
|
||||
# Save the invocation information
|
||||
try:
|
||||
if not os.path.exists(jid_dir):
|
||||
os.makedirs(jid_dir)
|
||||
serial.dump(
|
||||
clear_load,
|
||||
salt.utils.fopen(os.path.join(jid_dir, LOAD_P), 'w+b')
|
||||
)
|
||||
except IOError as exc:
|
||||
log.warning('Could not write job invocation cache file: {0}'.format(exc))
|
||||
log.debug('Job cache write failure: {0}'.format(exc))
|
||||
|
||||
|
||||
def get_load(jid):
|
||||
|
@ -49,20 +49,7 @@ def hash(*args, **kwargs):
|
||||
salt-run survey.hash "*" file.get_hash /etc/salt/minion survey_sort=up
|
||||
'''
|
||||
|
||||
bulk_ret = _get_pool_results(*args, **kwargs)
|
||||
for k in bulk_ret:
|
||||
print('minion pool :\n'
|
||||
'------------')
|
||||
print(k['pool'])
|
||||
print('pool size :\n'
|
||||
'----------')
|
||||
print(' ' + str(len(k['pool'])))
|
||||
print('pool result :\n'
|
||||
'-------')
|
||||
print(' ' + str(k['result']))
|
||||
print('\n')
|
||||
|
||||
return bulk_ret
|
||||
return _get_pool_results(*args, **kwargs)
|
||||
|
||||
|
||||
def diff(*args, **kwargs):
|
||||
|
@ -17,6 +17,7 @@ except ImportError:
|
||||
# Import salt libs
|
||||
from salt.exceptions import SaltRenderError
|
||||
import salt.utils
|
||||
import salt.utils.gitfs
|
||||
import logging
|
||||
import salt.minion
|
||||
import salt.loader
|
||||
@ -24,10 +25,12 @@ import salt.template
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
PER_REMOTE_PARAMS = ('ssl_verify',)
|
||||
|
||||
|
||||
def genrepo():
|
||||
'''
|
||||
Generate win_repo_cachefile based on sls files in the win_repo
|
||||
Generate winrepo_cachefile based on sls files in the winrepo_dir
|
||||
|
||||
CLI Example:
|
||||
|
||||
@ -35,13 +38,31 @@ def genrepo():
|
||||
|
||||
salt-run winrepo.genrepo
|
||||
'''
|
||||
if 'win_repo' in __opts__:
|
||||
salt.utils.warn_until(
|
||||
'Nitrogen',
|
||||
'The \'win_repo\' config option is deprecated, please use '
|
||||
'\'winrepo_dir\' instead.'
|
||||
)
|
||||
winrepo_dir = __opts__['win_repo']
|
||||
else:
|
||||
winrepo_dir = __opts__['winrepo_dir']
|
||||
|
||||
if 'win_repo_mastercachefile' in __opts__:
|
||||
salt.utils.warn_until(
|
||||
'Nitrogen',
|
||||
'The \'win_repo_mastercachefile\' config option is deprecated, '
|
||||
'please use \'winrepo_cachefile\' instead.'
|
||||
)
|
||||
winrepo_cachefile = __opts__['win_repo_mastercachefile']
|
||||
else:
|
||||
winrepo_cachefile = __opts__['winrepo_cachefile']
|
||||
|
||||
ret = {}
|
||||
repo = __opts__['win_repo']
|
||||
if not os.path.exists(repo):
|
||||
os.makedirs(repo)
|
||||
winrepo = __opts__['win_repo_mastercachefile']
|
||||
if not os.path.exists(winrepo_dir):
|
||||
os.makedirs(winrepo_dir)
|
||||
renderers = salt.loader.render(__opts__, __salt__)
|
||||
for root, _, files in os.walk(repo):
|
||||
for root, _, files in os.walk(winrepo_dir):
|
||||
for name in files:
|
||||
if name.endswith('.sls'):
|
||||
try:
|
||||
@ -50,25 +71,44 @@ def genrepo():
|
||||
renderers,
|
||||
__opts__['renderer'])
|
||||
except SaltRenderError as exc:
|
||||
log.debug('Failed to render {0}.'.format(os.path.join(root, name)))
|
||||
log.debug(
|
||||
'Failed to render {0}.'.format(
|
||||
os.path.join(root, name)
|
||||
)
|
||||
)
|
||||
log.debug('Error: {0}.'.format(exc))
|
||||
continue
|
||||
if config:
|
||||
revmap = {}
|
||||
for pkgname, versions in six.iteritems(config):
|
||||
log.debug(
|
||||
'Compiling winrepo data for package \'{0}\''
|
||||
.format(pkgname)
|
||||
)
|
||||
for version, repodata in six.iteritems(versions):
|
||||
log.debug(
|
||||
'Compiling winrepo data for {0} version {1}'
|
||||
.format(pkgname, version)
|
||||
)
|
||||
if not isinstance(version, six.string_types):
|
||||
config[pkgname][str(version)] = \
|
||||
config[pkgname].pop(version)
|
||||
if not isinstance(repodata, dict):
|
||||
log.debug('Failed to compile'
|
||||
'{0}.'.format(os.path.join(root, name)))
|
||||
__jid_event__.fire_event({'error': 'Failed to compile {0}.'.format(os.path.join(root, name))}, 'progress')
|
||||
log.debug(
|
||||
'Failed to compile {0}.'.format(
|
||||
os.path.join(root, name)
|
||||
)
|
||||
)
|
||||
__jid_event__.fire_event(
|
||||
{'error': 'Failed to compile {0}.'.format(
|
||||
os.path.join(root, name))},
|
||||
'progress')
|
||||
continue
|
||||
revmap[repodata['full_name']] = pkgname
|
||||
ret.setdefault('repo', {}).update(config)
|
||||
ret.setdefault('name_map', {}).update(revmap)
|
||||
with salt.utils.fopen(os.path.join(repo, winrepo), 'w+b') as repo:
|
||||
with salt.utils.fopen(
|
||||
os.path.join(winrepo_dir, winrepo_cachefile), 'w+b') as repo:
|
||||
repo.write(msgpack.dumps(ret))
|
||||
return ret
|
||||
|
||||
@ -83,23 +123,70 @@ def update_git_repos():
|
||||
|
||||
salt-run winrepo.update_git_repos
|
||||
'''
|
||||
ret = {}
|
||||
mminion = salt.minion.MasterMinion(__opts__)
|
||||
repo = __opts__['win_repo']
|
||||
gitrepos = __opts__['win_gitrepos']
|
||||
for gitrepo in gitrepos:
|
||||
if '/' in gitrepo:
|
||||
targetname = gitrepo.split('/')[-1]
|
||||
else:
|
||||
targetname = gitrepo
|
||||
rev = None
|
||||
# If a revision is specified, use it.
|
||||
if len(gitrepo.strip().split(' ')) > 1:
|
||||
rev, gitrepo = gitrepo.strip().split(' ')
|
||||
gittarget = os.path.join(repo, targetname)
|
||||
result = mminion.states['git.latest'](gitrepo,
|
||||
rev=rev,
|
||||
target=gittarget,
|
||||
force=True)
|
||||
ret[result['name']] = result['result']
|
||||
return ret
|
||||
if 'win_repo' in __opts__:
|
||||
salt.utils.warn_until(
|
||||
'Nitrogen',
|
||||
'The \'win_repo\' config option is deprecated, please use '
|
||||
'\'winrepo_dir\' instead.'
|
||||
)
|
||||
winrepo_dir = __opts__['win_repo']
|
||||
else:
|
||||
winrepo_dir = __opts__['winrepo_dir']
|
||||
|
||||
if 'win_gitrepos' in __opts__:
|
||||
salt.utils.warn_until(
|
||||
'Nitrogen',
|
||||
'The \'win_gitrepos\' config option is deprecated, please use '
|
||||
'\'winrepo_remotes\' instead.'
|
||||
)
|
||||
winrepo_remotes = __opts__['win_gitrepos']
|
||||
else:
|
||||
winrepo_remotes = __opts__['winrepo_remotes']
|
||||
|
||||
if not any((salt.utils.gitfs.HAS_GITPYTHON, salt.utils.gitfs.HAS_PYGIT2)):
|
||||
# Use legacy code
|
||||
if not salt.utils.is_windows():
|
||||
# Don't warn on Windows, because Windows can't do cool things like
|
||||
# use pygit2. It has to fall back to git.latest.
|
||||
salt.utils.warn_until(
|
||||
'Nitrogen',
|
||||
'winrepo git support now requires either GitPython or pygit2. '
|
||||
'Please install either GitPython >= {0} (or pygit2 >= {1} with '
|
||||
'libgit2 >= {2}), clear out the winrepo_dir ({3}), and '
|
||||
'restart the salt-master service.'.format(
|
||||
salt.utils.gitfs.GITPYTHON_MINVER,
|
||||
salt.utils.gitfs.PYGIT2_MINVER,
|
||||
salt.utils.gitfs.LIBGIT2_MINVER,
|
||||
winrepo_dir
|
||||
)
|
||||
)
|
||||
ret = {}
|
||||
mminion = salt.minion.MasterMinion(__opts__)
|
||||
for remote in winrepo_remotes:
|
||||
if '/' in remote:
|
||||
targetname = remote.split('/')[-1]
|
||||
else:
|
||||
targetname = remote
|
||||
rev = None
|
||||
# If a revision is specified, use it.
|
||||
if len(remote.strip().split(' ')) > 1:
|
||||
rev, remote = remote.strip().split(' ')
|
||||
gittarget = os.path.join(winrepo_dir, targetname)
|
||||
result = mminion.states['git.latest'](remote,
|
||||
rev=rev,
|
||||
target=gittarget,
|
||||
force=True)
|
||||
ret[result['name']] = result['result']
|
||||
return ret
|
||||
else:
|
||||
# New winrepo code utilizing salt.utils.gitfs
|
||||
try:
|
||||
winrepo = salt.utils.gitfs.WinRepo(__opts__)
|
||||
winrepo.init_remotes(winrepo_remotes, PER_REMOTE_PARAMS)
|
||||
winrepo.fetch_remotes()
|
||||
winrepo.checkout()
|
||||
except Exception as exc:
|
||||
msg = 'Failed to update winrepo_remotes: {0}'.format(exc)
|
||||
log.error(msg, exc_info_on_loglevel=logging.DEBUG)
|
||||
return msg
|
||||
return winrepo.winrepo_dirs
|
||||
|
@ -461,7 +461,7 @@ def present(name, bare=True, user=None, force=False, shared=None):
|
||||
shared
|
||||
Specify the permission for sharing, see git-init for details (Default: None)
|
||||
|
||||
.. versionadded:: XXXX
|
||||
.. versionadded:: 2015.5
|
||||
'''
|
||||
name = os.path.expanduser(name)
|
||||
ret = {'name': name, 'result': True, 'comment': '', 'changes': {}}
|
||||
|
@ -359,11 +359,15 @@ def present(name,
|
||||
win_description (Windows Only)
|
||||
A brief description of the purpose of the users account.
|
||||
.. versionchanged:: 2015.8.0
|
||||
'''
|
||||
fullname = salt.utils.locales.sdecode(fullname)
|
||||
roomnumber = salt.utils.locales.sdecode(roomnumber)
|
||||
workphone = salt.utils.locales.sdecode(workphone)
|
||||
homephone = salt.utils.locales.sdecode(homephone)
|
||||
'''
|
||||
if fullname is not None:
|
||||
fullname = salt.utils.locales.sdecode(fullname)
|
||||
if roomnumber is not None:
|
||||
roomnumber = salt.utils.locales.sdecode(roomnumber)
|
||||
if workphone is not None:
|
||||
workphone = salt.utils.locales.sdecode(workphone)
|
||||
if homephone is not None:
|
||||
homephone = salt.utils.locales.sdecode(homephone)
|
||||
|
||||
ret = {'name': name,
|
||||
'changes': {},
|
||||
|
@ -16,6 +16,7 @@ import itertools
|
||||
|
||||
# Salt Modules
|
||||
import salt.runner
|
||||
import salt.utils
|
||||
import salt.config
|
||||
|
||||
|
||||
@ -57,28 +58,52 @@ def genrepo(name, force=False, allow_empty=False):
|
||||
'changes': {},
|
||||
'comment': ''}
|
||||
|
||||
master_config = salt.config.master_config(os.path.join(salt.syspaths.CONFIG_DIR, 'master'))
|
||||
win_repo = master_config['win_repo']
|
||||
win_repo_mastercachefile = master_config['win_repo_mastercachefile']
|
||||
master_config = salt.config.master_config(
|
||||
os.path.join(salt.syspaths.CONFIG_DIR, 'master')
|
||||
)
|
||||
|
||||
# Check if the win_repo directory exists
|
||||
# if not search for a file with a newer mtime than the win_repo_mastercachefile file
|
||||
if 'win_repo' in master_config:
|
||||
salt.utils.warn_until(
|
||||
'Nitrogen',
|
||||
'The \'win_repo\' config option is deprecated, please use '
|
||||
'\'winrepo_dir\' instead.'
|
||||
)
|
||||
winrepo_dir = master_config['win_repo']
|
||||
else:
|
||||
winrepo_dir = master_config['winrepo_dir']
|
||||
|
||||
if 'win_repo_mastercachefile' in master_config:
|
||||
salt.utils.warn_until(
|
||||
'Nitrogen',
|
||||
'The \'win_repo_mastercachefile\' config option is deprecated, '
|
||||
'please use \'winrepo_cachefile\' instead.'
|
||||
)
|
||||
winrepo_cachefile = master_config['win_repo_mastercachefile']
|
||||
else:
|
||||
winrepo_cachefile = master_config['winrepo_cachefile']
|
||||
|
||||
# We're actually looking for the full path to the cachefile here, so
|
||||
# prepend the winrepo_dir
|
||||
winrepo_cachefile = os.path.join(winrepo_dir, winrepo_cachefile)
|
||||
|
||||
# Check if the winrepo directory exists
|
||||
# if not search for a file with a newer mtime than the winrepo_cachefile file
|
||||
execute = False
|
||||
if not force:
|
||||
if not os.path.exists(win_repo):
|
||||
if not os.path.exists(winrepo_dir):
|
||||
ret['result'] = False
|
||||
ret['comment'] = 'missing {0}'.format(win_repo)
|
||||
ret['comment'] = '{0} is missing'.format(winrepo_dir)
|
||||
return ret
|
||||
elif not os.path.exists(win_repo_mastercachefile):
|
||||
elif not os.path.exists(winrepo_cachefile):
|
||||
execute = True
|
||||
ret['comment'] = 'missing {0}'.format(win_repo_mastercachefile)
|
||||
ret['comment'] = '{0} is missing'.format(winrepo_cachefile)
|
||||
else:
|
||||
win_repo_mastercachefile_mtime = os.stat(win_repo_mastercachefile)[stat.ST_MTIME]
|
||||
for root, dirs, files in os.walk(win_repo):
|
||||
winrepo_cachefile_mtime = os.stat(winrepo_cachefile)[stat.ST_MTIME]
|
||||
for root, dirs, files in os.walk(winrepo_dir):
|
||||
for name in itertools.chain(files, dirs):
|
||||
full_path = os.path.join(root, name)
|
||||
if os.stat(full_path)[stat.ST_MTIME] > win_repo_mastercachefile_mtime:
|
||||
ret['comment'] = 'mtime({0}) < mtime({1})'.format(win_repo_mastercachefile, full_path)
|
||||
if os.stat(full_path)[stat.ST_MTIME] > winrepo_cachefile_mtime:
|
||||
ret['comment'] = 'mtime({0}) < mtime({1})'.format(winrepo_cachefile, full_path)
|
||||
execute = True
|
||||
break
|
||||
|
||||
@ -93,7 +118,7 @@ def genrepo(name, force=False, allow_empty=False):
|
||||
runner_ret = runner.cmd('winrepo.genrepo', [])
|
||||
ret['changes'] = {'winrepo': runner_ret}
|
||||
if isinstance(runner_ret, dict) and runner_ret == {} and not allow_empty:
|
||||
os.remove(win_repo_mastercachefile)
|
||||
os.remove(winrepo_cachefile)
|
||||
ret['result'] = False
|
||||
ret['comment'] = 'winrepo.genrepo returned empty'
|
||||
return ret
|
||||
|
@ -84,6 +84,14 @@ except ImportError:
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
# Minimum versions for backend providers
|
||||
GITPYTHON_MINVER = '0.3'
|
||||
PYGIT2_MINVER = '0.20.3'
|
||||
LIBGIT2_MINVER = '0.20.0'
|
||||
# dulwich.__version__ is a versioninfotuple so we can compare tuples
|
||||
# instead of using distutils.version.LooseVersion
|
||||
DULWICH_MINVER = (0, 9, 4)
|
||||
|
||||
|
||||
def failhard(role):
|
||||
'''
|
||||
@ -175,6 +183,12 @@ class GitProvider(object):
|
||||
self.id = remote
|
||||
self.get_url()
|
||||
|
||||
# Winrepo doesn't support the 'root' option, but it still must be part
|
||||
# of the GitProvider object because other code depends on it. Add it as
|
||||
# an empty string.
|
||||
if 'root' not in repo_conf:
|
||||
repo_conf['root'] = ''
|
||||
|
||||
# Set all repo config params as attributes
|
||||
for key, val in six.iteritems(repo_conf):
|
||||
setattr(self, key, val)
|
||||
@ -212,15 +226,15 @@ class GitProvider(object):
|
||||
log.critical(msg, exc_info_on_loglevel=logging.DEBUG)
|
||||
failhard(self.role)
|
||||
|
||||
def check_pillar_root(self):
|
||||
def check_root(self):
|
||||
'''
|
||||
Check if the relative root path exists in the checked-out copy of the
|
||||
remote. Return the full path to that relative root if it does exist,
|
||||
otherwise return None.
|
||||
'''
|
||||
pillar_root = os.path.join(self.cachedir, self.root)
|
||||
if os.path.isdir(pillar_root):
|
||||
return pillar_root
|
||||
root_dir = os.path.join(self.cachedir, self.root).rstrip(os.sep)
|
||||
if os.path.isdir(root_dir):
|
||||
return root_dir
|
||||
log.error(
|
||||
'Root path \'{0}\' not present in {1} remote \'{2}\', '
|
||||
'skipping.'.format(self.root, self.role, self.id)
|
||||
@ -350,10 +364,10 @@ class GitProvider(object):
|
||||
'''
|
||||
Examine self.id and assign self.url (and self.branch, for git_pillar)
|
||||
'''
|
||||
if self.role == 'git_pillar':
|
||||
# With git_pillar, the remote is specified in the format
|
||||
# "<branch> <url>", so that we can get a unique identifier to
|
||||
# hash for each remote.
|
||||
if self.role in ('git_pillar', 'winrepo'):
|
||||
# With winrepo and git_pillar, the remote is specified in the
|
||||
# format '<branch> <url>', so that we can get a unique identifier
|
||||
# to hash for each remote.
|
||||
try:
|
||||
self.branch, self.url = self.id.split(None, 1)
|
||||
except ValueError:
|
||||
@ -394,7 +408,7 @@ class GitPython(GitProvider):
|
||||
self.repo.git.checkout(ref)
|
||||
except Exception:
|
||||
continue
|
||||
return self.check_pillar_root()
|
||||
return self.check_root()
|
||||
log.error(
|
||||
'Failed to checkout {0} from {1} remote \'{2}\': remote ref does '
|
||||
'not exist'.format(self.branch, self.role, self.id)
|
||||
@ -578,7 +592,7 @@ class GitPython(GitProvider):
|
||||
except KeyError:
|
||||
# File not found or repo_path points to a directory
|
||||
break
|
||||
return blob, blob.hexsha
|
||||
return blob, blob.hexsha if blob is not None else blob
|
||||
|
||||
def get_tree(self, tgt_env):
|
||||
'''
|
||||
@ -646,10 +660,10 @@ class Pygit2(GitProvider):
|
||||
self.repo.checkout(local_ref)
|
||||
# Reset HEAD to the commit id of the remote ref
|
||||
self.repo.reset(oid, pygit2.GIT_RESET_HARD)
|
||||
return self.check_pillar_root()
|
||||
return self.check_root()
|
||||
elif tag_ref in refs:
|
||||
self.repo.checkout(tag_ref)
|
||||
return self.check_pillar_root()
|
||||
return self.check_root()
|
||||
except Exception as exc:
|
||||
log.error(
|
||||
'Failed to checkout {0} from {1} remote \'{2}\': {3}'.format(
|
||||
@ -933,7 +947,7 @@ class Pygit2(GitProvider):
|
||||
blob = self.repo[oid]
|
||||
except KeyError:
|
||||
break
|
||||
return blob, blob.hex
|
||||
return blob, blob.hex if blob is not None else blob
|
||||
|
||||
def get_tree(self, tgt_env):
|
||||
'''
|
||||
@ -1271,7 +1285,7 @@ class Dulwich(GitProvider): # pylint: disable=abstract-method
|
||||
break
|
||||
except KeyError:
|
||||
break
|
||||
return blob, blob.sha().hexdigest()
|
||||
return blob, blob.sha().hexdigest() if blob is not None else blob
|
||||
|
||||
def get_conf(self):
|
||||
'''
|
||||
@ -1437,11 +1451,14 @@ class GitBase(object):
|
||||
'''
|
||||
Base class for gitfs/git_pillar
|
||||
'''
|
||||
def __init__(self, opts, valid_providers=VALID_PROVIDERS):
|
||||
def __init__(self, opts, valid_providers=VALID_PROVIDERS, cache_root=None):
|
||||
self.opts = opts
|
||||
self.valid_providers = valid_providers
|
||||
self.get_provider()
|
||||
self.cache_root = os.path.join(self.opts['cachedir'], self.role)
|
||||
if cache_root is not None:
|
||||
self.cache_root = cache_root
|
||||
else:
|
||||
self.cache_root = os.path.join(self.opts['cachedir'], self.role)
|
||||
self.env_cache = os.path.join(self.cache_root, 'envs.p')
|
||||
self.hash_cachedir = os.path.join(
|
||||
self.cache_root, self.role, 'hash')
|
||||
@ -1782,15 +1799,14 @@ class GitBase(object):
|
||||
|
||||
# pylint: disable=no-member
|
||||
gitver = distutils.version.LooseVersion(git.__version__)
|
||||
minver_str = '0.3.0'
|
||||
minver = distutils.version.LooseVersion(minver_str)
|
||||
minver = distutils.version.LooseVersion(GITPYTHON_MINVER)
|
||||
# pylint: enable=no-member
|
||||
errors = []
|
||||
if gitver < minver:
|
||||
errors.append(
|
||||
'Git fileserver backend is enabled in master config file, but '
|
||||
'the GitPython version is earlier than {0}. Version {1} '
|
||||
'detected.'.format(minver_str, git.__version__)
|
||||
'detected.'.format(GITPYTHON_MINVER, git.__version__)
|
||||
)
|
||||
if not salt.utils.which('git'):
|
||||
errors.append(
|
||||
@ -1834,12 +1850,10 @@ class GitBase(object):
|
||||
|
||||
# pylint: disable=no-member
|
||||
pygit2ver = distutils.version.LooseVersion(pygit2.__version__)
|
||||
pygit2_minver_str = '0.20.3'
|
||||
pygit2_minver = distutils.version.LooseVersion(pygit2_minver_str)
|
||||
pygit2_minver = distutils.version.LooseVersion(PYGIT2_MINVER)
|
||||
|
||||
libgit2ver = distutils.version.LooseVersion(pygit2.LIBGIT2_VERSION)
|
||||
libgit2_minver_str = '0.20.0'
|
||||
libgit2_minver = distutils.version.LooseVersion(libgit2_minver_str)
|
||||
libgit2_minver = distutils.version.LooseVersion(LIBGIT2_MINVER)
|
||||
# pylint: enable=no-member
|
||||
|
||||
errors = []
|
||||
@ -1847,13 +1861,13 @@ class GitBase(object):
|
||||
errors.append(
|
||||
'Git fileserver backend is enabled in master config file, but '
|
||||
'pygit2 version is earlier than {0}. Version {1} detected.'
|
||||
.format(pygit2_minver_str, pygit2.__version__)
|
||||
.format(PYGIT2_MINVER, pygit2.__version__)
|
||||
)
|
||||
if libgit2ver < libgit2_minver:
|
||||
errors.append(
|
||||
'Git fileserver backend is enabled in master config file, but '
|
||||
'libgit2 version is earlier than {0}. Version {1} detected.'
|
||||
.format(libgit2_minver_str, pygit2.LIBGIT2_VERSION)
|
||||
.format(LIBGIT2_MINVER, pygit2.LIBGIT2_VERSION)
|
||||
)
|
||||
if not salt.utils.which('git'):
|
||||
errors.append(
|
||||
@ -1893,16 +1907,13 @@ class GitBase(object):
|
||||
elif 'dulwich' not in self.valid_providers:
|
||||
return False
|
||||
|
||||
dulwich_version = dulwich.__version__
|
||||
dulwich_min_version = (0, 9, 4)
|
||||
|
||||
errors = []
|
||||
|
||||
if dulwich_version < dulwich_min_version:
|
||||
if dulwich.__version__ < DULWICH_MINVER:
|
||||
errors.append(
|
||||
'Git fileserver backend is enabled in the master config file, but '
|
||||
'the installed version of Dulwich is earlier than {0}. Version {1} '
|
||||
'detected.'.format(dulwich_min_version, dulwich_version)
|
||||
'detected.'.format(DULWICH_MINVER, dulwich.__version__)
|
||||
)
|
||||
|
||||
if errors:
|
||||
@ -2218,7 +2229,6 @@ class GitPillar(GitBase):
|
||||
else:
|
||||
base_branch = self.opts['{0}_branch'.format(self.role)]
|
||||
env = 'base' if repo.branch == base_branch else repo.branch
|
||||
log.critical(env)
|
||||
self.pillar_dirs[cachedir] = env
|
||||
|
||||
def update(self):
|
||||
@ -2232,3 +2242,36 @@ class GitPillar(GitBase):
|
||||
and just run pillar.fetch_remotes() there.
|
||||
'''
|
||||
return self.fetch_remotes()
|
||||
|
||||
|
||||
class WinRepo(GitBase):
|
||||
'''
|
||||
Functionality specific to the winrepo runner
|
||||
'''
|
||||
def __init__(self, opts):
|
||||
self.role = 'winrepo'
|
||||
# Dulwich has no function to check out a branch/tag, so this will be
|
||||
# limited to GitPython and Pygit2 for the forseeable future.
|
||||
if 'win_repo' in opts:
|
||||
salt.utils.warn_until(
|
||||
'Nitrogen',
|
||||
'The \'win_repo\' config option is deprecated, please use '
|
||||
'\'winrepo_dir\' instead.'
|
||||
)
|
||||
winrepo_dir = opts['win_repo']
|
||||
else:
|
||||
winrepo_dir = opts['winrepo_dir']
|
||||
GitBase.__init__(self,
|
||||
opts,
|
||||
valid_providers=('gitpython', 'pygit2'),
|
||||
cache_root=winrepo_dir)
|
||||
|
||||
def checkout(self):
|
||||
'''
|
||||
Checkout the targeted branches/tags from the winrepo remotes
|
||||
'''
|
||||
self.winrepo_dirs = {}
|
||||
for repo in self.remotes:
|
||||
cachedir = repo.checkout()
|
||||
if cachedir is not None:
|
||||
self.winrepo_dirs[repo.url] = cachedir
|
||||
|
@ -168,6 +168,31 @@ class UserTest(integration.ModuleCase,
|
||||
ret = self.run_state('user.absent', name='salt_test')
|
||||
self.assertSaltTrueReturn(ret)
|
||||
|
||||
@destructiveTest
|
||||
@skipIf(os.geteuid() != 0, 'you must be root to run this test')
|
||||
def test_user_present_gecos_none_fields(self):
|
||||
'''
|
||||
This is a DESTRUCTIVE TEST it creates a new user on the on the minion.
|
||||
|
||||
It ensures that if no GECOS data is supplied, the fields will be coerced
|
||||
into empty strings as opposed to the string "None".
|
||||
'''
|
||||
ret = self.run_state(
|
||||
'user.present', name='salt_test', fullname=None, roomnumber=None,
|
||||
workphone=None, homephone=None
|
||||
)
|
||||
self.assertSaltTrueReturn(ret)
|
||||
|
||||
ret = self.run_function('user.info', ['salt_test'])
|
||||
self.assertReturnNonEmptySaltType(ret)
|
||||
self.assertEqual('', ret['fullname'])
|
||||
self.assertEqual('', ret['roomnumber'])
|
||||
self.assertEqual('', ret['workphone'])
|
||||
self.assertEqual('', ret['homephone'])
|
||||
|
||||
ret = self.run_state('user.absent', name='salt_test')
|
||||
self.assertSaltTrueReturn(ret)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from integration import run_tests
|
||||
|
@ -90,9 +90,9 @@ class TimezoneTestCase(TestCase):
|
||||
'''
|
||||
Test to unlinks, then symlinks /etc/localtime to the set timezone.
|
||||
'''
|
||||
ret = ('Zone does not exist: /usr/share/lib/zoneinfo/timezone')
|
||||
mock = MagicMock(side_effect=[False, True, True])
|
||||
with patch.dict(timezone.__grains__, {'os_family': 'Solaris'}):
|
||||
def zone_checking_and_unlinking():
|
||||
ret = ('Zone does not exist: /usr/share/lib/zoneinfo/timezone')
|
||||
mock = MagicMock(side_effect=[False, True, True])
|
||||
with patch.object(os.path, 'exists', mock):
|
||||
self.assertEqual(timezone.set_zone('timezone'), ret)
|
||||
|
||||
@ -102,6 +102,14 @@ class TimezoneTestCase(TestCase):
|
||||
MagicMock(return_value=None)}):
|
||||
self.assertTrue(timezone.set_zone('timezone'))
|
||||
|
||||
with patch.dict(timezone.__grains__, {'os_family': 'Solaris'}):
|
||||
with patch.object(salt.utils, 'which', return_value=False):
|
||||
zone_checking_and_unlinking()
|
||||
|
||||
with patch.object(salt.utils, 'which', return_value=True):
|
||||
with patch.dict(timezone.__salt__, {'cmd.run': MagicMock(return_value='')}):
|
||||
zone_checking_and_unlinking()
|
||||
|
||||
def test_zone_compare(self):
|
||||
'''
|
||||
Test to checks the hash sum between the given timezone, and the
|
||||
|
@ -36,14 +36,14 @@ class WinRepoTestCase(TestCase):
|
||||
@patch('salt.loader.render', MagicMock(return_valu=''))
|
||||
def test_genrepo(self):
|
||||
'''
|
||||
Test to generate win_repo_cachefile
|
||||
based on sls files in the win_repo
|
||||
Test to generate winrepo_cachefile based on sls files in the
|
||||
winrepo_dir
|
||||
'''
|
||||
with patch.dict(win_repo.__opts__, {'win_repo': 'c:\\salt'}):
|
||||
with patch.dict(win_repo.__opts__, {'winrepo_dir': 'c:\\salt'}):
|
||||
mock_bool = MagicMock(return_value=True)
|
||||
with patch.object(os.path, 'exists', mock_bool):
|
||||
with patch.dict(win_repo.__opts__,
|
||||
{'win_repo_cachefile': 'cache.c'}):
|
||||
{'winrepo_cachefile': 'cache.c'}):
|
||||
mock = MagicMock(return_value={})
|
||||
with patch.object(os, 'walk', mock):
|
||||
with patch('salt.utils.fopen', mock_open()):
|
||||
@ -53,11 +53,11 @@ class WinRepoTestCase(TestCase):
|
||||
|
||||
def test_update_git_repos(self):
|
||||
'''
|
||||
Test to checkout git repos containing
|
||||
Windows Software Package Definitions
|
||||
Test to checkout git repos containing Windows software package
|
||||
definitions
|
||||
'''
|
||||
with patch.dict(win_repo.__opts__, {'win_repo': 'c:\\salt'}):
|
||||
with patch.dict(win_repo.__opts__, {'win_gitrepos': {}}):
|
||||
with patch.dict(win_repo.__opts__, {'winrepo_dir': 'c:\\salt'}):
|
||||
with patch.dict(win_repo.__opts__, {'winrepo_remotes': {}}):
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch.object(salt.output, 'display_output', mock):
|
||||
self.assertDictEqual(win_repo.update_git_repos(), {})
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
# Import Python Libs
|
||||
from __future__ import absolute_import
|
||||
from datetime import datetime
|
||||
|
||||
# Import Salt Testing Libs
|
||||
from salttesting import TestCase, skipIf
|
||||
@ -20,6 +21,16 @@ ensure_in_syspath('../../')
|
||||
# Import Salt Libs
|
||||
from salt.modules import win_system
|
||||
|
||||
# Import 3rd Party Libs
|
||||
try:
|
||||
import win32net # pylint: disable=W0611
|
||||
import win32api # pylint: disable=W0611
|
||||
import pywintypes # pylint: disable=W0611
|
||||
from ctypes import windll # pylint: disable=W0611
|
||||
HAS_WIN32NET_MODS = True
|
||||
except ImportError:
|
||||
HAS_WIN32NET_MODS = False
|
||||
|
||||
win_system.__salt__ = {}
|
||||
|
||||
|
||||
@ -43,6 +54,7 @@ class WinSystemTestCase(TestCase):
|
||||
self.assertEqual(win_system.init(3),
|
||||
'Not implemented on Windows at this time.')
|
||||
|
||||
@skipIf(not HAS_WIN32NET_MODS, 'this test needs the w32net library')
|
||||
def test_poweroff(self):
|
||||
'''
|
||||
Test to poweroff a running system
|
||||
@ -51,6 +63,7 @@ class WinSystemTestCase(TestCase):
|
||||
with patch.object(win_system, 'shutdown', mock):
|
||||
self.assertEqual(win_system.poweroff(), 'salt')
|
||||
|
||||
@skipIf(not HAS_WIN32NET_MODS, 'this test needs the w32net library')
|
||||
def test_reboot(self):
|
||||
'''
|
||||
Test to reboot the system
|
||||
@ -60,6 +73,7 @@ class WinSystemTestCase(TestCase):
|
||||
self.assertEqual(win_system.reboot(), 'salt')
|
||||
mock.assert_called_once_with(['shutdown', '/r', '/t', '300'], python_shell=False)
|
||||
|
||||
@skipIf(not HAS_WIN32NET_MODS, 'this test needs the w32net library')
|
||||
def test_reboot_with_timeout_in_minutes(self):
|
||||
'''
|
||||
Test to reboot the system with a timeout
|
||||
@ -69,6 +83,7 @@ class WinSystemTestCase(TestCase):
|
||||
self.assertEqual(win_system.reboot(5, in_seconds=False), 'salt')
|
||||
mock.assert_called_once_with(['shutdown', '/r', '/t', '300'], python_shell=False)
|
||||
|
||||
@skipIf(not HAS_WIN32NET_MODS, 'this test needs the w32net library')
|
||||
def test_reboot_with_timeout_in_seconds(self):
|
||||
'''
|
||||
Test to reboot the system with a timeout
|
||||
@ -78,6 +93,7 @@ class WinSystemTestCase(TestCase):
|
||||
self.assertEqual(win_system.reboot(5, in_seconds=True), 'salt')
|
||||
mock.assert_called_once_with(['shutdown', '/r', '/t', '5'], python_shell=False)
|
||||
|
||||
@skipIf(not HAS_WIN32NET_MODS, 'this test needs the w32net library')
|
||||
def test_reboot_with_wait(self):
|
||||
'''
|
||||
Test to reboot the system with a timeout and
|
||||
@ -91,6 +107,7 @@ class WinSystemTestCase(TestCase):
|
||||
mock.assert_called_once_with(['shutdown', '/r', '/t', '300'], python_shell=False)
|
||||
sleep_mock.assert_called_once_with(330)
|
||||
|
||||
@skipIf(not HAS_WIN32NET_MODS, 'this test needs the w32net library')
|
||||
def test_shutdown(self):
|
||||
'''
|
||||
Test to shutdown a running system
|
||||
@ -99,6 +116,7 @@ class WinSystemTestCase(TestCase):
|
||||
with patch.dict(win_system.__salt__, {'cmd.run': mock}):
|
||||
self.assertEqual(win_system.shutdown(), 'salt')
|
||||
|
||||
@skipIf(not HAS_WIN32NET_MODS, 'this test needs the w32net library')
|
||||
def test_shutdown_hard(self):
|
||||
'''
|
||||
Test to shutdown a running system with no timeout or warning
|
||||
@ -107,6 +125,7 @@ class WinSystemTestCase(TestCase):
|
||||
with patch.dict(win_system.__salt__, {'cmd.run': mock}):
|
||||
self.assertEqual(win_system.shutdown_hard(), 'salt')
|
||||
|
||||
@skipIf(not HAS_WIN32NET_MODS, 'this test needs the w32net library')
|
||||
def test_set_computer_name(self):
|
||||
'''
|
||||
Test to set the Windows computer name
|
||||
@ -126,6 +145,7 @@ class WinSystemTestCase(TestCase):
|
||||
|
||||
self.assertFalse(win_system.set_computer_name("salt"))
|
||||
|
||||
@skipIf(not HAS_WIN32NET_MODS, 'this test needs the w32net library')
|
||||
def test_get_pending_computer_name(self):
|
||||
'''
|
||||
Test to get a pending computer name.
|
||||
@ -140,6 +160,7 @@ class WinSystemTestCase(TestCase):
|
||||
self.assertEqual(win_system.get_pending_computer_name(),
|
||||
'(salt)')
|
||||
|
||||
@skipIf(not HAS_WIN32NET_MODS, 'this test needs the w32net library')
|
||||
def test_get_computer_name(self):
|
||||
'''
|
||||
Test to get the Windows computer name
|
||||
@ -150,6 +171,7 @@ class WinSystemTestCase(TestCase):
|
||||
|
||||
self.assertFalse(win_system.get_computer_name())
|
||||
|
||||
@skipIf(not HAS_WIN32NET_MODS, 'this test needs the w32net library')
|
||||
def test_set_computer_desc(self):
|
||||
'''
|
||||
Test to set the Windows computer description
|
||||
@ -163,6 +185,7 @@ class WinSystemTestCase(TestCase):
|
||||
),
|
||||
{'Computer Description': "Salt's comp"})
|
||||
|
||||
@skipIf(not HAS_WIN32NET_MODS, 'this test needs the w32net library')
|
||||
def test_get_computer_desc(self):
|
||||
'''
|
||||
Test to get the Windows computer description
|
||||
@ -173,6 +196,7 @@ class WinSystemTestCase(TestCase):
|
||||
|
||||
self.assertFalse(win_system.get_computer_desc())
|
||||
|
||||
@skipIf(not HAS_WIN32NET_MODS, 'this test needs w32net and other windows libraries')
|
||||
def test_join_domain(self):
|
||||
'''
|
||||
Test to join a computer to an Active Directory domain
|
||||
@ -193,10 +217,16 @@ class WinSystemTestCase(TestCase):
|
||||
'''
|
||||
Test to get system time
|
||||
'''
|
||||
mock = MagicMock(return_value="11:31:15 AM")
|
||||
with patch.dict(win_system.__salt__, {'cmd.run': mock}):
|
||||
self.assertEqual(win_system.get_system_time(), '11:31:15 AM')
|
||||
tm = datetime.strftime(datetime.now(), "%I:%M %p")
|
||||
win_tm = win_system.get_system_time()
|
||||
try:
|
||||
self.assertEqual(win_tm, tm)
|
||||
except AssertionError:
|
||||
# handle race condition
|
||||
import re
|
||||
self.assertTrue(re.search(r'^\d{2}:\d{2} \w{2}$', win_tm))
|
||||
|
||||
@skipIf(not HAS_WIN32NET_MODS, 'this test needs the w32net library')
|
||||
def test_set_system_time(self):
|
||||
'''
|
||||
Test to set system time
|
||||
@ -213,10 +243,10 @@ class WinSystemTestCase(TestCase):
|
||||
'''
|
||||
Test to get system date
|
||||
'''
|
||||
mock = MagicMock(return_value="03-28-13")
|
||||
with patch.dict(win_system.__salt__, {'cmd.run': mock}):
|
||||
self.assertEqual(win_system.get_system_date(), '03-28-13')
|
||||
date = datetime.strftime(datetime.now(), "%a %m/%d/%Y")
|
||||
self.assertEqual(win_system.get_system_date(), date)
|
||||
|
||||
@skipIf(not HAS_WIN32NET_MODS, 'this test needs the w32net library')
|
||||
def test_set_system_date(self):
|
||||
'''
|
||||
Test to set system date
|
||||
|
@ -57,11 +57,11 @@ class MockRunnerClient(object):
|
||||
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||
class WinrepoTestCase(TestCase):
|
||||
'''
|
||||
Validate the winrepo state
|
||||
Validate the winrepo state
|
||||
'''
|
||||
def test_genrepo(self):
|
||||
'''
|
||||
Test to refresh the winrepo.p file of the repository
|
||||
Test to refresh the winrepo.p file of the repository
|
||||
'''
|
||||
ret = {'name': 'salt',
|
||||
'changes': {},
|
||||
@ -70,21 +70,21 @@ class WinrepoTestCase(TestCase):
|
||||
mock = MagicMock(side_effect=[False, True, True, True, True, True,
|
||||
True])
|
||||
with patch.object(os.path, 'exists', mock):
|
||||
ret.update({'comment': 'missing /srv/salt/win/repo'})
|
||||
ret.update({'comment': '/srv/salt/win/repo is missing'})
|
||||
self.assertDictEqual(winrepo.genrepo('salt'), ret)
|
||||
|
||||
mock = MagicMock(return_value={'win_repo': 'salt',
|
||||
'win_repo_mastercachefile': 'abc'})
|
||||
mock = MagicMock(return_value={'winrepo_dir': 'salt',
|
||||
'winrepo_cachefile': 'abc'})
|
||||
with patch.object(salt.config, 'master_config', mock):
|
||||
mock = MagicMock(return_value=[0, 1, 2, 3, 4, 5, 6, 7, 8])
|
||||
with patch.object(os, 'stat', mock):
|
||||
mock = MagicMock(return_value=[])
|
||||
with patch.object(os, 'walk', mock):
|
||||
with patch.dict(winrepo.__opts__, {"test": True}):
|
||||
with patch.dict(winrepo.__opts__, {'test': True}):
|
||||
ret.update({'comment': '', 'result': None})
|
||||
self.assertDictEqual(winrepo.genrepo('salt'), ret)
|
||||
|
||||
with patch.dict(winrepo.__opts__, {"test": False}):
|
||||
with patch.dict(winrepo.__opts__, {'test': False}):
|
||||
ret.update({'result': True})
|
||||
self.assertDictEqual(winrepo.genrepo('salt'), ret)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user