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
ca2f2c4e
Commit
ca2f2c4e
authored
Jun 19, 2015
by
Toshio Kuratomi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix problem with jail and zone connection plugins and symlinks from within the jail/zone.
parent
f0777d9c
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
93 additions
and
61 deletions
+93
-61
lib/ansible/plugins/connections/jail.py
+46
-31
lib/ansible/plugins/connections/zone.py
+47
-30
No files found.
lib/ansible/plugins/connections/jail.py
View file @
ca2f2c4e
# Based on local.py (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
# Based on local.py (c) 2012, Michael DeHaan <michael.dehaan@gmail.com>
# and chroot.py (c) 2013, Maykel Moya <mmoya@speedyrails.com>
# and chroot.py (c) 2013, Maykel Moya <mmoya@speedyrails.com>
# (c) 2013, Michael Scherer <misc@zarb.org>
# (c) 2013, Michael Scherer <misc@zarb.org>
# (c) 2015, Toshio Kuratomi <tkuratomi@ansible.com>
#
#
# This file is part of Ansible
# This file is part of Ansible
#
#
...
@@ -22,14 +23,15 @@ __metaclass__ = type
...
@@ -22,14 +23,15 @@ __metaclass__ = type
import
distutils.spawn
import
distutils.spawn
import
traceback
import
traceback
import
os
import
os
import
shutil
import
subprocess
import
subprocess
from
ansible
import
errors
from
ansible
import
errors
from
ansible.callbacks
import
vvv
from
ansible.callbacks
import
vvv
import
ansible.constants
as
C
import
ansible.constants
as
C
BUFSIZE
=
4096
class
Connection
(
object
):
class
Connection
(
object
):
''' Local
chroot
based connections '''
''' Local
BSD Jail
based connections '''
def
_search_executable
(
self
,
executable
):
def
_search_executable
(
self
,
executable
):
cmd
=
distutils
.
spawn
.
find_executable
(
executable
)
cmd
=
distutils
.
spawn
.
find_executable
(
executable
)
...
@@ -81,9 +83,9 @@ class Connection(object):
...
@@ -81,9 +83,9 @@ class Connection(object):
self
.
port
=
port
self
.
port
=
port
def
connect
(
self
,
port
=
None
):
def
connect
(
self
,
port
=
None
):
''' connect to the
chroot
; nothing to do here '''
''' connect to the
jail
; nothing to do here '''
vvv
(
"THIS IS A LOCAL
CHROOT
DIR"
,
host
=
self
.
jail
)
vvv
(
"THIS IS A LOCAL
JAIL
DIR"
,
host
=
self
.
jail
)
return
self
return
self
...
@@ -95,8 +97,14 @@ class Connection(object):
...
@@ -95,8 +97,14 @@ class Connection(object):
local_cmd
=
'
%
s "
%
s"
%
s'
%
(
self
.
jexec_cmd
,
self
.
jail
,
cmd
)
local_cmd
=
'
%
s "
%
s"
%
s'
%
(
self
.
jexec_cmd
,
self
.
jail
,
cmd
)
return
local_cmd
return
local_cmd
def
exec_command
(
self
,
cmd
,
tmp_path
,
become_user
=
None
,
sudoable
=
False
,
executable
=
'/bin/sh'
,
in_data
=
None
):
def
_buffered_exec_command
(
self
,
cmd
,
tmp_path
,
become_user
=
None
,
sudoable
=
False
,
executable
=
'/bin/sh'
,
in_data
=
None
,
stdin
=
subprocess
.
PIPE
):
''' run a command on the chroot '''
''' run a command on the jail. This is only needed for implementing
put_file() get_file() so that we don't have to read the whole file
into memory.
compared to exec_command() it looses some niceties like being able to
return the process's exit code immediately.
'''
if
sudoable
and
self
.
runner
.
become
and
self
.
runner
.
become_method
not
in
self
.
become_methods_supported
:
if
sudoable
and
self
.
runner
.
become
and
self
.
runner
.
become_method
not
in
self
.
become_methods_supported
:
raise
errors
.
AnsibleError
(
"Internal Error: this module does not support running commands via
%
s"
%
self
.
runner
.
become_method
)
raise
errors
.
AnsibleError
(
"Internal Error: this module does not support running commands via
%
s"
%
self
.
runner
.
become_method
)
...
@@ -110,45 +118,52 @@ class Connection(object):
...
@@ -110,45 +118,52 @@ class Connection(object):
vvv
(
"EXEC
%
s"
%
(
local_cmd
),
host
=
self
.
jail
)
vvv
(
"EXEC
%
s"
%
(
local_cmd
),
host
=
self
.
jail
)
p
=
subprocess
.
Popen
(
local_cmd
,
shell
=
isinstance
(
local_cmd
,
basestring
),
p
=
subprocess
.
Popen
(
local_cmd
,
shell
=
isinstance
(
local_cmd
,
basestring
),
cwd
=
self
.
runner
.
basedir
,
cwd
=
self
.
runner
.
basedir
,
stdin
=
s
ubprocess
.
PIPE
,
stdin
=
s
tdin
,
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
PIPE
)
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
PIPE
)
return
p
def
exec_command
(
self
,
cmd
,
tmp_path
,
become_user
=
None
,
sudoable
=
False
,
executable
=
'/bin/sh'
,
in_data
=
None
):
''' run a command on the jail '''
p
=
self
.
_buffered_exec_command
(
cmd
,
tmp_path
,
become_user
,
sudoable
,
executable
,
in_data
)
stdout
,
stderr
=
p
.
communicate
()
stdout
,
stderr
=
p
.
communicate
()
return
(
p
.
returncode
,
''
,
stdout
,
stderr
)
return
(
p
.
returncode
,
''
,
stdout
,
stderr
)
def
_normalize_path
(
self
,
path
,
prefix
):
if
not
path
.
startswith
(
os
.
path
.
sep
):
path
=
os
.
path
.
join
(
os
.
path
.
sep
,
path
)
normpath
=
os
.
path
.
normpath
(
path
)
return
os
.
path
.
join
(
prefix
,
normpath
[
1
:])
def
_copy_file
(
self
,
in_path
,
out_path
):
if
not
os
.
path
.
exists
(
in_path
):
raise
errors
.
AnsibleFileNotFound
(
"file or module does not exist:
%
s"
%
in_path
)
try
:
shutil
.
copyfile
(
in_path
,
out_path
)
except
shutil
.
Error
:
traceback
.
print_exc
()
raise
errors
.
AnsibleError
(
"failed to copy:
%
s and
%
s are the same"
%
(
in_path
,
out_path
))
except
IOError
:
traceback
.
print_exc
()
raise
errors
.
AnsibleError
(
"failed to transfer file to
%
s"
%
out_path
)
def
put_file
(
self
,
in_path
,
out_path
):
def
put_file
(
self
,
in_path
,
out_path
):
''' transfer a file from local to
chroot
'''
''' transfer a file from local to
jail
'''
out_path
=
self
.
_normalize_path
(
out_path
,
self
.
get_jail_path
())
vvv
(
"PUT
%
s TO
%
s"
%
(
in_path
,
out_path
),
host
=
self
.
jail
)
vvv
(
"PUT
%
s TO
%
s"
%
(
in_path
,
out_path
),
host
=
self
.
jail
)
self
.
_copy_file
(
in_path
,
out_path
)
with
open
(
in_path
,
'rb'
)
as
in_file
:
p
=
self
.
_buffered_exec_command
(
'dd of=
%
s'
%
out_path
,
None
,
stdin
=
in_file
)
try
:
stdout
,
stderr
=
p
.
communicate
()
except
:
traceback
.
print_exc
()
raise
errors
.
AnsibleError
(
"failed to transfer file to
%
s"
%
out_path
)
if
p
.
returncode
!=
0
:
raise
errors
.
AnsibleError
(
"failed to transfer file to
%
s:
\n
%
s
\n
%
s"
%
(
out_path
,
stdout
,
stderr
))
def
fetch_file
(
self
,
in_path
,
out_path
):
def
fetch_file
(
self
,
in_path
,
out_path
):
''' fetch a file from
chroot
to local '''
''' fetch a file from
jail
to local '''
in_path
=
self
.
_normalize_path
(
in_path
,
self
.
get_jail_path
())
vvv
(
"FETCH
%
s TO
%
s"
%
(
in_path
,
out_path
),
host
=
self
.
jail
)
vvv
(
"FETCH
%
s TO
%
s"
%
(
in_path
,
out_path
),
host
=
self
.
jail
)
self
.
_copy_file
(
in_path
,
out_path
)
p
=
self
.
_buffered_exec_command
(
'dd if=
%
s bs=
%
s'
%
(
in_path
,
BUFSIZE
),
None
)
with
open
(
out_path
,
'wb+'
)
as
out_file
:
try
:
for
chunk
in
p
.
stdout
.
read
(
BUFSIZE
):
out_file
.
write
(
chunk
)
except
:
traceback
.
print_exc
()
raise
errors
.
AnsibleError
(
"failed to transfer file to
%
s"
%
out_path
)
stdout
,
stderr
=
p
.
communicate
()
if
p
.
returncode
!=
0
:
raise
errors
.
AnsibleError
(
"failed to transfer file to
%
s:
\n
%
s
\n
%
s"
%
(
out_path
,
stdout
,
stderr
))
def
close
(
self
):
def
close
(
self
):
''' terminate the connection; nothing to do here '''
''' terminate the connection; nothing to do here '''
...
...
lib/ansible/plugins/connections/zone.py
View file @
ca2f2c4e
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
# and chroot.py (c) 2013, Maykel Moya <mmoya@speedyrails.com>
# and chroot.py (c) 2013, Maykel Moya <mmoya@speedyrails.com>
# and jail.py (c) 2013, Michael Scherer <misc@zarb.org>
# and jail.py (c) 2013, Michael Scherer <misc@zarb.org>
# (c) 2015, Dagobert Michelsen <dam@baltic-online.de>
# (c) 2015, Dagobert Michelsen <dam@baltic-online.de>
# (c) 2015, Toshio Kuratomi <tkuratomi@ansible.com>
#
#
# This file is part of Ansible
# This file is part of Ansible
#
#
...
@@ -23,13 +24,13 @@ __metaclass__ = type
...
@@ -23,13 +24,13 @@ __metaclass__ = type
import
distutils.spawn
import
distutils.spawn
import
traceback
import
traceback
import
os
import
os
import
shutil
import
subprocess
import
subprocess
from
subprocess
import
Popen
,
PIPE
from
ansible
import
errors
from
ansible
import
errors
from
ansible.callbacks
import
vvv
from
ansible.callbacks
import
vvv
import
ansible.constants
as
C
import
ansible.constants
as
C
BUFSIZE
=
4096
class
Connection
(
object
):
class
Connection
(
object
):
''' Local zone based connections '''
''' Local zone based connections '''
...
@@ -44,7 +45,7 @@ class Connection(object):
...
@@ -44,7 +45,7 @@ class Connection(object):
cwd
=
self
.
runner
.
basedir
,
cwd
=
self
.
runner
.
basedir
,
stdin
=
subprocess
.
PIPE
,
stdin
=
subprocess
.
PIPE
,
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
PIPE
)
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
PIPE
)
#stdout, stderr = p.communicate()
zones
=
[]
zones
=
[]
for
l
in
pipe
.
stdout
.
readlines
():
for
l
in
pipe
.
stdout
.
readlines
():
# 1:work:running:/zones/work:3126dc59-9a07-4829-cde9-a816e4c5040e:native:shared
# 1:work:running:/zones/work:3126dc59-9a07-4829-cde9-a816e4c5040e:native:shared
...
@@ -97,13 +98,20 @@ class Connection(object):
...
@@ -97,13 +98,20 @@ class Connection(object):
# a modifier
# a modifier
def
_generate_cmd
(
self
,
executable
,
cmd
):
def
_generate_cmd
(
self
,
executable
,
cmd
):
if
executable
:
if
executable
:
### TODO: Why was "-c" removed from here? (vs jail.py)
local_cmd
=
[
self
.
zlogin_cmd
,
self
.
zone
,
executable
,
cmd
]
local_cmd
=
[
self
.
zlogin_cmd
,
self
.
zone
,
executable
,
cmd
]
else
:
else
:
local_cmd
=
'
%
s "
%
s"
%
s'
%
(
self
.
zlogin_cmd
,
self
.
zone
,
cmd
)
local_cmd
=
'
%
s "
%
s"
%
s'
%
(
self
.
zlogin_cmd
,
self
.
zone
,
cmd
)
return
local_cmd
return
local_cmd
def
exec_command
(
self
,
cmd
,
tmp_path
,
become_user
=
None
,
sudoable
=
False
,
executable
=
None
,
in_data
=
None
):
def
_buffered_exec_command
(
self
,
cmd
,
tmp_path
,
become_user
=
None
,
sudoable
=
False
,
executable
=
None
,
in_data
=
None
,
stdin
=
subprocess
.
PIPE
):
''' run a command on the zone '''
''' run a command on the zone. This is only needed for implementing
put_file() get_file() so that we don't have to read the whole file
into memory.
compared to exec_command() it looses some niceties like being able to
return the process's exit code immediately.
'''
if
sudoable
and
self
.
runner
.
become
and
self
.
runner
.
become_method
not
in
self
.
become_methods_supported
:
if
sudoable
and
self
.
runner
.
become
and
self
.
runner
.
become_method
not
in
self
.
become_methods_supported
:
raise
errors
.
AnsibleError
(
"Internal Error: this module does not support running commands via
%
s"
%
self
.
runner
.
become_method
)
raise
errors
.
AnsibleError
(
"Internal Error: this module does not support running commands via
%
s"
%
self
.
runner
.
become_method
)
...
@@ -112,52 +120,61 @@ class Connection(object):
...
@@ -112,52 +120,61 @@ class Connection(object):
raise
errors
.
AnsibleError
(
"Internal Error: this module does not support optimized module pipelining"
)
raise
errors
.
AnsibleError
(
"Internal Error: this module does not support optimized module pipelining"
)
# We happily ignore privilege escalation
# We happily ignore privilege escalation
if
executable
==
'/bin/sh'
:
executable
=
None
local_cmd
=
self
.
_generate_cmd
(
executable
,
cmd
)
local_cmd
=
self
.
_generate_cmd
(
executable
,
cmd
)
vvv
(
"EXEC
%
s"
%
(
local_cmd
),
host
=
self
.
zone
)
vvv
(
"EXEC
%
s"
%
(
local_cmd
),
host
=
self
.
zone
)
p
=
subprocess
.
Popen
(
local_cmd
,
shell
=
isinstance
(
local_cmd
,
basestring
),
p
=
subprocess
.
Popen
(
local_cmd
,
shell
=
isinstance
(
local_cmd
,
basestring
),
cwd
=
self
.
runner
.
basedir
,
cwd
=
self
.
runner
.
basedir
,
stdin
=
s
ubprocess
.
PIPE
,
stdin
=
s
tdin
,
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
PIPE
)
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
PIPE
)
return
p
def
exec_command
(
self
,
cmd
,
tmp_path
,
become_user
=
None
,
sudoable
=
False
,
executable
=
None
,
in_data
=
None
):
''' run a command on the zone '''
### TODO: Why all the precautions not to specify /bin/sh? (vs jail.py)
if
executable
==
'/bin/sh'
:
executable
=
None
p
=
self
.
_buffered_exec_command
(
cmd
,
tmp_path
,
become_user
,
sudoable
,
executable
,
in_data
)
stdout
,
stderr
=
p
.
communicate
()
stdout
,
stderr
=
p
.
communicate
()
return
(
p
.
returncode
,
''
,
stdout
,
stderr
)
return
(
p
.
returncode
,
''
,
stdout
,
stderr
)
def
_normalize_path
(
self
,
path
,
prefix
):
if
not
path
.
startswith
(
os
.
path
.
sep
):
path
=
os
.
path
.
join
(
os
.
path
.
sep
,
path
)
normpath
=
os
.
path
.
normpath
(
path
)
return
os
.
path
.
join
(
prefix
,
normpath
[
1
:])
def
_copy_file
(
self
,
in_path
,
out_path
):
if
not
os
.
path
.
exists
(
in_path
):
raise
errors
.
AnsibleFileNotFound
(
"file or module does not exist:
%
s"
%
in_path
)
try
:
shutil
.
copyfile
(
in_path
,
out_path
)
except
shutil
.
Error
:
traceback
.
print_exc
()
raise
errors
.
AnsibleError
(
"failed to copy:
%
s and
%
s are the same"
%
(
in_path
,
out_path
))
except
IOError
:
traceback
.
print_exc
()
raise
errors
.
AnsibleError
(
"failed to transfer file to
%
s"
%
out_path
)
def
put_file
(
self
,
in_path
,
out_path
):
def
put_file
(
self
,
in_path
,
out_path
):
''' transfer a file from local to zone '''
''' transfer a file from local to zone '''
out_path
=
self
.
_normalize_path
(
out_path
,
self
.
get_zone_path
())
vvv
(
"PUT
%
s TO
%
s"
%
(
in_path
,
out_path
),
host
=
self
.
zone
)
vvv
(
"PUT
%
s TO
%
s"
%
(
in_path
,
out_path
),
host
=
self
.
zone
)
self
.
_copy_file
(
in_path
,
out_path
)
with
open
(
in_path
,
'rb'
)
as
in_file
:
p
=
self
.
_buffered_exec_command
(
'dd of=
%
s'
%
out_path
,
None
,
stdin
=
in_file
)
try
:
stdout
,
stderr
=
p
.
communicate
()
except
:
traceback
.
print_exc
()
raise
errors
.
AnsibleError
(
"failed to transfer file to
%
s"
%
out_path
)
if
p
.
returncode
!=
0
:
raise
errors
.
AnsibleError
(
"failed to transfer file to
%
s:
\n
%
s
\n
%
s"
%
(
out_path
,
stdout
,
stderr
))
def
fetch_file
(
self
,
in_path
,
out_path
):
def
fetch_file
(
self
,
in_path
,
out_path
):
''' fetch a file from zone to local '''
''' fetch a file from zone to local '''
in_path
=
self
.
_normalize_path
(
in_path
,
self
.
get_zone_path
())
vvv
(
"FETCH
%
s TO
%
s"
%
(
in_path
,
out_path
),
host
=
self
.
zone
)
vvv
(
"FETCH
%
s TO
%
s"
%
(
in_path
,
out_path
),
host
=
self
.
zone
)
self
.
_copy_file
(
in_path
,
out_path
)
p
=
self
.
_buffered_exec_command
(
'dd if=
%
s bs=
%
s'
%
(
in_path
,
BUFSIZE
),
None
)
with
open
(
out_path
,
'wb+'
)
as
out_file
:
try
:
for
chunk
in
p
.
stdout
.
read
(
BUFSIZE
):
out_file
.
write
(
chunk
)
except
:
traceback
.
print_exc
()
raise
errors
.
AnsibleError
(
"failed to transfer file to
%
s"
%
out_path
)
stdout
,
stderr
=
p
.
communicate
()
if
p
.
returncode
!=
0
:
raise
errors
.
AnsibleError
(
"failed to transfer file to
%
s:
\n
%
s
\n
%
s"
%
(
out_path
,
stdout
,
stderr
))
def
close
(
self
):
def
close
(
self
):
''' terminate the connection; nothing to do here '''
''' terminate the connection; nothing to do here '''
...
...
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