def create(config_path): """ create a container from config :param config_path: path to config yaml """ config = Config(config_path) base_image = config.args['image'] container_id = str(uuid.uuid4()) console.log('creating a new container (%s)' % container_id) # setup the cgroup cg = cgroups.Cgroup(container_id) if 'limit' in config.args.keys(): if 'cpu' in config.args['limit'].keys(): cg.set_cpu_limit(config.args['limit']['cpu']) if 'mem' in config.args['limit'].keys(): cg.set_memory_limit(config.args['limit']['mem']) # file system tasks console.log('Spinning up a filesystem...') fs.setup_fs(base_image, container_id) for item in config.args.get('copy', []): console.log(f'{container_id}: copying {item["src"]} to {item["dest"]}') fs.copy_to_container(item['src'], item['dest'], container_id) # run commands if applicable commands = config.args.get('run', []) environment = dict(defaults.ENVIRONMENT, **config.args.get('env', {})) if len(commands) > 0: pocket_run.run(container_id, commands, environment)
def rm(pid): """ remove a pocket with pocket id :param pid: pocket id """ cg = cgroups.Cgroup(pid) cg.delete() fs.clean_fs(pid)
def put_in_cgroup(): try: print("exec :: put_in_cgroup :: Putting process in Cgroup...") pid = os.getpid() print("exec :: put_in_cgroup :: pid={}".format(pid)) cg = cgroups.Cgroup(container_id) cg.add(pid) print("exec :: put_in_cgroup :: Successfully put process in Cgroup.") except Exception as e: print("exec :: put_in_cgroup :: Failed to put process in Cgroup.") traceback.print_exc()
def Rm(container_id, **kwargs): try: for image_id in os.listdir('/var/myOwnDocker/ps/{0}'.format(container_id)): if image_id.endswith('.log'): shutil.rm(os.path.join('/var/myOwnDocker/ps/{0}'.format(container_id), image_id)) else: subprocess.run(['btrfs', 'subvolume', 'delete', '/var/myOwnDocker/ps/{0}/{1}'.format(container_id, image_id)], check=True) cg = cgroups.Cgroup(container_id) cg.delete() print("rm :: Successfully deleted container with id {0}".format(container_id)) except Exception as e: print("rm :: Failed to delete container with id {0}".format(container_id)) traceback.print_exc() shutil.rmtree('/var/myOwnDocker/ps/{0}'.format(container_id), ignore_errors=True)
def Exec(container_id, command, **kwargs): try: containers = Ps() if container_id not in containers: raise Exception("No container with id {0}".format(container_id)) try: cg = cgroups.Cgroup(container_id) except Exception as e: raise Exception("Container with id {0} is not running".format(container_id)) def put_in_cgroup(): try: print("exec :: put_in_cgroup :: Putting process in Cgroup...") pid = os.getpid() print("exec :: put_in_cgroup :: pid={}".format(pid)) cg = cgroups.Cgroup(container_id) cg.add(pid) print("exec :: put_in_cgroup :: Successfully put process in Cgroup.") except Exception as e: print("exec :: put_in_cgroup :: Failed to put process in Cgroup.") traceback.print_exc() print("exec :: Running command {1} in container with id {0}...".format(container_id, command)) process = subprocess.run([command], preexec_fn=put_in_cgroup, universal_newlines=True, check=True, executable='/bin/bash') out, err = process.stdout, process.stderr if out is None: out = "" if err is None: err = "" with open(os.path.join('/var/myOwnDocker/ps/{0}'.format(container_id), 'out.log'), 'a') as f: f.write(out + '\n') with open(os.path.join('/var/myOwnDocker/ps/{0}'.format(container_id), 'err.log'), 'a') as f: f.write(err + '\n') print("exec :: Command {1} ran successfully in container with id {0}.".format(container_id, command)) except Exception as e: print("exec :: Failed to run command {1} in container with id {0}.".format(container_id, command)) traceback.print_exc()
def run(container_id, commands, environment=None): """ run commands in a container that has already been created :param container_id: container id :param commands: list of commands to execute :param environment: dictionary of key-value pairs """ if environment is None: environment = {} if not os.path.exists(fs.get_path_to_container(container_id)): console.error("Container does not exist") return pid = os.fork() if pid == 0: # container process console.log('Pocket starting with process-id: %d' % os.getpid()) cgroups.Cgroup(container_id).add(os.getpid()) os.chroot(fs.get_path_to_container(container_id)) os.chdir('/') unshare.unshare(unshare.CLONE_NEWUTS | unshare.CLONE_NEWNS | unshare.CLONE_NEWPID) pid2 = os.fork() if pid2 == 0: fs.mount("/proc", "/proc", "proc") os.system(f'/bin/hostname {container_id}') # execute the commands for command in commands: console.log(f'{container_id}: executing - {command}') os.execve( command.split(" ")[0], command.split(" "), environment) else: os.waitpid(pid2, 0) else: _, status = os.waitpid(pid, 0) fs.unmount(os.path.join(fs.get_path_to_container(container_id), "proc")) console.log(f'Pocket pid: {pid} exited with status {status}')
def put_in_cgroup(): try: print( "run :: put_in_cgroup :: Putting process in Cgroup..." ) pid = os.getpid() print("run :: put_in_cgroup :: pid={}".format(pid)) cg = cgroups.Cgroup(uuid) cg.add(pid) print("run :: put_in_cgroup :: Added pid in Cgroup.") pyroute2.netns.setns(netns_name) print("run :: put_in_cgroup :: Isolated NetNS.") os.chdir(new_root_path) os.chroot(new_root_path) print( "run :: put_in_cgroup :: Successfully put process in Cgroup." ) except Exception as e: print( "run :: put_in_cgroup :: Failed to put process in Cgroup." ) traceback.print_exc()
def Run(image_id, command, **kwargs): try: images = Images() if image_id not in images: raise Exception("No image with id {0}".format(image_id)) while True: uuid = ''.join(random.choices('0123456789', k=6)) containers = Ps() if uuid not in containers: break uuid_path = os.path.join('/var/myOwnDocker/ps', uuid) if not os.path.exists(uuid_path): os.makedirs(uuid_path) print("run :: Creating container with id {0}...".format(uuid)) ip = str(random.randint(100, 255)) mac = str(int(uuid[-2:])) with pyroute2.IPDB() as ipdb: veth0_name = 'veth0_{0}'.format(uuid) veth1_name = 'veth1_{0}'.format(uuid) netns_name = 'netns_{0}'.format(uuid) bridge_interface_name = 'bridge0' with ipdb.create(kind='veth', ifname=veth0_name, peer=veth1_name) as interface: interface.up() if bridge_interface_name not in ipdb.interfaces.keys(): ipdb.create(kind='bridge', ifname=bridge_interface_name).commit() interface.set_target('master', bridge_interface_name) pyroute2.netns.create(netns_name) with ipdb.interfaces[veth1_name] as veth1: veth1.net_ns_fd = netns_name ns = pyroute2.IPDB(nl=pyroute2.NetNS(netns_name)) with ns.interfaces.lo as lo: lo.up() with ns.interfaces[veth1_name] as veth1: veth1.address = "02:42:ac:11:00:{0}".format(mac) veth1.add_ip('10.0.0.{0}/24'.format(ip)) veth1.up() ns.routes.add({'dst': 'default', 'gateway': '10.0.0.1'}).commit() print("run :: Creating snapshot...") subprocess.run([ 'btrfs', 'subvolume', 'snapshot', '/var/myOwnDocker/images/{0}'.format(image_id), '/var/myOwnDocker/ps/{0}'.format(uuid) ], check=True) with open( '/var/myOwnDocker/ps/{0}/{1}/etc/resolv.conf'.format( uuid, image_id), 'w') as f: f.write('nameserver 8.8.8.8\n') with open( '/var/myOwnDocker/ps/{0}/{1}/{2}.cmd'.format( uuid, image_id, uuid), 'w') as f: f.write(command + '\n') try: print("run :: Creating Cgroup...") user = os.getlogin() cgroups.user.create_user_cgroups(user) cg = cgroups.Cgroup(uuid) cg.set_cpu_limit(50) cg.set_memory_limit(512) new_root_path = '/var/myOwnDocker/ps/{0}/{1}'.format( uuid, image_id) def put_in_cgroup(): try: print( "run :: put_in_cgroup :: Putting process in Cgroup..." ) pid = os.getpid() print("run :: put_in_cgroup :: pid={}".format(pid)) cg = cgroups.Cgroup(uuid) cg.add(pid) print("run :: put_in_cgroup :: Added pid in Cgroup.") pyroute2.netns.setns(netns_name) print("run :: put_in_cgroup :: Isolated NetNS.") os.chdir(new_root_path) os.chroot(new_root_path) print( "run :: put_in_cgroup :: Successfully put process in Cgroup." ) except Exception as e: print( "run :: put_in_cgroup :: Failed to put process in Cgroup." ) traceback.print_exc() print( "run :: Running container with id {0} and command {1}...". format(uuid, command)) process = subprocess.run([ 'unshare -fmuip --mount-proc && /bin/mount -t proc proc /proc && sleep 2 && ' + command ], preexec_fn=put_in_cgroup, universal_newlines=True, check=True, executable='/bin/bash') out, err = process.stdout, process.stderr if out is None: out = "" if err is None: err = "" with open( os.path.join('/var/myOwnDocker/ps/{0}'.format(uuid), 'out.log'), 'a') as f: f.write(out + '\n') with open( os.path.join('/var/myOwnDocker/ps/{0}'.format(uuid), 'err.log'), 'a') as f: f.write(err + '\n') print( "run :: Container with id {0} and command {1} ran successfully." .format(uuid, command)) except: print( "run :: Failed to run container with id {0} and command {1}." .format(uuid, command)) traceback.print_exc() finally: pyroute2.NetNS(netns_name).close() pyroute2.netns.remove(netns_name) ipdb.interfaces[veth0_name].remove() except Exception as e: print("run :: Failed to create container.") traceback.print_exc()
def get_cgroup(container_id): cgroup_id = get_cgroup_id(container_id) with contextlib.redirect_stderr(open(os.devnull, 'w')): return cgroups.Cgroup(cgroup_id)