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
f07e55c5
Commit
f07e55c5
authored
Aug 18, 2012
by
Michael DeHaan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Adds 'delegate_to' as a task option which can be used to signal load balancers and outage windows.
parent
fda4f808
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
56 additions
and
27 deletions
+56
-27
CHANGELOG.md
+1
-0
lib/ansible/playbook/task.py
+10
-3
lib/ansible/runner/__init__.py
+45
-24
No files found.
CHANGELOG.md
View file @
f07e55c5
...
...
@@ -39,6 +39,7 @@ Ansible Changes By Release
*
ANSIBLE_KEEP_REMOTE_FILES=1 can be used in debugging (envrionment variable)
*
add pattern= as a paramter to the service module
*
various fixes to mysql & postresql modules
*
adds 'delegate_to' for a task, which can be used to signal outage windows and load balancers on behalf of hosts
0.
6 "Cabo" -- August 6, 2012
...
...
lib/ansible/playbook/task.py
View file @
f07e55c5
...
...
@@ -23,13 +23,15 @@ class Task(object):
__slots__
=
[
'name'
,
'action'
,
'only_if'
,
'async_seconds'
,
'async_poll_interval'
,
'notify'
,
'module_name'
,
'module_args'
,
'module_vars'
,
'play'
,
'notified_by'
,
'tags'
,
'register'
,
'with_items'
,
'first_available_file'
,
'ignore_errors'
'play'
,
'notified_by'
,
'tags'
,
'register'
,
'with_items'
,
'delegate_to'
,
'first_available_file'
,
'ignore_errors'
]
# to prevent typos and such
VALID_KEYS
=
[
'name'
,
'action'
,
'only_if'
,
'async'
,
'poll'
,
'notify'
,
'with_items'
,
'first_available_file'
,
'include'
,
'tags'
,
'register'
,
'ignore_errors'
'name'
,
'action'
,
'only_if'
,
'async'
,
'poll'
,
'notify'
,
'with_items'
,
'first_available_file'
,
'include'
,
'tags'
,
'register'
,
'ignore_errors'
,
'delegate_to'
]
def
__init__
(
self
,
play
,
ds
,
module_vars
=
None
):
...
...
@@ -63,6 +65,8 @@ class Task(object):
self
.
notify
=
ds
.
get
(
'notify'
,
[])
self
.
first_available_file
=
ds
.
get
(
'first_available_file'
,
None
)
self
.
with_items
=
ds
.
get
(
'with_items'
,
None
)
self
.
delegate_to
=
ds
.
get
(
'delegate_to'
,
None
)
self
.
ignore_errors
=
ds
.
get
(
'ignore_errors'
,
False
)
# notify can be a string or a list, store as a list
...
...
@@ -99,6 +103,9 @@ class Task(object):
self
.
with_items
=
[
]
self
.
module_vars
[
'items'
]
=
self
.
with_items
# allow runner to see delegate_to option
self
.
module_vars
[
'delegate_to'
]
=
self
.
delegate_to
# make ignore_errors accessable to Runner code
self
.
module_vars
[
'ignore_errors'
]
=
self
.
ignore_errors
...
...
lib/ansible/runner/__init__.py
View file @
f07e55c5
...
...
@@ -70,15 +70,25 @@ class ReturnData(object):
__slots__
=
[
'result'
,
'comm_ok'
,
'host'
]
def
__init__
(
self
,
host
=
None
,
result
=
None
,
comm_ok
=
True
):
self
.
host
=
host
def
__init__
(
self
,
conn
=
None
,
host
=
None
,
result
=
None
,
comm_ok
=
True
):
# which host is this ReturnData about?
if
conn
is
not
None
:
delegate_for
=
getattr
(
conn
,
'_delegate_for'
,
None
)
if
delegate_for
:
self
.
host
=
delegate_for
else
:
self
.
host
=
conn
.
host
else
:
self
.
host
=
host
self
.
result
=
result
self
.
comm_ok
=
comm_ok
if
type
(
self
.
result
)
in
[
str
,
unicode
]:
self
.
result
=
utils
.
parse_json
(
self
.
result
)
if
host
is
None
:
if
self
.
host
is
None
:
raise
Exception
(
"host not set"
)
if
type
(
self
.
result
)
!=
dict
:
raise
Exception
(
"dictionary result expected"
)
...
...
@@ -236,13 +246,13 @@ class Runner(object):
cmd
=
" "
.
join
([
str
(
x
)
for
x
in
[
remote_module_path
,
async_jid
,
async_limit
,
async_module
]])
res
=
self
.
_low_level_exec_command
(
conn
,
cmd
,
tmp
,
sudoable
=
True
)
return
ReturnData
(
host
=
conn
.
host
,
result
=
res
)
return
ReturnData
(
conn
=
conn
,
result
=
res
)
# *****************************************************
def
_execute_raw
(
self
,
conn
,
tmp
,
inject
=
None
):
''' execute a non-module command for bootstrapping, or if there's no python on a device '''
return
ReturnData
(
host
=
conn
.
host
,
result
=
dict
(
return
ReturnData
(
conn
=
conn
,
result
=
dict
(
stdout
=
self
.
_low_level_exec_command
(
conn
,
self
.
module_args
,
tmp
,
sudoable
=
True
)
))
...
...
@@ -292,7 +302,7 @@ class Runner(object):
dest
=
options
.
get
(
'dest'
,
None
)
if
(
source
is
None
and
not
'first_available_file'
in
inject
)
or
dest
is
None
:
result
=
dict
(
failed
=
True
,
msg
=
"src and dest are required"
)
return
ReturnData
(
host
=
conn
.
host
,
result
=
result
)
return
ReturnData
(
conn
=
conn
,
result
=
result
)
# if we have first_available_file in our vars
# look up the files and use the first one we find as src
...
...
@@ -306,7 +316,7 @@ class Runner(object):
break
if
not
found
:
results
=
dict
(
failed
=
True
,
msg
=
"could not find src in first_available_file list"
)
return
ReturnData
(
host
=
conn
.
host
,
results
=
results
)
return
ReturnData
(
conn
=
conn
,
results
=
results
)
source
=
utils
.
template
(
source
,
inject
)
source
=
utils
.
path_dwim
(
self
.
basedir
,
source
)
...
...
@@ -314,7 +324,7 @@ class Runner(object):
local_md5
=
utils
.
md5
(
source
)
if
local_md5
is
None
:
result
=
dict
(
failed
=
True
,
msg
=
"could not find src=
%
s"
%
source
)
return
ReturnData
(
host
=
conn
.
host
,
result
=
result
)
return
ReturnData
(
conn
=
conn
,
result
=
result
)
remote_md5
=
self
.
_remote_md5
(
conn
,
tmp
,
dest
)
...
...
@@ -334,7 +344,7 @@ class Runner(object):
else
:
# no need to transfer the file, already correct md5
result
=
dict
(
changed
=
False
,
md5sum
=
remote_md5
,
transferred
=
False
)
return
ReturnData
(
host
=
conn
.
host
,
result
=
result
)
.
daisychain
(
'file'
)
return
ReturnData
(
conn
=
conn
,
result
=
result
)
.
daisychain
(
'file'
)
# *****************************************************
...
...
@@ -347,7 +357,7 @@ class Runner(object):
dest
=
options
.
get
(
'dest'
,
None
)
if
source
is
None
or
dest
is
None
:
results
=
dict
(
failed
=
True
,
msg
=
"src and dest are required"
)
return
ReturnData
(
host
=
conn
.
host
,
result
=
results
)
return
ReturnData
(
conn
=
conn
,
result
=
results
)
# apply templating to source argument
source
=
utils
.
template
(
source
,
inject
)
...
...
@@ -365,13 +375,13 @@ class Runner(object):
# but keep going to fetch other log files
if
remote_md5
==
'0'
:
result
=
dict
(
msg
=
"unable to calculate the md5 sum of the remote file"
,
file
=
source
,
changed
=
False
)
return
ReturnData
(
host
=
conn
.
host
,
result
=
result
)
return
ReturnData
(
conn
=
conn
,
result
=
result
)
if
remote_md5
==
'1'
:
result
=
dict
(
msg
=
"the remote file does not exist, not transferring, ignored"
,
file
=
source
,
changed
=
False
)
return
ReturnData
(
host
=
conn
.
host
,
result
=
result
)
return
ReturnData
(
conn
=
conn
,
result
=
result
)
if
remote_md5
==
'2'
:
result
=
dict
(
msg
=
"no read permission on remote file, not transferring, ignored"
,
file
=
source
,
changed
=
False
)
return
ReturnData
(
host
=
conn
.
host
,
result
=
result
)
return
ReturnData
(
conn
=
conn
,
result
=
result
)
# calculate md5 sum for the local file
local_md5
=
utils
.
md5
(
dest
)
...
...
@@ -386,12 +396,12 @@ class Runner(object):
new_md5
=
utils
.
md5
(
dest
)
if
new_md5
!=
remote_md5
:
result
=
dict
(
failed
=
True
,
md5sum
=
new_md5
,
msg
=
"md5 mismatch"
,
file
=
source
)
return
ReturnData
(
host
=
conn
.
host
,
result
=
result
)
return
ReturnData
(
conn
=
conn
,
result
=
result
)
result
=
dict
(
changed
=
True
,
md5sum
=
new_md5
)
return
ReturnData
(
host
=
conn
.
host
,
result
=
result
)
return
ReturnData
(
conn
=
conn
,
result
=
result
)
else
:
result
=
dict
(
changed
=
False
,
md5sum
=
local_md5
,
file
=
source
)
return
ReturnData
(
host
=
conn
.
host
,
result
=
result
)
return
ReturnData
(
conn
=
conn
,
result
=
result
)
# *****************************************************
...
...
@@ -407,7 +417,7 @@ class Runner(object):
dest
=
options
.
get
(
'dest'
,
None
)
if
(
source
is
None
and
'first_available_file'
not
in
inject
)
or
dest
is
None
:
result
=
dict
(
failed
=
True
,
msg
=
"src and dest are required"
)
return
ReturnData
(
host
=
conn
.
host
,
comm_ok
=
False
,
result
=
result
)
return
ReturnData
(
conn
=
conn
,
comm_ok
=
False
,
result
=
result
)
# if we have first_available_file in our vars
# look up the files and use the first one we find as src
...
...
@@ -421,7 +431,7 @@ class Runner(object):
break
if
not
found
:
result
=
dict
(
failed
=
True
,
msg
=
"could not find src in first_available_file list"
)
return
ReturnData
(
host
=
conn
.
host
,
comm_ok
=
False
,
result
=
result
)
return
ReturnData
(
conn
=
conn
,
comm_ok
=
False
,
result
=
result
)
source
=
utils
.
template
(
source
,
inject
)
...
...
@@ -430,7 +440,8 @@ class Runner(object):
resultant
=
utils
.
template_from_file
(
self
.
basedir
,
source
,
inject
)
except
Exception
,
e
:
result
=
dict
(
failed
=
True
,
msg
=
str
(
e
))
return
ReturnData
(
host
=
conn
.
host
,
comm_ok
=
False
,
result
=
result
)
return
ReturnData
(
conn
=
conn
,
comm_ok
=
False
,
result
=
result
)
xfered
=
self
.
_transfer_str
(
conn
,
tmp
,
'source'
,
resultant
)
# run the copy module, queue the file module
...
...
@@ -483,8 +494,10 @@ class Runner(object):
inject
.
update
(
self
.
module_vars
)
inject
[
'hostvars'
]
=
self
.
setup_cache
items
=
self
.
module_vars
.
get
(
'items'
,
[])
# allow with_items to work in playbooks...
# apt and yum are converted into a single call, others run in a loop
items
=
self
.
module_vars
.
get
(
'items'
,
[])
if
isinstance
(
items
,
basestring
)
and
items
.
startswith
(
"$"
):
items
=
items
.
replace
(
"$"
,
""
)
if
items
in
inject
:
...
...
@@ -499,6 +512,8 @@ class Runner(object):
inject
[
'item'
]
=
","
.
join
(
items
)
items
=
[]
# logic to decide how to run things depends on whether with_items is used
if
len
(
items
)
==
0
:
return
self
.
_executor_internal_inner
(
host
,
inject
,
port
)
else
:
...
...
@@ -570,8 +585,14 @@ class Runner(object):
return
ReturnData
(
host
=
host
,
result
=
result
)
conn
=
None
actual_host
=
host
try
:
conn
=
self
.
connector
.
connect
(
host
,
port
)
delegate_to
=
inject
.
get
(
'delegate_to'
,
None
)
if
delegate_to
is
not
None
:
actual_host
=
delegate_to
conn
=
self
.
connector
.
connect
(
actual_host
,
port
)
if
delegate_to
is
not
None
:
conn
.
_delegate_for
=
host
except
errors
.
AnsibleConnectionFailed
,
e
:
result
=
dict
(
failed
=
True
,
msg
=
"FAILED:
%
s"
%
str
(
e
))
return
ReturnData
(
host
=
host
,
comm_ok
=
False
,
result
=
result
)
...
...
@@ -627,17 +648,17 @@ class Runner(object):
# no callbacks
return
result
if
'skipped'
in
data
:
self
.
callbacks
.
on_skipped
(
result
.
host
)
self
.
callbacks
.
on_skipped
(
host
)
elif
not
result
.
is_successful
():
ignore_errors
=
self
.
module_vars
.
get
(
'ignore_errors'
,
False
)
self
.
callbacks
.
on_failed
(
result
.
host
,
data
,
ignore_errors
)
self
.
callbacks
.
on_failed
(
host
,
data
,
ignore_errors
)
if
ignore_errors
:
if
'failed'
in
result
.
result
:
result
.
result
[
'failed'
]
=
False
if
'rc'
in
result
.
result
:
result
.
result
[
'rc'
]
=
0
else
:
self
.
callbacks
.
on_ok
(
result
.
host
,
data
)
self
.
callbacks
.
on_ok
(
host
,
data
)
return
result
# *****************************************************
...
...
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