#!/usr/bin/python # # (c) 2014, Pavel Antonov # # 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 . ###################################################################### 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()