diff options
| author | Brad Bishop <bradleyb@fuzziesquirrel.com> | 2019-07-08 15:24:31 +0300 |
|---|---|---|
| committer | Brad Bishop <bradleyb@fuzziesquirrel.com> | 2019-07-08 16:34:48 +0300 |
| commit | 2939317205d1f39eefebec7bd6ba01faaa0f9369 (patch) | |
| tree | 45f4ba1e0bca7dc394b7fa77ca3122f1121a6a55 /poky/scripts | |
| parent | 963b1beb7e04e1c6c55bea2104b856e3121202db (diff) | |
| download | openbmc-2.7.0-rc1.tar.xz | |
reset upstream subtrees to warrior HEAD2.7.0-rc1
Reset the following subtrees on warrior HEAD:
meta-security: 4f7be0d252(warrior)
poky: 38d5c8ea98(warrior)
meta-raspberrypi: 6c73694912(warrior)
meta-openembedded: 6fa72d587a(warrior)
Change-Id: Id2550baeb90de14bdd9ee8c06f2c619fc719bc68
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
Diffstat (limited to 'poky/scripts')
| -rw-r--r-- | poky/scripts/lib/recipetool/create_buildsys_python.py | 22 | ||||
| -rw-r--r-- | poky/scripts/lib/resulttool/merge.py | 20 | ||||
| -rw-r--r-- | poky/scripts/lib/resulttool/resultutils.py | 19 | ||||
| -rw-r--r-- | poky/scripts/lib/resulttool/store.py | 9 | ||||
| -rw-r--r-- | poky/scripts/lib/wic/engine.py | 7 | ||||
| -rw-r--r-- | poky/scripts/lib/wic/filemap.py | 5 | ||||
| -rw-r--r-- | poky/scripts/lib/wic/partition.py | 2 | ||||
| -rw-r--r-- | poky/scripts/lib/wic/plugins/source/bootimg-efi.py | 60 | ||||
| -rw-r--r-- | poky/scripts/lib/wic/plugins/source/bootimg-pcbios.py | 8 | ||||
| -rw-r--r-- | poky/scripts/lib/wic/plugins/source/isoimage-isohybrid.py | 21 | ||||
| -rwxr-xr-x | poky/scripts/pybootchartgui/pybootchartgui.py | 2 | ||||
| -rw-r--r-- | poky/scripts/pybootchartgui/pybootchartgui/draw.py | 1383 | ||||
| -rw-r--r-- | poky/scripts/pybootchartgui/pybootchartgui/gui.py | 208 | ||||
| -rw-r--r-- | poky/scripts/pybootchartgui/pybootchartgui/parsing.py | 12 | ||||
| -rwxr-xr-x | poky/scripts/runqemu | 71 | ||||
| -rwxr-xr-x | poky/scripts/wic | 5 |
16 files changed, 868 insertions, 986 deletions
diff --git a/poky/scripts/lib/recipetool/create_buildsys_python.py b/poky/scripts/lib/recipetool/create_buildsys_python.py index ac9bc9237c..1a38bd0b14 100644 --- a/poky/scripts/lib/recipetool/create_buildsys_python.py +++ b/poky/scripts/lib/recipetool/create_buildsys_python.py @@ -31,11 +31,11 @@ def tinfoil_init(instance): class PythonRecipeHandler(RecipeHandler): - base_pkgdeps = ['python3-core'] - excluded_pkgdeps = ['python3-dbg'] - # os.path is provided by python3-core + base_pkgdeps = ['python-core'] + excluded_pkgdeps = ['python-dbg'] + # os.path is provided by python-core assume_provided = ['builtins', 'os.path'] - # Assumes that the host python3 builtin_module_names is sane for target too + # Assumes that the host python builtin_module_names is sane for target too assume_provided = assume_provided + list(sys.builtin_module_names) bbvar_map = { @@ -215,9 +215,9 @@ class PythonRecipeHandler(RecipeHandler): self.apply_info_replacements(info) if uses_setuptools: - classes.append('setuptools3') + classes.append('setuptools') else: - classes.append('distutils3') + classes.append('distutils') if license_str: for i, line in enumerate(lines_before): @@ -282,7 +282,7 @@ class PythonRecipeHandler(RecipeHandler): for feature, feature_reqs in extras_req.items(): unmapped_deps.difference_update(feature_reqs) - feature_req_deps = ('python3-' + r.replace('.', '-').lower() for r in sorted(feature_reqs)) + feature_req_deps = ('python-' + r.replace('.', '-').lower() for r in sorted(feature_reqs)) lines_after.append('PACKAGECONFIG[{}] = ",,,{}"'.format(feature.lower(), ' '.join(feature_req_deps))) inst_reqs = set() @@ -293,7 +293,7 @@ class PythonRecipeHandler(RecipeHandler): if inst_reqs: unmapped_deps.difference_update(inst_reqs) - inst_req_deps = ('python3-' + r.replace('.', '-').lower() for r in sorted(inst_reqs)) + inst_req_deps = ('python-' + r.replace('.', '-').lower() for r in sorted(inst_reqs)) lines_after.append('# WARNING: the following rdepends are from setuptools install_requires. These') lines_after.append('# upstream names may not correspond exactly to bitbake package names.') lines_after.append('RDEPENDS_${{PN}} += "{}"'.format(' '.join(inst_req_deps))) @@ -356,7 +356,7 @@ class PythonRecipeHandler(RecipeHandler): return info, 'setuptools' in imported_modules, non_literals, extensions def get_setup_args_info(self, setupscript='./setup.py'): - cmd = ['python3', setupscript] + cmd = ['python', setupscript] info = {} keys = set(self.bbvar_map.keys()) keys |= set(self.setuparg_list_fields) @@ -390,7 +390,7 @@ class PythonRecipeHandler(RecipeHandler): def get_setup_byline(self, fields, setupscript='./setup.py'): info = {} - cmd = ['python3', setupscript] + cmd = ['python', setupscript] cmd.extend('--' + self.setuparg_map.get(f, f.lower()) for f in fields) try: info_lines = self.run_command(cmd, cwd=os.path.dirname(setupscript)).splitlines() @@ -527,7 +527,7 @@ class PythonRecipeHandler(RecipeHandler): pkgdata_dir = tinfoil.config_data.getVar('PKGDATA_DIR') ldata = tinfoil.config_data.createCopy() - bb.parse.handle('classes/python3-dir.bbclass', ldata, True) + bb.parse.handle('classes/python-dir.bbclass', ldata, True) python_sitedir = ldata.getVar('PYTHON_SITEPACKAGES_DIR') dynload_dir = os.path.join(os.path.dirname(python_sitedir), 'lib-dynload') diff --git a/poky/scripts/lib/resulttool/merge.py b/poky/scripts/lib/resulttool/merge.py index 18b4825a18..70d23a48fd 100644 --- a/poky/scripts/lib/resulttool/merge.py +++ b/poky/scripts/lib/resulttool/merge.py @@ -11,23 +11,16 @@ import json import resulttool.resultutils as resultutils def merge(args, logger): - configvars = {} - if not args.not_add_testseries: - configvars = resultutils.extra_configvars.copy() - if args.executed_by: - configvars['EXECUTED_BY'] = args.executed_by if resultutils.is_url(args.target_results) or os.path.isdir(args.target_results): - results = resultutils.load_resultsdata(args.target_results, configmap=resultutils.store_map, configvars=configvars) - resultutils.append_resultsdata(results, args.base_results, configmap=resultutils.store_map, configvars=configvars) + results = resultutils.load_resultsdata(args.target_results, configmap=resultutils.store_map) + resultutils.append_resultsdata(results, args.base_results, configmap=resultutils.store_map) resultutils.save_resultsdata(results, args.target_results) else: - results = resultutils.load_resultsdata(args.base_results, configmap=resultutils.flatten_map, configvars=configvars) + results = resultutils.load_resultsdata(args.base_results, configmap=resultutils.flatten_map) if os.path.exists(args.target_results): - resultutils.append_resultsdata(results, args.target_results, configmap=resultutils.flatten_map, configvars=configvars) + resultutils.append_resultsdata(results, args.target_results, configmap=resultutils.flatten_map) resultutils.save_resultsdata(results, os.path.dirname(args.target_results), fn=os.path.basename(args.target_results)) - logger.info('Merged results to %s' % os.path.dirname(args.target_results)) - return 0 def register_commands(subparsers): @@ -40,7 +33,4 @@ def register_commands(subparsers): help='the results file/directory/URL to import') parser_build.add_argument('target_results', help='the target file or directory to merge the base_results with') - parser_build.add_argument('-t', '--not-add-testseries', action='store_true', - help='do not add testseries configuration to results') - parser_build.add_argument('-x', '--executed-by', default='', - help='add executed-by configuration to each result file') + diff --git a/poky/scripts/lib/resulttool/resultutils.py b/poky/scripts/lib/resulttool/resultutils.py index e595c185df..ea4ab42d9a 100644 --- a/poky/scripts/lib/resulttool/resultutils.py +++ b/poky/scripts/lib/resulttool/resultutils.py @@ -42,12 +42,10 @@ def is_url(p): """ return p.startswith('http://') or p.startswith('https://') -extra_configvars = {'TESTSERIES': ''} - # # Load the json file and append the results data into the provided results dict # -def append_resultsdata(results, f, configmap=store_map, configvars=extra_configvars): +def append_resultsdata(results, f, configmap=store_map): if type(f) is str: if is_url(f): with urllib.request.urlopen(f) as response: @@ -63,15 +61,12 @@ def append_resultsdata(results, f, configmap=store_map, configvars=extra_configv for res in data: if "configuration" not in data[res] or "result" not in data[res]: raise ValueError("Test results data without configuration or result section?") - for config in configvars: - if config == "TESTSERIES" and "TESTSERIES" not in data[res]["configuration"]: - data[res]["configuration"]["TESTSERIES"] = testseries - continue - if config not in data[res]["configuration"]: - data[res]["configuration"][config] = configvars[config] + if "TESTSERIES" not in data[res]["configuration"]: + data[res]["configuration"]["TESTSERIES"] = testseries testtype = data[res]["configuration"].get("TEST_TYPE") if testtype not in configmap: raise ValueError("Unknown test type %s" % testtype) + configvars = configmap[testtype] testpath = "/".join(data[res]["configuration"].get(i) for i in configmap[testtype]) if testpath not in results: results[testpath] = {} @@ -81,16 +76,16 @@ def append_resultsdata(results, f, configmap=store_map, configvars=extra_configv # Walk a directory and find/load results data # or load directly from a file # -def load_resultsdata(source, configmap=store_map, configvars=extra_configvars): +def load_resultsdata(source, configmap=store_map): results = {} if is_url(source) or os.path.isfile(source): - append_resultsdata(results, source, configmap, configvars) + append_resultsdata(results, source, configmap) return results for root, dirs, files in os.walk(source): for name in files: f = os.path.join(root, name) if name == "testresults.json": - append_resultsdata(results, f, configmap, configvars) + append_resultsdata(results, f, configmap) return results def filter_resultsdata(results, resultid): diff --git a/poky/scripts/lib/resulttool/store.py b/poky/scripts/lib/resulttool/store.py index 79c83dd8b7..06505aecc0 100644 --- a/poky/scripts/lib/resulttool/store.py +++ b/poky/scripts/lib/resulttool/store.py @@ -21,19 +21,16 @@ import oeqa.utils.gitarchive as gitarchive def store(args, logger): tempdir = tempfile.mkdtemp(prefix='testresults.') try: - configvars = resultutils.extra_configvars.copy() - if args.executed_by: - configvars['EXECUTED_BY'] = args.executed_by results = {} logger.info('Reading files from %s' % args.source) if resultutils.is_url(args.source) or os.path.isfile(args.source): - resultutils.append_resultsdata(results, args.source, configvars=configvars) + resultutils.append_resultsdata(results, args.source) else: for root, dirs, files in os.walk(args.source): for name in files: f = os.path.join(root, name) if name == "testresults.json": - resultutils.append_resultsdata(results, f, configvars=configvars) + resultutils.append_resultsdata(results, f) elif args.all: dst = f.replace(args.source, tempdir + "/") os.makedirs(os.path.dirname(dst), exist_ok=True) @@ -96,6 +93,4 @@ def register_commands(subparsers): help='include all files, not just testresults.json files') parser_build.add_argument('-e', '--allow-empty', action='store_true', help='don\'t error if no results to store are found') - parser_build.add_argument('-x', '--executed-by', default='', - help='add executed-by configuration to each result file') diff --git a/poky/scripts/lib/wic/engine.py b/poky/scripts/lib/wic/engine.py index 61939ad194..42e93c3eb8 100644 --- a/poky/scripts/lib/wic/engine.py +++ b/poky/scripts/lib/wic/engine.py @@ -75,8 +75,7 @@ def find_canned_image(scripts_path, wks_file): for fname in files: if fname.endswith("~") or fname.endswith("#"): continue - if ((fname.endswith(".wks") and wks_file + ".wks" == fname) or \ - (fname.endswith(".wks.in") and wks_file + ".wks.in" == fname)): + if fname.endswith(".wks") and wks_file + ".wks" == fname: fullpath = os.path.join(canned_wks_dir, fname) return fullpath return None @@ -93,7 +92,7 @@ def list_canned_images(scripts_path): for fname in files: if fname.endswith("~") or fname.endswith("#"): continue - if fname.endswith(".wks") or fname.endswith(".wks.in"): + if fname.endswith(".wks"): fullpath = os.path.join(canned_wks_dir, fname) with open(fullpath) as wks: for line in wks: @@ -102,7 +101,7 @@ def list_canned_images(scripts_path): if idx != -1: desc = line[idx + len("short-description:"):].strip() break - basename = fname.split('.')[0] + basename = os.path.splitext(fname)[0] print(" %s\t\t%s" % (basename.ljust(30), desc)) diff --git a/poky/scripts/lib/wic/filemap.py b/poky/scripts/lib/wic/filemap.py index a3919fbcad..244c07a71c 100644 --- a/poky/scripts/lib/wic/filemap.py +++ b/poky/scripts/lib/wic/filemap.py @@ -32,10 +32,7 @@ def get_block_size(file_obj): """ # Get the block size of the host file-system for the image file by calling # the FIGETBSZ ioctl (number 2). - try: - binary_data = fcntl.ioctl(file_obj, 2, struct.pack('I', 0)) - except OSError: - raise IOError("Unable to determine block size") + binary_data = fcntl.ioctl(file_obj, 2, struct.pack('I', 0)) bsize = struct.unpack('I', binary_data)[0] if not bsize: import os diff --git a/poky/scripts/lib/wic/partition.py b/poky/scripts/lib/wic/partition.py index 01466b258d..6a1dc59501 100644 --- a/poky/scripts/lib/wic/partition.py +++ b/poky/scripts/lib/wic/partition.py @@ -308,7 +308,7 @@ class Partition(): dosfs_cmd = "mkdosfs %s -i %s %s %s -C %s %d" % \ (label_str, self.fsuuid, size_str, extraopts, rootfs, - rootfs_size) + max(8250, rootfs_size)) exec_native_cmd(dosfs_cmd, native_sysroot) mcopy_cmd = "mcopy -i %s -s %s/* ::/" % (rootfs, rootfs_dir) diff --git a/poky/scripts/lib/wic/plugins/source/bootimg-efi.py b/poky/scripts/lib/wic/plugins/source/bootimg-efi.py index 5cc5c8a6b8..652323fa77 100644 --- a/poky/scripts/lib/wic/plugins/source/bootimg-efi.py +++ b/poky/scripts/lib/wic/plugins/source/bootimg-efi.py @@ -55,10 +55,8 @@ class BootimgEFIPlugin(SourcePlugin): if not bootimg_dir: raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting") - initrds = initrd.split(';') - for rd in initrds: - cp_cmd = "cp %s/%s %s" % (bootimg_dir, rd, hdddir) - exec_cmd(cp_cmd, True) + cp_cmd = "cp %s/%s %s" % (bootimg_dir, initrd, hdddir) + exec_cmd(cp_cmd, True) else: logger.debug("Ignoring missing initrd") @@ -73,24 +71,13 @@ class BootimgEFIPlugin(SourcePlugin): grubefi_conf += "timeout=%s\n" % bootloader.timeout grubefi_conf += "menuentry '%s'{\n" % (title if title else "boot") - kernel = get_bitbake_var("KERNEL_IMAGETYPE") - if not kernel: - kernel = "bzImage" - - label = source_params.get('label') - label_conf = "root=%s" % creator.rootdev - if label: - label_conf = "LABEL=%s" % label + kernel = "/bzImage" - grubefi_conf += "linux /%s %s rootwait %s\n" \ - % (kernel, label_conf, bootloader.append) + grubefi_conf += "linux %s root=%s rootwait %s\n" \ + % (kernel, creator.rootdev, bootloader.append) if initrd: - initrds = initrd.split(';') - grubefi_conf += "initrd" - for rd in initrds: - grubefi_conf += " /%s" % rd - grubefi_conf += "\n" + grubefi_conf += "initrd /%s\n" % initrd grubefi_conf += "}\n" @@ -125,10 +112,8 @@ class BootimgEFIPlugin(SourcePlugin): if not bootimg_dir: raise WicError("Couldn't find DEPLOY_DIR_IMAGE, exiting") - initrds = initrd.split(';') - for rd in initrds: - cp_cmd = "cp %s/%s %s" % (bootimg_dir, rd, hdddir) - exec_cmd(cp_cmd, True) + cp_cmd = "cp %s/%s %s" % (bootimg_dir, initrd, hdddir) + exec_cmd(cp_cmd, True) else: logger.debug("Ignoring missing initrd") @@ -153,28 +138,17 @@ class BootimgEFIPlugin(SourcePlugin): if not custom_cfg: # Create systemd-boot configuration using parameters from wks file - kernel = get_bitbake_var("KERNEL_IMAGETYPE") - if not kernel: - kernel = "bzImage" - + kernel = "/bzImage" title = source_params.get('title') boot_conf = "" boot_conf += "title %s\n" % (title if title else "boot") - boot_conf += "linux /%s\n" % kernel - - label = source_params.get('label') - label_conf = "LABEL=Boot root=%s" % creator.rootdev - if label: - label_conf = "LABEL=%s" % label - - boot_conf += "options %s %s\n" % \ - (label_conf, bootloader.append) + boot_conf += "linux %s\n" % kernel + boot_conf += "options LABEL=Boot root=%s %s\n" % \ + (creator.rootdev, bootloader.append) if initrd: - initrds = initrd.split(';') - for rd in initrds: - boot_conf += "initrd /%s\n" % rd + boot_conf += "initrd /%s\n" % initrd logger.debug("Writing systemd-boot config " "%s/hdd/boot/loader/entries/boot.conf", cr_workdir) @@ -224,12 +198,8 @@ class BootimgEFIPlugin(SourcePlugin): hdddir = "%s/hdd/boot" % cr_workdir - kernel = get_bitbake_var("KERNEL_IMAGETYPE") - if not kernel: - kernel = "bzImage" - - install_cmd = "install -m 0644 %s/%s %s/%s" % \ - (staging_kernel_dir, kernel, hdddir, kernel) + install_cmd = "install -m 0644 %s/bzImage %s/bzImage" % \ + (staging_kernel_dir, hdddir) exec_cmd(install_cmd) diff --git a/poky/scripts/lib/wic/plugins/source/bootimg-pcbios.py b/poky/scripts/lib/wic/plugins/source/bootimg-pcbios.py index 670d347747..6c9f54a897 100644 --- a/poky/scripts/lib/wic/plugins/source/bootimg-pcbios.py +++ b/poky/scripts/lib/wic/plugins/source/bootimg-pcbios.py @@ -149,12 +149,8 @@ class BootimgPcbiosPlugin(SourcePlugin): hdddir = "%s/hdd/boot" % cr_workdir - kernel = get_bitbake_var("KERNEL_IMAGETYPE") - if not kernel: - kernel = "bzImage" - - cmds = ("install -m 0644 %s/%s %s/vmlinuz" % - (staging_kernel_dir, kernel, hdddir), + cmds = ("install -m 0644 %s/bzImage %s/vmlinuz" % + (staging_kernel_dir, hdddir), "install -m 444 %s/syslinux/ldlinux.sys %s/ldlinux.sys" % (bootimg_dir, hdddir), "install -m 0644 %s/syslinux/vesamenu.c32 %s/vesamenu.c32" % diff --git a/poky/scripts/lib/wic/plugins/source/isoimage-isohybrid.py b/poky/scripts/lib/wic/plugins/source/isoimage-isohybrid.py index 74d6f14519..96d07ff629 100644 --- a/poky/scripts/lib/wic/plugins/source/isoimage-isohybrid.py +++ b/poky/scripts/lib/wic/plugins/source/isoimage-isohybrid.py @@ -70,10 +70,8 @@ class IsoImagePlugin(SourcePlugin): syslinux_conf += "DEFAULT boot\n" syslinux_conf += "LABEL boot\n" - kernel = get_bitbake_var("KERNEL_IMAGETYPE") - if not kernel: - kernel = "bzImage" - syslinux_conf += "KERNEL /" + kernel + "\n" + kernel = "/bzImage" + syslinux_conf += "KERNEL " + kernel + "\n" syslinux_conf += "APPEND initrd=/initrd LABEL=boot %s\n" \ % bootloader.append @@ -116,11 +114,9 @@ class IsoImagePlugin(SourcePlugin): grubefi_conf += "\n" grubefi_conf += "menuentry 'boot'{\n" - kernel = get_bitbake_var("KERNEL_IMAGETYPE") - if not kernel: - kernel = "bzImage" + kernel = "/bzImage" - grubefi_conf += "linux /%s rootwait %s\n" \ + grubefi_conf += "linux %s rootwait %s\n" \ % (kernel, bootloader.append) grubefi_conf += "initrd /initrd \n" grubefi_conf += "}\n" @@ -272,12 +268,9 @@ class IsoImagePlugin(SourcePlugin): if os.path.isfile("%s/initrd.cpio.gz" % cr_workdir): os.remove("%s/initrd.cpio.gz" % cr_workdir) - kernel = get_bitbake_var("KERNEL_IMAGETYPE") - if not kernel: - kernel = "bzImage" - - install_cmd = "install -m 0644 %s/%s %s/%s" % \ - (kernel_dir, kernel, isodir, kernel) + # Install bzImage + install_cmd = "install -m 0644 %s/bzImage %s/bzImage" % \ + (kernel_dir, isodir) exec_cmd(install_cmd) #Create bootloader for efi boot diff --git a/poky/scripts/pybootchartgui/pybootchartgui.py b/poky/scripts/pybootchartgui/pybootchartgui.py index 1c4062b42c..7ce1a5be40 100755 --- a/poky/scripts/pybootchartgui/pybootchartgui.py +++ b/poky/scripts/pybootchartgui/pybootchartgui.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +#!/usr/bin/env python # # This file is part of pybootchartgui. diff --git a/poky/scripts/pybootchartgui/pybootchartgui/draw.py b/poky/scripts/pybootchartgui/pybootchartgui/draw.py index add5c53882..201ce4577f 100644 --- a/poky/scripts/pybootchartgui/pybootchartgui/draw.py +++ b/poky/scripts/pybootchartgui/pybootchartgui/draw.py @@ -19,23 +19,22 @@ import math import re import random import colorsys -import functools from operator import itemgetter class RenderOptions: - def __init__(self, app_options): - # should we render a cumulative CPU time chart - self.cumulative = True - self.charts = True - self.kernel_only = False - self.app_options = app_options + def __init__(self, app_options): + # should we render a cumulative CPU time chart + self.cumulative = True + self.charts = True + self.kernel_only = False + self.app_options = app_options - def proc_tree (self, trace): - if self.kernel_only: - return trace.kernel_tree - else: - return trace.proc_tree + def proc_tree (self, trace): + if self.kernel_only: + return trace.kernel_tree + else: + return trace.proc_tree # Process tree background color. BACK_COLOR = (1.0, 1.0, 1.0, 1.0) @@ -137,11 +136,11 @@ TASK_COLOR_PACKAGE_WRITE = (0.0, 0.50, 0.50, 1.0) # Distinct colors used for different disk volumnes. # If we have more volumns, colors get re-used. VOLUME_COLORS = [ - (1.0, 1.0, 0.00, 1.0), - (0.0, 1.00, 0.00, 1.0), - (1.0, 0.00, 1.00, 1.0), - (0.0, 0.00, 1.00, 1.0), - (0.0, 1.00, 1.00, 1.0), + (1.0, 1.0, 0.00, 1.0), + (0.0, 1.00, 0.00, 1.0), + (1.0, 0.00, 1.00, 1.0), + (0.0, 0.00, 1.00, 1.0), + (0.0, 1.00, 1.00, 1.0), ] # Process states @@ -153,7 +152,7 @@ STATE_STOPPED = 4 STATE_ZOMBIE = 5 STATE_COLORS = [(0, 0, 0, 0), PROC_COLOR_R, PROC_COLOR_S, PROC_COLOR_D, \ - PROC_COLOR_T, PROC_COLOR_Z, PROC_COLOR_X, PROC_COLOR_W] + PROC_COLOR_T, PROC_COLOR_Z, PROC_COLOR_X, PROC_COLOR_W] # CumulativeStats Types STAT_TYPE_CPU = 0 @@ -161,80 +160,80 @@ STAT_TYPE_IO = 1 # Convert ps process state to an int def get_proc_state(flag): - return "RSDTZXW".find(flag) + 1 + return "RSDTZXW".find(flag) + 1 def draw_text(ctx, text, color, x, y): - ctx.set_source_rgba(*color) - ctx.move_to(x, y) - ctx.show_text(text) + ctx.set_source_rgba(*color) + ctx.move_to(x, y) + ctx.show_text(text) def draw_fill_rect(ctx, color, rect): - ctx.set_source_rgba(*color) - ctx.rectangle(*rect) - ctx.fill() + ctx.set_source_rgba(*color) + ctx.rectangle(*rect) + ctx.fill() def draw_rect(ctx, color, rect): - ctx.set_source_rgba(*color) - ctx.rectangle(*rect) - ctx.stroke() + ctx.set_source_rgba(*color) + ctx.rectangle(*rect) + ctx.stroke() def draw_legend_box(ctx, label, fill_color, x, y, s): - draw_fill_rect(ctx, fill_color, (x, y - s, s, s)) - draw_rect(ctx, PROC_BORDER_COLOR, (x, y - s, s, s)) - draw_text(ctx, label, TEXT_COLOR, x + s + 5, y) + draw_fill_rect(ctx, fill_color, (x, y - s, s, s)) + draw_rect(ctx, PROC_BORDER_COLOR, (x, y - s, s, s)) + draw_text(ctx, label, TEXT_COLOR, x + s + 5, y) def draw_legend_line(ctx, label, fill_color, x, y, s): - draw_fill_rect(ctx, fill_color, (x, y - s/2, s + 1, 3)) - ctx.arc(x + (s + 1)/2.0, y - (s - 3)/2.0, 2.5, 0, 2.0 * math.pi) - ctx.fill() - draw_text(ctx, label, TEXT_COLOR, x + s + 5, y) + draw_fill_rect(ctx, fill_color, (x, y - s/2, s + 1, 3)) + ctx.arc(x + (s + 1)/2.0, y - (s - 3)/2.0, 2.5, 0, 2.0 * math.pi) + ctx.fill() + draw_text(ctx, label, TEXT_COLOR, x + s + 5, y) def draw_label_in_box(ctx, color, label, x, y, w, maxx): - label_w = ctx.text_extents(label)[2] - label_x = x + w / 2 - label_w / 2 - if label_w + 10 > w: - label_x = x + w + 5 - if label_x + label_w > maxx: - label_x = x - label_w - 5 - draw_text(ctx, label, color, label_x, y) + label_w = ctx.text_extents(label)[2] + label_x = x + w / 2 - label_w / 2 + if label_w + 10 > w: + label_x = x + w + 5 + if label_x + label_w > maxx: + label_x = x - label_w - 5 + draw_text(ctx, label, color, label_x, y) def draw_sec_labels(ctx, options, rect, sec_w, nsecs): - ctx.set_font_size(AXIS_FONT_SIZE) - prev_x = 0 - for i in range(0, rect[2] + 1, sec_w): - if ((i / sec_w) % nsecs == 0) : - if options.app_options.as_minutes : - label = "%.1f" % (i / sec_w / 60.0) - else : - label = "%d" % (i / sec_w) - label_w = ctx.text_extents(label)[2] - x = rect[0] + i - label_w/2 - if x >= prev_x: - draw_text(ctx, label, TEXT_COLOR, x, rect[1] - 2) - prev_x = x + label_w + ctx.set_font_size(AXIS_FONT_SIZE) + prev_x = 0 + for i in range(0, rect[2] + 1, sec_w): + if ((i / sec_w) % nsecs == 0) : + if options.app_options.as_minutes : + label = "%.1f" % (i / sec_w / 60.0) + else : + label = "%d" % (i / sec_w) + label_w = ctx.text_extents(label)[2] + x = rect[0] + i - label_w/2 + if x >= prev_x: + draw_text(ctx, label, TEXT_COLOR, x, rect[1] - 2) + prev_x = x + label_w def draw_box_ticks(ctx, rect, sec_w): - draw_rect(ctx, BORDER_COLOR, tuple(rect)) - - ctx.set_line_cap(cairo.LINE_CAP_SQUARE) - - for i in range(sec_w, rect[2] + 1, sec_w): - if ((i / sec_w) % 10 == 0) : - ctx.set_line_width(1.5) - elif sec_w < 5 : - continue - else : - ctx.set_line_width(1.0) - if ((i / sec_w) % 30 == 0) : - ctx.set_source_rgba(*TICK_COLOR_BOLD) - else : - ctx.set_source_rgba(*TICK_COLOR) - ctx.move_to(rect[0] + i, rect[1] + 1) - ctx.line_to(rect[0] + i, rect[1] + rect[3] - 1) - ctx.stroke() - ctx.set_line_width(1.0) - - ctx.set_line_cap(cairo.LINE_CAP_BUTT) + draw_rect(ctx, BORDER_COLOR, tuple(rect)) + + ctx.set_line_cap(cairo.LINE_CAP_SQUARE) + + for i in range(sec_w, rect[2] + 1, sec_w): + if ((i / sec_w) % 10 == 0) : + ctx.set_line_width(1.5) + elif sec_w < 5 : + continue + else : + ctx.set_line_width(1.0) + if ((i / sec_w) % 30 == 0) : + ctx.set_source_rgba(*TICK_COLOR_BOLD) + else : + ctx.set_source_rgba(*TICK_COLOR) + ctx.move_to(rect[0] + i, rect[1] + 1) + ctx.line_to(rect[0] + i, rect[1] + rect[3] - 1) + ctx.stroke() + ctx.set_line_width(1.0) + + ctx.set_line_cap(cairo.LINE_CAP_BUTT) def draw_annotations(ctx, proc_tree, times, rect): ctx.set_line_cap(cairo.LINE_CAP_SQUARE) @@ -253,51 +252,51 @@ def draw_annotations(ctx, proc_tree, times, rect): ctx.set_dash([]) def draw_chart(ctx, color, fill, chart_bounds, data, proc_tree, data_range): - ctx.set_line_width(0.5) - x_shift = proc_tree.start_time - - def transform_point_coords(point, x_base, y_base, \ - xscale, yscale, x_trans, y_trans): - x = (point[0] - x_base) * xscale + x_trans - y = (point[1] - y_base) * -yscale + y_trans + chart_bounds[3] - return x, y - - max_x = max (x for (x, y) in data) - max_y = max (y for (x, y) in data) - # avoid divide by zero - if max_y == 0: - max_y = 1.0 - xscale = float (chart_bounds[2]) / (max_x - x_shift) - # If data_range is given, scale the chart so that the value range in - # data_range matches the chart bounds exactly. - # Otherwise, scale so that the actual data matches the chart bounds. - if data_range: - yscale = float(chart_bounds[3]) / (data_range[1] - data_range[0]) - ybase = data_range[0] - else: - yscale = float(chart_bounds[3]) / max_y - ybase = 0 - - first = transform_point_coords (data[0], x_shift, ybase, xscale, yscale, \ - chart_bounds[0], chart_bounds[1]) - last = transform_point_coords (data[-1], x_shift, ybase, xscale, yscale, \ - chart_bounds[0], chart_bounds[1]) - - ctx.set_source_rgba(*color) - ctx.move_to(*first) - for point in data: - x, y = transform_point_coords (point, x_shift, ybase, xscale, yscale, \ - chart_bounds[0], chart_bounds[1]) - ctx.line_to(x, y) - if fill: - ctx.stroke_preserve() - ctx.line_to(last[0], chart_bounds[1]+chart_bounds[3]) - ctx.line_to(first[0], chart_bounds[1]+chart_bounds[3]) - ctx.line_to(first[0], first[1]) - ctx.fill() - else: - ctx.stroke() - ctx.set_line_width(1.0) + ctx.set_line_width(0.5) + x_shift = proc_tree.start_time + + def transform_point_coords(point, x_base, y_base, \ + xscale, yscale, x_trans, y_trans): + x = (point[0] - x_base) * xscale + x_trans + y = (point[1] - y_base) * -yscale + y_trans + chart_bounds[3] + return x, y + + max_x = max (x for (x, y) in data) + max_y = max (y for (x, y) in data) + # avoid divide by zero + if max_y == 0: + max_y = 1.0 + xscale = float (chart_bounds[2]) / (max_x - x_shift) + # If data_range is given, scale the chart so that the value range in + # data_range matches the chart bounds exactly. + # Otherwise, scale so that the actual data matches the chart bounds. + if data_range: + yscale = float(chart_bounds[3]) / (data_range[1] - data_range[0]) + ybase = data_range[0] + else: + yscale = float(chart_bounds[3]) / max_y + ybase = 0 + + first = transform_point_coords (data[0], x_shift, ybase, xscale, yscale, \ + chart_bounds[0], chart_bounds[1]) + last = transform_point_coords (data[-1], x_shift, ybase, xscale, yscale, \ + chart_bounds[0], chart_bounds[1]) + + ctx.set_source_rgba(*color) + ctx.move_to(*first) + for point in data: + x, y = transform_point_coords (point, x_shift, ybase, xscale, yscale, \ + chart_bounds[0], chart_bounds[1]) + ctx.line_to(x, y) + if fill: + ctx.stroke_preserve() + ctx.line_to(last[0], chart_bounds[1]+chart_bounds[3]) + ctx.line_to(first[0], chart_bounds[1]+chart_bounds[3]) + ctx.line_to(first[0], first[1]) + ctx.fill() + else: + ctx.stroke() + ctx.set_line_width(1.0) bar_h = 55 meminfo_bar_h = 2 * bar_h @@ -312,344 +311,338 @@ CUML_HEIGHT = 2000 # Increased value to accomodate CPU and I/O Graphs OPTIONS = None def extents(options, xscale, trace): - start = min(trace.start.keys()) - end = start - - processes = 0 - for proc in trace.processes: - if not options.app_options.show_all and \ - trace.processes[proc][1] - trace.processes[proc][0] < options.app_options.mintime: - continue - - if trace.processes[proc][1] > end: - end = trace.processes[proc][1] - processes += 1 - - if trace.min is not None and trace.max is not None: - start = trace.min - end = trace.max - - w = int ((end - start) * sec_w_base * xscale) + 2 * off_x - h = proc_h * processes + header_h + 2 * off_y - - if options.charts: - if trace.cpu_stats: - h += 30 + bar_h - if trace.disk_stats: - h += 30 + bar_h - if trace.monitor_disk: - h += 30 + bar_h - if trace.mem_stats: - h += meminfo_bar_h - - # Allow for width of process legend and offset - if w < (720 + off_x): - w = 720 + off_x - - return (w, h) + start = min(trace.start.keys()) + end = start + + processes = 0 + for proc in trace.processes: + if not options.app_options.show_all and \ + trace.processes[proc][1] - trace.processes[proc][0] < options.app_options.mintime: + continue + + if trace.processes[proc][1] > end: + end = trace.processes[proc][1] + processes += 1 + + if trace.min is not None and trace.max is not None: + start = trace.min + end = trace.max + + w = int ((end - start) * sec_w_base * xscale) + 2 * off_x + h = proc_h * processes + header_h + 2 * off_y + + if options.charts: + if trace.cpu_stats: + h += 30 + bar_h + if trace.disk_stats: + h += 30 + bar_h + if trace.monitor_disk: + h += 30 + bar_h + if trace.mem_stats: + h += meminfo_bar_h + + return (w, h) def clip_visible(clip, rect): - xmax = max (clip[0], rect[0]) - ymax = max (clip[1], rect[1]) - xmin = min (clip[0] + clip[2], rect[0] + rect[2]) - ymin = min (clip[1] + clip[3], rect[1] + rect[3]) - return (xmin > xmax and ymin > ymax) + xmax = max (clip[0], rect[0]) + ymax = max (clip[1], rect[1]) + xmin = min (clip[0] + clip[2], rect[0] + rect[2]) + ymin = min (clip[1] + clip[3], rect[1] + rect[3]) + return (xmin > xmax and ymin > ymax) def render_charts(ctx, options, clip, trace, curr_y, w, h, sec_w): - proc_tree = options.proc_tree(trace) - - # render bar legend - if trace.cpu_stats: - ctx.set_font_size(LEGEND_FONT_SIZE) - - draw_legend_box(ctx, "CPU (user+sys)", CPU_COLOR, off_x, curr_y+20, leg_s) - draw_legend_box(ctx, "I/O (wait)", IO_COLOR, off_x + 120, curr_y+20, leg_s) - - # render I/O wait - chart_rect = (off_x, curr_y+30, w, bar_h) - if clip_visible (clip, chart_rect): - draw_box_ticks (ctx, chart_rect, sec_w) - draw_annotations (ctx, proc_tree, trace.times, chart_rect) - draw_chart (ctx, IO_COLOR, True, chart_rect, \ - [(sample.time, sample.user + sample.sys + sample.io) for sample in trace.cpu_stats], \ - proc_tree, None) - # render CPU load - draw_chart (ctx, CPU_COLOR, True, chart_rect, \ - [(sample.time, sample.user + sample.sys) for sample in trace.cpu_stats], \ - proc_tree, None) - - curr_y = curr_y + 30 + bar_h - - # render second chart - if trace.disk_stats: - draw_legend_line(ctx, "Disk throughput", DISK_TPUT_COLOR, off_x, curr_y+20, leg_s) - draw_legend_box(ctx, "Disk utilization", IO_COLOR, off_x + 120, curr_y+20, leg_s) - - # render I/O utilization - chart_rect = (off_x, curr_y+30, w, bar_h) - if clip_visible (clip, chart_rect): - draw_box_ticks (ctx, chart_rect, sec_w) - draw_annotations (ctx, proc_tree, trace.times, chart_rect) - draw_chart (ctx, IO_COLOR, True, chart_rect, \ - [(sample.time, sample.util) for sample in trace.disk_stats], \ - proc_tree, None) - - # render disk throughput - max_sample = max (trace.disk_stats, key = lambda s: s.tput) - if clip_visible (clip, chart_rect): - draw_chart (ctx, DISK_TPUT_COLOR, False, chart_rect, \ - [(sample.time, sample.tput) for sample in trace.disk_stats], \ - proc_tree, None) - - pos_x = off_x + ((max_sample.time - proc_tree.start_time) * w / proc_tree.duration) - - shift_x, shift_y = -20, 20 - if (pos_x < off_x + 245): - shift_x, shift_y = 5, 40 - - label = "%dMB/s" % round ((max_sample.tput) / 1024.0) - draw_text (ctx, label, DISK_TPUT_COLOR, pos_x + shift_x, curr_y + shift_y) - - curr_y = curr_y + 30 + bar_h - - # render disk space usage - # - # Draws the amount of disk space used on each volume relative to the - # lowest recorded amount. The graphs for each volume are stacked above - # each other so that total disk usage is visible. - if trace.monitor_disk: - ctx.set_font_size(LEGEND_FONT_SIZE) - # Determine set of volumes for which we have - # information and the minimal amount of used disk - # space for each. Currently samples are allowed to - # not have a values for all volumes; drawing could be - # made more efficient if that wasn't the case. - volumes = set() - min_used = {} - for sample in trace.monitor_disk: - for volume, used in sample.records.items(): - volumes.add(volume) - if volume not in min_used or min_used[volume] > used: - min_used[volume] = used - volumes = sorted(list(volumes)) - disk_scale = 0 - for i, volume in enumerate(volumes): - volume_scale = max([sample.records[volume] - min_used[volume] - for sample in trace.monitor_disk - if volume in sample.records]) - # Does not take length of volume name into account, but fixed offset - # works okay in practice. - draw_legend_box(ctx, '%s (max: %u MiB)' % (volume, volume_scale / 1024 / 1024), - VOLUME_COLORS[i % len(VOLUME_COLORS)], - off_x + i * 250, curr_y+20, leg_s) - disk_scale += volume_scale - - # render used amount of disk space - chart_rect = (off_x, curr_y+30, w, bar_h) - if clip_visible (clip, chart_rect): - draw_box_ticks (ctx, chart_rect, sec_w) - draw_annotations (ctx, proc_tree, trace.times, chart_rect) - for i in range(len(volumes), 0, -1): - draw_chart (ctx, VOLUME_COLORS[(i - 1) % len(VOLUME_COLORS)], True, chart_rect, \ - [(sample.time, - # Sum up used space of all volumes including the current one - # so that the graphs appear as stacked on top of each other. - functools.reduce(lambda x,y: x+y, - [sample.records[volume] - min_used[volume] - for volume in volumes[0:i] - if volume in sample.records], - 0)) - for sample in trace.monitor_disk], \ - proc_tree, [0, disk_scale]) - - curr_y = curr_y + 30 + bar_h - - # render mem usage - chart_rect = (off_x, curr_y+30, w, meminfo_bar_h) - mem_stats = trace.mem_stats - if mem_stats and clip_visible (clip, chart_rect): - mem_scale = max(sample.buffers for sample in mem_stats) - draw_legend_box(ctx, "Mem cached (scale: %u MiB)" % (float(mem_scale) / 1024), MEM_CACHED_COLOR, off_x, curr_y+20, leg_s) - draw_legend_box(ctx, "Used", MEM_USED_COLOR, off_x + 240, curr_y+20, leg_s) - draw_legend_box(ctx, "Buffers", MEM_BUFFERS_COLOR, off_x + 360, curr_y+20, leg_s) - draw_legend_line(ctx, "Swap (scale: %u MiB)" % max([(sample.swap)/1024 for sample in mem_stats]), \ - MEM_SWAP_COLOR, off_x + 480, curr_y+20, leg_s) - draw_box_ticks(ctx, chart_rect, sec_w) - draw_annotations(ctx, proc_tree, trace.times, chart_rect) - draw_chart(ctx, MEM_BUFFERS_COLOR, True, chart_rect, \ - [(sample.time, sample.buffers) for sample in trace.mem_stats], \ - proc_tree, [0, mem_scale]) - draw_chart(ctx, MEM_USED_COLOR, True, chart_rect, \ - [(sample.time, sample.used) for sample in mem_stats], \ - proc_tree, [0, mem_scale]) - draw_chart(ctx, MEM_CACHED_COLOR, True, chart_rect, \ - [(sample.time, sample.cached) for sample in mem_stats], \ - proc_tree, [0, mem_scale]) - draw_chart(ctx, MEM_SWAP_COLOR, False, chart_rect, \ - [(sample.time, float(sample.swap)) for sample in mem_stats], \ - proc_tree, None) - - curr_y = curr_y + meminfo_bar_h - - return curr_y + proc_tree = options.proc_tree(trace) + + # render bar legend + if trace.cpu_stats: + ctx.set_font_size(LEGEND_FONT_SIZE) + + draw_legend_box(ctx, "CPU (user+sys)", CPU_COLOR, off_x, curr_y+20, leg_s) + draw_legend_box(ctx, "I/O (wait)", IO_COLOR, off_x + 120, curr_y+20, leg_s) + + # render I/O wait + chart_rect = (off_x, curr_y+30, w, bar_h) + if clip_visible (clip, chart_rect): + draw_box_ticks (ctx, chart_rect, sec_w) + draw_annotations (ctx, proc_tree, trace.times, chart_rect) + draw_chart (ctx, IO_COLOR, True, chart_rect, \ + [(sample.time, sample.user + sample.sys + sample.io) for sample in trace.cpu_stats], \ + proc_tree, None) + # render CPU load + draw_chart (ctx, CPU_COLOR, True, chart_rect, \ + [(sample.time, sample.user + sample.sys) for sample in trace.cpu_stats], \ + proc_tree, None) + + curr_y = curr_y + 30 + bar_h + + # render second chart + if trace.disk_stats: + draw_legend_line(ctx, "Disk throughput", DISK_TPUT_COLOR, off_x, curr_y+20, leg_s) + draw_legend_box(ctx, "Disk utilization", IO_COLOR, off_x + 120, curr_y+20, leg_s) + + # render I/O utilization + chart_rect = (off_x, curr_y+30, w, bar_h) + if clip_visible (clip, chart_rect): + draw_box_ticks (ctx, chart_rect, sec_w) + draw_annotations (ctx, proc_tree, trace.times, chart_rect) + draw_chart (ctx, IO_COLOR, True, chart_rect, \ + [(sample.time, sample.util) for sample in trace.disk_stats], \ + proc_tree, None) + + # render disk throughput + max_sample = max (trace.disk_stats, key = lambda s: s.tput) + if clip_visible (clip, chart_rect): + draw_chart (ctx, DISK_TPUT_COLOR, False, chart_rect, \ + [(sample.time, sample.tput) for sample in trace.disk_stats], \ + proc_tree, None) + + pos_x = off_x + ((max_sample.time - proc_tree.start_time) * w / proc_tree.duration) + + shift_x, shift_y = -20, 20 + if (pos_x < off_x + 245): + shift_x, shift_y = 5, 40 + + label = "%dMB/s" % round ((max_sample.tput) / 1024.0) + draw_text (ctx, label, DISK_TPUT_COLOR, pos_x + shift_x, curr_y + shift_y) + + curr_y = curr_y + 30 + bar_h + + # render disk space usage + # + # Draws the amount of disk space used on each volume relative to the + # lowest recorded amount. The graphs for each volume are stacked above + # each other so that total disk usage is visible. + if trace.monitor_disk: + ctx.set_font_size(LEGEND_FONT_SIZE) + # Determine set of volumes for which we have + # information and the minimal amount of used disk + # space for each. Currently samples are allowed to + # not have a values for all volumes; drawing could be + # made more efficient if that wasn't the case. + volumes = set() + min_used = {} + for sample in trace.monitor_disk: + for volume, used in sample.records.items(): + volumes.add(volume) + if volume not in min_used or min_used[volume] > used: + min_used[volume] = used + volumes = sorted(list(volumes)) + disk_scale = 0 + for i, volume in enumerate(volumes): + volume_scale = max([sample.records[volume] - min_used[volume] + for sample in trace.monitor_disk + if volume in sample.records]) + # Does not take length of volume name into account, but fixed offset + # works okay in practice. + draw_legend_box(ctx, '%s (max: %u MiB)' % (volume, volume_scale / 1024 / 1024), + VOLUME_COLORS[i % len(VOLUME_COLORS)], + off_x + i * 250, curr_y+20, leg_s) + disk_scale += volume_scale + + # render used amount of disk space + chart_rect = (off_x, curr_y+30, w, bar_h) + if clip_visible (clip, chart_rect): + draw_box_ticks (ctx, chart_rect, sec_w) + draw_annotations (ctx, proc_tree, trace.times, chart_rect) + for i in range(len(volumes), 0, -1): + draw_chart (ctx, VOLUME_COLORS[(i - 1) % len(VOLUME_COLORS)], True, chart_rect, \ + [(sample.time, + # Sum up used space of all volumes including the current one + # so that the graphs appear as stacked on top of each other. + reduce(lambda x,y: x+y, + [sample.records[volume] - min_used[volume] + for volume in volumes[0:i] + if volume in sample.records], + 0)) + for sample in trace.monitor_disk], \ + proc_tree, [0, disk_scale]) + + curr_y = curr_y + 30 + bar_h + + # render mem usage + chart_rect = (off_x, curr_y+30, w, meminfo_bar_h) + mem_stats = trace.mem_stats + if mem_stats and clip_visible (clip, chart_rect): + mem_scale = max(sample.buffers for sample in mem_stats) + draw_legend_box(ctx, "Mem cached (scale: %u MiB)" % (float(mem_scale) / 1024), MEM_CACHED_COLOR, off_x, curr_y+20, leg_s) + draw_legend_box(ctx, "Used", MEM_USED_COLOR, off_x + 240, curr_y+20, leg_s) + draw_legend_box(ctx, "Buffers", MEM_BUFFERS_COLOR, off_x + 360, curr_y+20, leg_s) + draw_legend_line(ctx, "Swap (scale: %u MiB)" % max([(sample.swap)/1024 for sample in mem_stats]), \ + MEM_SWAP_COLOR, off_x + 480, curr_y+20, leg_s) + draw_box_ticks(ctx, chart_rect, sec_w) + draw_annotations(ctx, proc_tree, trace.times, chart_rect) + draw_chart(ctx, MEM_BUFFERS_COLOR, True, chart_rect, \ + [(sample.time, sample.buffers) for sample in trace.mem_stats], \ + proc_tree, [0, mem_scale]) + draw_chart(ctx, MEM_USED_COLOR, True, chart_rect, \ + [(sample.time, sample.used) for sample in mem_stats], \ + proc_tree, [0, mem_scale]) + draw_chart(ctx, MEM_CACHED_COLOR, True, chart_rect, \ + [(sample.time, sample.cached) for sample in mem_stats], \ + proc_tree, [0, mem_scale]) + draw_chart(ctx, MEM_SWAP_COLOR, False, chart_rect, \ + [(sample.time, float(sample.swap)) for sample in mem_stats], \ + proc_tree, None) + + curr_y = curr_y + meminfo_bar_h + + return curr_y def render_processes_chart(ctx, options, trace, curr_y, w, h, sec_w): - chart_rect = [off_x, curr_y+header_h, w, h - curr_y - 1 * off_y - header_h ] - - draw_legend_box (ctx, "Configure", \ - TASK_COLOR_CONFIGURE, off_x , curr_y + 45, leg_s) - draw_legend_box (ctx, "Compile", \ - TASK_COLOR_COMPILE, off_x+120, curr_y + 45, leg_s) - draw_legend_box (ctx, "Install", \ - TASK_COLOR_INSTALL, off_x+240, curr_y + 45, leg_s) - draw_legend_box (ctx, "Populate Sysroot", \ - TASK_COLOR_SYSROOT, off_x+360, curr_y + 45, leg_s) - draw_legend_box (ctx, "Package", \ - TASK_COLOR_PACKAGE, off_x+480, curr_y + 45, leg_s) - draw_legend_box (ctx, "Package Write", \ - TASK_COLOR_PACKAGE_WRITE, off_x+600, curr_y + 45, leg_s) - - ctx.set_font_size(PROC_TEXT_FONT_SIZE) - - draw_box_ticks(ctx, chart_rect, sec_w) - draw_sec_labels(ctx, options, chart_rect, sec_w, 30) - - y = curr_y+header_h - - offset = trace.min or min(trace.start.keys()) - for start in sorted(trace.start.keys()): - for process in sorted(trace.start[start]): - if not options.app_options.show_all and \ - trace.processes[process][1] - start < options.app_options.mintime: - continue - task = process.split(":")[1] - - #print(process) - #print(trace.processes[process][1]) - #print(s) - - x = chart_rect[0] + (start - offset) * sec_w - w = ((trace.processes[process][1] - start) * sec_w) - - #print("proc at %s %s %s %s" % (x, y, w, proc_h)) - col = None - if task == "do_compile": - col = TASK_COLOR_COMPILE - elif task == "do_configure": - col = TASK_COLOR_CONFIGURE - elif task == "do_install": - col = TASK_COLOR_INSTALL - elif task == "do_populate_sysroot": - col = TASK_COLOR_SYSROOT - elif task == "do_package": - col = TASK_COLOR_PACKAGE - elif task == "do_package_write_rpm" or \ + chart_rect = [off_x, curr_y+header_h, w, h - 2 * off_y - header_h - leg_s + proc_h] + + draw_legend_box (ctx, "Configure", \ + TASK_COLOR_CONFIGURE, off_x , curr_y + 45, leg_s) + draw_legend_box (ctx, "Compile", \ + TASK_COLOR_COMPILE, off_x+120, curr_y + 45, leg_s) + draw_legend_box (ctx, "Install", \ + TASK_COLOR_INSTALL, off_x+240, curr_y + 45, leg_s) + draw_legend_box (ctx, "Populate Sysroot", \ + TASK_COLOR_SYSROOT, off_x+360, curr_y + 45, leg_s) + draw_legend_box (ctx, "Package", \ + TASK_COLOR_PACKAGE, off_x+480, curr_y + 45, leg_s) + draw_legend_box (ctx, "Package Write", + TASK_COLOR_PACKAGE_WRITE, off_x+600, curr_y + 45, leg_s) + + ctx.set_font_size(PROC_TEXT_FONT_SIZE) + + draw_box_ticks(ctx, chart_rect, sec_w) + draw_sec_labels(ctx, options, chart_rect, sec_w, 30) + + y = curr_y+header_h + + offset = trace.min or min(trace.start.keys()) + for s in sorted(trace.start.keys()): + for val in sorted(trace.start[s]): + if not options.app_options.show_all and \ + trace.processes[val][1] - s < options.app_options.mintime: + continue + task = val.split(":")[1] + #print val + #print trace.processes[val][1] + #print s + x = chart_rect[0] + (s - offset) * sec_w + w = ((trace.processes[val][1] - s) * sec_w) + + #print "proc at %s %s %s %s" % (x, y, w, proc_h) + col = None + if task == "do_compile": + col = TASK_COLOR_COMPILE + elif task == "do_configure": + col = TASK_COLOR_CONFIGURE + elif task == "do_install": + col = TASK_COLOR_INSTALL + elif task == "do_populate_sysroot": + col = TASK_COLOR_SYSROOT + elif task == "do_package": + col = TASK_COLOR_PACKAGE + elif task == "do_package_write_rpm" or \ task == "do_package_write_deb" or \ task == "do_package_write_ipk": - col = TASK_COLOR_PACKAGE_WRITE - else: - col = WHITE + col = TASK_COLOR_PACKAGE_WRITE + else: + col = WHITE - if col: - draw_fill_rect(ctx, col, (x, y, w, proc_h)) - draw_rect(ctx, PROC_BORDER_COLOR, (x, y, w, proc_h)) + if col: + draw_fill_rect(ctx, col, (x, y, w, proc_h)) + draw_rect(ctx, PROC_BORDER_COLOR, (x, y, w, proc_h)) - draw_label_in_box(ctx, PROC_TEXT_COLOR, process, x, y + proc_h - 4, w, proc_h) - y = y + proc_h + draw_label_in_box(ctx, PROC_TEXT_COLOR, val, x, y + proc_h - 4, w, proc_h) + y = y + proc_h - return curr_y + return curr_y # # Render the chart. # def render(ctx, options, xscale, trace): - (w, h) = extents (options, xscale, trace) - global OPTIONS - OPTIONS = options.app_options + (w, h) = extents (options, xscale, trace) + global OPTIONS + OPTIONS = options.app_options - # x, y, w, h - clip = ctx.clip_extents() + # x, y, w, h + clip = ctx.clip_extents() - sec_w = int (xscale * sec_w_base) - ctx.set_line_width(1.0) - ctx.select_font_face(FONT_NAME) - draw_fill_rect(ctx, WHITE, (0, 0, max(w, MIN_IMG_W), h)) - w -= 2*off_x - curr_y = off_y; + sec_w = int (xscale * sec_w_base) + ctx.set_line_width(1.0) + ctx.select_font_face(FONT_NAME) + draw_fill_rect(ctx, WHITE, (0, 0, max(w, MIN_IMG_W), h)) + w -= 2*off_x + curr_y = off_y; - if options.charts: - curr_y = render_charts (ctx, options, clip, trace, curr_y, w, h, sec_w) + if options.charts: + curr_y = render_charts (ctx, options, clip, trace, curr_y, w, h, sec_w) - curr_y = render_processes_chart (ctx, options, trace, curr_y, w, h, sec_w) + curr_y = render_processes_chart (ctx, options, trace, curr_y, w, h, sec_w) - return + return - proc_tree = options.proc_tree (trace) + proc_tree = options.proc_tree (trace) - # draw the title and headers - if proc_tree.idle: - duration = proc_tree.idle - else: - duration = proc_tree.duration + # draw the title and headers + if proc_tree.idle: + duration = proc_tree.idle + else: + duration = proc_tree.duration - if not options.kernel_only: - curr_y = draw_header (ctx, trace.headers, duration) - else: - curr_y = off_y; + if not options.kernel_only: + curr_y = draw_header (ctx, trace.headers, duration) + else: + curr_y = off_y; - # draw process boxes - proc_height = h - if proc_tree.taskstats and options.cumulative: - proc_height -= CUML_HEIGHT + # draw process boxes + proc_height = h + if proc_tree.taskstats and options.cumulative: + proc_height -= CUML_HEIGHT - draw_process_bar_chart(ctx, clip, options, proc_tree, trace.times, - curr_y, w, proc_height, sec_w) + draw_process_bar_chart(ctx, clip, options, proc_tree, trace.times, + curr_y, w, proc_height, sec_w) - curr_y = proc_height - ctx.set_font_size(SIG_FONT_SIZE) - draw_text(ctx, SIGNATURE, SIG_COLOR, off_x + 5, proc_height - 8) + curr_y = proc_height + ctx.set_font_size(SIG_FONT_SIZE) + draw_text(ctx, SIGNATURE, SIG_COLOR, off_x + 5, proc_height - 8) - # draw a cumulative CPU-time-per-process graph - if proc_tree.taskstats and options.cumulative: - cuml_rect = (off_x, curr_y + off_y, w, CUML_HEIGHT/2 - off_y * 2) - if clip_visible (clip, cuml_rect): - draw_cuml_graph(ctx, proc_tree, cuml_rect, duration, sec_w, STAT_TYPE_CPU) + # draw a cumulative CPU-time-per-process graph + if proc_tree.taskstats and options.cumulative: + cuml_rect = (off_x, curr_y + off_y, w, CUML_HEIGHT/2 - off_y * 2) + if clip_visible (clip, cuml_rect): + draw_cuml_graph(ctx, proc_tree, cuml_rect, duration, sec_w, STAT_TYPE_CPU) - # draw a cumulative I/O-time-per-process graph - if proc_tree.taskstats and options.cumulative: - cuml_rect = (off_x, curr_y + off_y * 100, w, CUML_HEIGHT/2 - off_y * 2) - if clip_visible (clip, cuml_rect): - draw_cuml_graph(ctx, proc_tree, cuml_rect, duration, sec_w, STAT_TYPE_IO) + # draw a cumulative I/O-time-per-process graph + if proc_tree.taskstats and options.cumulative: + cuml_rect = (off_x, curr_y + off_y * 100, w, CUML_HEIGHT/2 - off_y * 2) + if clip_visible (clip, cuml_rect): + draw_cuml_graph(ctx, proc_tree, cuml_rect, duration, sec_w, STAT_TYPE_IO) def draw_process_bar_chart(ctx, clip, options, proc_tree, times, curr_y, w, h, sec_w): - header_size = 0 - if not options.kernel_only: - draw_legend_box (ctx, "Running (%cpu)", - PROC_COLOR_R, off_x , curr_y + 45, leg_s) - draw_legend_box (ctx, "Unint.sleep (I/O)", - PROC_COLOR_D, off_x+120, curr_y + 45, leg_s) - draw_legend_box (ctx, "Sleeping", - PROC_COLOR_S, off_x+240, curr_y + 45, leg_s) - draw_legend_box (ctx, "Zombie", - PROC_COLOR_Z, off_x+360, curr_y + 45, leg_s) - header_size = 45 - - chart_rect = [off_x, curr_y + header_size + 15, - w, h - 2 * off_y - (curr_y + header_size + 15) + proc_h] - ctx.set_font_size (PROC_TEXT_FONT_SIZE) - - draw_box_ticks (ctx, chart_rect, sec_w) - if sec_w > 100: - nsec = 1 - else: - nsec = 5 - draw_sec_labels (ctx, options, chart_rect, sec_w, nsec) - draw_annotations (ctx, proc_tree, times, chart_rect) - - y = curr_y + 60 - for root in proc_tree.process_tree: - draw_processes_recursively(ctx, root, proc_tree, y, proc_h, chart_rect, clip) - y = y + proc_h * proc_tree.num_nodes([root]) + header_size = 0 + if not options.kernel_only: + draw_legend_box (ctx, "Running (%cpu)", + PROC_COLOR_R, off_x , curr_y + 45, leg_s) + draw_legend_box (ctx, "Unint.sleep (I/O)", + PROC_COLOR_D, off_x+120, curr_y + 45, leg_s) + draw_legend_box (ctx, "Sleeping", + PROC_COLOR_S, off_x+240, curr_y + 45, leg_s) + draw_legend_box (ctx, "Zombie", + PROC_COLOR_Z, off_x+360, curr_y + 45, leg_s) + header_size = 45 + + chart_rect = [off_x, curr_y + header_size + 15, + w, h - 2 * off_y - (curr_y + header_size + 15) + proc_h] + ctx.set_font_size (PROC_TEXT_FONT_SIZE) + + draw_box_ticks (ctx, chart_rect, sec_w) + if sec_w > 100: + nsec = 1 + else: + nsec = 5 + draw_sec_labels (ctx, options, chart_rect, sec_w, nsec) + draw_annotations (ctx, proc_tree, times, chart_rect) + + y = curr_y + 60 + for root in proc_tree.process_tree: + draw_processes_recursively(ctx, root, proc_tree, y, proc_h, chart_rect, clip) + y = y + proc_h * proc_tree.num_nodes([root]) def draw_header (ctx, headers, duration): @@ -685,291 +678,291 @@ def draw_header (ctx, headers, duration): return header_y def draw_processes_recursively(ctx, proc, proc_tree, y, proc_h, rect, clip) : - x = rect[0] + ((proc.start_time - proc_tree.start_time) * rect[2] / proc_tree.duration) - w = ((proc.duration) * rect[2] / proc_tree.duration) - - draw_process_activity_colors(ctx, proc, proc_tree, x, y, w, proc_h, rect, clip) - draw_rect(ctx, PROC_BORDER_COLOR, (x, y, w, proc_h)) - ipid = int(proc.pid) - if not OPTIONS.show_all: - cmdString = proc.cmd - else: - cmdString = '' - if (OPTIONS.show_pid or OPTIONS.show_all) and ipid is not 0: - cmdString = cmdString + " [" + str(ipid // 1000) + "]" - if OPTIONS.show_all: - if proc.args: - cmdString = cmdString + " '" + "' '".join(proc.args) + "'" - else: - cmdString = cmdString + " " + proc.exe - - draw_label_in_box(ctx, PROC_TEXT_COLOR, cmdString, x, y + proc_h - 4, w, rect[0] + rect[2]) - - next_y = y + proc_h - for child in proc.child_list: - if next_y > clip[1] + clip[3]: - break - child_x, child_y = draw_processes_recursively(ctx, child, proc_tree, next_y, proc_h, rect, clip) - draw_process_connecting_lines(ctx, x, y, child_x, child_y, proc_h) - next_y = next_y + proc_h * proc_tree.num_nodes([child]) - - return x, y + x = rect[0] + ((proc.start_time - proc_tree.start_time) * rect[2] / proc_tree.duration) + w = ((proc.duration) * rect[2] / proc_tree.duration) + + draw_process_activity_colors(ctx, proc, proc_tree, x, y, w, proc_h, rect, clip) + draw_rect(ctx, PROC_BORDER_COLOR, (x, y, w, proc_h)) + ipid = int(proc.pid) + if not OPTIONS.show_all: + cmdString = proc.cmd + else: + cmdString = '' + if (OPTIONS.show_pid or OPTIONS.show_all) and ipid is not 0: + cmdString = cmdString + " [" + str(ipid // 1000) + "]" + if OPTIONS.show_all: + if proc.args: + cmdString = cmdString + " '" + "' '".join(proc.args) + "'" + else: + cmdString = cmdString + " " + proc.exe + + draw_label_in_box(ctx, PROC_TEXT_COLOR, cmdString, x, y + proc_h - 4, w, rect[0] + rect[2]) + + next_y = y + proc_h + for child in proc.child_list: + if next_y > clip[1] + clip[3]: + break + child_x, child_y = draw_processes_recursively(ctx, child, proc_tree, next_y, proc_h, rect, clip) + draw_process_connecting_lines(ctx, x, y, child_x, child_y, proc_h) + next_y = next_y + proc_h * proc_tree.num_nodes([child]) + + return x, y def draw_process_activity_colors(ctx, proc, proc_tree, x, y, w, proc_h, rect, clip): - if y > clip[1] + clip[3] or y + proc_h + 2 < clip[1]: - return + if y > clip[1] + clip[3] or y + proc_h + 2 < clip[1]: + return - draw_fill_rect(ctx, PROC_COLOR_S, (x, y, w, proc_h)) + draw_fill_rect(ctx, PROC_COLOR_S, (x, y, w, proc_h)) - last_tx = -1 - for sample in proc.samples : - tx = rect[0] + round(((sample.time - proc_tree.start_time) * rect[2] / proc_tree.duration)) + last_tx = -1 + for sample in proc.samples : + tx = rect[0] + round(((sample.time - proc_tree.start_time) * rect[2] / proc_tree.duration)) - # samples are sorted chronologically - if tx < clip[0]: - continue - if tx > clip[0] + clip[2]: - break + # samples are sorted chronologically + if tx < clip[0]: + continue + if tx > clip[0] + clip[2]: + break - tw = round(proc_tree.sample_period * rect[2] / float(proc_tree.duration)) - if last_tx != -1 and abs(last_tx - tx) <= tw: - tw -= last_tx - tx - tx = last_tx - tw = max (tw, 1) # nice to see at least something + tw = round(proc_tree.sample_period * rect[2] / float(proc_tree.duration)) + if last_tx != -1 and abs(last_tx - tx) <= tw: + tw -= last_tx - tx + tx = last_tx + tw = max (tw, 1) # nice to see at least something - last_tx = tx + tw - state = get_proc_state( sample.state ) + last_tx = tx + tw + state = get_proc_state( sample.state ) - color = STATE_COLORS[state] - if state == STATE_RUNNING: - alpha = min (sample.cpu_sample.user + sample.cpu_sample.sys, 1.0) - color = tuple(list(PROC_COLOR_R[0:3]) + [alpha]) -# print "render time %d [ tx %d tw %d ], sample state %s color %s alpha %g" % (sample.time, tx, tw, state, color, alpha) - elif state == STATE_SLEEPING: - continue + color = STATE_COLORS[state] + if state == STATE_RUNNING: + alpha = min (sample.cpu_sample.user + sample.cpu_sample.sys, 1.0) + color = tuple(list(PROC_COLOR_R[0:3]) + [alpha]) +# print "render time %d [ tx %d tw %d ], sample state %s color %s alpha %g" % (sample.time, tx, tw, state, color, alpha) + elif state == STATE_SLEEPING: + continue - draw_fill_rect(ctx, color, (tx, y, tw, proc_h)) + draw_fill_rect(ctx, color, (tx, y, tw, proc_h)) def draw_process_connecting_lines(ctx, px, py, x, y, proc_h): - ctx.set_source_rgba(*DEP_COLOR) - ctx.set_dash([2, 2]) - if abs(px - x) < 3: - dep_off_x = 3 - dep_off_y = proc_h / 4 - ctx.move_to(x, y + proc_h / 2) - ctx.line_to(px - dep_off_x, y + proc_h / 2) - ctx.line_to(px - dep_off_x, py - dep_off_y) - ctx.line_to(px, py - dep_off_y) - else: - ctx.move_to(x, y + proc_h / 2) - ctx.line_to(px, y + proc_h / 2) - ctx.line_to(px, py) - ctx.stroke() - ctx.set_dash([]) + ctx.set_source_rgba(*DEP_COLOR) + ctx.set_dash([2, 2]) + if abs(px - x) < 3: + dep_off_x = 3 + dep_off_y = proc_h / 4 + ctx.move_to(x, y + proc_h / 2) + ctx.line_to(px - dep_off_x, y + proc_h / 2) + ctx.line_to(px - dep_off_x, py - dep_off_y) + ctx.line_to(px, py - dep_off_y) + else: + ctx.move_to(x, y + proc_h / 2) + ctx.line_to(px, y + proc_h / 2) + ctx.line_to(px, py) + ctx.stroke() + ctx.set_dash([]) # elide the bootchart collector - it is quite distorting def elide_bootchart(proc): - return proc.cmd == 'bootchartd' or proc.cmd == 'bootchart-colle' + return proc.cmd == 'bootchartd' or proc.cmd == 'bootchart-colle' class CumlSample: - def __init__(self, proc): - self.cmd = proc.cmd - self.samples = [] - self.merge_samples (proc) - self.color = None - - def merge_samples(self, proc): - self.samples.extend (proc.samples) - self.samples.sort (key = lambda p: p.time) - - def next(self): - global palette_idx - palette_idx += HSV_STEP - return palette_idx - - def get_color(self): - if self.color is None: - i = self.next() % HSV_MAX_MOD - h = 0.0 - if i is not 0: - h = (1.0 * i) / HSV_MAX_MOD - s = 0.5 - v = 1.0 - c = colorsys.hsv_to_rgb (h, s, v) - self.color = (c[0], c[1], c[2], 1.0) - return self.color + def __init__(self, proc): + self.cmd = proc.cmd + self.samples = [] + self.merge_samples (proc) + self.color = None + + def merge_samples(self, proc): + self.samples.extend (proc.samples) + self.samples.sort (key = lambda p: p.time) + + def next(self): + global palette_idx + palette_idx += HSV_STEP + return palette_idx + + def get_color(self): + if self.color is None: + i = self.next() % HSV_MAX_MOD + h = 0.0 + if i is not 0: + h = (1.0 * i) / HSV_MAX_MOD + s = 0.5 + v = 1.0 + c = colorsys.hsv_to_rgb (h, s, v) + self.color = (c[0], c[1], c[2], 1.0) + return self.color def draw_cuml_graph(ctx, proc_tree, chart_bounds, duration, sec_w, stat_type): - global palette_idx - palette_idx = 0 - - time_hash = {} - total_time = 0.0 - m_proc_list = {} - - if stat_type is STAT_TYPE_CPU: - sample_value = 'cpu' - else: - sample_value = 'io' - for proc in proc_tree.process_list: - if elide_bootchart(proc): - continue - - for sample in proc.samples: - total_time += getattr(sample.cpu_sample, sample_value) - if not sample.time in time_hash: - time_hash[sample.time] = 1 - - # merge pids with the same cmd - if not proc.cmd in m_proc_list: - m_proc_list[proc.cmd] = CumlSample (proc) - continue - s = m_proc_list[proc.cmd] - s.merge_samples (proc) - - # all the sample times - times = sorted(time_hash) - if len (times) < 2: - print("degenerate boot chart") - return - - pix_per_ns = chart_bounds[3] / total_time -# print "total time: %g pix-per-ns %g" % (total_time, pix_per_ns) - - # FIXME: we have duplicates in the process list too [!] - why !? - - # Render bottom up, left to right - below = {} - for time in times: - below[time] = chart_bounds[1] + chart_bounds[3] - - # same colors each time we render - random.seed (0) - - ctx.set_line_width(1) - - legends = [] - labels = [] - - # render each pid in order - for cs in m_proc_list.values(): - row = {} - cuml = 0.0 - - # print "pid : %s -> %g samples %d" % (proc.cmd, cuml, len (cs.samples)) - for sample in cs.samples: - cuml += getattr(sample.cpu_sample, sample_value) - row[sample.time] = cuml - - process_total_time = cuml - - # hide really tiny processes - if cuml * pix_per_ns <= 2: - continue - - last_time = times[0] - y = last_below = below[last_time] - last_cuml = cuml = 0.0 - - ctx.set_source_rgba(*cs.get_color()) - for time in times: - render_seg = False - - # did the underlying trend increase ? - if below[time] != last_below: - last_below = below[last_time] - last_cuml = cuml - render_seg = True - - # did we move up a pixel increase ? - if time in row: - nc = round (row[time] * pix_per_ns) - if nc != cuml: - last_cuml = cuml - cuml = nc - render_seg = True - -# if last_cuml > cuml: -# assert fail ... - un-sorted process samples - - # draw the trailing rectangle from the last time to - # before now, at the height of the last segment. - if render_seg: - w = math.ceil ((time - last_time) * chart_bounds[2] / proc_tree.duration) + 1 - x = chart_bounds[0] + round((last_time - proc_tree.start_time) * chart_bounds[2] / proc_tree.duration) - ctx.rectangle (x, below[last_time] - last_cuml, w, last_cuml) - ctx.fill() -# ctx.stroke() - last_time = time - y = below [time] - cuml - - row[time] = y - - # render the last segment - x = chart_bounds[0] + round((last_time - proc_tree.start_time) * chart_bounds[2] / proc_tree.duration) - y = below[last_time] - cuml - ctx.rectangle (x, y, chart_bounds[2] - x, cuml) - ctx.fill() -# ctx.stroke() - - # render legend if it will fit - if cuml > 8: - label = cs.cmd - extnts = ctx.text_extents(label) - label_w = extnts[2] - label_h = extnts[3] -# print "Text extents %g by %g" % (label_w, label_h) - labels.append((label, - chart_bounds[0] + chart_bounds[2] - label_w - off_x * 2, - y + (cuml + label_h) / 2)) - if cs in legends: - print("ARGH - duplicate process in list !") - - legends.append ((cs, process_total_time)) - - below = row - - # render grid-lines over the top - draw_box_ticks(ctx, chart_bounds, sec_w) - - # render labels - for l in labels: - draw_text(ctx, l[0], TEXT_COLOR, l[1], l[2]) - - # Render legends - font_height = 20 - label_width = 300 - LEGENDS_PER_COL = 15 - LEGENDS_TOTAL = 45 - ctx.set_font_size (TITLE_FONT_SIZE) - dur_secs = duration / 100 - cpu_secs = total_time / 1000000000 - - # misleading - with multiple CPUs ... -# idle = ((dur_secs - cpu_secs) / dur_secs) * 100.0 - if stat_type is STAT_TYPE_CPU: - label = "Cumulative CPU usage, by process; total CPU: " \ - " %.5g(s) time: %.3g(s)" % (cpu_secs, dur_secs) - else: - label = "Cumulative I/O usage, by process; total I/O: " \ - " %.5g(s) time: %.3g(s)" % (cpu_secs, dur_secs) - - draw_text(ctx, label, TEXT_COLOR, chart_bounds[0] + off_x, - chart_bounds[1] + font_height) - - i = 0 - legends = sorted(legends, key=itemgetter(1), reverse=True) - ctx.set_font_size(TEXT_FONT_SIZE) - for t in legends: - cs = t[0] - time = t[1] - x = chart_bounds[0] + off_x + int (i/LEGENDS_PER_COL) * label_width - y = chart_bounds[1] + font_height * ((i % LEGENDS_PER_COL) + 2) - str = "%s - %.0f(ms) (%2.2f%%)" % (cs.cmd, time/1000000, (time/total_time) * 100.0) - draw_legend_box(ctx, str, cs.color, x, y, leg_s) - i = i + 1 - if i >= LEGENDS_TOTAL: - break + global palette_idx + palette_idx = 0 + + time_hash = {} + total_time = 0.0 + m_proc_list = {} + + if stat_type is STAT_TYPE_CPU: + sample_value = 'cpu' + else: + sample_value = 'io' + for proc in proc_tree.process_list: + if elide_bootchart(proc): + continue + + for sample in proc.samples: + total_time += getattr(sample.cpu_sample, sample_value) + if not sample.time in time_hash: + time_hash[sample.time] = 1 + + # merge pids with the same cmd + if not proc.cmd in m_proc_list: + m_proc_list[proc.cmd] = CumlSample (proc) + continue + s = m_proc_list[proc.cmd] + s.merge_samples (proc) + + # all the sample times + times = sorted(time_hash) + if len (times) < 2: + print("degenerate boot chart") + return + + pix_per_ns = chart_bounds[3] / total_time +# print "total time: %g pix-per-ns %g" % (total_time, pix_per_ns) + + # FIXME: we have duplicates in the process list too [!] - why !? + + # Render bottom up, left to right + below = {} + for time in times: + below[time] = chart_bounds[1] + chart_bounds[3] + + # same colors each time we render + random.seed (0) + + ctx.set_line_width(1) + + legends = [] + labels = [] + + # render each pid in order + for cs in m_proc_list.values(): + row = {} + cuml = 0.0 + + # print "pid : %s -> %g samples %d" % (proc.cmd, cuml, len (cs.samples)) + for sample in cs.samples: + cuml += getattr(sample.cpu_sample, sample_value) + row[sample.time] = cuml + + process_total_time = cuml + + # hide really tiny processes + if cuml * pix_per_ns <= 2: + continue + + last_time = times[0] + y = last_below = below[last_time] + last_cuml = cuml = 0.0 + + ctx.set_source_rgba(*cs.get_color()) + for time in times: + render_seg = False + + # did the underlying trend increase ? + if below[time] != last_below: + last_below = below[last_time] + last_cuml = cuml + render_seg = True + + # did we move up a pixel increase ? + if time in row: + nc = round (row[time] * pix_per_ns) + if nc != cuml: + last_cuml = cuml + cuml = nc + render_seg = True + +# if last_cuml > cuml: +# assert fail ... - un-sorted process samples + + # draw the trailing rectangle from the last time to + # before now, at the height of the last segment. + if render_seg: + w = math.ceil ((time - last_time) * chart_bounds[2] / proc_tree.duration) + 1 + x = chart_bounds[0] + round((last_time - proc_tree.start_time) * chart_bounds[2] / proc_tree.duration) + ctx.rectangle (x, below[last_time] - last_cuml, w, last_cuml) + ctx.fill() +# ctx.stroke() + last_time = time + y = below [time] - cuml + + row[time] = y + + # render the last segment + x = chart_bounds[0] + round((last_time - proc_tree.start_time) * chart_bounds[2] / proc_tree.duration) + y = below[last_time] - cuml + ctx.rectangle (x, y, chart_bounds[2] - x, cuml) + ctx.fill() +# ctx.stroke() + + # render legend if it will fit + if cuml > 8: + label = cs.cmd + extnts = ctx.text_extents(label) + label_w = extnts[2] + label_h = extnts[3] +# print "Text extents %g by %g" % (label_w, label_h) + labels.append((label, + chart_bounds[0] + chart_bounds[2] - label_w - off_x * 2, + y + (cuml + label_h) / 2)) + if cs in legends: + print("ARGH - duplicate process in list !") + + legends.append ((cs, process_total_time)) + + below = row + + # render grid-lines over the top + draw_box_ticks(ctx, chart_bounds, sec_w) + + # render labels + for l in labels: + draw_text(ctx, l[0], TEXT_COLOR, l[1], l[2]) + + # Render legends + font_height = 20 + label_width = 300 + LEGENDS_PER_COL = 15 + LEGENDS_TOTAL = 45 + ctx.set_font_size (TITLE_FONT_SIZE) + dur_secs = duration / 100 + cpu_secs = total_time / 1000000000 + + # misleading - with multiple CPUs ... +# idle = ((dur_secs - cpu_secs) / dur_secs) * 100.0 + if stat_type is STAT_TYPE_CPU: + label = "Cumulative CPU usage, by process; total CPU: " \ + " %.5g(s) time: %.3g(s)" % (cpu_secs, dur_secs) + else: + label = "Cumulative I/O usage, by process; total I/O: " \ + " %.5g(s) time: %.3g(s)" % (cpu_secs, dur_secs) + + draw_text(ctx, label, TEXT_COLOR, chart_bounds[0] + off_x, + chart_bounds[1] + font_height) + + i = 0 + legends = sorted(legends, key=itemgetter(1), reverse=True) + ctx.set_font_size(TEXT_FONT_SIZE) + for t in legends: + cs = t[0] + time = t[1] + x = chart_bounds[0] + off_x + int (i/LEGENDS_PER_COL) * label_width + y = chart_bounds[1] + font_height * ((i % LEGENDS_PER_COL) + 2) + str = "%s - %.0f(ms) (%2.2f%%)" % (cs.cmd, time/1000000, (time/total_time) * 100.0) + draw_legend_box(ctx, str, cs.color, x, y, leg_s) + i = i + 1 + if i >= LEGENDS_TOTAL: + break diff --git a/poky/scripts/pybootchartgui/pybootchartgui/gui.py b/poky/scripts/pybootchartgui/pybootchartgui/gui.py index e1fe915563..7fedd232df 100644 --- a/poky/scripts/pybootchartgui/pybootchartgui/gui.py +++ b/poky/scripts/pybootchartgui/pybootchartgui/gui.py @@ -13,83 +13,64 @@ # You should have received a copy of the GNU General Public License # along with pybootchartgui. If not, see <http://www.gnu.org/licenses/>. -import gi -gi.require_version('Gtk', '3.0') -from gi.repository import Gtk as gtk -from gi.repository import Gtk -from gi.repository import Gdk -from gi.repository import GObject as gobject -from gi.repository import GObject - +import gobject +import gtk +import gtk.gdk +import gtk.keysyms from . import draw from .draw import RenderOptions -class PyBootchartWidget(gtk.DrawingArea, gtk.Scrollable): +class PyBootchartWidget(gtk.DrawingArea): __gsignals__ = { - 'clicked' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING, Gdk.Event)), + 'expose-event': 'override', + 'clicked' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING, gtk.gdk.Event)), 'position-changed' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_INT, gobject.TYPE_INT)), 'set-scroll-adjustments' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gtk.Adjustment, gtk.Adjustment)) } - hadjustment = GObject.property(type=Gtk.Adjustment, - default=Gtk.Adjustment(), - flags=GObject.PARAM_READWRITE) - hscroll_policy = GObject.property(type=Gtk.ScrollablePolicy, - default=Gtk.ScrollablePolicy.MINIMUM, - flags=GObject.PARAM_READWRITE) - vadjustment = GObject.property(type=Gtk.Adjustment, - default=Gtk.Adjustment(), - flags=GObject.PARAM_READWRITE) - vscroll_policy = GObject.property(type=Gtk.ScrollablePolicy, - default=Gtk.ScrollablePolicy.MINIMUM, - flags=GObject.PARAM_READWRITE) - def __init__(self, trace, options, xscale): gtk.DrawingArea.__init__(self) self.trace = trace self.options = options - self.set_can_focus(True) + self.set_flags(gtk.CAN_FOCUS) - self.add_events(Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.BUTTON_RELEASE_MASK) + self.add_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK) self.connect("button-press-event", self.on_area_button_press) self.connect("button-release-event", self.on_area_button_release) - self.add_events(Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.POINTER_MOTION_HINT_MASK | Gdk.EventMask.BUTTON_RELEASE_MASK) + self.add_events(gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.POINTER_MOTION_HINT_MASK | gtk.gdk.BUTTON_RELEASE_MASK) self.connect("motion-notify-event", self.on_area_motion_notify) self.connect("scroll-event", self.on_area_scroll_event) self.connect('key-press-event', self.on_key_press_event) + self.connect('set-scroll-adjustments', self.on_set_scroll_adjustments) self.connect("size-allocate", self.on_allocation_size_changed) self.connect("position-changed", self.on_position_changed) - self.connect("draw", self.on_draw) - self.zoom_ratio = 1.0 self.xscale = xscale self.x, self.y = 0.0, 0.0 self.chart_width, self.chart_height = draw.extents(self.options, self.xscale, self.trace) - self.our_width, self.our_height = self.chart_width, self.chart_height - - self.hadj = gtk.Adjustment(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) - self.vadj = gtk.Adjustment(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) - self.vadj.connect('value-changed', self.on_adjustments_changed) - self.hadj.connect('value-changed', self.on_adjustments_changed) - - def bound_vals(self): - self.x = max(0, self.x) - self.y = max(0, self.y) - self.x = min(self.chart_width - self.our_width, self.x) - self.y = min(self.chart_height - self.our_height, self.y) - - def on_draw(self, darea, cr): - # set a clip region - #cr.rectangle( - # self.x, self.y, - # self.chart_width, self.chart_height - #) - #cr.clip() + self.hadj = None + self.vadj = None + self.hadj_changed_signal_id = None + self.vadj_changed_signal_id = None + + def do_expose_event(self, event): + cr = self.window.cairo_create() + + # set a clip region for the expose event + cr.rectangle( + event.area.x, event.area.y, + event.area.width, event.area.height + ) + cr.clip() + self.draw(cr, self.get_allocation()) + return False + + def draw(self, cr, rect): cr.set_source_rgba(1.0, 1.0, 1.0, 1.0) cr.paint() cr.scale(self.zoom_ratio, self.zoom_ratio) @@ -103,7 +84,7 @@ class PyBootchartWidget(gtk.DrawingArea, gtk.Scrollable): def zoom_image (self, zoom_ratio): self.zoom_ratio = zoom_ratio - self._set_scroll_adjustments() + self._set_scroll_adjustments (self.hadj, self.vadj) self.queue_draw() def zoom_to_rect (self, rect): @@ -141,101 +122,126 @@ class PyBootchartWidget(gtk.DrawingArea, gtk.Scrollable): def show_toggled(self, button): self.options.app_options.show_all = button.get_property ('active') self.chart_width, self.chart_height = draw.extents(self.options, self.xscale, self.trace) - self._set_scroll_adjustments() + self._set_scroll_adjustments(self.hadj, self.vadj) self.queue_draw() POS_INCREMENT = 100 def on_key_press_event(self, widget, event): - if event.keyval == Gdk.keyval_from_name("Left"): + if event.keyval == gtk.keysyms.Left: self.x -= self.POS_INCREMENT/self.zoom_ratio - elif event.keyval == Gdk.keyval_from_name("Right"): + elif event.keyval == gtk.keysyms.Right: self.x += self.POS_INCREMENT/self.zoom_ratio - elif event.keyval == Gdk.keyval_from_name("Up"): + elif event.keyval == gtk.keysyms.Up: self.y -= self.POS_INCREMENT/self.zoom_ratio - elif event.keyval == Gdk.keyval_from_name("Down"): + elif event.keyval == gtk.keysyms.Down: self.y += self.POS_INCREMENT/self.zoom_ratio else: return False - self.bound_vals() self.queue_draw() self.position_changed() return True def on_area_button_press(self, area, event): if event.button == 2 or event.button == 1: - window = self.get_window() - window.set_cursor(Gdk.Cursor(Gdk.CursorType.FLEUR)) + area.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.FLEUR)) self.prevmousex = event.x self.prevmousey = event.y - if event.type not in (Gdk.EventType.BUTTON_PRESS, Gdk.EventType.BUTTON_RELEASE): + if event.type not in (gtk.gdk.BUTTON_PRESS, gtk.gdk.BUTTON_RELEASE): return False return False def on_area_button_release(self, area, event): if event.button == 2 or event.button == 1: - window = self.get_window() - window.set_cursor(Gdk.Cursor(Gdk.CursorType.ARROW)) + area.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.ARROW)) self.prevmousex = None self.prevmousey = None return True return False def on_area_scroll_event(self, area, event): - if event.state & Gdk.CONTROL_MASK: - if event.direction == Gdk.SCROLL_UP: + if event.state & gtk.gdk.CONTROL_MASK: + if event.direction == gtk.gdk.SCROLL_UP: self.zoom_image(self.zoom_ratio * self.ZOOM_INCREMENT) return True - if event.direction == Gdk.SCROLL_DOWN: + if event.direction == gtk.gdk.SCROLL_DOWN: self.zoom_image(self.zoom_ratio / self.ZOOM_INCREMENT) return True return False def on_area_motion_notify(self, area, event): state = event.state - if state & Gdk.ModifierType.BUTTON2_MASK or state & Gdk.ModifierType.BUTTON1_MASK: + if state & gtk.gdk.BUTTON2_MASK or state & gtk.gdk.BUTTON1_MASK: x, y = int(event.x), int(event.y) # pan the image self.x += (self.prevmousex - x)/self.zoom_ratio self.y += (self.prevmousey - y)/self.zoom_ratio - self.bound_vals() self.queue_draw() self.prevmousex = x self.prevmousey = y self.position_changed() return True + def on_set_scroll_adjustments(self, area, hadj, vadj): + self._set_scroll_adjustments (hadj, vadj) + def on_allocation_size_changed(self, widget, allocation): self.hadj.page_size = allocation.width self.hadj.page_increment = allocation.width * 0.9 self.vadj.page_size = allocation.height self.vadj.page_increment = allocation.height * 0.9 - self.our_width = allocation.width - if self.chart_width < self.our_width: - self.our_width = self.chart_width - self.our_height = allocation.height - if self.chart_height < self.our_height: - self.our_height = self.chart_height - self._set_scroll_adjustments() def _set_adj_upper(self, adj, upper): - - if adj.get_upper() != upper: - adj.set_upper(upper) - - def _set_scroll_adjustments(self): - self._set_adj_upper (self.hadj, self.zoom_ratio * (self.chart_width - self.our_width)) - self._set_adj_upper (self.vadj, self.zoom_ratio * (self.chart_height - self.our_height)) + changed = False + value_changed = False + + if adj.upper != upper: + adj.upper = upper + changed = True + + max_value = max(0.0, upper - adj.page_size) + if adj.value > max_value: + adj.value = max_value + value_changed = True + + if changed: + adj.changed() + if value_changed: + adj.value_changed() + + def _set_scroll_adjustments(self, hadj, vadj): + if hadj == None: + hadj = gtk.Adjustment(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) + if vadj == None: + vadj = gtk.Adjustment(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) + + if self.hadj_changed_signal_id != None and \ + self.hadj != None and hadj != self.hadj: + self.hadj.disconnect (self.hadj_changed_signal_id) + if self.vadj_changed_signal_id != None and \ + self.vadj != None and vadj != self.vadj: + self.vadj.disconnect (self.vadj_changed_signal_id) + + if hadj != None: + self.hadj = hadj + self._set_adj_upper (self.hadj, self.zoom_ratio * self.chart_width) + self.hadj_changed_signal_id = self.hadj.connect('value-changed', self.on_adjustments_changed) + + if vadj != None: + self.vadj = vadj + self._set_adj_upper (self.vadj, self.zoom_ratio * self.chart_height) + self.vadj_changed_signal_id = self.vadj.connect('value-changed', self.on_adjustments_changed) def on_adjustments_changed(self, adj): - self.x = self.hadj.get_value() / self.zoom_ratio - self.y = self.vadj.get_value() / self.zoom_ratio + self.x = self.hadj.value / self.zoom_ratio + self.y = self.vadj.value / self.zoom_ratio self.queue_draw() def on_position_changed(self, widget, x, y): - self.hadj.set_value(x * self.zoom_ratio) - #self.hadj.value_changed() - self.vadj.set_value(y * self.zoom_ratio) + self.hadj.value = x * self.zoom_ratio + self.vadj.value = y * self.zoom_ratio + +PyBootchartWidget.set_set_scroll_adjustments_signal('set-scroll-adjustments') class PyBootchartShell(gtk.VBox): ui = ''' @@ -254,7 +260,7 @@ class PyBootchartShell(gtk.VBox): def __init__(self, window, trace, options, xscale): gtk.VBox.__init__(self) - self.widget2 = PyBootchartWidget(trace, options, xscale) + self.widget = PyBootchartWidget(trace, options, xscale) # Create a UIManager instance uimanager = self.uimanager = gtk.UIManager() @@ -269,12 +275,12 @@ class PyBootchartShell(gtk.VBox): # Create actions actiongroup.add_actions(( - ('Expand', gtk.STOCK_ADD, None, None, None, self.widget2.on_expand), - ('Contract', gtk.STOCK_REMOVE, None, None, None, self.widget2.on_contract), - ('ZoomIn', gtk.STOCK_ZOOM_IN, None, None, None, self.widget2.on_zoom_in), - ('ZoomOut', gtk.STOCK_ZOOM_OUT, None, None, None, self.widget2.on_zoom_out), - ('ZoomFit', gtk.STOCK_ZOOM_FIT, 'Fit Width', None, None, self.widget2.on_zoom_fit), - ('Zoom100', gtk.STOCK_ZOOM_100, None, None, None, self.widget2.on_zoom_100), + ('Expand', gtk.STOCK_ADD, None, None, None, self.widget.on_expand), + ('Contract', gtk.STOCK_REMOVE, None, None, None, self.widget.on_contract), + ('ZoomIn', gtk.STOCK_ZOOM_IN, None, None, None, self.widget.on_zoom_in), + ('ZoomOut', gtk.STOCK_ZOOM_OUT, None, None, None, self.widget.on_zoom_out), + ('ZoomFit', gtk.STOCK_ZOOM_FIT, 'Fit Width', None, None, self.widget.on_zoom_fit), + ('Zoom100', gtk.STOCK_ZOOM_100, None, None, None, self.widget.on_zoom_100), )) # Add the actiongroup to the uimanager @@ -284,33 +290,29 @@ class PyBootchartShell(gtk.VBox): uimanager.add_ui_from_string(self.ui) # Scrolled window - scrolled = gtk.ScrolledWindow(self.widget2.hadj, self.widget2.vadj) - scrolled.add(self.widget2) - - #scrolled.set_hadjustment() - #scrolled.set_vadjustment(self.widget2.vadj) - scrolled.set_policy(gtk.PolicyType.ALWAYS, gtk.PolicyType.ALWAYS) + scrolled = gtk.ScrolledWindow() + scrolled.add(self.widget) # toolbar / h-box hbox = gtk.HBox(False, 8) # Create a Toolbar toolbar = uimanager.get_widget('/ToolBar') - hbox.pack_start(toolbar, True, True, 0) + hbox.pack_start(toolbar, True, True) if not options.kernel_only: # Misc. options button = gtk.CheckButton("Show more") - button.connect ('toggled', self.widget2.show_toggled) + button.connect ('toggled', self.widget.show_toggled) button.set_active(options.app_options.show_all) - hbox.pack_start (button, False, True, 0) + hbox.pack_start (button, False, True) - self.pack_start(hbox, False, True, 0) - self.pack_start(scrolled, True, True, 0) + self.pack_start(hbox, False) + self.pack_start(scrolled) self.show_all() def grab_focus(self, window): - window.set_focus(self.widget2) + window.set_focus(self.widget) class PyBootchartWindow(gtk.Window): diff --git a/poky/scripts/pybootchartgui/pybootchartgui/parsing.py b/poky/scripts/pybootchartgui/pybootchartgui/parsing.py index ef2d3d309c..bcfb2da569 100644 --- a/poky/scripts/pybootchartgui/pybootchartgui/parsing.py +++ b/poky/scripts/pybootchartgui/pybootchartgui/parsing.py @@ -267,7 +267,7 @@ def _parse_headers(file): value = line.strip() headers[last] += value return headers, last - return reduce(parse, file.read().split('\n'), (defaultdict(str),''))[0] + return reduce(parse, file.read().decode('utf-8').split('\n'), (defaultdict(str),''))[0] def _parse_timed_blocks(file): """Parses (ie., splits) a file into so-called timed-blocks. A @@ -281,7 +281,7 @@ def _parse_timed_blocks(file): return (int(lines[0]), lines[1:]) except ValueError: raise ParseError("expected a timed-block, but timestamp '%s' is not an integer" % lines[0]) - blocks = file.read().split('\n\n') + blocks = file.read().decode('utf-8').split('\n\n') return [parse(block) for block in blocks if block.strip() and not block.endswith(' not running\n')] def _parse_proc_ps_log(writer, file): @@ -577,7 +577,7 @@ def _parse_dmesg(writer, file): processMap['k-boot'] = kernel base_ts = False max_ts = 0 - for line in file.read().split('\n'): + for line in file.read().decode('utf-8').split('\n'): t = timestamp_re.match (line) if t is None: # print "duff timestamp " + line @@ -665,7 +665,7 @@ def _parse_pacct(writer, file): def _parse_paternity_log(writer, file): parent_map = {} parent_map[0] = 0 - for line in file.read().split('\n'): + for line in file.read().decode('utf-8').split('\n'): if not line: continue elems = line.split(' ') # <Child> <Parent> @@ -678,7 +678,7 @@ def _parse_paternity_log(writer, file): def _parse_cmdline_log(writer, file): cmdLines = {} - for block in file.read().split('\n\n'): + for block in file.read().decode('utf-8').split('\n\n'): lines = block.split('\n') if len (lines) >= 3: # print "Lines '%s'" % (lines[0]) @@ -751,7 +751,7 @@ def parse_file(writer, state, filename): if state.filename is None: state.filename = filename basename = os.path.basename(filename) - with open(filename, "r") as file: + with open(filename, "rb") as file: return _do_parse(writer, state, filename, file) def parse_paths(writer, state, paths): diff --git a/poky/scripts/runqemu b/poky/scripts/runqemu index 4079f2b17d..19fd521cd9 100755 --- a/poky/scripts/runqemu +++ b/poky/scripts/runqemu @@ -185,11 +185,10 @@ class BaseConfig(object): self.lock_descriptor = None self.bitbake_e = '' self.snapshot = False - self.wictypes = ('wic', 'wic.vmdk', 'wic.qcow2', 'wic.vdi') self.fstypes = ('ext2', 'ext3', 'ext4', 'jffs2', 'nfs', 'btrfs', 'cpio.gz', 'cpio', 'ramfs', 'tar.bz2', 'tar.gz') - self.vmtypes = ('hddimg', 'hdddirect', 'iso') - self.fsinfo = {} + self.vmtypes = ('hddimg', 'hdddirect', 'wic', 'wic.vmdk', + 'wic.qcow2', 'wic.vdi', 'iso') self.network_device = "-device e1000,netdev=net0,mac=@MAC@" # Use different mac section for tap and slirp to avoid # conflicts, e.g., when one is running with tap, the other is @@ -254,7 +253,7 @@ class BaseConfig(object): def check_arg_fstype(self, fst): """Check and set FSTYPE""" - if fst not in self.fstypes + self.vmtypes + self.wictypes: + if fst not in self.fstypes + self.vmtypes: logger.warning("Maybe unsupported FSTYPE: %s" % fst) if not self.fstype or self.fstype == fst: if fst == 'ramfs': @@ -391,7 +390,7 @@ class BaseConfig(object): unknown_arg = "" for arg in sys.argv[1:]: - if arg in self.fstypes + self.vmtypes + self.wictypes: + if arg in self.fstypes + self.vmtypes: self.check_arg_fstype(arg) elif arg == 'nographic': self.qemu_opt_script += ' -nographic' @@ -492,13 +491,12 @@ class BaseConfig(object): yocto_paravirt_kvm_wiki = "https://wiki.yoctoproject.org/wiki/Running_an_x86_Yocto_Linux_image_under_QEMU_KVM" dev_kvm = '/dev/kvm' dev_vhost = '/dev/vhost-net' - if self.qemu_system.endswith(('i386', 'x86_64')): - with open('/proc/cpuinfo', 'r') as f: - kvm_cap = re.search('vmx|svm', "".join(f.readlines())) - if not kvm_cap: - logger.error("You are trying to enable KVM on a cpu without VT support.") - logger.error("Remove kvm from the command-line, or refer:") - raise RunQemuError(yocto_kvm_wiki) + with open('/proc/cpuinfo', 'r') as f: + kvm_cap = re.search('vmx|svm', "".join(f.readlines())) + if not kvm_cap: + logger.error("You are trying to enable KVM on a cpu without VT support.") + logger.error("Remove kvm from the command-line, or refer:") + raise RunQemuError(yocto_kvm_wiki) if not os.path.exists(dev_kvm): logger.error("Missing KVM device. Have you inserted kvm modules?") @@ -537,40 +535,6 @@ class BaseConfig(object): else: raise RunQemuError("FSTYPE is NULL!") - # parse QB_FSINFO into dict, e.g. { 'wic': ['no-kernel-in-fs', 'a-flag'], 'ext4': ['another-flag']} - wic_fs = False - qb_fsinfo = self.get('QB_FSINFO') - if qb_fsinfo: - qb_fsinfo = qb_fsinfo.split() - for fsinfo in qb_fsinfo: - try: - fstype, fsflag = fsinfo.split(':') - - if fstype == 'wic': - if fsflag == 'no-kernel-in-fs': - wic_fs = True - elif fsflag == 'kernel-in-fs': - wic_fs = False - else: - logger.warn('Unknown flag "%s:%s" in QB_FSINFO', fstype, fsflag) - continue - else: - logger.warn('QB_FSINFO is not supported for image type "%s"', fstype) - continue - - if fstype in self.fsinfo: - self.fsinfo[fstype].append(fsflag) - else: - self.fsinfo[fstype] = [fsflag] - except Exception: - logger.error('Invalid parameter "%s" in QB_FSINFO', fsinfo) - - # treat wic images as vmimages (with kernel) or as fsimages (rootfs only) - if wic_fs: - self.fstypes = self.fstypes + self.wictypes - else: - self.vmtypes = self.vmtypes + self.wictypes - def check_rootfs(self): """Check and set rootfs""" @@ -745,7 +709,6 @@ class BaseConfig(object): else: os.putenv('QEMU_AUDIO_DRV', 'none') - self.check_qemu_system() self.check_kvm() self.check_fstype() self.check_rootfs() @@ -867,11 +830,7 @@ class BaseConfig(object): if self.dtb: print('DTB: [%s]' % self.dtb) print('MACHINE: [%s]' % self.get('MACHINE')) - try: - fstype_flags = ' (' + ', '.join(self.fsinfo[self.fstype]) + ')' - except KeyError: - fstype_flags = '' - print('FSTYPE: [%s%s]' % (self.fstype, fstype_flags)) + print('FSTYPE: [%s]' % self.fstype) if self.fstype == 'nfs': print('NFS_DIR: [%s]' % self.rootfs) else: @@ -1175,23 +1134,21 @@ class BaseConfig(object): return 'qemu-system-%s' % qbsys - def check_qemu_system(self): + def setup_final(self): qemu_system = self.get('QB_SYSTEM_NAME') if not qemu_system: qemu_system = self.guess_qb_system() if not qemu_system: raise RunQemuError("Failed to boot, QB_SYSTEM_NAME is NULL!") - self.qemu_system = qemu_system - def setup_final(self): - qemu_bin = os.path.join(self.bindir_native, self.qemu_system) + qemu_bin = os.path.join(self.bindir_native, qemu_system) # It is possible to have qemu-native in ASSUME_PROVIDED, and it won't # find QEMU in sysroot, it needs to use host's qemu. if not os.path.exists(qemu_bin): logger.info("QEMU binary not found in %s, trying host's QEMU" % qemu_bin) for path in (os.environ['PATH'] or '').split(':'): - qemu_bin_tmp = os.path.join(path, self.qemu_system) + qemu_bin_tmp = os.path.join(path, qemu_system) logger.info("Trying: %s" % qemu_bin_tmp) if os.path.exists(qemu_bin_tmp): qemu_bin = qemu_bin_tmp diff --git a/poky/scripts/wic b/poky/scripts/wic index 1d89fb2eda..5c4b8f6605 100755 --- a/poky/scripts/wic +++ b/poky/scripts/wic @@ -487,9 +487,6 @@ subcommands = { def init_parser(parser): parser.add_argument("--version", action="version", version="%(prog)s {version}".format(version=__version__)) - parser.add_argument("-D", "--debug", dest="debug", action="store_true", - default=False, help="output debug information") - subparsers = parser.add_subparsers(dest='command', help=hlp.wic_usage) for subcmd in subcommands: subparser = subparsers.add_parser(subcmd, help=subcommands[subcmd][2]) @@ -503,8 +500,6 @@ def main(argv): init_parser(parser) args = parser.parse_args(argv) - if args.debug: - logger.setLevel(logging.DEBUG) if "command" in vars(args): if args.command == "help": |
