def prepare(self, conn): mnt_point = tempfile.mkdtemp(dir='/tmp') export_path = "%s:%s" % ( self.poolArgs['source']['host'], self.poolArgs['source']['path']) mount_cmd = ["mount", "-o", 'soft,timeo=100,retrans=3,retry=0', export_path, mnt_point] umount_cmd = ["umount", "-f", export_path] mounted = False # 2 seconds looks like a reasonable time to wait for a refresh # in the UI and enough time to verify that the NFS server # is down. cmd_timeout = 2 with RollbackContext() as rollback: rollback.prependDefer(os.rmdir, mnt_point) try: run_command(mount_cmd, cmd_timeout) rollback.prependDefer(run_command, umount_cmd, cmd_timeout) except TimeoutExpired: raise InvalidParameter("KCHPOOL0012E", {'path': export_path}) with open("/proc/mounts", "rb") as f: rawMounts = f.read() output_items = ['dev_path', 'mnt_point', 'type'] mounts = parse_cmd_output(rawMounts, output_items) for item in mounts: if 'dev_path' in item and item['dev_path'] == export_path: mounted = True if not mounted: raise InvalidParameter("KCHPOOL0013E", {'path': export_path})
def _has_sudo(self, result): _master, slave = pty.openpty() os.setsid() fcntl.ioctl(slave, termios.TIOCSCTTY, 0) out, err, exit = run_command(['sudo', '-l', '-U', self.user[USER_NAME], 'sudo']) if exit == 0: debug("User %s is allowed to run sudo" % self.user[USER_NAME]) # sudo allows a wide range of configurations, such as controlling # which binaries the user can execute with sudo. # For now, we will just check whether the user is allowed to run # any command with sudo. out, err, exit = run_command(['sudo', '-l', '-U', self.user[USER_NAME]]) for line in out.split('\n'): if line and re.search("(ALL)", line): result.value = 1 debug("User %s can run any command with sudo" % result.value) return debug("User %s can only run some commands with sudo" % self.user[USER_NAME]) else: debug("User %s is not allowed to run sudo" % self.user[USER_NAME])
def _has_sudo(self, result): result.value = False _master, slave = pty.openpty() os.setsid() fcntl.ioctl(slave, termios.TIOCSCTTY, 0) out, err, exit = run_command( ['sudo', '-l', '-U', self.user[USER_NAME], 'sudo']) if exit == 0: debug("User %s is allowed to run sudo" % self.user[USER_NAME]) # sudo allows a wide range of configurations, such as controlling # which binaries the user can execute with sudo. # For now, we will just check whether the user is allowed to run # any command with sudo. out, err, exit = run_command( ['sudo', '-l', '-U', self.user[USER_NAME]]) for line in out.split('\n'): if line and re.search("(ALL)", line): result.value = True debug("User %s can run any command with sudo" % result.value) return debug("User %s can only run some commands with sudo" % self.user[USER_NAME]) else: debug("User %s is not allowed to run sudo" % self.user[USER_NAME])
def prepare(self, conn): mnt_point = tempfile.mkdtemp(dir='/tmp') export_path = "%s:%s" % ( self.poolArgs['source']['host'], self.poolArgs['source']['path']) mount_cmd = ["mount", "-o", 'soft,timeo=100,retrans=3,retry=0', export_path, mnt_point] umount_cmd = ["umount", "-f", export_path] mounted = False # Due to an NFS bug (See Red Hat BZ 1023059), NFSv4 exports may take # 10-15 seconds to mount the first time. cmd_timeout = 15 with RollbackContext() as rollback: rollback.prependDefer(os.rmdir, mnt_point) try: run_command(mount_cmd, cmd_timeout) rollback.prependDefer(run_command, umount_cmd, cmd_timeout) except TimeoutExpired: raise InvalidParameter("KCHPOOL0012E", {'path': export_path}) with open("/proc/mounts", "rb") as f: rawMounts = f.read() output_items = ['dev_path', 'mnt_point', 'type'] mounts = parse_cmd_output(rawMounts, output_items) for item in mounts: if 'dev_path' in item and item['dev_path'] == export_path: mounted = True if not mounted: raise InvalidParameter("KCHPOOL0013E", {'path': export_path})
def update(self, name, params): """ Update/add a subscription machine at IBM SEP tool. """ # check if the hostname to update is the same of the current # subscription and unsubscribe it if not - we are working with # only one subscription at the moment. if ((self._activation_info['hostname'] != '') and (params['hostname'] != self._activation_info['hostname'])): cmd = ['/opt/ibm/seprovider/bin/unsubscribe', '-h', self._activation_info['hostname']] output, error, rc = run_command(cmd) if rc != 0: kimchi_log.error('SEP execution error: %s - %s - %s' % (cmd, rc, error)) raise OperationFailed('GINSEP0004E', {'cmd': cmd, 'rc': rc, 'error': error}) # update the current subscription info, or add a new one. cmd = ['/opt/ibm/seprovider/bin/subscribe', '-h', params['hostname'], '-p', params['port'], '-c', params['community']] output, error, rc = run_command(cmd) if rc != 0: kimchi_log.error('SEP execution error: %s - %s - %s' % (cmd, rc, error)) raise OperationFailed('GINSEP0004E', {'cmd': cmd, 'rc': rc, 'error': error}) self._sep_status = 'running'
def update(self, name, params): if detect_live_vm(): kimchi_log.error('Cannot update system fw while running VMs.') raise OperationFailed('GINFW0001E') fw_path = params['path'] pow_ok = params.get('overwrite-perm-ok', True) # First unpack the rpm to get the fw img file # FIXME: When there's a .deb package available, add support for that command = ['rpm', '-U', '--force', '--ignoreos', fw_path] output, error, rc = run_command(command) if rc: # rpm returns num failed pkgs on failure or neg for unknown raise OperationFailed('GINFW0002E', {'rc': rc, 'err': error}) # The image file should now be in /tmp/fwupdate/ # and match the rpm name. image_file, ext = os.path.splitext(os.path.basename(fw_path)) if image_file is None: kimchi_log.error('FW update failed: ' 'No image file found in the package file.') raise OperationFailed('GINFW0003E') command = ['update_flash', '-f', os.path.join('/tmp/fwupdate', '%s.img' % image_file)] if not pow_ok: command.insert(1, '-n') kimchi_log.info('FW update: System will reboot to flash the firmware.') output, error, rc = run_command(command) if rc: raise OperationFailed('GINFW0004E', {'rc': rc})
def prepare(self, conn): mnt_point = tempfile.mkdtemp(dir='/tmp') export_path = "%s:%s" % (self.poolArgs['source']['host'], self.poolArgs['source']['path']) mount_cmd = [ "mount", "-o", 'soft,timeo=100,retrans=3,retry=0', export_path, mnt_point ] umount_cmd = ["umount", "-f", export_path] mounted = False # Due to an NFS bug (See Red Hat BZ 1023059), NFSv4 exports may take # 10-15 seconds to mount the first time. cmd_timeout = 15 with RollbackContext() as rollback: rollback.prependDefer(os.rmdir, mnt_point) try: run_command(mount_cmd, cmd_timeout) rollback.prependDefer(run_command, umount_cmd, cmd_timeout) except TimeoutExpired: raise InvalidParameter("KCHPOOL0012E", {'path': export_path}) with open("/proc/mounts", "rb") as f: rawMounts = f.read() output_items = ['dev_path', 'mnt_point', 'type'] mounts = parse_cmd_output(rawMounts, output_items) for item in mounts: if 'dev_path' in item and item['dev_path'] == export_path: mounted = True if not mounted: raise InvalidParameter("KCHPOOL0013E", {'path': export_path})
def prepare(self, conn): mnt_point = tempfile.mkdtemp(dir='/tmp') export_path = "%s:%s" % (self.poolArgs['source']['host'], self.poolArgs['source']['path']) mount_cmd = [ "mount", "-o", 'soft,timeo=100,retrans=3,retry=0', export_path, mnt_point ] umount_cmd = ["umount", "-f", export_path] mounted = False # 2 seconds looks like a reasonable time to wait for a refresh # in the UI and enough time to verify that the NFS server # is down. cmd_timeout = 2 with RollbackContext() as rollback: rollback.prependDefer(os.rmdir, mnt_point) try: run_command(mount_cmd, cmd_timeout) rollback.prependDefer(run_command, umount_cmd, cmd_timeout) except TimeoutExpired: raise InvalidParameter("KCHPOOL0012E", {'path': export_path}) with open("/proc/mounts", "rb") as f: rawMounts = f.read() output_items = ['dev_path', 'mnt_point', 'type'] mounts = parse_cmd_output(rawMounts, output_items) for item in mounts: if 'dev_path' in item and item['dev_path'] == export_path: mounted = True if not mounted: raise InvalidParameter("KCHPOOL0013E", {'path': export_path})
def update(self, name, params): if detect_live_vm(): kimchi_log.error('Cannot update system fw while running VMs.') raise OperationFailed('GINFW0001E') fw_path = params['path'] pow_ok = params.get('overwrite-perm-ok', True) # First unpack the rpm to get the fw img file # FIXME: When there's a .deb package available, add support for that command = ['rpm', '-U', '--force', '--ignoreos', fw_path] output, error, rc = run_command(command) if rc: # rpm returns num failed pkgs on failure or neg for unknown raise OperationFailed('GINFW0002E', {'rc': rc, 'err': error}) # The image file should now be in /tmp/fwupdate/ # and match the rpm name. image_file, ext = os.path.splitext(os.path.basename(fw_path)) if image_file is None: kimchi_log.error('FW update failed: ' 'No image file found in the package file.') raise OperationFailed('GINFW0003E') command = [ 'update_flash', '-f', os.path.join('/tmp/fwupdate', '%s.img' % image_file) ] if not pow_ok: command.insert(1, '-n') kimchi_log.info('FW update: System will reboot to flash the firmware.') output, error, rc = run_command(command) if rc: raise OperationFailed('GINFW0004E', {'rc': rc})
def _update_lvm_disks(self, pool_name, disks): # check if all the disks/partitions exists in the host for disk in disks: lsblk_cmd = ['lsblk', disk] output, error, returncode = run_command(lsblk_cmd) if returncode != 0: kimchi_log.error( '%s is not a valid disk/partition. Could not ' 'add it to the pool %s.', disk, pool_name) raise OperationFailed('KCHPOOL0027E', { 'disk': disk, 'pool': pool_name }) # add disks to the lvm pool using vgextend + virsh refresh vgextend_cmd = ["vgextend", pool_name] vgextend_cmd += disks output, error, returncode = run_command(vgextend_cmd) if returncode != 0: msg = "Could not add disks to pool %s, error: %s" kimchi_log.error(msg, pool_name, error) raise OperationFailed('KCHPOOL0028E', { 'pool': pool_name, 'err': error }) # refreshing pool state pool = self.get_storagepool(pool_name, self.conn) if pool.isActive(): pool.refresh(0)
def __init__(self, **kargs): self.guest_threads_enabled = False self.sockets = 0 self.cores_present = 0 self.cores_available = 0 self.cores_per_socket = 0 self.threads_per_core = 0 self.max_threads = 0 self.conn = kargs['conn'] libvirt_topology = None try: connect = self.conn.get() libvirt_topology = get_topo_capabilities(connect) except Exception as e: kimchi_log.info("Unable to get CPU topology capabilities: %s" % e.message) return if libvirt_topology is None: kimchi_log.info("cpu_info topology not supported.") return if ARCH == 'power': # IBM PowerPC self.guest_threads_enabled = True out, error, rc = run_command(['ppc64_cpu', '--smt']) if rc or 'on' in out: # SMT has to be disabled for guest to use threads as CPUs. # rc is always zero, whether SMT is off or on. self.guest_threads_enabled = False out, error, rc = run_command(['ppc64_cpu', '--cores-present']) if not rc: self.cores_present = int(out.split()[-1]) out, error, rc = run_command(['ppc64_cpu', '--cores-on']) if not rc: self.cores_available = int(out.split()[-1]) out, error, rc = run_command(['ppc64_cpu', '--threads-per-core']) if not rc: self.threads_per_core = int(out.split()[-1]) self.sockets = self.cores_present/self.threads_per_core if self.sockets == 0: self.sockets = 1 self.cores_per_socket = self.cores_present/self.sockets else: # Intel or AMD self.guest_threads_enabled = True self.sockets = int(libvirt_topology.get('sockets')) self.cores_per_socket = int(libvirt_topology.get('cores')) self.cores_present = self.cores_per_socket * self.sockets self.cores_available = self.cores_present self.threads_per_core = int(libvirt_topology.get('threads'))
def __init__(self, **kargs): self.guest_threads_enabled = False self.sockets = 0 self.cores_present = 0 self.cores_available = 0 self.cores_per_socket = 0 self.threads_per_core = 0 self.max_threads = 0 self.conn = kargs['conn'] libvirt_topology = None try: connect = self.conn.get() libvirt_topology = get_topo_capabilities(connect) except Exception as e: kimchi_log.info("Unable to get CPU topology capabilities: %s" % e.message) return if libvirt_topology is None: kimchi_log.info("cpu_info topology not supported.") return if ARCH == 'power': # IBM PowerPC self.guest_threads_enabled = True out, error, rc = run_command(['ppc64_cpu', '--smt']) if rc or 'on' in out: # SMT has to be disabled for guest to use threads as CPUs. # rc is always zero, whether SMT is off or on. self.guest_threads_enabled = False out, error, rc = run_command(['ppc64_cpu', '--cores-present']) if not rc: self.cores_present = int(out.split()[-1]) out, error, rc = run_command(['ppc64_cpu', '--cores-on']) if not rc: self.cores_available = int(out.split()[-1]) out, error, rc = run_command(['ppc64_cpu', '--threads-per-core']) if not rc: self.threads_per_core = int(out.split()[-1]) self.sockets = self.cores_present / self.threads_per_core if self.sockets == 0: self.sockets = 1 self.cores_per_socket = self.cores_present / self.sockets else: # Intel or AMD self.guest_threads_enabled = True self.sockets = int(libvirt_topology.get('sockets')) self.cores_per_socket = int(libvirt_topology.get('cores')) self.cores_present = self.cores_per_socket * self.sockets self.cores_available = self.cores_present self.threads_per_core = int(libvirt_topology.get('threads'))
def _validate_pci_passthrough_env(): # Linux kernel < 3.5 doesn't provide /sys/kernel/iommu_groups if os.path.isdir('/sys/kernel/iommu_groups'): if not glob.glob('/sys/kernel/iommu_groups/*'): raise InvalidOperation("KCHVMHDEV0003E") # Enable virt_use_sysfs on RHEL6 and older distributions # In recent Fedora, there is no virt_use_sysfs. out, err, rc = run_command(['getsebool', 'virt_use_sysfs']) if rc == 0 and out.rstrip('\n') != "virt_use_sysfs --> on": out, err, rc = run_command( ['setsebool', '-P', 'virt_use_sysfs=on']) if rc != 0: kimchi_log.warning("Unable to turn on sebool virt_use_sysfs")
def _validate_pci_passthrough_env(): # Linux kernel < 3.5 doesn't provide /sys/kernel/iommu_groups if os.path.isdir('/sys/kernel/iommu_groups'): if not glob.glob('/sys/kernel/iommu_groups/*'): raise InvalidOperation("KCHVMHDEV0003E") # Enable virt_use_sysfs on RHEL6 and older distributions # In recent Fedora, there is no virt_use_sysfs. out, err, rc = run_command(['getsebool', 'virt_use_sysfs']) if rc == 0 and out.rstrip('\n') != "virt_use_sysfs --> on": out, err, rc = run_command(['setsebool', '-P', 'virt_use_sysfs=on']) if rc != 0: kimchi_log.warning("Unable to turn on sebool virt_use_sysfs")
def _get_subscriber(self): activation_info = [] entry = {} cmd = ['/opt/ibm/seprovider/bin/getSubscriber'] output, error, rc = run_command(cmd) # no subscriber: return empty if rc == 1: return activation_info # error: report if rc != 0: kimchi_log.error('SEP execution error: %s - %s - %s' % (cmd, rc, error)) raise OperationFailed('GINSEP0007E') if len(output) > 1: # iterate over lines and parse to dict for line in output.splitlines(): if len(line) > 0: entry = SUBSCRIBER.search(line).groupdict() activation_info.append(entry["hostname"]) return activation_info
def stop(self, params=None): cmd = ['systemctl', 'stop', 'sepctl'] output, error, rc = run_command(cmd) if rc != 0: kimchi_log.error('Error stopping SEP service: %s - %s - %s' % (cmd, rc, error)) raise OperationFailed('GINSEP0009E', {'error': error})
def start(self, params=None): cmd = ['systemctl', 'start', 'sepctl'] output, error, rc = run_command(cmd) if rc != 0: kimchi_log.error('SEP service initialization error: %s - %s - %s' % (cmd, rc, error)) raise OperationFailed('GINSEP0008E', {'error': error})
def _peer_deregister(self): cmd = ["slptool", "deregister", "service:kimchid://%s" % self.url] out, error, ret = run_command(cmd) if out and len(out) != 0: kimchi_log.error("Unable to deregister server on openSLP." " Details: %s" % out)
def __init__(self): # This stores all packages to be updated for Kimchi perspective. It's a # dictionary of dictionaries, in the format {'package_name': package}, # where: # package = {'package_name': <string>, 'version': <string>, # 'arch': <string>, 'repository': <string> # } self._packages = {} # This stores the number of packages to update self._num2update = 0 # Get the distro of host machine and creates an object related to # correct package management system try: __import__('yum') kimchi_log.info("Loading YumUpdate features.") self._pkg_mnger = YumUpdate() except ImportError: try: __import__('apt') kimchi_log.info("Loading AptUpdate features.") self._pkg_mnger = AptUpdate() except ImportError: zypper_help = ["zypper", "--help"] (stdout, stderr, returncode) = run_command(zypper_help) if returncode == 0: kimchi_log.info("Loading ZypperUpdate features.") self._pkg_mnger = ZypperUpdate() else: raise Exception("There is no compatible package manager " "for this system.")
def _set_default_gateway(self, gateway): old_route = self._get_default_route_entry() if old_route is None: old_gateway, old_iface = None, None else: old_gateway, old_iface = old_route.gateway, old_route.dev _, err, rc = run_command(['ip', 'route', 'del', 'default']) if rc and not ('No such process' in err): raise OperationFailed('GINNET0010E', {'reason': err}) _, err, rc = run_command(['ip', 'route', 'add', 'default', 'via', gateway]) if rc: raise OperationFailed('GINNET0011E', {'reason': err}) self._save_gateway_changes(old_iface, old_gateway)
def lookup(self, subscription): """ Returns a dictionary with all SEP information. """ cmd = ['/opt/ibm/seprovider/bin/getSubscriber'] output, error, rc = run_command(cmd) # error: report if rc != 0: kimchi_log.error('SEP execution error: %s - %s - %s' % (cmd, rc, error)) raise OperationFailed('GINSEP0005E', {'error': error}) if len(output) > 1: # iterate over lines and parse to dict for line in output.splitlines(): if len(line) > 0: entry = SUBSCRIBER.search(line).groupdict() # subscriber found if entry["hostname"] == subscription: return entry raise NotFoundError("GINSEP0006E", {'hostname': subscription})
def parse_hdds(temperature_unit): # hddtemp will strangely convert a non-number (see error case # below) to 32 deg F. So just always ask for C and convert later. out, error, rc = run_command(['hddtemp']) if rc: kimchi_log.error("Error retrieving HD temperatures: rc %s." "output: %s" % (rc, error)) return None hdds = OrderedDict() for hdd in out.splitlines(): hdd_name = '' hdd_temp = 0.0 try: hdd_items = hdd.split(':') hdd_name, hdd_temp = hdd_items[0], hdd_items[2] hdd_temp = re.sub('°[C|F]', '', hdd_temp).strip() except Exception as e: kimchi_log.error('Sensors hdd parse error: %s' % e.message) continue try: # Try to convert the number to a float. If it fails, # don't add this disk to the list. hdd_temp = float(hdd_temp) if (temperature_unit == 'F'): hdd_temp = 9.0 / 5.0 * hdd_temp + 32 hdds[hdd_name] = hdd_temp except ValueError: # If no sensor data, parse float will fail. For example: # "/dev/sda: IBM IPR-10 5D831200: S.M.A.R.T. not available" kimchi_log.warning("Sensors hdd: %s" % hdd) hdds['unit'] = temperature_unit return hdds
def parse_hdds(temperature_unit): # hddtemp will strangely convert a non-number (see error case # below) to 32 deg F. So just always ask for C and convert later. out, error, rc = run_command(['hddtemp']) if rc: kimchi_log.error("Error retrieving HD temperatures: rc %s." "output: %s" % (rc, error)) return None hdds = OrderedDict() for hdd in out.splitlines(): hdd_name = '' hdd_temp = 0.0 try: hdd_items = hdd.split(':') hdd_name, hdd_temp = hdd_items[0], hdd_items[2] hdd_temp = re.sub('°[C|F]', '', hdd_temp).strip() except Exception as e: kimchi_log.error('Sensors hdd parse error: %s' % e.message) continue try: # Try to convert the number to a float. If it fails, # don't add this disk to the list. hdd_temp = float(hdd_temp) if(temperature_unit == 'F'): hdd_temp = 9.0/5.0 * hdd_temp + 32 hdds[hdd_name] = hdd_temp except ValueError: # If no sensor data, parse float will fail. For example: # "/dev/sda: IBM IPR-10 5D831200: S.M.A.R.T. not available" kimchi_log.warning("Sensors hdd: %s" % hdd) hdds['unit'] = temperature_unit return hdds
def reject(self, name): command = ['update_flash', '-r'] output, error, rc = run_command(command) if rc: raise OperationFailed('GINFW0006E', {'rc': rc}) # update_flash returns a message on success, so log it. kimchi_log.info(output)
def _set_default_gateway(self, gateway): old_route = self._get_default_route_entry() if old_route is None: old_gateway, old_iface = None, None else: old_gateway, old_iface = old_route.gateway, old_route.dev _, err, rc = run_command(['ip', 'route', 'del', 'default']) if rc and not ('No such process' in err): raise OperationFailed('GINNET0010E', {'reason': err}) _, err, rc = run_command( ['ip', 'route', 'add', 'default', 'via', gateway]) if rc: raise OperationFailed('GINNET0011E', {'reason': err}) self._save_gateway_changes(old_iface, old_gateway)
def sosreport_generate(cb, name): try: command = ['sosreport', '--batch', '--name=%s' % name] output, error, retcode = run_command(command) if retcode < 0: raise OperationFailed("KCHDR0003E", {'name': name, 'err': retcode}) elif retcode > 0: raise OperationFailed("KCHDR0003E", {'name': name, 'err': retcode}) # SOSREPORT might create file in /tmp or /var/tmp # FIXME: The right way should be passing the tar.xz file directory # though the parameter '--tmp-dir', but it is failing in Fedora 20 patterns = ['/tmp/sosreport-%s-*', '/var/tmp/sosreport-%s-*'] reports = [] reportFile = None for p in patterns: reports = reports + [f for f in glob.glob(p % name)] for f in reports: if not fnmatch.fnmatch(f, '*.md5'): reportFile = f break # Some error in sosreport happened if reportFile is None: kimchi_log.error('Debug report file not found. See sosreport ' 'output for detail:\n%s', output) fname = (patterns[0] % name).split('/')[-1] raise OperationFailed('KCHDR0004E', {'name': fname}) md5_report_file = reportFile + '.md5' report_file_extension = '.' + reportFile.split('.', 1)[1] path = config.get_debugreports_path() target = os.path.join(path, name + report_file_extension) # Moving report msg = 'Moving debug report file "%s" to "%s"' % (reportFile, target) kimchi_log.info(msg) shutil.move(reportFile, target) # Deleting md5 msg = 'Deleting report md5 file: "%s"' % (md5_report_file) kimchi_log.info(msg) md5 = open(md5_report_file).read().strip() kimchi_log.info('Md5 file content: "%s"', md5) os.remove(md5_report_file) cb('OK', True) return except OSError: raise except Exception, e: # No need to call cb to update the task status here. # The task object will catch the exception rasied here # and update the task status there log = logging.getLogger('Model') log.warning('Exception in generating debug file: %s', e) raise OperationFailed("KCHDR0005E", {'name': name, 'err': e})
def is_nm_running(): '''Tries to determine whether NetworkManager is running.''' out, err, rc = run_command(['nmcli', 'dev', 'status']) if rc != 0: return False return True
def is_nm_running(): """Tries to determine whether NetworkManager is running.""" out, err, rc = run_command(["nmcli", "dev", "status"]) if rc != 0: return False return True
def lookup(self, params=None): output, error, rc = run_command('lsmcode') if rc: kimchi_log.error('Unable to retreive firmware level.') return {'level': 'Unknown'} # Cut out the chatter from the command output levels = output.split()[5:] levels = " ".join(levels) return {'level': levels}
def lookup(self, params): cmd = ['systemctl', 'status', "sepctl"] output, error, rc = run_command(cmd) # workarround to get the correct output from this command if rc == 0: return {"status": "running"} return {"status": "not running"}
def stop(self, params=None): cmd = ['/opt/ibm/seprovider/bin/sepcli', 'stop'] output, error, rc = run_command(cmd) if rc != 10: kimchi_log.error('SEP execution error: %s - %s - %s' % (cmd, rc, error)) raise OperationFailed('GINSEP0004E', {'cmd': cmd, 'rc': rc, 'error': error}) self._sep_status = 'not running'
def _get_active_powersaving_profile(self): tuned_cmd = ["tuned-adm", "active"] output, error, returncode = run_command(tuned_cmd) # This is a possible scenario where tuned is running # but there is no active profile yet. No need to # report/issue an error. if returncode != 0: return None output = output.split() return output[-1].rstrip()
def _rollback_on_failure(self, gateway): _, err, rc = run_command(['ip', 'route', 'del', 'default']) if rc and not ('No such process' in err): raise OperationFailed('GINNET0010E', {'reason': err}) if gateway: _, err, rc = run_command(['ip', 'route', 'add', 'default', 'via', gateway]) if rc: raise OperationFailed('GINNET0011E', {'reason': err}) conn = LibvirtConnection("qemu:///system").get() try: conn.changeRollback() except libvirt.libvirtError as e: # In case the timeout thread is preempted, and confirm_change() is # called before our changeRollback(), we can just ignore the # VIR_ERR_OPERATION_INVALID error. if e.get_error_code() != libvirt.VIR_ERR_OPERATION_INVALID: raise
def _rollback_on_failure(self, gateway): _, err, rc = run_command(['ip', 'route', 'del', 'default']) if rc and not ('No such process' in err): raise OperationFailed('GINNET0010E', {'reason': err}) if gateway: _, err, rc = run_command( ['ip', 'route', 'add', 'default', 'via', gateway]) if rc: raise OperationFailed('GINNET0011E', {'reason': err}) conn = LibvirtConnection("qemu:///system").get() try: conn.changeRollback() except libvirt.libvirtError as e: # In case the timeout thread is preempted, and confirm_change() is # called before our changeRollback(), we can just ignore the # VIR_ERR_OPERATION_INVALID error. if e.get_error_code() != libvirt.VIR_ERR_OPERATION_INVALID: raise
def _qemu_support_spice(self): qemu_path = find_qemu_binary(find_emulator=True) out, err, rc = run_command(['ldd', qemu_path]) if rc != 0: kimchi_log.error('Failed to find qemu binary dependencies: %s', err) return False for line in out.split('\n'): if line.lstrip().startswith('libspice-server.so'): return True return False
def __init__(self): self.error = None # Check if running with any distro other than # RHEL/Fedora, where the 'tuned-adm' package exists. # The idea is to check by the existence of 'yum' # to take care of Ubuntu/Debian verification, and then # check yum to see if the package is installed. yum_cmd = ["yum", "--version"] output, err, returncode = run_command(yum_cmd) if output is None: self.error = 'GINPOWER001E' else: tuned_cmd = ["tuned-adm", "active"] output, err, returncode = run_command(tuned_cmd) # return code '2' at 'tuned-adm active' means that # the tuned daemon is not active if returncode == 2: self.error = 'GINPOWER002E' elif output is None: self.error = 'GINPOWER003E'
def update(self, profile, params): if params['active'] and self.active_powerprofile != profile: self.active_powerprofile = profile tuned_cmd = ["tuned-adm", "profile", profile] output, error, returncode = run_command(tuned_cmd) if returncode != 0: kimchi_log.error('Could not activate power profile %s, ' 'error: %s', powerprofile, error) raise OperationFailed('Error while activating power ' 'saving profile %s.', powerprofile) return profile
def update(self, powerprofile, params): if params['active'] and self.active_powerprofile != powerprofile: self.active_powerprofile = powerprofile tuned_cmd = ["tuned-adm", "profile", powerprofile] output, error, returncode = run_command(tuned_cmd) if returncode != 0: kimchi_log.error('Could not activate power profile %s, ' 'error: %s', powerprofile, error) raise OperationFailed("GINPOWER004E", {'profile': powerprofile}) return powerprofile
def update(self, powerprofile, params): if params['active'] and self.active_powerprofile != powerprofile: self.active_powerprofile = powerprofile tuned_cmd = ["tuned-adm", "profile", powerprofile] output, error, returncode = run_command(tuned_cmd) if returncode != 0: kimchi_log.error( 'Could not activate power profile %s, ' 'error: %s', powerprofile, error) raise OperationFailed("GINPOWER004E", {'profile': powerprofile}) return powerprofile
def _tar_create_archive(directory_path, archive_id, include, exclude): archive_file = os.path.join(directory_path, archive_id + '.tar.gz') exclude = ['--exclude=' + toExclude for toExclude in exclude] cmd = ['tar', '--create', '--gzip', '--absolute-names', '--file', archive_file, '--selinux', '--acl', '--xattrs'] + exclude + include out, err, rc = run_command(cmd) if rc != 0: raise OperationFailed( 'GINHBK0001E', {'name': archive_file, 'cmd': ' '.join(cmd)}) return archive_file
def has_sudo(self): out, err, exit = run_command( ['sudo', '-l', '-U', self.user[USER_ID], 'sudo']) if exit == 0: debug("User %s is allowed to run sudo" % self.user[USER_ID]) # sudo allows a wide range of configurations, such as controlling # which binaries the user can execute with sudo. # For now, we will just check whether the user is allowed to run # any command with sudo. out, err, exit = run_command( ['sudo', '-l', '-U', self.user[USER_ID]]) for line in out.split('\n'): if line and re.search("(ALL)", line): self.user[USER_SUDO] = True debug("User %s can run any command with sudo" % self.user[USER_ID]) return self.user[USER_SUDO] debug("User %s can only run some commands with sudo" % self.user[USER_ID]) else: debug("User %s is not allowed to run sudo" % self.user[USER_ID]) return self.user[USER_SUDO]
def get_list(self): if self.error is not None: kimchi_log.error(self.error) raise OperationFailed(self.error) profiles = [] tuned_cmd = ["tuned-adm", "list"] output, error, returncode = run_command(tuned_cmd) lines_output = output.rstrip("\n").split("\n") for line in lines_output: if line.startswith('-'): line = line.strip("- ") profiles.append(line) return profiles
def _ensure_iface_up(self, iface): if netinfo.operstate(iface) != 'up': _, err, rc = run_command(['ip', 'link', 'set', 'dev', iface, 'up']) if rc != 0: raise OperationFailed("KCHNET0020E", {'iface': iface, 'err': err}) # Add a delay to wait for the link change takes into effect. for i in range(10): time.sleep(1) if netinfo.operstate(iface) == 'up': break else: raise OperationFailed("KCHNET0021E", {'iface': iface})
def probe_img_info(path): cmd = ["qemu-img", "info", "--output=json", path] info = dict() try: out = run_command(cmd, 10)[0] except TimeoutExpired: kimchi_log.warning("Cannot decide format of base img %s", path) return None info = json.loads(out) info['virtual-size'] = info['virtual-size'] >> 30 info['actual-size'] = info['actual-size'] >> 30 return info
def update(self, powerprofile, params): if params['active'] and self.active_powerprofile != powerprofile: self.active_powerprofile = powerprofile tuned_cmd = ["tuned-adm", "profile", powerprofile] output, error, returncode = run_command(tuned_cmd) if returncode != 0: kimchi_log.error( 'Could not activate power profile %s, ' 'error: %s', powerprofile, error) raise OperationFailed( 'Error while activating power ' 'saving profile %s.', powerprofile) return powerprofile
def _get_default_route_entry(self): # Default route entry reads like this: # default via 9.115.126.1 dev wlp3s0 proto static metric 1024 out, err, rc = run_command( ['ip', '-4', 'route', 'list', 'match', '0/0']) if not rc: if out: routes = [line.split() for line in out.split('\n')] return next(Route(r[0], r[2], r[4]) for r in routes) else: return None else: raise OperationFailed('GINNET0009E', {'err': err})
def get_list(self): profiles = [] tuned_cmd = ["tuned-adm", "list"] output, error, returncode = run_command(tuned_cmd) if returncode != 0: kimchi_log.error('Could not retrieve power profiles, error: %s', error) raise OperationFailed('Error while retrieving power saving ' 'profiles.') lines_output = output.rstrip("\n").split("\n") for line in lines_output: if line.startswith('-'): line = line.strip("- ") profiles.append(line) return profiles