def get(self, rmthost, rmtpath, localpath, **kwargs): if unix.ishost(self._host, 'Remote') and rmthost == 'localhost': return unix.Local().remote.put(rmtpath, self._host.ip, localpath, rmtuser=kwargs.pop('rmtuser', self._host.username), **kwargs) method = kwargs.pop('method', 'scp') rmtuser = kwargs.pop('rmtuser', 'root') try: args = (rmtpath, localpath) kwargs.update(src_host=rmthost, src_user=rmtuser) return getattr(self, method)(*args, **kwargs) except AttributeError: return [False, [], ["unknown copy method '%s'" % method]]
def LXC(host): unix.isvalid(host) if not unix.ishost(host, 'Linux'): raise LXCError('this is not a Linux host') class Hypervisor(host.__class__): def __init__(self): host.__class__.__init__(self) self.__dict__.update(host.__dict__) def list_containers(self, **kwargs): def format_value(key, val): return (([v.strip() for v in val.split(',')] if val != '-' else []) if 'ipv' in key else ({'YES': True, 'NO': False}.get(val) if val in ['YES', 'NO'] else val)) kwargs.update({'fancy': True, 'fancy_format': ','.join(_FIELDS), '1': True}) status, stdout, stderr = self.execute('lxc-ls', **kwargs) if not status: raise LXCError(stderr) return {values[0]: {key: format_value(key, val) for key, val in zip(_FIELDS[1:], values[1:])} for container in stdout.splitlines()[2:] for values in [re.split('\s{2,}', container)]} @property def container(self): return Container(weakref.ref(self)()) @property def device(self): return Device(weakref.ref(self)()) class Container(object): def __init__(self, host): self._host = host def exists(self, name): return True if name in self._host.list_containers() else False def info(self, name, **kwargs): kwargs.update(name=name) status, stdout, stderr = self._host.execute('lxc-info', **kwargs) if not status: raise LXCError(stderr) return {param.lower().strip().replace(' use', ''): value.strip() for line in stdout.splitlines() for param, value in [line.split(':')]} def state(self, name): return self.info(name, state=True)['state'] def console(self, name, **kwargs): self._host.execute('lxc-console', name=name, TTY=True, INTERACTIVE=True, **kwargs) def create(self, name, tmpl_opts={}, **kwargs): def format_opt(opt, value): opt = '%s%s' % ('-' if len(opt) == 1 else '--', opt) return '%s %s' % (opt, value if isinstance(value, str) else '') tmpl_args = ' '.join(format_opt(opt, value) for opt, value in tmpl_opts.items()) with self._host.set_controls(escape_args=False): return self._host.execute('lxc-create', '--', tmpl_args, name=name, **kwargs) def destroy(self, name, **kwargs): return self._host.execute('lxc-destroy', name=name, **kwargs) def start(self, name, **kwargs): return self._host.execute('lxc-start', name=name, **kwargs) class Device: def __init__(self, host): self._host = host def add(self, name, device): return self._host.execute('lxc-device', 'add', device, n=name) return Hypervisor()
def Rpm(host, root=''): unix.isvalid(host) if unix.ishost(host, 'RpmHost'): if unix.ishost(host, 'Local'): new_host = unix.Local() else: new_host = unix.Remote() new_host.__dict__.update(host.__dict__) return Rpm(new_host, root) host = unix.linux.Linux(host, root) class RpmHost(host.__class__): def __init__(self, root=''): host.__class__.__init__(self, root) self.__dict__.update(host.__dict__) def set_hostname(self, hostname): try: self.write( '/etc/sysconfig/network', '\n'.join(( 'NETWORKING=yes', 'NETWORKING_IPV6=no', 'HOSTNAME=%s' % hostname )) ) return [True, '', ''] except IOError as ioerr: return [False, '', ioerr] def set_network(self, interfaces): network_root = '/etc/sysconfig/network-scripts' self.rm(path.join(network_root, 'ifcfg-ext')) for index, interface in enumerate(interfaces): interface_conf = [ 'DEVICE=eth%s' % index, 'BOOTPROTO=none', 'ONBOOT=yes', 'NETMASK=%s' % interface['netmask'], 'IPADDR=%s' % interface['address'], 'TYPE=Ethernet', 'USERCTL=no', 'IPV6INIT=no', 'PEERDNS=yes' ] if 'gateway' in interface: interface_conf.insert(5, 'GATEWAY=%s' % interface['gateway']) try: self.write( path.join(network_root, 'ifcfg-eth%s' % index), '\n'.join(interface_conf) ) except IOError as ioerr: return [False, '', ioerr] return [True, '', ''] def check_pkg(self, package): status, stdout = self.execute('rpm -qa')[:2] if status and stdout.find(package) != -1: return True return False def add_repository(self, filepath): return self.get(filepath, os.path.join( '/etc/yum.repos.d', os.path.basename(filepath)) ) def yum_install(self, packages, interative=True,repository=''): yum_cmd = '-y' if not repository else '-y --enablerepo=%s' % repository return self.execute( 'yum install %s %s' % (yum_cmd, ' '.join(packages)), interactive ) def yum_remove(self, packages): return self.execute('yum erase -y %s' % ' '.join(packages)) def rpm_install(self, filepath): return self.execute('rpm -U %s' % filepath) return RpmHost(root)
def Deb(host, root=''): unix.isvalid(host) if unix.ishost(host, 'DebHost'): if unix.ishost(host, 'Local'): new_host = unix.Local() else: new_host = unix.Remote() new_host.__dict__.update(host.__dict__) return Deb(new_host, root) host = unix.linux.Linux(host, root) class DebHost(host.__class__): def __init__(self, root=''): host.__class__.__init__(self, root) self.__dict__.update(host.__dict__) # Check this is a Debian-like system. @property def distribution(self): return self.execute('lsb_release -i')[1].split(':')[1].strip() @property def release(self): return self.execute('lsb_release -r')[1].split(':')[1].strip() @property def codename(self): return self.execute('lsb_release -c')[1].split(':')[1].strip() def set_hostname(self, hostname): try: self.write('/etc/hostname', hostname) return [True, '', ''] except IOError as ioerr: return [False, '', ioerr] def set_network(self, interfaces): main_conf = ['auto lo', 'iface lo inet loopback'] # For each interface, creating a configuration file interfaces_conf = [] for index, interface in enumerate(interfaces): interface_name = 'eth%s' % index interface_conf = [ 'auto %s' % interface_name, 'iface %s inet static' % interface_name, ' address %s' % interface['address'], ' netmask %s' % interface['netmask'], ] if 'gateway' in interface: interface_conf.insert( -2, ' gateway %s' % interface['gateway'] ) interfaces_conf.append(interface_conf) if self.distribution == 'Ubuntu' and float(self.release) < 11.04: for interface_conf in interfaces_conf: main_conf.append('') main_conf.extend(interface_conf) else: # Add a line main_conf.extend(['', 'source %s*' % NETCONF_DIR]) # Creating the directory where configuration files of each # interfaces are stored. output = self.mkdir(NETCONF_DIR) if not output[0]: return [False, '', output[2]] for index, interface_conf in enumerate(interfaces_conf): try: self.write( path.join(NETCONF_DIR, 'eth%s' % index), '\n'.join(interface_conf) ) except IOError as ioerr: return [False, '', ioerr] # Creating main configuration file. try: self.write(NETCONF_FILE, '\n'.join(main_conf)) except IOError as ioerr: return [False, '', ioerr] return [True, '', ''] def check_pkg(self, package): status, stdout = self.execute('dpkg -l')[:2] for line in stdout.split('\n'): if status and line.find(package) != -1 and line[0] != 'r': return True return False def add_key(self, filepath): remote_filepath = path.join('/tmp', path.basename(filepath)) self.get(filepath, remote_filepath) return self.execute('apt-key add %s' % remote_filepath) def add_repository(self, filepath): return self.get(filepath, path.join( '/etc/apt/sources.list.d', path.basename(filepath) )) def apt_update(self): return self.execute('aptitude update') def apt_install(self, packages, interactive=True): return self.execute( '%s aptitude install -y %s' % (NO_DEBCONF, ' '.join(packages)), interactive ) def apt_search(self, package, interactive=True): status, stdout, stderr = self.execute( "aptitude search %s" % package, interactive ) if status: for line in stdout.split("\n"): if line.find(package) != -1: return True return False def apt_remove(self, packages, purge=False): apt_command = 'purge -y' if purge else 'remove -y' return self.execute( '%s aptitude %s %s' % (NO_DEBCONF, apt_command, ' '.join(packages)) ) def deb_install(self, filepath, force=False): command = '-i --force-depends' if force else '-i' return self.execute('%s dpkg %s %s' % (NO_DEBCONF, command, filepath)) return DebHost(root)
def Linux(host, root=''): # Check it a valid host (ie: *Local* or *Remote*) unix.isvalid(host) if unix.ishost(host, 'LinuxHost'): if unix.ishost(host, 'Local'): new_host = unix.Local() else: new_host = unix.Remote() new_host.__dict__.update(host.__dict__) return Linux(new_host, root) class LinuxHost(host.__class__): """Inherit class from *host* and deepcopy object.""" def __init__(self, root=''): host.__class__.__init__(self) self.__dict__.update(host.__dict__) # If *root*, check that the directory contain # a valid Linux environment. self.root = root def __chroot(self): """Mount specials filesystems for having a "valid" chrooted environment. This may be needed when install a package in a chrooted environment for example.""" # Use parent (ie: Local or Remote) *execute* function. super(LinuxHost, self).execute( 'mount -t proc proc %s/proc/' % self.root ) super(LinuxHost, self).execute( 'mount -t sysfs sys %s/sys/' % self.root ) super(LinuxHost, self).execute( 'mount -o bind /dev %s/dev/' % self.root ) def __unchroot(self): """Umount specials filesystems on the chrooted environment.""" # Use parent (ie: Local or Remote) *execute* function. super(LinuxHost, self).execute('umount %s/proc/' % self.root) super(LinuxHost, self).execute('umount %s/sys/' % self.root) super(LinuxHost, self).execute('umount %s/dev/' % self.root) def execute(self, command, interactive=False, chroot=False): """Refine the *execute* wrapper function, taking into account if it must be executed in a chrooted environment. if *chroot* is given, specials filesystems (*proc*, *sys* and *dev*) are mounted before execution of the command and unmounted after. """ if chroot and self.root: self.__chroot() command = 'chroot %s %s' % (self.root, command) \ if self.root \ else command result = super(LinuxHost, self).execute(command, interactive) if chroot and self.root: self.__unchroot() return result def read(self, path, **kwargs): """Refine the *read* function, taking into account if it must be executed in a chroot environment.""" if self.root: if not os.path.isabs(path): raise IOError("'%s' is not an absolute path") path = os.path.join(self.root, path[1:]) return super(LinuxHost, self).read(path, **kwargs) def write(self, path, content, **kwargs): """Refine the *write* function, taking into account if it must be executed in a chroot environment.""" if self.root: if not os.path.isabs(path): raise IOError("'%s' is not an absolute path") path = os.path.join(self.root, path[1:]) super(LinuxHost, self).write(path, content, **kwargs) def isloaded(self, module): status, stdout, stderr = self.execute('lsmod') if not status: return False for line in stdout.split('\n')[1:-1]: if line.split()[0] == module: return True return False def load(self, module, options=()): return self.execute('modprobe %s %s' % (module, ' '.join(options))) def unload(self, module): return self.execute('modprobe -r %s' % module) def service(self, name, action, type='upstart'): return self.execute( { 'upstart': lambda: "service %s %s" % (name, action), 'init': lambda: "/etc/init.d/%s %s" % (name, action) }.get(type)() ) def set_password(self, username, password): shadow_file = '/etc/shadow' hashed_password = crypt.crypt(password, '$6$%s$' % ''.join( [random.choice(string.letters + string.digits) for i in xrange(0,8)] )) shadow_line = '%s:%s:%s:0:99999:7:::' % ( username, hashed_password, (datetime.today() - datetime(1970, 1, 1)).days ) new_content = [] in_file = False for line in self.readlines(shadow_file): if line.find(username) != -1: new_content.append(shadow_line) in_file = True else: new_content.append(line) if not in_file: new_content.append(shadow_line) try: self.write(shadow_file, '\n'.join(new_content)) return [True, '', ''] except IOError: return [False, '', ioerr] def set_hosts(self, ip, hostname, domain): try: self.write( '/etc/hosts', HOSTS_CONTENT \ .replace("$(IP)", ip) \ .replace("$(HOSTNAME)", hostname) \ .replace("$(DOMAIN)", domain) ) return [True, '', ''] except IOError as ioerr: return [False, '', ioerr] def set_sshkeys(self, algos=['rsa', 'dsa']): sshd_dir = '/etc/ssh' keys = [ os.path.join(sshd_dir, filename) \ for filename in self.listdir(sshd_dir) if 'ssh_host_' in filename ] for key in keys: output = self.execute("rm %s" % key) if not output[0]: output[2] = "Unable to remove old keys: %s" % output[2] return output for algo in algos: output = self.execute( 'ssh-keygen -N "" -t %s -f %s/ssh_host_%s_key' % ( algo, sshd_dir, algo ) ) if not output[0]: output[2] = "Unable to generate %s keys: %s" % ( algo.upper(), output[2] ) return output return [True, '', ''] return LinuxHost(root)
def LXC(host): unix.isvalid(host) if not unix.ishost(host, 'Linux'): raise LXCError('this is not a Linux host') class Hypervisor(host.__class__): def __init__(self): host.__class__.__init__(self) self.__dict__.update(host.__dict__) def list_containers(self, **kwargs): def format_value(key, val): return (([v.strip() for v in val.split(',')] if val != '-' else []) if 'ipv' in key else ({ 'YES': True, 'NO': False }.get(val) if val in ['YES', 'NO'] else val)) kwargs.update({ 'fancy': True, 'fancy_format': ','.join(_FIELDS), '1': True }) status, stdout, stderr = self.execute('lxc-ls', **kwargs) if not status: raise LXCError(stderr) return { values[0]: { key: format_value(key, val) for key, val in zip(_FIELDS[1:], values[1:]) } for container in stdout.splitlines()[2:] for values in [re.split('\s{2,}', container)] } @property def container(self): return Container(weakref.ref(self)()) @property def device(self): return Device(weakref.ref(self)()) class Container(object): def __init__(self, host): self._host = host def exists(self, name): return True if name in self._host.list_containers() else False def info(self, name, **kwargs): kwargs.update(name=name) status, stdout, stderr = self._host.execute('lxc-info', **kwargs) if not status: raise LXCError(stderr) return { param.lower().strip().replace(' use', ''): value.strip() for line in stdout.splitlines() for param, value in [line.split(':')] } def state(self, name): return self.info(name, state=True)['state'] def console(self, name, **kwargs): self._host.execute('lxc-console', name=name, TTY=True, INTERACTIVE=True, **kwargs) def create(self, name, tmpl_opts={}, **kwargs): def format_opt(opt, value): opt = '%s%s' % ('-' if len(opt) == 1 else '--', opt) return '%s %s' % (opt, value if isinstance(value, str) else '') tmpl_args = ' '.join( format_opt(opt, value) for opt, value in tmpl_opts.items()) with self._host.set_controls(escape_args=False): return self._host.execute('lxc-create', '--', tmpl_args, name=name, **kwargs) def destroy(self, name, **kwargs): return self._host.execute('lxc-destroy', name=name, **kwargs) def start(self, name, **kwargs): return self._host.execute('lxc-start', name=name, **kwargs) class Device: def __init__(self, host): self._host = host def add(self, name, device): return self._host.execute('lxc-device', 'add', device, n=name) return Hypervisor()