mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 00:55:19 +00:00
Typos, white-space, unused/missing imports, wrapping, PEP-8.
This commit is contained in:
parent
3f157549c2
commit
7ccb5e4cec
52
README
52
README
@ -1,12 +1,50 @@
|
|||||||
What is Salt?
|
What is Salt?
|
||||||
|
|
||||||
We’re not just talking about NaCl.
|
We’re not just talking about NaCl.
|
||||||
Salt is a distributed remote execution system used to execute commands and query data. It was developed in order to bring the best solutions found in the world of remote execution together and make them better, faster and more malleable. Salt accomplishes this via its ability to handle larger loads of information, and not just dozens, but hundreds or even thousands of individual servers, handle them quickly and through a simple and manageable interface.
|
Salt is a distributed remote execution system used to execute commands and query
|
||||||
Versatility between massive scale deployments and smaller systems may seem daunting, but Salt is very simple to set up and maintain, regardless of the size of the project. The architecture of Salt is designed to work with any number of servers, from a handful of local network systems to international deployments across disparate datacenters. The topology is a simple server/client model with the needed functionality built into a single set of daemons. While the default configuration will work with little to no modification, salt can be fine tuned to meet specific needs.
|
data. It was developed in order to bring the best solutions found in the world
|
||||||
The core function of salt is to enable remote commands to be called in parallel rather than in serial, to use a secure and encrypted protocol, the smallest and fastest network payloads possible and with a simple programmer interface. Salt also introduces more granular controls to the realm of remote execution, allowing for commands to be executed in parallel and for systems to be targeted based on more than just hostname, but by system properties.
|
of remote execution together and make them better, faster and more malleable.
|
||||||
Salt takes advantage of a number of technologies and techniques. The networking layer is built with the excellent zeromq networking library, so salt itself contains a viable, and transparent, amq broker inside the daemon. Salt uses public keys for authentication with the master daemon, then uses faster aes encryption for payload communication, this means that authentication and encryption are also built into Salt. Salt takes advantage of communication via python pickles, enabling fast and light network traffic.
|
|
||||||
In order to allow for simple expansion, Salt execution routines can be written as plain python modules, and the data collected from salt executions can be sent back to the master server, or to any arbitrary program. Salt can be called from a simple python api, or from the command line, so that salt can be used to execute one-off commands as well as operate as an integral part of a larger application.
|
|
||||||
The result is a system that can execute commands across groups of varying size, from very few to very many servers at considerably high speed. A system that is very fast, easy to set up and amazingly malleable, able to suit the needs of any number of servers working within the same system. Salt’s unique architecture brings together the best of the remote execution world, amplifies its capabilities and expands its range, resulting in this system that is as versatile as it is practical, able to suit any network.
|
|
||||||
Salt is developed under the Apache 2.0 licence, and can be used for open and proprietary projects. Please submit your expansions to back so that we can all benefit together as Salt grows. So, please feel free to sprinkle some of this around your systems and let the deliciousness come forth.
|
|
||||||
|
|
||||||
|
Salt accomplishes this via its ability to handle larger loads of information,
|
||||||
|
and not just dozens, but hundreds or even thousands of individual servers,
|
||||||
|
handle them quickly and through a simple and manageable interface.
|
||||||
|
Versatility between massive scale deployments and smaller systems may seem
|
||||||
|
daunting, but Salt is very simple to set up and maintain, regardless of the
|
||||||
|
size of the project. The architecture of Salt is designed to work with any
|
||||||
|
number of servers, from a handful of local network systems to international
|
||||||
|
deployments across disparate data-centers. The topology is a simple server/client
|
||||||
|
model with the needed functionality built into a single set of daemons.
|
||||||
|
While the default configuration will work with little to no modification, salt
|
||||||
|
can be fine tuned to meet specific needs.
|
||||||
|
The core function of salt is to enable remote commands to be called in parallel
|
||||||
|
rather than in serial, to use a secure and encrypted protocol, the smallest and
|
||||||
|
fastest network payloads possible and with a simple programmer interface.
|
||||||
|
Salt also introduces more granular controls to the realm of remote execution,
|
||||||
|
allowing for commands to be executed in parallel and for systems to be targeted
|
||||||
|
based on more than just hostname, but by system properties.
|
||||||
|
Salt takes advantage of a number of technologies and techniques. The networking
|
||||||
|
layer is built with the excellent zeromq networking library, so salt itself
|
||||||
|
contains a viable, and transparent, amq broker inside the daemon. Salt uses
|
||||||
|
public keys for authentication with the master daemon, then uses faster aes
|
||||||
|
encryption for payload communication, this means that authentication and
|
||||||
|
encryption are also built into Salt. Salt takes advantage of communication via
|
||||||
|
python pickles, enabling fast and light network traffic.
|
||||||
|
In order to allow for simple expansion, Salt execution routines can be written
|
||||||
|
as plain python modules, and the data collected from salt executions can be sent
|
||||||
|
back to the master server, or to any arbitrary program. Salt can be called from
|
||||||
|
a simple python api, or from the command line, so that salt can be used to
|
||||||
|
execute one-off commands as well as operate as an integral part of a larger
|
||||||
|
application.
|
||||||
|
|
||||||
|
The result is a system that can execute commands across groups of varying size,
|
||||||
|
from very few to very many servers at considerably high speed. A system that is
|
||||||
|
very fast, easy to set up and amazingly malleable, able to suit the needs of any
|
||||||
|
number of servers working within the same system. Salt’s unique architecture
|
||||||
|
brings together the best of the remote execution world, amplifies its
|
||||||
|
capabilities and expands its range, resulting in this system that is as
|
||||||
|
versatile as it is practical, able to suit any network.
|
||||||
|
|
||||||
|
Salt is developed under the Apache 2.0 licence, and can be used for open and
|
||||||
|
proprietary projects. Please submit your expansions to back so that we can all
|
||||||
|
benefit together as Salt grows. So, please feel free to sprinkle some of this
|
||||||
|
around your systems and let the deliciousness come forth.
|
||||||
|
@ -24,23 +24,28 @@ The timeout in seconds to wait for replies from the salt minions.
|
|||||||
|
|
||||||
.TP
|
.TP
|
||||||
-E, --pcre
|
-E, --pcre
|
||||||
The target expresion will be interpereted as a pcre regular expression rather than a shell glob.
|
The target expression will be interpreted as a pcre regular expression rather than a shell glob.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
-L, --list
|
-L, --list
|
||||||
The target expression will be interpereted as a comma delimited list, example: server1.foo.bar,server2.foo.bar,example7.quo.qux
|
The target expression will be interpreted as a comma delimited list,
|
||||||
|
example: server1.foo.bar,server2.foo.bar,example7.quo.qux
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
-G, --grain
|
-G, --grain
|
||||||
The target expression matches values returned by the salt grains system on the minions. The target expresion is in the format of '<grain value>:<pcre regular expresion>'; example: 'os:Arch.*'
|
The target expression matches values returned by the salt grains system on the
|
||||||
|
minions. The target expression is in the format of '<grain value>:<pcre regular expression>';
|
||||||
|
example: 'os:Arch.*'
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
-Q, --query
|
-Q, --query
|
||||||
Execute a salt command query, this can be used to find the results os a previous function call: -Q test.echo')
|
Execute a salt command query, this can be used to find the results os a previous
|
||||||
|
function call: -Q test.echo')
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
-c CONFIG, --config=CONFIG
|
-c CONFIG, --config=CONFIG
|
||||||
The location of the salt master configuration file, the salt master settings are required to know where the connections are; default=/etc/salt/master
|
The location of the salt master configuration file, the salt master settings are
|
||||||
|
required to know where the connections are; default=/etc/salt/master
|
||||||
|
|
||||||
.SH AUTHORS
|
.SH AUTHORS
|
||||||
Thomas S. Hatch <thatch@gmail.com>
|
Thomas S. Hatch <thatch@gmail.com>
|
||||||
|
@ -32,7 +32,8 @@ Accepts all pending public keys.
|
|||||||
|
|
||||||
.TP
|
.TP
|
||||||
-c CONFIG, --config=CONFIG
|
-c CONFIG, --config=CONFIG
|
||||||
The master configuration file needs to be read to determine where the salt keys are stored via the pki_dir configuration value; default=/etc/salt/master
|
The master configuration file needs to be read to determine where the salt keys
|
||||||
|
are stored via the pki_dir configuration value; default=/etc/salt/master
|
||||||
|
|
||||||
|
|
||||||
.SH AUTHORS
|
.SH AUTHORS
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
.TH salt-minion 1 "May 2011" "salt-minion 0.8.7" "salt-minion Manual"
|
.TH salt-minion 1 "May 2011" "salt-minion 0.8.7" "salt-minion Manual"
|
||||||
|
|
||||||
.SH NAME
|
.SH NAME
|
||||||
salt-minion \- The salt minion daemon, recieves commands from a remote salt master.
|
salt-minion \- The salt minion daemon, receives commands from a remote salt master.
|
||||||
|
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B salt-minion [ options ]
|
.B salt-minion [ options ]
|
||||||
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
The salt minion recieves commands from the central salt master and replies with the results of said commands.
|
The salt minion receives commands from the central salt master and replies with
|
||||||
|
the results of said commands.
|
||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
|
@ -13,7 +13,8 @@ salt \- Parallel remote execution system
|
|||||||
.B salt -Q test.ping
|
.B salt -Q test.ping
|
||||||
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
Salt allows for commands to be executed across a swath of remote systems in parallel. This means that remote systems can be both controleed and querried with ease.
|
Salt allows for commands to be executed across a swath of remote systems in parallel.
|
||||||
|
This means that remote systems can be both controlled and queried with ease.
|
||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
@ -26,23 +27,29 @@ The timeout in seconds to wait for replies from the salt minions.
|
|||||||
|
|
||||||
.TP
|
.TP
|
||||||
-E, --pcre
|
-E, --pcre
|
||||||
The target expresion will be interpereted as a pcre regular expression rather than a shell glob.
|
The target expression will be interpreted as a pcre regular expression rather than
|
||||||
|
a shell glob.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
-L, --list
|
-L, --list
|
||||||
The target expression will be interpereted as a comma delimited list, example: server1.foo.bar,server2.foo.bar,example7.quo.qux
|
The target expression will be interpreted as a comma delimited list,
|
||||||
|
example: server1.foo.bar,server2.foo.bar,example7.quo.qux
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
-G, --grain
|
-G, --grain
|
||||||
The target expression matches values returned by the salt grains system on the minions. The target expresion is in the format of '<grain value>:<pcre regular expresion>'; example: 'os:Arch.*'
|
The target expression matches values returned by the salt grains system on the
|
||||||
|
minions. The target expression is in the format of '<grain value>:<pcre regular expression>';
|
||||||
|
example: 'os:Arch.*'
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
-Q, --query
|
-Q, --query
|
||||||
Execute a salt command query, this can be used to find the results os a previous function call: -Q test.echo')
|
Execute a salt command query, this can be used to find the results os a previous
|
||||||
|
function call: -Q test.echo')
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
-c CONFIG, --config=CONFIG
|
-c CONFIG, --config=CONFIG
|
||||||
The location of the salt master configuration file, the salt master settings are required to know where the connections are; default=/etc/salt/master
|
The location of the salt master configuration file, the salt master settings are
|
||||||
|
required to know where the connections are; default=/etc/salt/master
|
||||||
|
|
||||||
.SH AUTHORS
|
.SH AUTHORS
|
||||||
Thomas S. Hatch <thatch@gmail.com>
|
Thomas S. Hatch <thatch@gmail.com>
|
||||||
|
@ -11,13 +11,17 @@ salt \- The salt distributed system controller
|
|||||||
.B salt [options]
|
.B salt [options]
|
||||||
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
Salt is a powerful remote execution manager that can be used to administer servers in a fast and efficient way.
|
Salt is a powerful remote execution manager that can be used to administer
|
||||||
|
servers in a fast and efficient way.
|
||||||
|
|
||||||
.SH SETTING UP SALT
|
.SH SETTING UP SALT
|
||||||
The Salt system setup is amazingly simple, as this is one of the central design goals of Salt. Setting up Salt only requires that the salt master be running and the salt minions point to the salt master.
|
The Salt system setup is amazingly simple, as this is one of the central design
|
||||||
|
goals of Salt. Setting up Salt only requires that the salt master be running and
|
||||||
|
the salt minions point to the salt master.
|
||||||
|
|
||||||
.SS INSTALATION
|
.SS INSTALATION
|
||||||
The salt install is simple, for many distributions pakages should be available for download, or salt can be installed via the python packaging tools.
|
The salt install is simple, for many distributions packages should be available
|
||||||
|
for download, or salt can be installed via the python packaging tools.
|
||||||
.P
|
.P
|
||||||
Installing salt from source is a simple task, download the latest source tarball from
|
Installing salt from source is a simple task, download the latest source tarball from
|
||||||
.URL "https://github.com/thatch45/salt/downloads"
|
.URL "https://github.com/thatch45/salt/downloads"
|
||||||
@ -31,15 +35,16 @@ Next untar the download and run the python setup:
|
|||||||
# python2 setup.py install
|
# python2 setup.py install
|
||||||
|
|
||||||
.SS SALT DEPENDENCIES
|
.SS SALT DEPENDENCIES
|
||||||
This is a basic python setup, nothing fancy. Salt does require a number of dependencies though, all of which should be available in your distribution's packages.
|
This is a basic python setup, nothing fancy. Salt does require a number of
|
||||||
|
dependencies though, all of which should be available in your distribution's packages.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\(bu
|
\(bu
|
||||||
python2.7 - python2.6 should work, but it is untested
|
python2.7 - python2.6 should work, but it is untested
|
||||||
.TP
|
.TP
|
||||||
\(bu
|
\(bu
|
||||||
pyzmq - zeromq python bindings
|
pyzmq - zeromq python bindings
|
||||||
.TP
|
.TP
|
||||||
\(bu
|
\(bu
|
||||||
python-m2crypto - Crypto backend
|
python-m2crypto - Crypto backend
|
||||||
.TP
|
.TP
|
||||||
@ -50,7 +55,9 @@ python-yaml - Reading configuration files
|
|||||||
pycrypto - Another crypto backend
|
pycrypto - Another crypto backend
|
||||||
|
|
||||||
.SS RUNNING SALT
|
.SS RUNNING SALT
|
||||||
To run Salt you need to ensure that a master and a minion are running and referencing each other. Starting the master and minion daemons is done with the respective commands.
|
To run Salt you need to ensure that a master and a minion are running and
|
||||||
|
referencing each other. Starting the master and minion daemons is done with the
|
||||||
|
respective commands.
|
||||||
|
|
||||||
On the salt master server:
|
On the salt master server:
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ import salt.config
|
|||||||
|
|
||||||
def verify_env(dirs):
|
def verify_env(dirs):
|
||||||
'''
|
'''
|
||||||
Verify that the named direcotries are in place and that the environment
|
Verify that the named directories are in place and that the environment
|
||||||
can shake the salt
|
can shake the salt
|
||||||
'''
|
'''
|
||||||
for dir_ in dirs:
|
for dir_ in dirs:
|
||||||
|
@ -25,7 +25,7 @@ class SaltCMD(object):
|
|||||||
'''
|
'''
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
'''
|
'''
|
||||||
Cretae a SaltCMD object
|
Create a SaltCMD object
|
||||||
'''
|
'''
|
||||||
self.opts = self.__parse()
|
self.opts = self.__parse()
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ class SaltCMD(object):
|
|||||||
Parse the command line
|
Parse the command line
|
||||||
'''
|
'''
|
||||||
parser = optparse.OptionParser()
|
parser = optparse.OptionParser()
|
||||||
|
|
||||||
parser.add_option('-t',
|
parser.add_option('-t',
|
||||||
'--timeout',
|
'--timeout',
|
||||||
default=5,
|
default=5,
|
||||||
@ -63,7 +63,7 @@ class SaltCMD(object):
|
|||||||
help='Instead of using shell globs to evaluate the target'\
|
help='Instead of using shell globs to evaluate the target'\
|
||||||
+ ' use a grain value to identify targets, the syntax'\
|
+ ' use a grain value to identify targets, the syntax'\
|
||||||
+ ' for the target is the grain key followed by a pcre'\
|
+ ' for the target is the grain key followed by a pcre'\
|
||||||
+ ' regular expresion:\n"os:Arch.*"')
|
+ ' regular expression:\n"os:Arch.*"')
|
||||||
parser.add_option('-X',
|
parser.add_option('-X',
|
||||||
'--exsel',
|
'--exsel',
|
||||||
default=False,
|
default=False,
|
||||||
@ -97,7 +97,7 @@ class SaltCMD(object):
|
|||||||
action='store_true',
|
action='store_true',
|
||||||
dest='raw_out',
|
dest='raw_out',
|
||||||
help='Print the output from the salt command in raw python'\
|
help='Print the output from the salt command in raw python'\
|
||||||
+ ' form, this is suitible for re-reading the output into'\
|
+ ' form, this is suitable for re-reading the output into'\
|
||||||
+ ' an executing python script with eval.')
|
+ ' an executing python script with eval.')
|
||||||
if JSON:
|
if JSON:
|
||||||
parser.add_option('--json-out',
|
parser.add_option('--json-out',
|
||||||
@ -179,7 +179,7 @@ class SaltCMD(object):
|
|||||||
args.append('exsel')
|
args.append('exsel')
|
||||||
else:
|
else:
|
||||||
args.append('glob')
|
args.append('glob')
|
||||||
|
|
||||||
if self.opts['return']:
|
if self.opts['return']:
|
||||||
args.append(self.opts['return'])
|
args.append(self.opts['return'])
|
||||||
ret = local.cmd(*args)
|
ret = local.cmd(*args)
|
||||||
@ -224,7 +224,7 @@ class SaltCP(object):
|
|||||||
Parse the command line
|
Parse the command line
|
||||||
'''
|
'''
|
||||||
parser = optparse.OptionParser()
|
parser = optparse.OptionParser()
|
||||||
|
|
||||||
parser.add_option('-t',
|
parser.add_option('-t',
|
||||||
'--timeout',
|
'--timeout',
|
||||||
default=5,
|
default=5,
|
||||||
@ -253,7 +253,7 @@ class SaltCP(object):
|
|||||||
help='Instead of using shell globs to evaluate the target'\
|
help='Instead of using shell globs to evaluate the target'\
|
||||||
+ ' use a grain value to identify targets, the syntax'\
|
+ ' use a grain value to identify targets, the syntax'\
|
||||||
+ ' for the target is the grains key followed by a pcre'\
|
+ ' for the target is the grains key followed by a pcre'\
|
||||||
+ ' regular expresion:\n"os:Arch.*"')
|
+ ' regular expression:\n"os:Arch.*"')
|
||||||
parser.add_option('-c',
|
parser.add_option('-c',
|
||||||
'--config',
|
'--config',
|
||||||
default='/etc/salt/master',
|
default='/etc/salt/master',
|
||||||
@ -315,7 +315,7 @@ class SaltKey(object):
|
|||||||
default=False,
|
default=False,
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='List all public keys')
|
help='List all public keys')
|
||||||
|
|
||||||
parser.add_option('-a',
|
parser.add_option('-a',
|
||||||
'--accept',
|
'--accept',
|
||||||
dest='accept',
|
dest='accept',
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
'''
|
'''
|
||||||
The caller module is used as a frontend to manage direct calls to the salt
|
The caller module is used as a front-end to manage direct calls to the salt
|
||||||
minion modules.
|
minion modules.
|
||||||
'''
|
'''
|
||||||
# Import python modules
|
# Import python modules
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
'''
|
'''
|
||||||
The cp module is used to execute the logic used by the salt-cp command
|
The cp module is used to execute the logic used by the salt-cp command
|
||||||
line application, salt-cp is NOT intended to broadcast large files, it is
|
line application, salt-cp is NOT intended to broadcast large files, it is
|
||||||
intened to handle text files.
|
intended to handle text files.
|
||||||
Salt-cp can be used to distribute configuration files
|
Salt-cp can be used to distribute configuration files
|
||||||
'''
|
'''
|
||||||
# Import python modules
|
# Import python modules
|
||||||
@ -73,7 +73,7 @@ class SaltCP(object):
|
|||||||
args.append('list')
|
args.append('list')
|
||||||
elif self.opts['grain']:
|
elif self.opts['grain']:
|
||||||
args.append('grain')
|
args.append('grain')
|
||||||
|
|
||||||
ret = local.cmd(*args)
|
ret = local.cmd(*args)
|
||||||
|
|
||||||
print yaml.dump(ret)
|
print yaml.dump(ret)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
'''
|
'''
|
||||||
The client module is used to create a client connection to the publisher
|
The client module is used to create a client connection to the publisher
|
||||||
The data structurte needs to be:
|
The data structure needs to be:
|
||||||
{'enc': 'clear',
|
{'enc': 'clear',
|
||||||
'load': {'fun': '<mod.callable>',
|
'load': {'fun': '<mod.callable>',
|
||||||
'arg':, ('arg1', 'arg2', ...),
|
'arg':, ('arg1', 'arg2', ...),
|
||||||
@ -10,17 +10,17 @@ The data structurte needs to be:
|
|||||||
# The components here are simple, and they need to be and stay simple, we
|
# The components here are simple, and they need to be and stay simple, we
|
||||||
# want a client to have 3 external concerns, and maybe a forth configurable
|
# want a client to have 3 external concerns, and maybe a forth configurable
|
||||||
# option.
|
# option.
|
||||||
# The concers are
|
# The concerns are
|
||||||
# 1. Who executes the command?
|
# 1. Who executes the command?
|
||||||
# 2. what is the function being run?
|
# 2. what is the function being run?
|
||||||
# 3. What arguments need to be passed to the function?
|
# 3. What arguments need to be passed to the function?
|
||||||
# 4. How long do we wait for all of the replies?
|
# 4. How long do we wait for all of the replies?
|
||||||
#
|
#
|
||||||
# Next there are a number of tasks, first we need some kind of authentication
|
# Next there are a number of tasks, first we need some kind of authentication
|
||||||
# This Client initially will be the master root client, which will run as the
|
# This Client initially will be the master root client, which will run as the
|
||||||
# root user on the master server.
|
# root user on the master server.
|
||||||
# BUT we also want a client to be able to work over the network, so that
|
# BUT we also want a client to be able to work over the network, so that
|
||||||
# controllers can exist within disperate applicaitons.
|
# controllers can exist within disparate applications.
|
||||||
# The problem is that this is a security nightmare, so I am going to start
|
# The problem is that this is a security nightmare, so I am going to start
|
||||||
# small, and only start with the ability to execute salt commands locally.
|
# small, and only start with the ability to execute salt commands locally.
|
||||||
# This means that the primary client to build is, the LocalClient
|
# This means that the primary client to build is, the LocalClient
|
||||||
@ -90,7 +90,7 @@ class LocalClient(object):
|
|||||||
|
|
||||||
def _check_pcre_minions(self, expr):
|
def _check_pcre_minions(self, expr):
|
||||||
'''
|
'''
|
||||||
Return the minions found by looking via regular expresions
|
Return the minions found by looking via regular expressions
|
||||||
'''
|
'''
|
||||||
ret = set()
|
ret = set()
|
||||||
cwd = os.getcwd()
|
cwd = os.getcwd()
|
||||||
@ -184,10 +184,10 @@ class LocalClient(object):
|
|||||||
'grain': self._check_grain_minions,
|
'grain': self._check_grain_minions,
|
||||||
'exsel': self._check_grain_minions,
|
'exsel': self._check_grain_minions,
|
||||||
}[expr_form](expr)
|
}[expr_form](expr)
|
||||||
|
|
||||||
def pub(self, tgt, fun, arg=(), expr_form='glob', ret=''):
|
def pub(self, tgt, fun, arg=(), expr_form='glob', ret=''):
|
||||||
'''
|
'''
|
||||||
Take the required arguemnts and publish the given command.
|
Take the required arguments and publish the given command.
|
||||||
Arguments:
|
Arguments:
|
||||||
tgt:
|
tgt:
|
||||||
The tgt is a regex or a glob used to match up the ids on
|
The tgt is a regex or a glob used to match up the ids on
|
||||||
@ -195,11 +195,11 @@ class LocalClient(object):
|
|||||||
all of the minions and then the minions determine if the
|
all of the minions and then the minions determine if the
|
||||||
command is for them based on the tgt value.
|
command is for them based on the tgt value.
|
||||||
fun:
|
fun:
|
||||||
The function nane to be called on the remote host(s), this must
|
The function name to be called on the remote host(s), this must
|
||||||
be a string in the format "<modulename>.<function name>"
|
be a string in the format "<modulename>.<function name>"
|
||||||
arg:
|
arg:
|
||||||
The arg option needs to be a tuple of arguments to pass to the
|
The arg option needs to be a tuple of arguments to pass to the
|
||||||
calling function, if left blank
|
calling function, if left blank
|
||||||
Returns:
|
Returns:
|
||||||
jid:
|
jid:
|
||||||
A string, as returned by the publisher, which is the job id,
|
A string, as returned by the publisher, which is the job id,
|
||||||
@ -207,7 +207,7 @@ class LocalClient(object):
|
|||||||
minions:
|
minions:
|
||||||
A set, the targets that the tgt passed should match.
|
A set, the targets that the tgt passed should match.
|
||||||
'''
|
'''
|
||||||
# Run a check_minions, if no minons match return False
|
# Run a check_minions, if no minions match return False
|
||||||
# format the payload - make a function that does this in the payload
|
# format the payload - make a function that does this in the payload
|
||||||
# module
|
# module
|
||||||
# make the zmq client
|
# make the zmq client
|
||||||
@ -229,8 +229,7 @@ class LocalClient(object):
|
|||||||
# Prep zmq
|
# Prep zmq
|
||||||
context = zmq.Context()
|
context = zmq.Context()
|
||||||
socket = context.socket(zmq.REQ)
|
socket = context.socket(zmq.REQ)
|
||||||
socket.connect('tcp://' + self.opts['interface'] + ':'\
|
socket.connect('tcp://%(interface)s:%(ret_port)s' % self.opts)
|
||||||
+ str(self.opts['ret_port']))
|
|
||||||
socket.send(package)
|
socket.send(package)
|
||||||
payload = salt.payload.unpackage(socket.recv())
|
payload = salt.payload.unpackage(socket.recv())
|
||||||
return {'jid': payload['load']['jid'],
|
return {'jid': payload['load']['jid'],
|
||||||
|
@ -45,7 +45,7 @@ def minion_config(path):
|
|||||||
opts['master_uri'] = 'tcp://' + opts['master'] + ':'\
|
opts['master_uri'] = 'tcp://' + opts['master'] + ':'\
|
||||||
+ str(opts['master_port'])
|
+ str(opts['master_port'])
|
||||||
|
|
||||||
# Enableing open mode requires that the value be set to True, and nothing
|
# Enabling open mode requires that the value be set to True, and nothing
|
||||||
# else!
|
# else!
|
||||||
if opts['open_mode']:
|
if opts['open_mode']:
|
||||||
if opts['open_mode'] == True:
|
if opts['open_mode'] == True:
|
||||||
@ -91,7 +91,7 @@ def master_config(path):
|
|||||||
|
|
||||||
opts['aes'] = salt.crypt.Crypticle.generate_key_string()
|
opts['aes'] = salt.crypt.Crypticle.generate_key_string()
|
||||||
|
|
||||||
# Enableing open mode requires that the value be set to True, and nothing
|
# Enabling open mode requires that the value be set to True, and nothing
|
||||||
# else!
|
# else!
|
||||||
if opts['open_mode']:
|
if opts['open_mode']:
|
||||||
if opts['open_mode'] == True:
|
if opts['open_mode'] == True:
|
||||||
|
@ -48,7 +48,7 @@ class MasterKeys(dict):
|
|||||||
|
|
||||||
def __get_priv_key(self):
|
def __get_priv_key(self):
|
||||||
'''
|
'''
|
||||||
Retruns a private key object for the master
|
Returns a private key object for the master
|
||||||
'''
|
'''
|
||||||
key = None
|
key = None
|
||||||
try:
|
try:
|
||||||
@ -89,7 +89,7 @@ class Auth(object):
|
|||||||
|
|
||||||
def get_priv_key(self):
|
def get_priv_key(self):
|
||||||
'''
|
'''
|
||||||
Retruns a private key object for the minion
|
Returns a private key object for the minion
|
||||||
'''
|
'''
|
||||||
key = None
|
key = None
|
||||||
try:
|
try:
|
||||||
@ -107,7 +107,7 @@ class Auth(object):
|
|||||||
|
|
||||||
def minion_sign_in_payload(self):
|
def minion_sign_in_payload(self):
|
||||||
'''
|
'''
|
||||||
Generates the payload used to autnenticate with the master server. This
|
Generates the payload used to authenticate with the master server. This
|
||||||
payload consists of the passed in id_ and the ssh public key to encrypt
|
payload consists of the passed in id_ and the ssh public key to encrypt
|
||||||
the AES key sent back form the master.
|
the AES key sent back form the master.
|
||||||
'''
|
'''
|
||||||
@ -129,7 +129,7 @@ class Auth(object):
|
|||||||
Pass in the encrypted aes key.
|
Pass in the encrypted aes key.
|
||||||
Returns the decrypted aes seed key, a string
|
Returns the decrypted aes seed key, a string
|
||||||
'''
|
'''
|
||||||
log.info('Decypting the current master AES key')
|
log.info('Decrypting the current master AES key')
|
||||||
key = self.get_priv_key()
|
key = self.get_priv_key()
|
||||||
return key.private_decrypt(aes, 4)
|
return key.private_decrypt(aes, 4)
|
||||||
|
|
||||||
@ -137,7 +137,7 @@ class Auth(object):
|
|||||||
'''
|
'''
|
||||||
Takes the master pubkey and compares it to the saved master pubkey,
|
Takes the master pubkey and compares it to the saved master pubkey,
|
||||||
the token is encrypted with the master private key and must be
|
the token is encrypted with the master private key and must be
|
||||||
decrypted sucessfully to verify that the master has been connected to.
|
decrypted successfully to verify that the master has been connected to.
|
||||||
The token must decrypt with the public key, and it must say:
|
The token must decrypt with the public key, and it must say:
|
||||||
'salty bacon'
|
'salty bacon'
|
||||||
returns a bool
|
returns a bool
|
||||||
@ -274,7 +274,7 @@ class Crypticle(object):
|
|||||||
|
|
||||||
def loads(self, data, pickler=pickle):
|
def loads(self, data, pickler=pickle):
|
||||||
'''
|
'''
|
||||||
decrypt and unpickle a python object
|
decrypt and un-pickle a python object
|
||||||
'''
|
'''
|
||||||
data = self.decrypt(data)
|
data = self.decrypt(data)
|
||||||
# simple integrity check to verify that we got meaningful data
|
# simple integrity check to verify that we got meaningful data
|
||||||
@ -294,7 +294,7 @@ class SAuth(object):
|
|||||||
def __authenticate(self):
|
def __authenticate(self):
|
||||||
'''
|
'''
|
||||||
Authenticate with the master, this method breaks the functional
|
Authenticate with the master, this method breaks the functional
|
||||||
pardigmn, it will update the master information from a fresh sign in,
|
paradigm, it will update the master information from a fresh sign in,
|
||||||
signing in can occur as often as needed to keep up with the revolving
|
signing in can occur as often as needed to keep up with the revolving
|
||||||
master aes key.
|
master aes key.
|
||||||
'''
|
'''
|
||||||
|
@ -127,7 +127,7 @@ def os_data():
|
|||||||
grains['os'] = kernel
|
grains['os'] = kernel
|
||||||
|
|
||||||
# Load the virtual machine info
|
# Load the virtual machine info
|
||||||
|
|
||||||
grains.update(_virtual(grains))
|
grains.update(_virtual(grains))
|
||||||
grains.update(_ps(grains))
|
grains.update(_ps(grains))
|
||||||
return grains
|
return grains
|
||||||
|
@ -81,9 +81,9 @@ def call(fun, args=[], dirs=[]):
|
|||||||
|
|
||||||
class Loader(object):
|
class Loader(object):
|
||||||
'''
|
'''
|
||||||
Used to load in arbitrairy modules from a directory, the Loader can also be
|
Used to load in arbitrary modules from a directory, the Loader can also be
|
||||||
used to only load specific functions from a directory, or to call modules
|
used to only load specific functions from a directory, or to call modules
|
||||||
in an arbitrairy directory directly.
|
in an arbitrary directory directly.
|
||||||
'''
|
'''
|
||||||
def __init__(self, module_dirs, opts={}):
|
def __init__(self, module_dirs, opts={}):
|
||||||
self.module_dirs = module_dirs
|
self.module_dirs = module_dirs
|
||||||
@ -255,7 +255,7 @@ class Loader(object):
|
|||||||
def gen_grains(self):
|
def gen_grains(self):
|
||||||
'''
|
'''
|
||||||
Read the grains directory and execute all of the public callable
|
Read the grains directory and execute all of the public callable
|
||||||
members. then verify that the returns are python dicts and return a
|
members. then verify that the returns are python dict's and return a
|
||||||
dict containing all of the returned values.
|
dict containing all of the returned values.
|
||||||
'''
|
'''
|
||||||
grains = {}
|
grains = {}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
|
|
||||||
:copyright: © 2011 :email:`Pedro Algarvio (pedro@algarvio.me)`
|
:copyright: © 2011 :email:`Pedro Algarvio (pedro@algarvio.me)`
|
||||||
:license: Apache Version 2.0, see LICENSE for more details.
|
:license: Apache 2.0, see LICENSE for more details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
@ -19,7 +19,7 @@ import salt.utils
|
|||||||
import salt.crypt
|
import salt.crypt
|
||||||
import salt.payload
|
import salt.payload
|
||||||
import salt.client
|
import salt.client
|
||||||
# Import cryptogrogphy modules
|
# Import cryptography modules
|
||||||
from M2Crypto import RSA
|
from M2Crypto import RSA
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -61,7 +61,7 @@ class Master(object):
|
|||||||
|
|
||||||
class Publisher(multiprocessing.Process):
|
class Publisher(multiprocessing.Process):
|
||||||
'''
|
'''
|
||||||
The publihing interface, a simple zeromq publisher that sends out the
|
The publishing interface, a simple zeromq publisher that sends out the
|
||||||
commands.
|
commands.
|
||||||
'''
|
'''
|
||||||
def __init__(self, opts):
|
def __init__(self, opts):
|
||||||
@ -115,7 +115,7 @@ class ReqServer():
|
|||||||
A key needs to be placed in the filesystem with permissions 0400 so
|
A key needs to be placed in the filesystem with permissions 0400 so
|
||||||
clients are required to run as root.
|
clients are required to run as root.
|
||||||
'''
|
'''
|
||||||
log.info('Preparing the root key for local comunication')
|
log.info('Preparing the root key for local communication')
|
||||||
keyfile = os.path.join(self.opts['cachedir'], '.root_key')
|
keyfile = os.path.join(self.opts['cachedir'], '.root_key')
|
||||||
key = salt.crypt.Crypticle.generate_key_string()
|
key = salt.crypt.Crypticle.generate_key_string()
|
||||||
if os.path.isfile(keyfile):
|
if os.path.isfile(keyfile):
|
||||||
@ -139,7 +139,7 @@ class ReqServer():
|
|||||||
m_worker.start()
|
m_worker.start()
|
||||||
|
|
||||||
out_socket = self.context.socket(zmq.REQ)
|
out_socket = self.context.socket(zmq.REQ)
|
||||||
out_socket.connect('tcp://127.0.0.1:' + str(work_port))
|
out_socket.connect('tcp://127.0.0.1:%s' % work_port)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
package = in_socket.recv()
|
package = in_socket.recv()
|
||||||
@ -188,7 +188,7 @@ class MWorker(multiprocessing.Process):
|
|||||||
'''
|
'''
|
||||||
context = zmq.Context(1)
|
context = zmq.Context(1)
|
||||||
socket = context.socket(zmq.REP)
|
socket = context.socket(zmq.REP)
|
||||||
socket.bind('tcp://127.0.0.1:' + self.port)
|
socket.bind('tcp://127.0.0.1:%s' % self.port)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
package = socket.recv()
|
package = socket.recv()
|
||||||
@ -202,8 +202,9 @@ class MWorker(multiprocessing.Process):
|
|||||||
job id directory.
|
job id directory.
|
||||||
'''
|
'''
|
||||||
jid_root = os.path.join(self.opts['cachedir'], 'jobs')
|
jid_root = os.path.join(self.opts['cachedir'], 'jobs')
|
||||||
jid = datetime.datetime.strftime(datetime.datetime.now(),
|
jid = datetime.datetime.strftime(
|
||||||
'%Y%m%d%H%M%S%f')
|
datetime.datetime.now(), '%Y%m%d%H%M%S%f'
|
||||||
|
)
|
||||||
jid_dir = os.path.join(jid_root, jid)
|
jid_dir = os.path.join(jid_root, jid)
|
||||||
if not os.path.isdir(jid_dir):
|
if not os.path.isdir(jid_dir):
|
||||||
os.makedirs(jid_dir)
|
os.makedirs(jid_dir)
|
||||||
@ -225,21 +226,21 @@ class MWorker(multiprocessing.Process):
|
|||||||
'''
|
'''
|
||||||
Take care of a cleartext command
|
Take care of a cleartext command
|
||||||
'''
|
'''
|
||||||
log.info('Clear payload recieved with command %(cmd)s', load)
|
log.info('Clear payload received with command %(cmd)s', load)
|
||||||
return getattr(self, load['cmd'])(load)
|
return getattr(self, load['cmd'])(load)
|
||||||
|
|
||||||
def _handle_pub(self, load):
|
def _handle_pub(self, load):
|
||||||
'''
|
'''
|
||||||
Handle a command sent via a public key pair
|
Handle a command sent via a public key pair
|
||||||
'''
|
'''
|
||||||
log.info('Pubkey payload recieved with command %(cmd)s', load)
|
log.info('Pubkey payload received with command %(cmd)s', load)
|
||||||
|
|
||||||
def _handle_aes(self, load):
|
def _handle_aes(self, load):
|
||||||
'''
|
'''
|
||||||
Handle a command sent via an aes key
|
Handle a command sent via an aes key
|
||||||
'''
|
'''
|
||||||
data = self.crypticle.loads(load)
|
data = self.crypticle.loads(load)
|
||||||
log.info('AES payload recieved with command %(cmd)s', load)
|
log.info('AES payload received with command %(cmd)s', load)
|
||||||
return getattr(self, data['cmd'])(data)
|
return getattr(self, data['cmd'])(data)
|
||||||
|
|
||||||
def _auth(self, load):
|
def _auth(self, load):
|
||||||
@ -247,7 +248,7 @@ class MWorker(multiprocessing.Process):
|
|||||||
Authenticate the client, use the sent public key to encrypt the aes key
|
Authenticate the client, use the sent public key to encrypt the aes key
|
||||||
which was generated at start up
|
which was generated at start up
|
||||||
'''
|
'''
|
||||||
# 1. Verify that the key we are recieving matches the stored key
|
# 1. Verify that the key we are receiving matches the stored key
|
||||||
# 2. Store the key if it is not there
|
# 2. Store the key if it is not there
|
||||||
# 3. make an rsa key with the pub key
|
# 3. make an rsa key with the pub key
|
||||||
# 4. encrypt the aes key as an encrypted pickle
|
# 4. encrypt the aes key as an encrypted pickle
|
||||||
@ -326,7 +327,7 @@ class MWorker(multiprocessing.Process):
|
|||||||
|
|
||||||
def _serve_file(self, load):
|
def _serve_file(self, load):
|
||||||
'''
|
'''
|
||||||
Return a chunk from a file based on the data recieved
|
Return a chunk from a file based on the data received
|
||||||
'''
|
'''
|
||||||
if not load.has_key('path') or not load.has_key('loc'):
|
if not load.has_key('path') or not load.has_key('loc'):
|
||||||
return False
|
return False
|
||||||
@ -368,7 +369,7 @@ class MWorker(multiprocessing.Process):
|
|||||||
jid_dir = os.path.join(self.opts['cachedir'], 'jobs', load['jid'])
|
jid_dir = os.path.join(self.opts['cachedir'], 'jobs', load['jid'])
|
||||||
if not os.path.isdir(jid_dir):
|
if not os.path.isdir(jid_dir):
|
||||||
log.error(
|
log.error(
|
||||||
'An inconsistency occured, a job was recieved with a job id '
|
'An inconsistency occurred, a job was received with a job id '
|
||||||
'that is not present on the master: %(jid)s', load
|
'that is not present on the master: %(jid)s', load
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
@ -380,7 +381,7 @@ class MWorker(multiprocessing.Process):
|
|||||||
|
|
||||||
def _send_cluster(self):
|
def _send_cluster(self):
|
||||||
'''
|
'''
|
||||||
Send the cluser data out
|
Send the cluster data out
|
||||||
'''
|
'''
|
||||||
log.debug('Sending out cluster data')
|
log.debug('Sending out cluster data')
|
||||||
ret = self.local.cmd(self.opts['cluster_masters'],
|
ret = self.local.cmd(self.opts['cluster_masters'],
|
||||||
@ -430,7 +431,7 @@ class MWorker(multiprocessing.Process):
|
|||||||
payload['load'] = self.crypticle.dumps(load)
|
payload['load'] = self.crypticle.dumps(load)
|
||||||
context = zmq.Context(1)
|
context = zmq.Context(1)
|
||||||
pub_sock = context.socket(zmq.PUSH)
|
pub_sock = context.socket(zmq.PUSH)
|
||||||
pub_sock.connect('tcp://127.0.0.1:' + self.opts['publish_pull_port'])
|
pub_sock.connect('tcp://127.0.0.1:%(publish_pull_port)s' % self.opts)
|
||||||
pub_sock.send(salt.payload.package(payload))
|
pub_sock.send(salt.payload.package(payload))
|
||||||
return {'enc': 'clear',
|
return {'enc': 'clear',
|
||||||
'load': {'jid': jid}}
|
'load': {'jid': jid}}
|
||||||
|
@ -36,7 +36,7 @@ log = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class Minion(object):
|
class Minion(object):
|
||||||
'''
|
'''
|
||||||
This class instanciates a minion, runs connections for a minion, and loads
|
This class instantiates a minion, runs connections for a minion, and loads
|
||||||
all of the functions into the minion
|
all of the functions into the minion
|
||||||
'''
|
'''
|
||||||
def __init__(self, opts):
|
def __init__(self, opts):
|
||||||
@ -85,7 +85,7 @@ class Minion(object):
|
|||||||
|
|
||||||
def _handle_aes(self, load):
|
def _handle_aes(self, load):
|
||||||
'''
|
'''
|
||||||
Takes the aes encrypted load, decypts is and runs the encapsulated
|
Takes the aes encrypted load, decrypts is and runs the encapsulated
|
||||||
instructions
|
instructions
|
||||||
'''
|
'''
|
||||||
data = None
|
data = None
|
||||||
@ -117,24 +117,32 @@ class Minion(object):
|
|||||||
|
|
||||||
def _handle_clear(self, load):
|
def _handle_clear(self, load):
|
||||||
'''
|
'''
|
||||||
Handle unencrypted transmisions
|
Handle un-encrypted transmissions
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _handle_decoded_payload(self, data):
|
def _handle_decoded_payload(self, data):
|
||||||
'''
|
'''
|
||||||
Override this method if you wish to handle the decoded data diferently.
|
Override this method if you wish to handle the decoded data differently.
|
||||||
'''
|
'''
|
||||||
if self.opts['multiprocessing']:
|
if self.opts['multiprocessing']:
|
||||||
if type(data['fun']) == type(list()):
|
if type(data['fun']) == type(list()):
|
||||||
multiprocessing.Process(target=lambda: self._thread_multi_return(data)).start()
|
multiprocessing.Process(
|
||||||
|
target=lambda: self._thread_multi_return(data)
|
||||||
|
).start()
|
||||||
else:
|
else:
|
||||||
multiprocessing.Process(target=lambda: self._thread_return(data)).start()
|
multiprocessing.Process(
|
||||||
|
target=lambda: self._thread_return(data)
|
||||||
|
).start()
|
||||||
else:
|
else:
|
||||||
if type(data['fun']) == type(list()):
|
if type(data['fun']) == type(list()):
|
||||||
threading.Thread(target=lambda: self._thread_multi_return(data)).start()
|
threading.Thread(
|
||||||
|
target=lambda: self._thread_multi_return(data)
|
||||||
|
).start()
|
||||||
else:
|
else:
|
||||||
threading.Thread(target=lambda: self._thread_return(data)).start()
|
threading.Thread(
|
||||||
|
target=lambda: self._thread_return(data)
|
||||||
|
).start()
|
||||||
|
|
||||||
def _glob_match(self, tgt):
|
def _glob_match(self, tgt):
|
||||||
'''
|
'''
|
||||||
@ -163,7 +171,7 @@ class Minion(object):
|
|||||||
|
|
||||||
def _grain_match(self, tgt):
|
def _grain_match(self, tgt):
|
||||||
'''
|
'''
|
||||||
Reads in the grains regular expresion match
|
Reads in the grains regular expression match
|
||||||
'''
|
'''
|
||||||
comps = tgt.split(':')
|
comps = tgt.split(':')
|
||||||
return bool(re.match(comps[1], self.opts['grains'][comps[0]]))
|
return bool(re.match(comps[1], self.opts['grains'][comps[0]]))
|
||||||
@ -206,7 +214,7 @@ class Minion(object):
|
|||||||
|
|
||||||
def _thread_multi_return(self, data):
|
def _thread_multi_return(self, data):
|
||||||
'''
|
'''
|
||||||
This methos should be used as a threading target, start the actual
|
This method should be used as a threading target, start the actual
|
||||||
minion side execution.
|
minion side execution.
|
||||||
'''
|
'''
|
||||||
ret = {'return': {}}
|
ret = {'return': {}}
|
||||||
@ -262,7 +270,7 @@ class Minion(object):
|
|||||||
def authenticate(self):
|
def authenticate(self):
|
||||||
'''
|
'''
|
||||||
Authenticate with the master, this method breaks the functional
|
Authenticate with the master, this method breaks the functional
|
||||||
pardigmn, it will update the master information from a fresh sign in,
|
paradigm, it will update the master information from a fresh sign in,
|
||||||
signing in can occur as often as needed to keep up with the revolving
|
signing in can occur as often as needed to keep up with the revolving
|
||||||
master aes key.
|
master aes key.
|
||||||
'''
|
'''
|
||||||
@ -271,7 +279,7 @@ class Minion(object):
|
|||||||
while True:
|
while True:
|
||||||
creds = auth.sign_in()
|
creds = auth.sign_in()
|
||||||
if creds != 'retry':
|
if creds != 'retry':
|
||||||
log.info('Authentication with master sucessful!')
|
log.info('Authentication with master successful!')
|
||||||
break
|
break
|
||||||
log.info('Waiting for minion key to be accepted by the master.')
|
log.info('Waiting for minion key to be accepted by the master.')
|
||||||
time.sleep(10)
|
time.sleep(10)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
'''
|
'''
|
||||||
Specilized routines used by the butter cloud component
|
Specialized routines used by the butter cloud component
|
||||||
'''
|
'''
|
||||||
# Import salt modules
|
# Import salt modules
|
||||||
import virt
|
import virt
|
||||||
@ -76,7 +76,7 @@ def _gen_pin_drives(pins):
|
|||||||
|
|
||||||
def _apply_overlay(vda, instance):
|
def _apply_overlay(vda, instance):
|
||||||
'''
|
'''
|
||||||
Use libguestfs to apply the overlay inder the specified instance to the
|
Use libguestfs to apply the overlay under the specified instance to the
|
||||||
specified vda
|
specified vda
|
||||||
'''
|
'''
|
||||||
overlay = os.path.join(instance, 'overlay')
|
overlay = os.path.join(instance, 'overlay')
|
||||||
|
@ -3,6 +3,7 @@ Minion side functions for salt-cp
|
|||||||
'''
|
'''
|
||||||
# Import python libs
|
# Import python libs
|
||||||
import os
|
import os
|
||||||
|
import hashlib
|
||||||
|
|
||||||
# Import salt libs
|
# Import salt libs
|
||||||
import salt.crypt
|
import salt.crypt
|
||||||
@ -14,7 +15,7 @@ def recv(files, dest):
|
|||||||
'''
|
'''
|
||||||
Used with salt-cp, pass the files dict, and the destination.
|
Used with salt-cp, pass the files dict, and the destination.
|
||||||
|
|
||||||
This function recieves small fast copy files from the master via salt-cp
|
This function receives small fast copy files from the master via salt-cp
|
||||||
'''
|
'''
|
||||||
ret = {}
|
ret = {}
|
||||||
for path, data in files.items():
|
for path, data in files.items():
|
||||||
@ -67,7 +68,7 @@ def get_file(path, dest):
|
|||||||
def cache_files(paths):
|
def cache_files(paths):
|
||||||
'''
|
'''
|
||||||
Used to gather many files from the master, the gathered files will be
|
Used to gather many files from the master, the gathered files will be
|
||||||
saved in the minion cachedir reflective to the paths retrived from the
|
saved in the minion cachedir reflective to the paths retrieved from the
|
||||||
master.
|
master.
|
||||||
'''
|
'''
|
||||||
auth = salt.crypt.SAuth(__opts__)
|
auth = salt.crypt.SAuth(__opts__)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
'''
|
'''
|
||||||
Module for running arbitrairy tests
|
Module for running arbitrary tests
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import time
|
import time
|
||||||
@ -26,7 +26,7 @@ def ping():
|
|||||||
|
|
||||||
def fib(long num):
|
def fib(long num):
|
||||||
'''
|
'''
|
||||||
Return a fibonachi sequence up to the passed number, and the time it took
|
Return a Fibonacci sequence up to the passed number, and the time it took
|
||||||
to compute in seconds. Used for performance tests
|
to compute in seconds. Used for performance tests
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
|
@ -10,7 +10,6 @@ data
|
|||||||
import os
|
import os
|
||||||
import grp
|
import grp
|
||||||
import pwd
|
import pwd
|
||||||
import hashlib
|
|
||||||
|
|
||||||
def gid_to_group(gid):
|
def gid_to_group(gid):
|
||||||
'''
|
'''
|
||||||
@ -135,7 +134,7 @@ def set_mode(path, mode):
|
|||||||
|
|
||||||
def chown(path, user, group):
|
def chown(path, user, group):
|
||||||
'''
|
'''
|
||||||
Chown a file, pass the filem the desired user and group
|
Chown a file, pass the file the desired user and group
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
salt '*' file.chown /etc/passwd root root
|
salt '*' file.chown /etc/passwd root root
|
||||||
|
@ -6,12 +6,14 @@ import socket
|
|||||||
from string import ascii_letters, digits
|
from string import ascii_letters, digits
|
||||||
|
|
||||||
def _sanitize_host(host):
|
def _sanitize_host(host):
|
||||||
return "".join([c for c in host[0:255] if c in (ascii_letters + digits + '.')])
|
return "".join([
|
||||||
|
c for c in host[0:255] if c in (ascii_letters + digits + '.')
|
||||||
|
])
|
||||||
|
|
||||||
def ping(host):
|
def ping(host):
|
||||||
'''
|
'''
|
||||||
Performs a ping to a host
|
Performs a ping to a host
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
salt '*' network.ping archlinux.org -c 4
|
salt '*' network.ping archlinux.org -c 4
|
||||||
'''
|
'''
|
||||||
@ -25,7 +27,7 @@ def ping(host):
|
|||||||
def netstat():
|
def netstat():
|
||||||
'''
|
'''
|
||||||
Return information on open ports and states
|
Return information on open ports and states
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
salt '*' network.netstat
|
salt '*' network.netstat
|
||||||
'''
|
'''
|
||||||
@ -66,7 +68,7 @@ def netstat():
|
|||||||
def traceroute(host):
|
def traceroute(host):
|
||||||
'''
|
'''
|
||||||
Performs a traceroute to a 3rd party host
|
Performs a traceroute to a 3rd party host
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
salt '*' network.traceroute archlinux.org
|
salt '*' network.traceroute archlinux.org
|
||||||
'''
|
'''
|
||||||
@ -98,7 +100,7 @@ def traceroute(host):
|
|||||||
def dig(host):
|
def dig(host):
|
||||||
'''
|
'''
|
||||||
Performs a DNS lookup with dig
|
Performs a DNS lookup with dig
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
salt '*' network.dig archlinux.org
|
salt '*' network.dig archlinux.org
|
||||||
'''
|
'''
|
||||||
@ -112,7 +114,7 @@ def dig(host):
|
|||||||
def isportopen(host, port):
|
def isportopen(host, port):
|
||||||
'''
|
'''
|
||||||
Return status of a port
|
Return status of a port
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
salt '*' network.isportopen 127.0.0.1 22
|
salt '*' network.isportopen 127.0.0.1 22
|
||||||
'''
|
'''
|
||||||
|
@ -153,13 +153,13 @@ def upgrade():
|
|||||||
pkgs[npkg] = {'old': '',
|
pkgs[npkg] = {'old': '',
|
||||||
'new': new[npkg]}
|
'new': new[npkg]}
|
||||||
return pkgs
|
return pkgs
|
||||||
|
|
||||||
def remove(name):
|
def remove(name):
|
||||||
'''
|
'''
|
||||||
Remove a single package with pacman -R
|
Remove a single package with pacman -R
|
||||||
|
|
||||||
Return a list containing the removed packages:
|
Return a list containing the removed packages:
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
salt '*' pkg.remove <package name>
|
salt '*' pkg.remove <package name>
|
||||||
'''
|
'''
|
||||||
@ -175,7 +175,7 @@ def purge(name):
|
|||||||
with it, this will call a pacman -Rsc
|
with it, this will call a pacman -Rsc
|
||||||
|
|
||||||
Return a list containing the removed packages:
|
Return a list containing the removed packages:
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
salt '*' pkg.purge <package name>
|
salt '*' pkg.purge <package name>
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ def stop(name):
|
|||||||
def status(name, sig=None):
|
def status(name, sig=None):
|
||||||
'''
|
'''
|
||||||
Return the status for a service, returns the PID or an empty string if the
|
Return the status for a service, returns the PID or an empty string if the
|
||||||
service is running or not, pass a signiture to use to find the service via
|
service is running or not, pass a signature to use to find the service via
|
||||||
ps
|
ps
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
'''
|
'''
|
||||||
Control the state system on the minion
|
Control the state system on the minion
|
||||||
'''
|
'''
|
||||||
# Import Python modules
|
|
||||||
import os
|
|
||||||
|
|
||||||
# Import salt modules
|
# Import salt modules
|
||||||
import salt.state
|
import salt.state
|
||||||
@ -41,7 +39,7 @@ def template(tem):
|
|||||||
'''
|
'''
|
||||||
st_ = salt.state.State(__opts__)
|
st_ = salt.state.State(__opts__)
|
||||||
return st_.call_template(tem)
|
return st_.call_template(tem)
|
||||||
|
|
||||||
def template_str(tem):
|
def template_str(tem):
|
||||||
'''
|
'''
|
||||||
Execute the information stored in a template file on the minion
|
Execute the information stored in a template file on the minion
|
||||||
@ -51,4 +49,4 @@ def template_str(tem):
|
|||||||
'''
|
'''
|
||||||
st_ = salt.state.State(__opts__)
|
st_ = salt.state.State(__opts__)
|
||||||
return st_.call_template_str(tem)
|
return st_.call_template_str(tem)
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import subprocess
|
|||||||
__opts__ = {}
|
__opts__ = {}
|
||||||
|
|
||||||
def custom():
|
def custom():
|
||||||
'''
|
'''
|
||||||
Return a custom composite of status data and info for this minon,
|
Return a custom composite of status data and info for this minon,
|
||||||
based on the minion config file. An example config like might be:
|
based on the minion config file. An example config like might be:
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ def custom():
|
|||||||
|
|
||||||
This function is meant to replace all_status(), which returns
|
This function is meant to replace all_status(), which returns
|
||||||
anything and everything, which we probably don't want.
|
anything and everything, which we probably don't want.
|
||||||
|
|
||||||
By default, nothing is returned. Warning: Depending on what you
|
By default, nothing is returned. Warning: Depending on what you
|
||||||
include, there can be a LOT here!
|
include, there can be a LOT here!
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ def custom():
|
|||||||
for item in __opts__[opt]:
|
for item in __opts__[opt]:
|
||||||
ret[item] = vals[item]
|
ret[item] = vals[item]
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def uptime():
|
def uptime():
|
||||||
'''
|
'''
|
||||||
@ -59,7 +59,7 @@ def loadavg():
|
|||||||
'''
|
'''
|
||||||
comps = open('/proc/loadavg', 'r').read().strip()
|
comps = open('/proc/loadavg', 'r').read().strip()
|
||||||
load_avg = comps.split()
|
load_avg = comps.split()
|
||||||
return {
|
return {
|
||||||
'1-min': load_avg[1],
|
'1-min': load_avg[1],
|
||||||
'5-min': load_avg[2],
|
'5-min': load_avg[2],
|
||||||
'15-min': load_avg[3],
|
'15-min': load_avg[3],
|
||||||
@ -105,7 +105,7 @@ def cpustats():
|
|||||||
|
|
||||||
def meminfo():
|
def meminfo():
|
||||||
'''
|
'''
|
||||||
Return the CPU stats for this minon
|
Return the CPU stats for this minion
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
salt '*' status.meminfo
|
salt '*' status.meminfo
|
||||||
@ -125,8 +125,8 @@ def meminfo():
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
def cpuinfo():
|
def cpuinfo():
|
||||||
'''
|
'''
|
||||||
Return the CPU info for this minon
|
Return the CPU info for this minion
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
salt '*' status.cpuinfo
|
salt '*' status.cpuinfo
|
||||||
@ -142,11 +142,11 @@ def cpuinfo():
|
|||||||
ret[comps[0]] = comps[1].split()
|
ret[comps[0]] = comps[1].split()
|
||||||
else:
|
else:
|
||||||
ret[comps[0]] = comps[1].strip()
|
ret[comps[0]] = comps[1].strip()
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def diskstats():
|
def diskstats():
|
||||||
'''
|
'''
|
||||||
Return the disk stats for this minon
|
Return the disk stats for this minion
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
salt '*' status.diskstats
|
salt '*' status.diskstats
|
||||||
@ -177,7 +177,7 @@ def diskstats():
|
|||||||
|
|
||||||
def vmstats():
|
def vmstats():
|
||||||
'''
|
'''
|
||||||
Return the virtual memory stats for this minon
|
Return the virtual memory stats for this minion
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
salt '*' status.vmstats
|
salt '*' status.vmstats
|
||||||
@ -192,8 +192,8 @@ def vmstats():
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
def netstats():
|
def netstats():
|
||||||
'''
|
'''
|
||||||
Return the network stats for this minon
|
Return the network stats for this minion
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
salt '*' status.netstats
|
salt '*' status.netstats
|
||||||
@ -206,22 +206,22 @@ def netstats():
|
|||||||
continue
|
continue
|
||||||
comps = line.split()
|
comps = line.split()
|
||||||
if comps[0] == headers[0]:
|
if comps[0] == headers[0]:
|
||||||
index = len(headers) - 1
|
index = len(headers) - 1
|
||||||
row = {}
|
row = {}
|
||||||
for field in range(index):
|
for field in range(index):
|
||||||
if field < 1:
|
if field < 1:
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
row[headers[field]] = comps[field]
|
row[headers[field]] = comps[field]
|
||||||
rowname = headers[0].replace(':', '')
|
rowname = headers[0].replace(':', '')
|
||||||
ret[rowname] = row
|
ret[rowname] = row
|
||||||
else:
|
else:
|
||||||
headers = comps
|
headers = comps
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def netdev():
|
def netdev():
|
||||||
'''
|
'''
|
||||||
Return the network device stats for this minon
|
Return the network device stats for this minion
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
salt '*' status.netdev
|
salt '*' status.netdev
|
||||||
@ -256,8 +256,8 @@ def netdev():
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
def w():
|
def w():
|
||||||
'''
|
'''
|
||||||
Return a list of logged in users for this minon, using the w command
|
Return a list of logged in users for this minion, using the w command
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
salt '*' status.w
|
salt '*' status.w
|
||||||
@ -270,7 +270,7 @@ def w():
|
|||||||
if not row.count(' '):
|
if not row.count(' '):
|
||||||
continue
|
continue
|
||||||
comps = row.split()
|
comps = row.split()
|
||||||
rec = {
|
rec = {
|
||||||
'user': comps[0],
|
'user': comps[0],
|
||||||
'tty': comps[1],
|
'tty': comps[1],
|
||||||
'login': comps[2],
|
'login': comps[2],
|
||||||
@ -278,13 +278,14 @@ def w():
|
|||||||
'jcpu': comps[4],
|
'jcpu': comps[4],
|
||||||
'pcpu': comps[5],
|
'pcpu': comps[5],
|
||||||
'what': ' '.join(comps[6:]),
|
'what': ' '.join(comps[6:]),
|
||||||
}
|
}
|
||||||
user_list.append( rec )
|
user_list.append( rec )
|
||||||
return user_list
|
return user_list
|
||||||
|
|
||||||
def all_status():
|
def all_status():
|
||||||
'''
|
'''
|
||||||
Return a composite of all status data and info for this minon. Warning: There is a LOT here!
|
Return a composite of all status data and info for this minoon.
|
||||||
|
Warning: There is a LOT here!
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
salt '*' status.all_status
|
salt '*' status.all_status
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
'''
|
'''
|
||||||
Module for viewing and modifying sysctl paramters
|
Module for viewing and modifying sysctl parameters
|
||||||
'''
|
'''
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
'''
|
'''
|
||||||
Module for running arbitrairy tests
|
Module for running arbitrary tests
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import time
|
import time
|
||||||
@ -50,7 +50,7 @@ def get_opts():
|
|||||||
|
|
||||||
def fib(num):
|
def fib(num):
|
||||||
'''
|
'''
|
||||||
Return a fibonachi sequence up to the passed number, and the time it took
|
Return a Fibonacci sequence up to the passed number, and the time it took
|
||||||
to compute in seconds. Used for performance tests
|
to compute in seconds. Used for performance tests
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
'''
|
'''
|
||||||
Work with vitual machines managed by libvirt
|
Work with virtual machines managed by libvirt
|
||||||
'''
|
'''
|
||||||
# Special Thanks to Michael Dehann, many of the concepts, and a few structures
|
# Special Thanks to Michael Dehann, many of the concepts, and a few structures
|
||||||
# of his in the virt func module have been used
|
# of his in the virt func module have been used
|
||||||
@ -39,7 +39,7 @@ def __get_conn():
|
|||||||
|
|
||||||
def _get_dom(vm_):
|
def _get_dom(vm_):
|
||||||
'''
|
'''
|
||||||
Return a domain object for the named vm
|
Return a domain object for the named vm
|
||||||
'''
|
'''
|
||||||
conn = __get_conn()
|
conn = __get_conn()
|
||||||
if not list_vms().count(vm_):
|
if not list_vms().count(vm_):
|
||||||
@ -63,7 +63,7 @@ def _libvirt_creds():
|
|||||||
def list_vms():
|
def list_vms():
|
||||||
'''
|
'''
|
||||||
Return a list of virtual machine names on the minion
|
Return a list of virtual machine names on the minion
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
salt '*' virt.list_vms
|
salt '*' virt.list_vms
|
||||||
'''
|
'''
|
||||||
@ -109,7 +109,6 @@ def node_info():
|
|||||||
salt '*' virt.node_info
|
salt '*' virt.node_info
|
||||||
'''
|
'''
|
||||||
conn = __get_conn()
|
conn = __get_conn()
|
||||||
info = {}
|
|
||||||
raw = conn.getInfo()
|
raw = conn.getInfo()
|
||||||
info = {
|
info = {
|
||||||
'cpumodel' : str(raw[0]),
|
'cpumodel' : str(raw[0]),
|
||||||
@ -343,7 +342,7 @@ def migrate(vm_, target):
|
|||||||
|
|
||||||
def seed_non_shared_migrate(disks, force=False):
|
def seed_non_shared_migrate(disks, force=False):
|
||||||
'''
|
'''
|
||||||
Non shared migration reqiuires that the disks be present on the migration
|
Non shared migration requires that the disks be present on the migration
|
||||||
destination, pass the disks information via this function, to the
|
destination, pass the disks information via this function, to the
|
||||||
migration destination before executing the migration.
|
migration destination before executing the migration.
|
||||||
|
|
||||||
@ -355,7 +354,7 @@ def seed_non_shared_migrate(disks, force=False):
|
|||||||
form = data['file format']
|
form = data['file format']
|
||||||
size = data['virtual size'].split()[1][1:]
|
size = data['virtual size'].split()[1][1:]
|
||||||
if os.path.isfile(fn_) and not force:
|
if os.path.isfile(fn_) and not force:
|
||||||
# the target exists, check to see if is is compatable
|
# the target exists, check to see if is is compatible
|
||||||
pre = yaml.load(subprocess.Popen('qemu-img info arch',
|
pre = yaml.load(subprocess.Popen('qemu-img info arch',
|
||||||
shell=True,
|
shell=True,
|
||||||
stdout=subprocess.PIPE).communicate()[0])
|
stdout=subprocess.PIPE).communicate()[0])
|
||||||
@ -375,7 +374,7 @@ def seed_non_shared_migrate(disks, force=False):
|
|||||||
|
|
||||||
def destroy(vm_):
|
def destroy(vm_):
|
||||||
'''
|
'''
|
||||||
Hard power down the virtual machine, this is equivelent to pulling the
|
Hard power down the virtual machine, this is equivalent to pulling the
|
||||||
power
|
power
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
@ -405,7 +404,7 @@ def undefine(vm_):
|
|||||||
|
|
||||||
def purge(vm_, dirs=False):
|
def purge(vm_, dirs=False):
|
||||||
'''
|
'''
|
||||||
Recursively destroy and delete a virtual machine, pass True for dirs to
|
Recursively destroy and delete a virtual machine, pass True for dir's to
|
||||||
also delete the directories containing the virtual machine disk images -
|
also delete the directories containing the virtual machine disk images -
|
||||||
USE WITH EXTREAME CAUTION!
|
USE WITH EXTREAME CAUTION!
|
||||||
|
|
||||||
@ -426,7 +425,7 @@ def purge(vm_, dirs=False):
|
|||||||
def virt_type():
|
def virt_type():
|
||||||
'''
|
'''
|
||||||
Returns the virtual machine type as a string
|
Returns the virtual machine type as a string
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
salt '*' virt.virt_type
|
salt '*' virt.virt_type
|
||||||
'''
|
'''
|
||||||
|
@ -14,7 +14,7 @@ def __virtual__():
|
|||||||
|
|
||||||
def _list_removed(old, new):
|
def _list_removed(old, new):
|
||||||
'''
|
'''
|
||||||
List the pachages which have been removed between the two package objects
|
List the packages which have been removed between the two package objects
|
||||||
'''
|
'''
|
||||||
pkgs = []
|
pkgs = []
|
||||||
for pkg in old:
|
for pkg in old:
|
||||||
@ -118,13 +118,13 @@ def upgrade():
|
|||||||
pkgs[npkg] = {'old': '',
|
pkgs[npkg] = {'old': '',
|
||||||
'new': new[npkg]}
|
'new': new[npkg]}
|
||||||
return pkgs
|
return pkgs
|
||||||
|
|
||||||
def remove(pkg):
|
def remove(pkg):
|
||||||
'''
|
'''
|
||||||
Remove a single package with yum remove
|
Remove a single package with yum remove
|
||||||
|
|
||||||
Return a list containing the removed packages:
|
Return a list containing the removed packages:
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
salt '*' pkg.remove <package name>
|
salt '*' pkg.remove <package name>
|
||||||
'''
|
'''
|
||||||
@ -139,7 +139,7 @@ def purge(pkg):
|
|||||||
Yum does not have a purge, this function calls remove
|
Yum does not have a purge, this function calls remove
|
||||||
|
|
||||||
Return a list containing the removed packages:
|
Return a list containing the removed packages:
|
||||||
|
|
||||||
CLI Example:
|
CLI Example:
|
||||||
salt '*' pkg.purge <package name>
|
salt '*' pkg.purge <package name>
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
'''
|
'''
|
||||||
Return data to a redis server
|
Return data to a redis server
|
||||||
This is a VERY simple example for pushing data to a redis server and is not
|
This is a VERY simple example for pushing data to a redis server and is not
|
||||||
nessisarily intended as a usable interface.
|
necessarily intended as a usable interface.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import redis
|
import redis
|
||||||
@ -21,7 +21,7 @@ def returner(ret):
|
|||||||
host=__opts__['redis.host'],
|
host=__opts__['redis.host'],
|
||||||
port=__opts__['redis.port'],
|
port=__opts__['redis.port'],
|
||||||
db=__opts__['redis.db'])
|
db=__opts__['redis.db'])
|
||||||
serv.sadd(ret['id'] + ':' + 'jobs', ret['jid'])
|
serv.sadd("%(id)s:jobs" % ret, ret['jid'])
|
||||||
serv.set(ret['jid'] + ':' + ret['id'], json.dumps(ret['return']))
|
serv.set("%(jid)s:%(id)s" % ret, json.dumps(ret['return']))
|
||||||
serv.sadd('jobs', ret['jid'])
|
serv.sadd('jobs', ret['jid'])
|
||||||
serv.sadd(ret['jid'], ret['id'])
|
serv.sadd(ret['jid'], ret['id'])
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
'''
|
'''
|
||||||
The module used to execute states in salt. A state is unlike a module execution
|
The module used to execute states in salt. A state is unlike a module execution
|
||||||
in that instead of just executing a command it ensure that a certian state is
|
in that instead of just executing a command it ensure that a certain state is
|
||||||
present on the system.
|
present on the system.
|
||||||
|
|
||||||
The data sent to the state calls is as follows:
|
The data sent to the state calls is as follows:
|
||||||
@ -15,6 +15,7 @@ import sys
|
|||||||
import os
|
import os
|
||||||
import copy
|
import copy
|
||||||
import inspect
|
import inspect
|
||||||
|
import tempfile
|
||||||
# Import Salt modules
|
# Import Salt modules
|
||||||
import salt.loader
|
import salt.loader
|
||||||
|
|
||||||
@ -71,7 +72,7 @@ class State(object):
|
|||||||
|
|
||||||
def format_call(self, data):
|
def format_call(self, data):
|
||||||
'''
|
'''
|
||||||
Formats low data into a list of dicts used to acctually call the state,
|
Formats low data into a list of dict's used to actually call the state,
|
||||||
returns:
|
returns:
|
||||||
{
|
{
|
||||||
'full': 'module.function',
|
'full': 'module.function',
|
||||||
@ -110,7 +111,7 @@ class State(object):
|
|||||||
|
|
||||||
def compile_high_data(self, high):
|
def compile_high_data(self, high):
|
||||||
'''
|
'''
|
||||||
"Compile" the high data as it is retireved from the cli or yaml into
|
"Compile" the high data as it is retrieved from the cli or yaml into
|
||||||
the individual state executor structures
|
the individual state executor structures
|
||||||
'''
|
'''
|
||||||
chunks = []
|
chunks = []
|
||||||
@ -148,8 +149,8 @@ class State(object):
|
|||||||
|
|
||||||
def compile_template(self, template):
|
def compile_template(self, template):
|
||||||
'''
|
'''
|
||||||
Take the path to a template and return the high data structure derived from the
|
Take the path to a template and return the high data structure derived
|
||||||
template.
|
from the template.
|
||||||
'''
|
'''
|
||||||
if not os.path.isfile(template):
|
if not os.path.isfile(template):
|
||||||
return {}
|
return {}
|
||||||
@ -157,8 +158,8 @@ class State(object):
|
|||||||
|
|
||||||
def compile_template_str(self, template):
|
def compile_template_str(self, template):
|
||||||
'''
|
'''
|
||||||
Take the path to a template and return the high data structure derived from the
|
Take the path to a template and return the high data structure derived
|
||||||
template.
|
from the template.
|
||||||
'''
|
'''
|
||||||
fn_ = tempfile.mkstemp()[1]
|
fn_ = tempfile.mkstemp()[1]
|
||||||
open(fn_, 'w+').write(template)
|
open(fn_, 'w+').write(template)
|
||||||
@ -168,7 +169,8 @@ class State(object):
|
|||||||
|
|
||||||
def call(self, data):
|
def call(self, data):
|
||||||
'''
|
'''
|
||||||
Call a state directly with the low data structure, verify data before processing
|
Call a state directly with the low data structure, verify data before
|
||||||
|
processing.
|
||||||
'''
|
'''
|
||||||
ret = {'changes': None,
|
ret = {'changes': None,
|
||||||
'result': False,
|
'result': False,
|
||||||
@ -178,7 +180,7 @@ class State(object):
|
|||||||
|
|
||||||
def call_chunks(self, chunks):
|
def call_chunks(self, chunks):
|
||||||
'''
|
'''
|
||||||
Itterate over a list of chunks and call them, checking for requires.
|
Iterate over a list of chunks and call them, checking for requires.
|
||||||
'''
|
'''
|
||||||
running = {}
|
running = {}
|
||||||
for low in chunks:
|
for low in chunks:
|
||||||
|
@ -37,7 +37,7 @@ def run(name,
|
|||||||
return ret
|
return ret
|
||||||
if unless:
|
if unless:
|
||||||
if __salt__['cmd.retcode'](unless) == 0:
|
if __salt__['cmd.retcode'](unless) == 0:
|
||||||
ret['comment'] = 'unless executed sucsessfully'
|
ret['comment'] = 'unless executed successfully'
|
||||||
ret['result'] = True
|
ret['result'] = True
|
||||||
return ret
|
return ret
|
||||||
if not os.path.isdir(cwd):
|
if not os.path.isdir(cwd):
|
||||||
|
@ -3,7 +3,6 @@ Manage file states
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import hashlib
|
|
||||||
import shutil
|
import shutil
|
||||||
import tempfile
|
import tempfile
|
||||||
import difflib
|
import difflib
|
||||||
@ -170,7 +169,7 @@ def managed(name,
|
|||||||
'changes': changes,
|
'changes': changes,
|
||||||
'result': False,
|
'result': False,
|
||||||
'comment': 'Source file ' + source + ' not found'}
|
'comment': 'Source file ' + source + ' not found'}
|
||||||
# Handle any template management that is neded
|
# Handle any template management that is needed
|
||||||
if template:
|
if template:
|
||||||
t_key = '_' + template
|
t_key = '_' + template
|
||||||
if locals().has_key(t_key):
|
if locals().has_key(t_key):
|
||||||
|
@ -30,34 +30,34 @@ def daemonize():
|
|||||||
'''
|
'''
|
||||||
Daemonize a process
|
Daemonize a process
|
||||||
'''
|
'''
|
||||||
try:
|
try:
|
||||||
pid = os.fork()
|
pid = os.fork()
|
||||||
if pid > 0:
|
if pid > 0:
|
||||||
# exit first parent
|
# exit first parent
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
except OSError, e:
|
except OSError, e:
|
||||||
print >> sys.stderr, "fork #1 failed: %d (%s)" % (e.errno, e.strerror)
|
print >> sys.stderr, "fork #1 failed: %d (%s)" % (e.errno, e.strerror)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# decouple from parent environment
|
# decouple from parent environment
|
||||||
os.chdir("/")
|
os.chdir("/")
|
||||||
os.setsid()
|
os.setsid()
|
||||||
os.umask(022)
|
os.umask(022)
|
||||||
|
|
||||||
# do second fork
|
# do second fork
|
||||||
try:
|
try:
|
||||||
pid = os.fork()
|
pid = os.fork()
|
||||||
if pid > 0:
|
if pid > 0:
|
||||||
# print "Daemon PID %d" % pid
|
# print "Daemon PID %d" % pid
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
except OSError, e:
|
except OSError, e:
|
||||||
print >> sys.stderr, "fork #2 failed: %d (%s)" % (e.errno, e.strerror)
|
print >> sys.stderr, "fork #2 failed: %d (%s)" % (e.errno, e.strerror)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
dev_null = open('/dev/null','rw')
|
dev_null = open('/dev/null','rw')
|
||||||
os.dup2(dev_null.fileno(), sys.stdin.fileno())
|
os.dup2(dev_null.fileno(), sys.stdin.fileno())
|
||||||
os.dup2(dev_null.fileno(), sys.stdout.fileno())
|
os.dup2(dev_null.fileno(), sys.stdout.fileno())
|
||||||
os.dup2(dev_null.fileno(), sys.stderr.fileno())
|
os.dup2(dev_null.fileno(), sys.stderr.fileno())
|
||||||
|
|
||||||
def check_root():
|
def check_root():
|
||||||
'''
|
'''
|
||||||
@ -65,9 +65,9 @@ def check_root():
|
|||||||
verify that root is the user before the application discovers it.
|
verify that root is the user before the application discovers it.
|
||||||
'''
|
'''
|
||||||
if os.getuid():
|
if os.getuid():
|
||||||
print 'Sorry, the salt must run as root, it needs to opperate'\
|
print ('Sorry, the salt must run as root, it needs to operate '
|
||||||
+ ' in a privileged environment to do what it does.\n' \
|
'in a privileged environment to do what it does.\n'
|
||||||
+ 'http://xkcd.com/838/'
|
'http://xkcd.com/838/')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
'''
|
'''
|
||||||
Publish commands to the salt system from the command line on the master.
|
Publish commands to the salt system from the command line on the master.
|
||||||
'''
|
'''
|
||||||
# Eventually we need to be able to interlink salt masters and form quorums,
|
# Eventually we need to be able to interlink salt masters and form quorum's,
|
||||||
# and create the ability for externel systesm to talk to salt. This interface
|
# and create the ability for external systems to talk to salt. This interface
|
||||||
# is just a cli interface so that we can get this kicked off and working
|
# is just a cli interface so that we can get this kicked off and working
|
||||||
import salt.cli
|
import salt.cli
|
||||||
|
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
'''
|
'''
|
||||||
Publish commands to the salt system from the command line on the master.
|
Publish commands to the salt system from the command line on the master.
|
||||||
'''
|
'''
|
||||||
# Eventually we need to be able to interlink salt masters and form quorums,
|
# Eventually we need to be able to interlink salt masters and form quorum's,
|
||||||
# and create the ability for externel systesm to talk to salt. This interface
|
# and create the ability for external systems to talk to salt. This interface
|
||||||
# is just a cli interface so that we can get this kicked off and working
|
# is just a cli interface so that we can get this kicked off and working
|
||||||
import salt.cli
|
import salt.cli
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user