You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
206 lines
5.4 KiB
206 lines
5.4 KiB
#!/usr/bin/python
|
|
#
|
|
|
|
# (c) 2014, Pavel Antonov <antonov@adwz.ru>
|
|
#
|
|
# This file is part of Ansible
|
|
#
|
|
# This module is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This software is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this software. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
######################################################################
|
|
|
|
DOCUMENTATION = '''
|
|
---
|
|
module: lxc_copy
|
|
author: Georg Hopp
|
|
version_added: "1.9"
|
|
short_description: copy files in an lxc
|
|
description:
|
|
- Very simple first start to copy files from host to lxc container
|
|
even in non privileged containers
|
|
options:
|
|
name:
|
|
description:
|
|
- Lxc container name to use
|
|
required: true
|
|
default: null
|
|
aliases: []
|
|
src:
|
|
description:
|
|
- Path to source file
|
|
required: true
|
|
default: null
|
|
aliases: []
|
|
dest:
|
|
description:
|
|
- Path to file in container
|
|
required: true
|
|
default: null
|
|
aliases: []
|
|
requirements: [ "lxc", "create_user_cgroup" ]
|
|
'''
|
|
|
|
EXAMPLES = '''
|
|
Copy a file from the host in the container:
|
|
|
|
- hosts: localhost
|
|
tasks:
|
|
- name: copy host file to container
|
|
lxc_copy:
|
|
name: ansible_test
|
|
src: nicefile
|
|
dest: /tmp/verynicefile
|
|
'''
|
|
|
|
try:
|
|
import lxc
|
|
import sys
|
|
import os
|
|
import json
|
|
import getpass
|
|
import hashlib
|
|
from contextlib import contextmanager
|
|
except ImportError, e:
|
|
print "failed=True msg='failed to import python module: %s'" % e
|
|
sys.exit(1)
|
|
|
|
class LxcManager:
|
|
@contextmanager
|
|
def lxc_started(self):
|
|
started = self.container.running
|
|
|
|
if not started and not self.container.running:
|
|
if (os.getuid() != 0):
|
|
uname = getpass.getuser()
|
|
subprocess.call(["create_user_cgroup"]);
|
|
for i in os.listdir('/sys/fs/cgroup'):
|
|
if (i == 'openrc'):
|
|
continue
|
|
with open('/sys/fs/cgroup/'+i+'/'+uname+'/tasks', 'a') as f:
|
|
f.write(str(os.getpid())+'\n');
|
|
|
|
self.container.start();
|
|
|
|
yield self
|
|
|
|
if not started and self.container.running:
|
|
self.container.shutdown(5)
|
|
|
|
def __init__(self, module):
|
|
self.module = module
|
|
self.name = self.module.params.get('name')
|
|
self.src = self.module.params.get('src')
|
|
self.dest = self.module.params.get('dest')
|
|
self.container = lxc.Container(self.name)
|
|
self.changed = False
|
|
self.log = []
|
|
self.error_msg = None
|
|
self.buffer_size = 20480
|
|
|
|
def get_log(self, as_string=True):
|
|
return "".join(self.log) if as_string else self.log
|
|
|
|
def _verify(self):
|
|
def work(dest):
|
|
digest = ''
|
|
try:
|
|
chk = hashlib.sha1()
|
|
with open(dest, 'r') as dfile:
|
|
data = dfile.read(self.buffer_size)
|
|
while(self.buffer_size == len(data)):
|
|
chk.update(data)
|
|
data = dfile.read(self.buffer_size)
|
|
chk.update(data)
|
|
digest = chk.hexdigest()
|
|
except:
|
|
pass
|
|
sys.stdout.write(digest)
|
|
sys.stdout.flush()
|
|
|
|
lxc_read, lxc_write = os.pipe()
|
|
|
|
pid = self.container.attach(work, self.dest, stdout=lxc_write)
|
|
os.close(lxc_write)
|
|
|
|
chk = hashlib.sha1()
|
|
with open(self.src, 'r') as dfile:
|
|
data = dfile.read(self.buffer_size)
|
|
while (self.buffer_size == len(data)):
|
|
chk.update(data)
|
|
data = dfile.read(self.buffer_size)
|
|
chk.update(data)
|
|
|
|
lxc_chk = os.read(lxc_read, 100) # read digest from container....
|
|
os.close(lxc_read)
|
|
|
|
self.files_equal = lxc_chk == chk.hexdigest()
|
|
self.local_sum = chk.hexdigest()
|
|
self.container_sum = lxc_chk
|
|
|
|
def copy(self):
|
|
with self.lxc_started():
|
|
self._verify()
|
|
if not self.files_equal:
|
|
def work(dest):
|
|
infno = sys.stdin.fileno()
|
|
with open(dest, 'w') as outfile:
|
|
data = os.read(infno, self.buffer_size)
|
|
while (self.buffer_size == len(data)):
|
|
outfile.write(data)
|
|
data = os.read(infno, self.buffer_size)
|
|
outfile.write(data)
|
|
|
|
lxc_read, lxc_write = os.pipe()
|
|
|
|
pid = self.container.attach(work, self.dest, stdin=lxc_read)
|
|
os.close(lxc_read)
|
|
|
|
with open(self.src, 'r') as infile:
|
|
data = infile.read(self.buffer_size)
|
|
while (self.buffer_size == len(data)):
|
|
os.write(lxc_write, data)
|
|
data = infile.read(self.buffer_size)
|
|
os.write(lxc_write, data)
|
|
|
|
os.close(lxc_write)
|
|
os.waitpid(pid, 0)
|
|
self.changed = True
|
|
|
|
def has_changed(self):
|
|
return self.changed
|
|
|
|
|
|
def main():
|
|
module = AnsibleModule(
|
|
argument_spec = dict(
|
|
name = dict(required=True, default=None),
|
|
src = dict(required=True, default=None),
|
|
dest = dict(required=True, default=None),
|
|
)
|
|
)
|
|
|
|
manager = LxcManager(module)
|
|
|
|
image_id = None
|
|
msg = ''
|
|
do_build = False
|
|
|
|
manager.copy()
|
|
|
|
module.exit_json(failed=False, changed=manager.has_changed(), msg="File copied")
|
|
|
|
# import module snippets
|
|
from ansible.module_utils.basic import *
|
|
if __name__ == '__main__':
|
|
main()
|