def __init__(self, name, hierarchies='all', user='******'): self.name = name # Get user self.user = user if self.user == 'current': self.user = getpass.getuser() # Get hierarchies if hierarchies == 'all': hierachies = HIERARCHIES self.hierarchies = [h for h in hierachies if h in HIERARCHIES] # Get user cgroups self.user_cgroups = {} system_hierarchies = os.listdir(BASE_CGROUPS) for hierarchy in self.hierarchies: if hierarchy not in system_hierarchies: raise CgroupsException( "Hierarchy %s is not mounted" % hierarchy) user_cgroup = os.path.join(BASE_CGROUPS, hierarchy, self.user) self.user_cgroups[hierarchy] = user_cgroup create_user_cgroups(self.user, script=False) # Create name cgroups self.cgroups = {} for hierarchy, user_cgroup in self.user_cgroups.items(): cgroup = os.path.join(user_cgroup, self.name) if not os.path.exists(cgroup): os.mkdir(cgroup) self.cgroups[hierarchy] = cgroup
def __init__(self, name, hierarchies='all', user='******'): self.name = name # Get user self.user = user if self.user == 'current': self.user = getpass.getuser() # Get hierarchies if hierarchies == 'all': hierarchies = HIERARCHIES self.hierarchies = [h for h in hierarchies if h in HIERARCHIES] # Get user cgroups self.user_cgroups = {} system_hierarchies = os.listdir(BASE_CGROUPS) for hierarchy in self.hierarchies: if hierarchy not in system_hierarchies: raise CgroupsException("Hierarchy %s is not mounted" % hierarchy) user_cgroup = os.path.join(BASE_CGROUPS, hierarchy, self.user) self.user_cgroups[hierarchy] = user_cgroup create_user_cgroups(self.user, script=False) # Create name cgroups self.cgroups = {} for hierarchy, user_cgroup in self.user_cgroups.items(): cgroup = os.path.join(user_cgroup, self.name) if not os.path.exists(cgroup): os.mkdir(cgroup) self.cgroups[hierarchy] = cgroup
def setup_cgroup(name): user = pwd.getpwuid(os.getuid())[0] print(user) create_user_cgroups(user) cg = Cgroup(name) print('cgroup', cg) cg.set_cpu_limit(100) print('memory limit', cg.memory_limit) cg.set_memory_limit(600) print('memory limit', cg.memory_limit)
def run(self, *args, **kwargs): images = ImagesCommand().list_images() image_name = kwargs['<name>'] ip_last_octet = 103 # TODO : configurable match = [i[3] for i in images if i[0] == image_name][0] target_file = os.path.join(_base_dir_, match) with open(target_file) as tf: image_details = json.loads(tf.read()) # setup environment details state = json.loads(image_details['history'][0]['v1Compatibility']) # Extract information about this container env_vars = state['config']['Env'] start_cmd = subprocess.list2cmdline(state['config']['Cmd']) working_dir = state['config']['WorkingDir'] id = uuid.uuid1() # unique-ish name name = 'c_' + str(id.fields[5])[:4] # unique-ish mac mac = str(id.fields[5])[:2] layer_dir = os.path.join(_base_dir_, match.replace('.json', ''), 'layers', 'contents') with IPDB() as ipdb: veth0_name = 'veth0_'+name veth1_name = 'veth1_'+name netns_name = 'netns_'+name bridge_if_name = 'bridge0' existing_interfaces = ipdb.interfaces.keys() # Create a new virtual interface with ipdb.create(kind='veth', ifname=veth0_name, peer=veth1_name) as i1: i1.up() if bridge_if_name not in existing_interfaces: ipdb.create(kind='bridge', ifname=bridge_if_name).commit() i1.set_target('master', bridge_if_name) # Create a network namespace netns.create(netns_name) # move the bridge interface into the new namespace with ipdb.interfaces[veth1_name] as veth1: veth1.net_ns_fd = netns_name # Use this network namespace as the database ns = IPDB(nl=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_last_octet)) veth1.up() ns.routes.add({ 'dst': 'default', 'gateway': '10.0.0.1'}).commit() try: # setup cgroup directory for this user user = os.getlogin() create_user_cgroups(user) # First we create the cgroup and we set it's cpu and memory limits cg = Cgroup(name) cg.set_cpu_limit(50) # TODO : get these as command line options cg.set_memory_limit(500) # Then we a create a function to add a process in the cgroup def in_cgroup(): try: pid = os.getpid() cg = Cgroup(name) for env in env_vars: log.info('Setting ENV %s' % env) os.putenv(*env.split('=', 1)) # Set network namespace netns.setns(netns_name) # add process to cgroup cg.add(pid) os.chroot(layer_dir) if working_dir != '': log.info("Setting working directory to %s" % working_dir) os.chdir(working_dir) except Exception as e: traceback.print_exc() log.error("Failed to preexecute function") log.error(e) cmd = start_cmd log.info('Running "%s"' % cmd) process = subprocess.Popen(cmd, preexec_fn=in_cgroup, shell=True) process.wait() print(process.stdout) log.error(process.stderr) except Exception as e: traceback.print_exc() log.error(e) finally: log.info('Finalizing') NetNS(netns_name).close() netns.remove(netns_name) ipdb.interfaces[veth0_name].remove() log.info('done')
def run(self, *args, **kwargs): images = ImagesCommand().list_images() image_name = kwargs['<name>'] ip_last_octet = 103 # TODO : configurable match = [i[3] for i in images if i[0] == image_name][0] target_file = os.path.join(_base_dir_, match) with open(target_file) as tf: image_details = json.loads(tf.read()) # setup environment details state = json.loads(image_details['history'][0]['v1Compatibility']) # Extract information about this container env_vars = state['config']['Env'] start_cmd = subprocess.list2cmdline(state['config']['Cmd']) working_dir = state['config']['WorkingDir'] id = uuid.uuid1() # unique-ish name name = 'c_' + str(id.fields[5])[:4] # unique-ish mac mac = str(id.fields[5])[:2] layer_dir = os.path.join(_base_dir_, match.replace('.json', ''), 'layers', 'contents') with IPDB() as ipdb: veth0_name = 'veth0_' + name veth1_name = 'veth1_' + name netns_name = 'netns_' + name bridge_if_name = 'bridge0' existing_interfaces = ipdb.interfaces.keys() # Create a new virtual interface with ipdb.create(kind='veth', ifname=veth0_name, peer=veth1_name) as i1: i1.up() if bridge_if_name not in existing_interfaces: ipdb.create(kind='bridge', ifname=bridge_if_name).commit() i1.set_target('master', bridge_if_name) # Create a network namespace netns.create(netns_name) # move the bridge interface into the new namespace with ipdb.interfaces[veth1_name] as veth1: veth1.net_ns_fd = netns_name # Use this network namespace as the database ns = IPDB(nl=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_last_octet)) veth1.up() ns.routes.add({'dst': 'default', 'gateway': '10.0.0.1'}).commit() try: # setup cgroup directory for this user user = os.getlogin() create_user_cgroups(user) # First we create the cgroup and we set it's cpu and memory limits cg = Cgroup(name) cg.set_cpu_limit( 50) # TODO : get these as command line options cg.set_memory_limit(500) # Then we a create a function to add a process in the cgroup def in_cgroup(): try: pid = os.getpid() cg = Cgroup(name) for env in env_vars: log.info('Setting ENV %s' % env) os.putenv(*env.split('=', 1)) # Set network namespace netns.setns(netns_name) # add process to cgroup cg.add(pid) os.chroot(layer_dir) if working_dir != '': log.info("Setting working directory to %s" % working_dir) os.chdir(working_dir) except Exception as e: traceback.print_exc() log.error("Failed to preexecute function") log.error(e) cmd = start_cmd log.info('Running "%s"' % cmd) process = subprocess.Popen(cmd, preexec_fn=in_cgroup, shell=True) process.wait() print(process.stdout) log.error(process.stderr) except Exception as e: traceback.print_exc() log.error(e) finally: log.info('Finalizing') NetNS(netns_name).close() netns.remove(netns_name) ipdb.interfaces[veth0_name].remove() log.info('done')
def main(): parser = argparse.ArgumentParser( prog="cgc", description="cli tool for managing processes using Control Groups Linux mechanism" ) parser.add_argument( '-v', '--verbose', dest='verbose', action='store', help='verbose actions level (DEBUG,INFO,WARN), default=INFO', default="INFO", ) parser.add_argument( 'action', choices=('useradd','run','cgadd','addpid','rmpid','cgls','frz','ufrz'), help="action to do", ) parser.add_argument( '--command', dest='command', action='store', type=str, help='command to run with some cgroup configuration', default=None, ) parser.add_argument( '--no-swap', dest='no_swap', action='store_true', help='run command with swap memmory limit set to 0 bytes' ) parser.add_argument( '--cpu', dest='cpu', action='store', type=int, help='run command with some percent of cpu-resource', default=None, ) parser.add_argument( '--mem', dest='mem', action='store', type=int, help='run command with memory limit', default=None ) parser.add_argument( '--cgroup', dest='cgroup', action='store', type=str, help='cgroup name', default=None, ) parser.add_argument( '--user', dest='user', action='store', help='username to grant privileges to use cgroups', default=None, ) args = parser.parse_args() print (args) # Logging formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') logstream = logging.StreamHandler() logstream.setFormatter(formatter) logger.addHandler(logstream) if args.verbose == 'DEBUG': logger.setLevel(logging.DEBUG) elif args.verbose == 'INFO': logger.setLevel(logging.INFO) elif args.verbose == 'WARN': logger.setLevel(logging.WARN) else: logger.setLevel(logging.ERROR) logger.debug('Logging level: %s' % args.verbose) print (args) if args.action == "run": print ("runing command {}".format(args.command)) run_command_with_cgroups_options(args.command,cpu=args.cpu,mem=args.mem,swapless=args.no_swap if args.no_swap else False,cgroup=args.cgroup) elif args.action == "useradd": print ("adding user {}".format(args.user)) create_user_cgroups(args.user)