def add_raw_rule(table, chain, rule, safe=False): """Adds rule to a fiven table/chain. :param ``str`` table: Name of the table where the chain resides. :param ``str`` chain: Name of the chain where to insert the rule. :param ``str`` rule: Raw iptables rule in the same format as "iptables -S" :param ``bool`` safe: Query iptables prior to adding to prevent duplicates """ add_cmd = ['iptables', '-t', table, '-A', chain] + rule.split() _LOGGER.info('%s', add_cmd) if safe: # Check if the rule already exists, and if it is, do nothing. list_cmd = ['iptables', '-t', table, '-S', chain] _LOGGER.info('%s', list_cmd) lines = [ line.strip() for line in subproc.check_output(list_cmd).splitlines() ] match = '-A %s %s' % (chain, rule) if match in lines: return subproc.check_call(add_cmd)
def _unmount_cgroup(name, mounts): """Remove mount points of a cgroup.""" _LOGGER.info('Unmounting cgroup %r(%r)', name, mounts) for mount in mounts: subproc.check_call( ['umount', '-vn', '-t', 'cgroup', mount] )
def flush_pt_conntrack_table(passthrough_ip): """Clear any entry in the conntrack table for a given passthrough IP. This should be run after all the forwarding rules have been removed. :param ``str`` passthrough_ip: External IP to scrub from the conntrack table. """ # This addresses the case for UDP session in particular. # # Since netfilter keeps connection state cache for 30 sec by default, udp # packets will not be routed if the same rule is recreated, rather they # will be routed to non previously associated container. # # Deleting connection state will ensure that netfilter connection tracking # works correctly. try: subproc.check_call(['conntrack', '-D', '-s', passthrough_ip]) except subproc.CalledProcessError as exc: # return code is 0 if entries were deleted, 1 if no matching # entries were found. if exc.returncode in (0, 1): pass else: raise
def validate_as_file(encoded_keytabs, basedir): """ validate keytab by given encoded data return keytab files validated """ temp_dir = tempfile.mkdtemp(dir=basedir) try: for encoded in encoded_keytabs: test_file = os.path.join(temp_dir, _NAME) keytabs2.write_keytab( test_file, encoded, ) try: subproc.check_call( ['kt_split', '--dir={}'.format(basedir), test_file]) except subproc.CalledProcessError: raise keytabs2.KeytabLockerError( 'wrong keytab data: {}'.format(encoded)) for kt_file in os.listdir(basedir): full_path = os.path.join(basedir, kt_file) # we ignore temp_dir in basedir if os.path.isdir(full_path): continue yield full_path finally: fs.rmtree_safe(temp_dir)
def mount_filesystem(block_dev, target_dir): """Mount filesystem on target directory. :param block_dev: Block device to mount """ subproc.check_call(['mount', '-n', block_dev, target_dir])
def link_set_down(devname): """Bring a network device down. :param ``str`` devname: The name of the network device. """ subproc.check_call([_IP_EXE, 'link', 'set', 'dev', devname, 'down'], )
def make_keytab(zkclient, spool_dir, host_kt=None): """Request keytabs from the locker. """ lockers = zkutils.with_retry(zkclient.get_children, z.KEYTAB_LOCKER) random.shuffle(lockers) for locker in lockers: host, port = locker.split(':') try: # put the tmp dir near the destination so they end up on # the same partition tmp_dir = tempfile.mkdtemp(dir=spool_dir) if _get_keytabs_from(host, port, tmp_dir): inputs = glob.glob(os.path.join(tmp_dir, '*')) if host_kt: inputs.append(host_kt) kt_file = os.path.join(spool_dir, 'krb5.keytab') kt_temp = os.path.join(tmp_dir, 'krb5.keytab') subproc.check_call(['kt_add', kt_temp] + inputs) os.rename(kt_temp, kt_file) break finally: shutil.rmtree(tmp_dir)
def control_svscan(scan_dir, actions): """Sends a control signal to a svscan instance.""" action_str = '-' for action in utils.get_iterable(actions): action_str += action.value subproc.check_call([_get_cmd('svscanctl'), action_str, scan_dir])
def _refresh_supervisor(self, instance_names=()): """Notify the supervisor of new instances to run.""" subproc.check_call(['s6_svscanctl', '-an', self.tm_env.running_dir]) for instance_name in instance_names: with lc.LogContext(_LOGGER, instance_name): _LOGGER.info('Starting') instance_run_link = os.path.join(self.tm_env.running_dir, instance_name) # Wait for the supervisor to pick up the new instance. for _ in range(10): res = subproc.call([ 's6_svok', instance_run_link, ]) if res == 0: break else: _LOGGER.warning('Supervisor has not picked it up yet') time.sleep(0.5) # Bring the instance up. subproc.check_call([ 's6_svc', '-uO', instance_run_link, ])
def bridge_delete(devname): """Delete a new network bridge device. :param ``str`` devname: The name of the network device. """ subproc.check_call([_BRCTL_EXE, 'delbr', devname], )
def route_add(dest, rtype='unicast', via=None, devname=None, src=None, route_scope=None): """Define a new entry in the routing table. :param ``str`` devname: The name of the network device. """ assert (rtype == 'unicast' and (devname or via)) or rtype == 'blackhole' route = [ 'ip', 'route', 'add', rtype, dest, ] if rtype == 'unicast': if via is not None: route += ['via', via] if devname is not None: route += ['dev', devname] if src is not None: route += ['src', src] if route_scope is not None: route += ['scope', route_scope] subproc.check_call(route)
def _watch_version(_data, _stat, event): """Force exit if server node is deleted.""" # If the node is deleted, we exit to pick up new version code. if event is not None and event.type == 'DELETED': # The version info not present, restart services and register # new checksum. _LOGGER.info('Upgrade requested, running: %s', cli_cmd) if cli_cmd: try: subproc.check_call(cli_cmd) # Record successful upgrade. except subprocess.CalledProcessError: _LOGGER.exception('Upgrade failed.') # Immediately trigger a watchdog timeout watchdogs.create( name='version_monitor', timeout='0s', content='Upgrade to ' '{code!r}({digest}) failed'.format(code=codepath, digest=digest), ).heartbeat() del info['digest'] _LOGGER.info('Upgrade complete.') utils.sys_exit(0) return True
def addr_add(addr, devname, ptp_addr=None, addr_scope='link'): """Add an IP address to a network device. :param ``str`` addr: IP address. :param ``str`` devname: The name of the network device. :param ``str`` ptp_addr: Peer address on Point-to-Point links. """ if ptp_addr is not None: ipaddr = [addr, 'peer', ptp_addr] else: ipaddr = [addr] subproc.check_call([ 'ip', 'addr', 'add', ] + ipaddr + [ 'dev', devname, 'scope', addr_scope, ], )
def _scan(self, scan_dir): """Tells the svscan instance to rescan the given scan dir.""" _LOGGER.debug('Scanning directory %r', scan_dir) try: subproc.check_call(['s6_svscanctl', '-a', scan_dir]) except subprocess.CalledProcessError as ex: _LOGGER.warning(ex)
def control_service(service_dir, actions, wait=None, timeout=0): """Sends a control signal to the supervised process. :returns: ``True`` - Command was successuful. ``False`` - Command timedout (only if `wait` was provided). :raises ``subproc.CalledProcessError``: With `returncode` set to `ERR_NO_SUP` if the service is not supervised. With `returncode` set to `ERR_COMMAND` if there is a problem communicating with the supervisor. """ cmd = [_get_cmd('svc')] if wait: cmd.append('-w' + _get_wait_action(wait).value) if timeout > 0: cmd.extend(['-T{}'.format(timeout)]) action_str = '-' for action in utils.get_iterable(actions): action_str += action.value cmd.append(action_str) cmd.append(service_dir) try: subproc.check_call(cmd) except subproc.CalledProcessError as err: if err.returncode == ERR_TIMEOUT: return False else: raise return True
def _scan(self): """Tells the svscan instance to rescan the directory.""" _LOGGER.debug('Scanning directory %r', self.init_dir) try: subproc.check_call(['s6-svscanctl', '-an', self.init_dir]) except subprocess.CalledProcessError as ex: _LOGGER.warning(ex)
def krbcc_ok(tkt_path): """Check if credential cache is valid (not expired).""" try: subproc.check_call(['klist', '-5', '-s', tkt_path]) return True except subproc.CalledProcessError: _LOGGER.warning('Ticket cache invalid: %s', tkt_path) return False
def _get_admin_tickets(self): """get/refresh admin tickets.""" adminktdir = tempfile.mkdtemp(prefix="ipakeytab-admin-") adminkt = "%s/krb5kt_%s" % (adminktdir, self.admin) subproc.check_call( ['kadmin.local', 'ktadd', '-k', adminkt, '-norandkey', admin]) subproc.check_call(['kinit', '-k', '-t', adminkt, admin]) shutil.rmtree(adminktdir)
def init_loopback_devices(loopdevice_numbers): """Create and initialize loopback devices.""" for i in six.moves.range(0, loopdevice_numbers): if not os.path.exists('/dev/loop%s' % i): subproc.check_call( ['mknod', '-m660', '/dev/loop%s' % i, 'b', '7', str(i)]) subproc.check_call(['chown', 'root.disk', '/dev/loop%s' % i])
def mount_tmpfs(newroot, path, size): """Mounts directory on tmpfs.""" while path.startswith('/'): path = path[1:] subproc.check_call([ 'mount', '-n', '-o', 'size=%s' % size, '-t', 'tmpfs', 'tmpfs', os.path.join(newroot, path) ])
def mount(subsystem): """Mounts cgroup subsystem.""" _LOGGER.info('Mounting cgroup: %s', subsystem) path = os.path.join(CGROOT, subsystem) if not os.path.exists(path): os.mkdir(path) subproc.check_call( ['mount', '-t', 'cgroup', '-o', subsystem, subsystem, path])
def make_keytab(kt_target, kt_components, owner=None): """Construct target keytab from individial components.""" _LOGGER.info('Creating keytab: %s %r, owner=%s', kt_target, kt_components, owner) cmd_line = ['kt_add', kt_target] + kt_components subproc.check_call(cmd_line) if owner: uid = pwd.getpwnam(owner).pw_uid os.chown(kt_target, uid, -1)
def gre_delete(grename): """Delete a GRE interface. """ subproc.check_call( [ 'ip', 'tunnel', 'del', grename, 'mode', 'gre', ], )
def make_keytab(kt_target, kt_components, owner=None): """Construct target keytab from individial components.""" _LOGGER.info('Creating keytab: %s %r, owner=%s', kt_target, kt_components, owner) cmd_line = ['kt_add', kt_target] + kt_components subproc.check_call(cmd_line) if owner: (uid, _gid) = utils.get_uid_gid(owner) os.chown(kt_target, uid, -1)
def is_down(svc_dir): """Check if service is running.""" try: subproc.check_call(['s6_svwait', '-t', '100', '-D', svc_dir]) return True except subprocess.CalledProcessError as err: # If wait timed out, the app is already running, do nothing. if err.returncode == 1: return False else: raise
def _create_root_dir(tm_env, container_dir, root_dir, app): """Prepares chrooted environment and creates all mountpoints. :param tm_env: Treadmill application environment :type tm_env: `appenv.AppEnvironment` """ # Generate a unique name for the app unique_name = appcfg.app_unique_name(app) # First wait for the block device to be ready localdisk_client = tm_env.svc_localdisk.make_client( os.path.join(container_dir, 'localdisk')) localdisk = localdisk_client.wait(unique_name) already_initialized = fs.test_filesystem(localdisk['block_dev']) if not already_initialized: # Format the block device fs.create_filesystem(localdisk['block_dev']) _LOGGER.info('Creating container root directory: %s', root_dir) fs.chroot_init(root_dir) fs.mount_filesystem(localdisk['block_dev'], root_dir) fs.make_rootfs(root_dir, app.proid) fs.configure_plugins(tm_env.root, root_dir, app) # Ensure .etc directory is clean in case of volume restore. try: shutil.rmtree(os.path.join(root_dir, '.etc')) except OSError as err: if err.errno != errno.ENOENT: raise shutil.copytree(os.path.join(tm_env.root, 'etc'), os.path.join(root_dir, '.etc')) shutil.copyfile('/etc/hosts', os.path.join(root_dir, '.etc/hosts')) shutil.copyfile('/etc/hosts', os.path.join(root_dir, '.etc/hosts.original')) hosts_aliases = os.path.join(root_dir, '.etc', 'hosts-aliases') fs.mkdir_safe(hosts_aliases) pwnam = pwd.getpwnam(app.proid) os.chown(hosts_aliases, pwnam.pw_uid, pwnam.pw_gid) # Always use our own resolv.conf. Safe to rbind, as we are running in # private mount subsystem by now. resolv_conf_path = os.path.join(tm_env.root, 'etc/resolv.conf') if os.path.exists(resolv_conf_path): subproc.check_call( ['mount', '-n', '--bind', resolv_conf_path, '/etc/resolv.conf'])
def is_supervised(service_dir): """Checks if the supervisor is running.""" try: subproc.check_call([_get_cmd('svok'), service_dir]) return True except subproc.CalledProcessError as err: # svok returns 1 when the service directory is not supervised. if err.returncode == 1: return False else: raise
def kinit_renew(tkt_path, user): """Run kinit -R against the existing CCNAME to renew the ticket.""" try: subproc.check_call(['kinit', '-R'], environ={ 'KRB5CCNAME': 'FILE:' + tkt_path, }, runas=user) _LOGGER.info('Tickets renewed successfully.') except subproc.CalledProcessError as err: _LOGGER.info('Error while renewing tickets, kinit rc: %s', err.returncode)
def bridge_delif(devname, interface): """Remove an interface from a bridge device. :param ``str`` devname: The name of the network device. """ subproc.check_call([ _BRCTL_EXE, 'delif', devname, interface, ], )
def bridge_addif(devname, interface): """Add an interface to a bridge device. :param ``str`` devname: The name of the network device. """ subproc.check_call([ _BRCTL_EXE, 'addif', devname, interface, ], )