Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
ansible
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OpenEdx
ansible
Commits
fc4ba46d
Commit
fc4ba46d
authored
Feb 26, 2012
by
Michael DeHaan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add a ton of comments so folks can understand what runner does. More refactoring is
certaintly possible too.
parent
c0ac0e9b
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
55 additions
and
31 deletions
+55
-31
lib/ansible/runner.py
+55
-31
No files found.
lib/ansible/runner.py
View file @
fc4ba46d
...
...
@@ -58,6 +58,7 @@ class Runner(object):
remote_pass -- provide only if you don't want to use keys or ssh-agent
'''
# save input values
self
.
host_list
=
self
.
_parse_hosts
(
host_list
)
self
.
module_path
=
module_path
self
.
module_name
=
module_name
...
...
@@ -71,18 +72,23 @@ class Runner(object):
def
_parse_hosts
(
self
,
host_list
):
''' parse the host inventory file if not sent as an array '''
# if the host list is given as a string load the host list
# from a file, one host per line
if
type
(
host_list
)
!=
list
:
host_list
=
os
.
path
.
expanduser
(
host_list
)
return
file
(
host_list
)
.
read
()
.
split
(
"
\n
"
)
return
host_list
def
_matches
(
self
,
host_name
,
pattern
=
None
):
''' returns if a hostname is matched by the pattern '''
# a pattern is in fnmatch format but more than one pattern
# can be strung together with semicolons. ex:
# atlanta-web*.example.com;dc-web*.example.com
if
host_name
==
''
:
return
False
if
not
pattern
:
pattern
=
self
.
pattern
subpatterns
=
pattern
.
split
(
";"
)
for
subpattern
in
subpatterns
:
if
fnmatch
.
fnmatch
(
host_name
,
subpattern
):
...
...
@@ -98,48 +104,66 @@ class Runner(object):
ssh
=
paramiko
.
SSHClient
()
ssh
.
set_missing_host_key_policy
(
paramiko
.
AutoAddPolicy
())
try
:
# try paramiko
ssh
.
connect
(
host
,
username
=
self
.
remote_user
,
allow_agent
=
True
,
look_for_keys
=
True
,
password
=
self
.
remote_pass
)
return
[
True
,
ssh
]
except
:
# it failed somehow, return the failure string
return
[
False
,
traceback
.
format_exc
()
]
def
_return_from_module
(
self
,
conn
,
host
,
result
):
''' helper function to handle JSON parsing of results '''
# disconnect from paramiko/SSH
conn
.
close
()
try
:
# try to parse the JSON response
return
[
host
,
True
,
json
.
loads
(
result
)
]
except
:
# it failed, say so, but return the string anyway
return
[
host
,
False
,
result
]
def
_delete_remote_files
(
self
,
conn
,
files
):
''' deletes one or more remote files '''
for
filename
in
files
:
self
.
_exec_command
(
conn
,
"rm -f
%
s"
%
filename
)
def
_transfer_file
(
self
,
conn
,
source
,
dest
):
''' transfers a remote file '''
self
.
remote_log
(
conn
,
'COPY remote:
%
s local:
%
s'
%
(
source
,
dest
))
ftp
=
conn
.
open_sftp
()
ftp
.
put
(
source
,
dest
)
ftp
.
close
()
s
ftp
=
conn
.
open_sftp
()
s
ftp
.
put
(
source
,
dest
)
s
ftp
.
close
()
def
_transfer_module
(
self
,
conn
):
'''
transfers a module file to the remote side to execute it,
but does not execute it yet
'''
outpath
=
self
.
_copy_module
(
conn
)
self
.
_exec_command
(
conn
,
"chmod +x
%
s"
%
outpath
)
return
outpath
def
_execute_module
(
self
,
conn
,
outpath
):
'''
runs a module that has already been transferred
'''
cmd
=
self
.
_command
(
outpath
)
result
=
self
.
_exec_command
(
conn
,
cmd
)
self
.
_delete_remote_files
(
conn
,
[
outpath
])
return
result
def
_execute_normal_module
(
self
,
conn
,
host
):
''' transfer a module, set it executable, and run it '''
'''
transfer & execute a module that is not 'copy' or 'template'
because those require extra work.
'''
module
=
self
.
_transfer_module
(
conn
)
result
=
self
.
_execute_module
(
conn
,
module
)
return
self
.
_return_from_module
(
conn
,
host
,
result
)
def
_parse_kv
(
self
,
args
):
''' helper function to convert a string of key/value items to a dict '''
options
=
{}
for
x
in
args
:
if
x
.
find
(
"="
)
!=
-
1
:
...
...
@@ -150,10 +174,12 @@ class Runner(object):
def
_execute_copy
(
self
,
conn
,
host
):
''' handler for file transfer operations '''
#
transfer the file to a remote tmp location
#
load up options
options
=
self
.
_parse_kv
(
self
.
module_args
)
source
=
options
[
'src'
]
dest
=
options
[
'dest'
]
# transfer the file to a remote tmp location
tmp_src
=
self
.
_get_tmp_path
(
conn
,
dest
.
split
(
"/"
)[
-
1
])
self
.
_transfer_file
(
conn
,
source
,
tmp_src
)
...
...
@@ -170,6 +196,7 @@ class Runner(object):
def
_execute_template
(
self
,
conn
,
host
):
''' handler for template operations '''
# load up options
options
=
self
.
_parse_kv
(
self
.
module_args
)
source
=
options
[
'src'
]
dest
=
options
[
'dest'
]
...
...
@@ -199,6 +226,10 @@ class Runner(object):
or a traceback string
'''
# depending on whether it's a normal module,
# or a request to use the copy or template
# module, call the appropriate executor function
ok
,
conn
=
self
.
_connect
(
host
)
if
not
ok
:
return
[
host
,
False
,
conn
]
...
...
@@ -209,19 +240,23 @@ class Runner(object):
elif
self
.
module_name
==
'template'
:
return
self
.
_execute_template
(
conn
,
host
)
else
:
# this would be a coding error in THIS module
# shouldn't occur
raise
Exception
(
"???"
)
def
_command
(
self
,
outpath
):
''' form up a command string '''
''' form up a command string
for running over SSH
'''
cmd
=
"
%
s
%
s"
%
(
outpath
,
" "
.
join
(
self
.
module_args
))
return
cmd
def
remote_log
(
self
,
conn
,
msg
):
''' this is the function we use to log things '''
stdin
,
stdout
,
stderr
=
conn
.
exec_command
(
'/usr/bin/logger -t ansible -p auth.info
%
r'
%
msg
)
# TODO: doesn't actually call logger on the remote box, should though
# TODO: maybe make that optional
def
_exec_command
(
self
,
conn
,
cmd
):
''' execute a command
over SSH
'''
''' execute a command
string over SSH, return the output
'''
msg
=
'
%
s:
%
s'
%
(
self
.
module_name
,
cmd
)
self
.
remote_log
(
conn
,
msg
)
stdin
,
stdout
,
stderr
=
conn
.
exec_command
(
cmd
)
...
...
@@ -229,11 +264,12 @@ class Runner(object):
return
results
def
_get_tmp_path
(
self
,
conn
,
file_name
):
''' gets a temporary path on a remote box '''
output
=
self
.
_exec_command
(
conn
,
"mktemp /tmp/
%
s.XXXXXX"
%
file_name
)
return
output
.
split
(
"
\n
"
)[
0
]
def
_copy_module
(
self
,
conn
):
''' transfer a module over SFTP '''
''' transfer a module over SFTP
, does not run it
'''
in_path
=
os
.
path
.
expanduser
(
os
.
path
.
join
(
self
.
module_path
,
self
.
module_name
)
)
...
...
@@ -244,17 +280,18 @@ class Runner(object):
sftp
.
close
()
return
out_path
def
match_hosts
(
self
,
pattern
=
None
):
''' return all matched hosts '''
def
match_hosts
(
self
,
pattern
):
''' return all matched hosts
fitting a pattern
'''
return
[
h
for
h
in
self
.
host_list
if
self
.
_matches
(
h
,
pattern
)
]
def
run
(
self
):
''' xfer & run module on all matched hosts '''
# find hosts that match the pattern
hosts
=
self
.
match_hosts
()
hosts
=
self
.
match_hosts
(
self
.
pattern
)
# attack pool of hosts in N forks
# _executor_hook does all of the work
hosts
=
[
(
self
,
x
)
for
x
in
hosts
]
if
self
.
forks
>
1
:
pool
=
multiprocessing
.
Pool
(
self
.
forks
)
...
...
@@ -263,7 +300,9 @@ class Runner(object):
results
=
[
_executor_hook
(
x
)
for
x
in
hosts
]
# sort hosts by ones we successfully contacted
# and ones we did not
# and ones we did not so that we can return a
# dictionary containing results of everything
results2
=
{
"contacted"
:
{},
"dark"
:
{}
...
...
@@ -278,18 +317,3 @@ class Runner(object):
return
results2
if
__name__
==
'__main__'
:
# test code...
r
=
Runner
(
host_list
=
DEFAULT_HOST_LIST
,
module_name
=
'ping'
,
module_args
=
''
,
pattern
=
'*'
,
forks
=
3
)
print
r
.
run
()
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment