def install_packages(packages): qa_common.log("Installing %i debuginfo packages" % len(packages)) qa_common.log("\n".join(packages)) # Intended as immutable install_cmd_base = [ "zypper", "--non-interactive", "--no-gpg-checks", "in", "-C" ] successful = 0 for package in packages: try: # Copy the cmd base to be amended instead of modifying # the original install_cmd = install_cmd_base + [package] qa_common.remote_cmd(target_ip, user, passwd, install_cmd, get_stderr=True) successful += 1 except subprocess.CalledProcessError as e: qa_common.log("Error message from remote:\n%s\n" % e.output) qa_common.log("Successfully installed %i packages" % successful)
def inject_credentials(cred_file_local, path, fname): mkdir_cmd = ["mkdir", "-p", path] cred_file = qa_common.read_file(cred_file_local) cred_file_name = path + fname inject_write_cmd = "echo \"" + cred_file + "\" > " + cred_file_name inject_cmd_template = "if [ ! -f \"%s\" ] ; then %s ; fi" inject_cmd = inject_cmd_template % (cred_file_name, inject_write_cmd) qa_common.remote_cmd(target_ip, user, passwd, mkdir_cmd) qa_common.remote_cmd(target_ip, user, passwd, inject_cmd)
def get_memory_stats(self, client): def parse_meminfo(data): result = {} for line in data.splitlines(): line = line.strip() if (line == ""): continue atoms = line.split() key = atoms[0].rstrip(":") value = int(atoms[1]) if (len(atoms) > 2): unit = atoms[2] else: unit = "B" result[key] = self.parse_unit(value, unit) return result result = {} my_cmd = "cat %s" % mem_path_r mem_output = qa_common.remote_cmd(client, my_cmd) mem_stats = parse_meminfo(mem_output) result["total"] = mem_stats["MemTotal"] result["free"] = mem_stats["MemFree"] + mem_stats["SwapFree"] result["buffers"] = mem_stats["Buffers"] result["cache"] = mem_stats["Cached"] + mem_stats["Slab"] result["used"] = result["total"] - \ result["free"] - \ result["buffers"] - \ result["cache"] return result
def parse_dump_files(core_list, result_list, core_path_prefix): # Catch binary name from file output, we're not interested in # anything else pattern = ".*ELF.+core file.+from '([^ ]+).*'" re_prog = re.compile(pattern) binary_match_id = 1 # Last atom is apparently always a blank line for dump in core_list: if (dump == ""): continue dump = dump.replace(" ", "\ ") file_cmd = ["file", dump] output = qa_common.remote_cmd(target_ip, user, passwd, file_cmd) re_match = re_prog.match(output) # Notify user if there is for example an empty file, but keep # going anyway if (re_match == None): qa_common.error("Non-matching core file " + dump) continue # If the dumps are on some other than current partition, # prefix the binary names with path to partition root binary = re_match.group(binary_match_id) binary = core_path_prefix + binary this_dump = {"binary": binary, "corefile": dump} result_list.append(this_dump)
def get_coredumps(partition_roots, core_dir): def parse_dump_files(core_list, result_list, core_path_prefix): # Catch binary name from file output, we're not interested in # anything else pattern = ".*ELF.+core file.+from '([^ ]+).*'" re_prog = re.compile(pattern) binary_match_id = 1 # Last atom is apparently always a blank line for dump in core_list: if (dump == ""): continue dump = dump.replace(" ", "\ ") file_cmd = ["file", dump] output = qa_common.remote_cmd(target_ip, user, passwd, file_cmd) re_match = re_prog.match(output) # Notify user if there is for example an empty file, but keep # going anyway if (re_match == None): qa_common.error("Non-matching core file " + dump) continue # If the dumps are on some other than current partition, # prefix the binary names with path to partition root binary = re_match.group(binary_match_id) binary = core_path_prefix + binary this_dump = {"binary": binary, "corefile": dump} result_list.append(this_dump) if (not isinstance(partition_roots, list)): if (isinstance(partition_roots, str)): partition_roots = [partition_roots] else: partition_roots = [] result_list = [] # Note: [1, 2] + [3, 4, 5] = [1, 2, 3, 4, 5], not for example # [1, 2, [3, 4, 5]] assert (isinstance(core_dir, str)) for core_path_prefix in partition_roots: assert (isinstance(core_path_prefix, str)) core_path = core_path_prefix + core_dir get_corelist_cmd = ["find"] + [core_path] + ["-type", "f"] core_list = qa_common.remote_cmd(target_ip, \ user, \ passwd, \ get_corelist_cmd).split("\n") parse_dump_files(core_list, result_list, core_path_prefix) return result_list
def invoke_gdb(gdb_path, binary, core_dump): # Use echo q instead of -ex q, even though it is very hacky. For some # reason, gdb will not give us the missing debuginfo information at all # if run with -ex q, so it needs to be worked around this way gdb_cmd = "echo q | %s %s %s 2>&1" % (gdb_path, binary, core_dump) result = qa_common.remote_cmd(target_ip, user, passwd, gdb_cmd, \ get_stderr=True).split("\n") return result
def get_procs(self, client): result = [] page_size = int(self.getconf(client, "PAGE_SIZE")) / 1024 vm_cmd = "cat /proc/[1-9]*/stat" stdout = qa_common.remote_cmd(client, vm_cmd) for line in stdout.splitlines(): proc = self.parse_procs(line, page_size) if (proc["rss"] >= self.rss_threshold): result.append(proc) return result
def read(self, client): my_cmd = "cat /proc/stat" # Substrings are 1) cpu name, and time spent in 2) user mode, # 3) low priority user mode, 4) system mode, 5) idle pattern = "^(cpu[0-9]+) ([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+)" p = re.compile(pattern) output = qa_common.remote_cmd(client, my_cmd).splitlines() i = 0 result = [] for line in output: match = p.match(line) if (not match): continue data = match.group(0, 1, 2, 3, 4, 5) run_time = float(data[2]) + float(data[3]) + \ float(data[4]) idle_time = float(data[5]) if (self.first_run): self.old_run_time.append(run_time) self.old_idle_time.append(idle_time) result.append(0.0) else: old_run_time = self.old_run_time[i] old_idle_time = self.old_idle_time[i] run_time_diff = run_time - old_run_time idle_time_diff = idle_time - old_idle_time usage = run_time_diff / (run_time_diff + \ idle_time_diff) result.append(round(usage, 3)) self.old_run_time[i] = run_time self.old_idle_time[i] = idle_time i += 1 self.first_run = False return result
def get_uptime(self, client): my_cmd = "cat %s" % uptime_path_r output = qa_common.remote_cmd(client, my_cmd) return float(output.split()[0])
def get_load(self, client, which): assert (which >= 0 and which <= 2) my_cmd = "cat %s" % load_path_r output = qa_common.remote_cmd(client, my_cmd) return float(output.split()[which])
def get_cpu_freq(self, client): my_cmd = "cat %s" % cpu_freq_path_r output = qa_common.remote_cmd(client, my_cmd) return int(output.strip())
def getconf(self, client, var): return qa_common.remote_cmd(client, "getconf %s" % var)