mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Add documentation for proxy minion ssh
This commit is contained in:
parent
07cac0b434
commit
7c8f236115
2 changed files with 260 additions and 0 deletions
|
@ -24,6 +24,9 @@ and discovery, control, status, remote execution, and state management.
|
|||
See the :doc:`Proxy Minion Walkthrough </topics/proxyminion/demo>` for an end-to-end
|
||||
demonstration of a working proxy minion.
|
||||
|
||||
See the :doc:`Proxy Minion SSH Walkthrough </topics/proxyminion/ssh>` for an end-to-end
|
||||
demonstration of a working SSH proxy minion.
|
||||
|
||||
New in 2015.8.2
|
||||
---------------
|
||||
|
||||
|
@ -540,3 +543,178 @@ And then in salt.proxy.rest_sample.py we find
|
|||
:glob:
|
||||
|
||||
demo
|
||||
|
||||
|
||||
|
||||
|
||||
SSH Proxymodules
|
||||
----------------
|
||||
|
||||
See above for a general introduction to writing proxy modules.
|
||||
All of the guidelines that apply to REST are the same for SSH.
|
||||
This sections specifically talks about the SSH proxy module and
|
||||
explains the working of the example proxy module ``ssh_sample``.
|
||||
|
||||
Here is a simple example proxymodule used to interface to a device over SSH.
|
||||
Code for the SSH shell is in the `salt-contrib GitHub repository <https://github.com/saltstack/salt-contrib/proxyminion_ssh_example>`_
|
||||
|
||||
This proxymodule enables "package" installation.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
This is a simple proxy-minion designed to connect to and communicate with
|
||||
a server that exposes functionality via SSH.
|
||||
This can be used as an option when the device does not provide
|
||||
an api over HTTP and doesn't have the python stack to run a minion.
|
||||
'''
|
||||
from __future__ import absolute_import
|
||||
|
||||
# Import python libs
|
||||
import json
|
||||
import logging
|
||||
|
||||
# Import Salt's libs
|
||||
from salt.utils.vt_helper import SSHConnection
|
||||
from salt.utils.vt import TerminalException
|
||||
|
||||
# This must be present or the Salt loader won't load this module
|
||||
__proxyenabled__ = ['ssh_sample']
|
||||
|
||||
DETAILS = {}
|
||||
|
||||
# Want logging!
|
||||
log = logging.getLogger(__file__)
|
||||
|
||||
|
||||
# This does nothing, it's here just as an example and to provide a log
|
||||
# entry when the module is loaded.
|
||||
def __virtual__():
|
||||
'''
|
||||
Only return if all the modules are available
|
||||
'''
|
||||
log.info('ssh_sample proxy __virtual__() called...')
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def init(opts):
|
||||
'''
|
||||
Required.
|
||||
Can be used to initialize the server connection.
|
||||
'''
|
||||
try:
|
||||
DETAILS['server'] = SSHConnection(host=__opts__['proxy']['host'],
|
||||
username=__opts__['proxy']['username'],
|
||||
password=__opts__['proxy']['password'])
|
||||
# connected to the SSH server
|
||||
out, err = DETAILS['server'].sendline('help')
|
||||
|
||||
except TerminalException as e:
|
||||
log.error(e)
|
||||
return False
|
||||
|
||||
|
||||
def shutdown(opts):
|
||||
'''
|
||||
Disconnect
|
||||
'''
|
||||
DETAILS['server'].close_connection()
|
||||
|
||||
|
||||
def parse(out):
|
||||
'''
|
||||
Extract json from out.
|
||||
|
||||
Parameter
|
||||
out: Type string. The data returned by the
|
||||
ssh command.
|
||||
'''
|
||||
jsonret = []
|
||||
in_json = False
|
||||
for ln_ in out.split('\n'):
|
||||
if '{' in ln_:
|
||||
in_json = True
|
||||
if in_json:
|
||||
jsonret.append(ln_)
|
||||
if '}' in ln_:
|
||||
in_json = False
|
||||
return json.loads('\n'.join(jsonret))
|
||||
|
||||
|
||||
def package_list():
|
||||
'''
|
||||
List "packages" by executing a command via ssh
|
||||
This function is called in response to the salt command
|
||||
|
||||
..code-block::bash
|
||||
salt target_minion pkg.list_pkgs
|
||||
|
||||
'''
|
||||
# Send the command to execute
|
||||
out, err = DETAILS['server'].sendline('pkg_list')
|
||||
|
||||
# "scrape" the output and return the right fields as a dict
|
||||
return parse(out)
|
||||
|
||||
|
||||
def package_install(name, **kwargs):
|
||||
'''
|
||||
Install a "package" on the REST server
|
||||
'''
|
||||
cmd = 'pkg_install ' + name
|
||||
if 'version' in kwargs:
|
||||
cmd += '/'+kwargs['version']
|
||||
else:
|
||||
cmd += '/1.0'
|
||||
|
||||
# Send the command to execute
|
||||
out, err = DETAILS['server'].sendline(cmd)
|
||||
|
||||
# "scrape" the output and return the right fields as a dict
|
||||
return parse(out)
|
||||
|
||||
|
||||
def package_remove(name):
|
||||
'''
|
||||
Remove a "package" on the REST server
|
||||
'''
|
||||
cmd = 'pkg_remove ' + name
|
||||
|
||||
# Send the command to execute
|
||||
out, err = DETAILS['server'].sendline(cmd)
|
||||
|
||||
# "scrape" the output and return the right fields as a dict
|
||||
return parse(out)
|
||||
|
||||
Connection Setup
|
||||
################
|
||||
|
||||
The ``init()`` method is responsible for connection setup. It uses the ``host``, ``username`` and ``password`` config variables defined in the pillar data. The ``prompt`` kwarg can be passed to ``SSHConnection`` if your SSH server's prompt differs from the example's prompt ``(Cmd)``. Instantiating the ``SSHConnection`` class establishes an SSH connection to the ssh server (using Salt VT).
|
||||
|
||||
Command execution
|
||||
#################
|
||||
|
||||
The ``package_*`` methods use the SSH connection (established in ``init()``) to send commands out to the SSH server. The ``sendline()`` method of ``SSHConnection`` class can be used to send commands out to the server. In the above example we send commands like ``pkg_list`` or ``pkg_install``. You can send any SSH command via this utility.
|
||||
|
||||
Output parsing
|
||||
##############
|
||||
|
||||
Output returned by ``sendline()`` is a tuple of strings representing the stdout and the stderr respectively. In the toy example shown we simply scrape the output and convert it to a python dictionary, as shown in the ``parse`` method. You can tailor this method to match your parsing logic.
|
||||
|
||||
Connection teardown
|
||||
###################
|
||||
|
||||
The ``shutdown`` method is responsible for calling the ``close_connection()`` method of ``SSHConnection`` class. This ends the SSH connection to the server.
|
||||
|
||||
For more information please refer to class `SSHConnection`_.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:glob:
|
||||
|
||||
ssh
|
||||
|
||||
.. _SSHConnection: https://github.com/saltstack/salt/blob/b8271c7512da7e048019ee26422be9e7d6b795ab/salt/utils/vt_helper.py#L28
|
||||
|
|
82
doc/topics/proxyminion/ssh.rst
Normal file
82
doc/topics/proxyminion/ssh.rst
Normal file
|
@ -0,0 +1,82 @@
|
|||
========================================
|
||||
Salt Proxy Minion SSH End-to-End Example
|
||||
========================================
|
||||
|
||||
The following is walkthrough that documents how to run a sample SSH service
|
||||
and configure one or more proxy minions to talk to and control it.
|
||||
|
||||
1. This walkthrough uses a custom SSH shell to provide an end to end example.
|
||||
Any other shells can be used too.
|
||||
|
||||
2. Setup the proxy command shell as shown https://github.com/saltstack/salt-contrib/tree/master/proxyminion_ssh_example
|
||||
|
||||
|
||||
Now, configure your salt-proxy.
|
||||
|
||||
1. Edit ``/etc/salt/proxy`` and add an entry for your master's location
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
master: localhost
|
||||
add_proxymodule_to_opts: False
|
||||
multiprocessing: False
|
||||
|
||||
2. On your salt-master, ensure that pillar is configured properly. Select an ID
|
||||
for your proxy (in this example we will name the proxy with the letter 'p'
|
||||
followed by the port the proxy is answering on). In your pillar topfile,
|
||||
place an entry for your proxy:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
base:
|
||||
'p8000':
|
||||
- p8000
|
||||
|
||||
|
||||
This says that Salt's pillar should load some values for the proxy ``p8000``
|
||||
from the file /srv/pillar/p8000.sls (if you have not changed your default pillar_roots)
|
||||
|
||||
3. In the pillar root for your base environment, create this file:
|
||||
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
p8000.sls
|
||||
---------
|
||||
|
||||
proxy:
|
||||
proxytype: ssh_sample
|
||||
host: saltyVM
|
||||
username: salt
|
||||
password: badpass
|
||||
|
||||
|
||||
4. Make sure your salt-master is running.
|
||||
|
||||
5. Start the salt-proxy in debug mode
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-proxy --proxyid=p8000 -l debug
|
||||
|
||||
6. Accept your proxy's key on your salt-master
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-key -y -a p8000
|
||||
The following keys are going to be accepted:
|
||||
Unaccepted Keys:
|
||||
p8000
|
||||
Key for minion p8000 accepted.
|
||||
|
||||
7. Now you should be able to run commands on your proxy.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt p8000 pkg.list_pkgs
|
||||
|
||||
8. The SSH shell implements a degenerately simple pkg.
|
||||
To "install" a package, use a standard
|
||||
``pkg.install``. If you pass '==' and a verrsion number after the package
|
||||
name then the service will parse that and accept that as the package's
|
||||
version.
|
Loading…
Add table
Reference in a new issue