mbligh | c86b0b4 | 2006-07-28 17:35:28 +0000 | [diff] [blame] | 1 | """ |
mbligh | 2da4d88 | 2009-01-21 19:05:40 +0000 | [diff] [blame] | 2 | DO NOT import this file directly - import client/bin/utils.py, |
| 3 | which will mix this in |
| 4 | |
mbligh | 53da18e | 2009-01-05 21:13:26 +0000 | [diff] [blame] | 5 | Convenience functions for use by tests or whomever. |
mbligh | c86b0b4 | 2006-07-28 17:35:28 +0000 | [diff] [blame] | 6 | |
mbligh | 2da4d88 | 2009-01-21 19:05:40 +0000 | [diff] [blame] | 7 | Note that this file is mixed in by utils.py - note very carefully the |
| 8 | precedence order defined there |
mbligh | 53da18e | 2009-01-05 21:13:26 +0000 | [diff] [blame] | 9 | """ |
Daniel Kurtz | f278e85 | 2014-03-04 21:57:30 -0800 | [diff] [blame] | 10 | import os, shutil, commands, pickle, glob |
| 11 | import math, re, fnmatch, logging, multiprocessing |
lmr | 959e816 | 2010-04-16 06:15:34 +0000 | [diff] [blame] | 12 | from autotest_lib.client.common_lib import error, utils, magic |
mbligh | ea397bb | 2008-02-02 19:17:51 +0000 | [diff] [blame] | 13 | |
| 14 | |
mbligh | f4c3532 | 2006-03-13 01:01:10 +0000 | [diff] [blame] | 15 | def grep(pattern, file): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 16 | """ |
| 17 | This is mainly to fix the return code inversion from grep |
| 18 | Also handles compressed files. |
mbligh | 7bdbfbd | 2006-09-30 16:47:01 +0000 | [diff] [blame] | 19 | |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 20 | returns 1 if the pattern is present in the file, 0 if not. |
| 21 | """ |
| 22 | command = 'grep "%s" > /dev/null' % pattern |
| 23 | ret = cat_file_to_cmd(file, command, ignore_status=True) |
| 24 | return not ret |
mbligh | af4efc2 | 2008-01-25 16:33:59 +0000 | [diff] [blame] | 25 | |
| 26 | |
mbligh | c86b0b4 | 2006-07-28 17:35:28 +0000 | [diff] [blame] | 27 | def difflist(list1, list2): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 28 | """returns items in list2 that are not in list1""" |
| 29 | diff = []; |
| 30 | for x in list2: |
| 31 | if x not in list1: |
| 32 | diff.append(x) |
| 33 | return diff |
mbligh | f4c3532 | 2006-03-13 01:01:10 +0000 | [diff] [blame] | 34 | |
mbligh | c86b0b4 | 2006-07-28 17:35:28 +0000 | [diff] [blame] | 35 | |
mbligh | 8ea61e2 | 2008-05-09 18:09:37 +0000 | [diff] [blame] | 36 | def cat_file_to_cmd(file, command, ignore_status=0, return_output=False): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 37 | """ |
| 38 | equivalent to 'cat file | command' but knows to use |
| 39 | zcat or bzcat if appropriate |
| 40 | """ |
mbligh | f2fa471 | 2008-09-10 20:36:29 +0000 | [diff] [blame] | 41 | if not os.path.isfile(file): |
| 42 | raise NameError('invalid file %s to cat to command %s' |
| 43 | % (file, command)) |
| 44 | |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 45 | if return_output: |
mbligh | 2da4d88 | 2009-01-21 19:05:40 +0000 | [diff] [blame] | 46 | run_cmd = utils.system_output |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 47 | else: |
mbligh | 2da4d88 | 2009-01-21 19:05:40 +0000 | [diff] [blame] | 48 | run_cmd = utils.system |
mbligh | 96ffb9b | 2008-03-28 14:35:42 +0000 | [diff] [blame] | 49 | |
lmr | 959e816 | 2010-04-16 06:15:34 +0000 | [diff] [blame] | 50 | if magic.guess_type(file) == 'application/x-bzip2': |
mbligh | f2fa471 | 2008-09-10 20:36:29 +0000 | [diff] [blame] | 51 | cat = 'bzcat' |
lmr | 959e816 | 2010-04-16 06:15:34 +0000 | [diff] [blame] | 52 | elif magic.guess_type(file) == 'application/x-gzip': |
mbligh | f2fa471 | 2008-09-10 20:36:29 +0000 | [diff] [blame] | 53 | cat = 'zcat' |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 54 | else: |
mbligh | f2fa471 | 2008-09-10 20:36:29 +0000 | [diff] [blame] | 55 | cat = 'cat' |
| 56 | return run_cmd('%s %s | %s' % (cat, file, command), |
| 57 | ignore_status=ignore_status) |
mbligh | f4c3532 | 2006-03-13 01:01:10 +0000 | [diff] [blame] | 58 | |
mbligh | c86b0b4 | 2006-07-28 17:35:28 +0000 | [diff] [blame] | 59 | |
mbligh | 712cd14 | 2006-04-22 18:57:50 +0000 | [diff] [blame] | 60 | def extract_tarball_to_dir(tarball, dir): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 61 | """ |
| 62 | Extract a tarball to a specified directory name instead of whatever |
| 63 | the top level of a tarball is - useful for versioned directory names, etc |
| 64 | """ |
| 65 | if os.path.exists(dir): |
lmr | 959e816 | 2010-04-16 06:15:34 +0000 | [diff] [blame] | 66 | if os.path.isdir(dir): |
| 67 | shutil.rmtree(dir) |
| 68 | else: |
| 69 | os.remove(dir) |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 70 | pwd = os.getcwd() |
| 71 | os.chdir(os.path.dirname(os.path.abspath(dir))) |
| 72 | newdir = extract_tarball(tarball) |
| 73 | os.rename(newdir, dir) |
| 74 | os.chdir(pwd) |
mbligh | 712cd14 | 2006-04-22 18:57:50 +0000 | [diff] [blame] | 75 | |
| 76 | |
mbligh | 712cd14 | 2006-04-22 18:57:50 +0000 | [diff] [blame] | 77 | def extract_tarball(tarball): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 78 | """Returns the directory extracted by the tarball.""" |
| 79 | extracted = cat_file_to_cmd(tarball, 'tar xvf - 2>/dev/null', |
| 80 | return_output=True).splitlines() |
mbligh | 5d423ca | 2008-04-16 23:06:12 +0000 | [diff] [blame] | 81 | |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 82 | dir = None |
mbligh | 5d423ca | 2008-04-16 23:06:12 +0000 | [diff] [blame] | 83 | |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 84 | for line in extracted: |
David Sharp | 77e0121 | 2015-03-06 15:01:06 -0800 | [diff] [blame] | 85 | if line.startswith('./'): |
| 86 | line = line[2:] |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 87 | if not line or line == '.': |
| 88 | continue |
| 89 | topdir = line.split('/')[0] |
| 90 | if os.path.isdir(topdir): |
| 91 | if dir: |
| 92 | assert(dir == topdir) |
| 93 | else: |
| 94 | dir = topdir |
| 95 | if dir: |
| 96 | return dir |
| 97 | else: |
| 98 | raise NameError('extracting tarball produced no dir') |
mbligh | 712cd14 | 2006-04-22 18:57:50 +0000 | [diff] [blame] | 99 | |
mbligh | cdf02a4 | 2006-04-23 02:22:49 +0000 | [diff] [blame] | 100 | |
lmr | d60882f | 2010-02-04 03:26:36 +0000 | [diff] [blame] | 101 | def unmap_url_cache(cachedir, url, expected_hash, method="md5"): |
mbligh | 53da18e | 2009-01-05 21:13:26 +0000 | [diff] [blame] | 102 | """ |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 103 | Downloads a file from a URL to a cache directory. If the file is already |
lmr | d60882f | 2010-02-04 03:26:36 +0000 | [diff] [blame] | 104 | at the expected position and has the expected hash, let's not download it |
| 105 | again. |
| 106 | |
| 107 | @param cachedir: Directory that might hold a copy of the file we want to |
| 108 | download. |
| 109 | @param url: URL for the file we want to download. |
| 110 | @param expected_hash: Hash string that we expect the file downloaded to |
| 111 | have. |
| 112 | @param method: Method used to calculate the hash string (md5, sha1). |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 113 | """ |
| 114 | # Let's convert cachedir to a canonical path, if it's not already |
| 115 | cachedir = os.path.realpath(cachedir) |
| 116 | if not os.path.isdir(cachedir): |
| 117 | try: |
lmr | d60882f | 2010-02-04 03:26:36 +0000 | [diff] [blame] | 118 | os.makedirs(cachedir) |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 119 | except: |
| 120 | raise ValueError('Could not create cache directory %s' % cachedir) |
| 121 | file_from_url = os.path.basename(url) |
| 122 | file_local_path = os.path.join(cachedir, file_from_url) |
lmr | d60882f | 2010-02-04 03:26:36 +0000 | [diff] [blame] | 123 | |
| 124 | file_hash = None |
| 125 | failure_counter = 0 |
| 126 | while not file_hash == expected_hash: |
| 127 | if os.path.isfile(file_local_path): |
| 128 | file_hash = hash_file(file_local_path, method) |
| 129 | if file_hash == expected_hash: |
| 130 | # File is already at the expected position and ready to go |
| 131 | src = file_from_url |
| 132 | else: |
| 133 | # Let's download the package again, it's corrupted... |
| 134 | logging.error("Seems that file %s is corrupted, trying to " |
Daniel Kurtz | f278e85 | 2014-03-04 21:57:30 -0800 | [diff] [blame] | 135 | "download it again", file_from_url) |
lmr | d60882f | 2010-02-04 03:26:36 +0000 | [diff] [blame] | 136 | src = url |
| 137 | failure_counter += 1 |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 138 | else: |
lmr | d60882f | 2010-02-04 03:26:36 +0000 | [diff] [blame] | 139 | # File is not there, let's download it |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 140 | src = url |
lmr | d60882f | 2010-02-04 03:26:36 +0000 | [diff] [blame] | 141 | if failure_counter > 1: |
| 142 | raise EnvironmentError("Consistently failed to download the " |
| 143 | "package %s. Aborting further download " |
| 144 | "attempts. This might mean either the " |
| 145 | "network connection has problems or the " |
| 146 | "expected hash string that was determined " |
Daniel Kurtz | f278e85 | 2014-03-04 21:57:30 -0800 | [diff] [blame] | 147 | "for this file is wrong", file_from_url) |
lmr | d60882f | 2010-02-04 03:26:36 +0000 | [diff] [blame] | 148 | file_path = utils.unmap_url(cachedir, src, cachedir) |
| 149 | |
| 150 | return file_path |
mbligh | ea30c8a | 2006-04-22 22:24:25 +0000 | [diff] [blame] | 151 | |
| 152 | |
mbligh | f4c3532 | 2006-03-13 01:01:10 +0000 | [diff] [blame] | 153 | def force_copy(src, dest): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 154 | """Replace dest with a new copy of src, even if it exists""" |
| 155 | if os.path.isfile(dest): |
| 156 | os.remove(dest) |
| 157 | if os.path.isdir(dest): |
| 158 | dest = os.path.join(dest, os.path.basename(src)) |
| 159 | shutil.copyfile(src, dest) |
| 160 | return dest |
mbligh | f4c3532 | 2006-03-13 01:01:10 +0000 | [diff] [blame] | 161 | |
| 162 | |
mbligh | fdbcaec | 2006-10-01 23:28:57 +0000 | [diff] [blame] | 163 | def force_link(src, dest): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 164 | """Link src to dest, overwriting it if it exists""" |
mbligh | 2da4d88 | 2009-01-21 19:05:40 +0000 | [diff] [blame] | 165 | return utils.system("ln -sf %s %s" % (src, dest)) |
mbligh | fdbcaec | 2006-10-01 23:28:57 +0000 | [diff] [blame] | 166 | |
| 167 | |
mbligh | cdf02a4 | 2006-04-23 02:22:49 +0000 | [diff] [blame] | 168 | def file_contains_pattern(file, pattern): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 169 | """Return true if file contains the specified egrep pattern""" |
| 170 | if not os.path.isfile(file): |
| 171 | raise NameError('file %s does not exist' % file) |
mbligh | 2da4d88 | 2009-01-21 19:05:40 +0000 | [diff] [blame] | 172 | return not utils.system('egrep -q "' + pattern + '" ' + file, ignore_status=True) |
mbligh | cdf02a4 | 2006-04-23 02:22:49 +0000 | [diff] [blame] | 173 | |
| 174 | |
| 175 | def list_grep(list, pattern): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 176 | """True if any item in list matches the specified pattern.""" |
| 177 | compiled = re.compile(pattern) |
| 178 | for line in list: |
| 179 | match = compiled.search(line) |
| 180 | if (match): |
| 181 | return 1 |
| 182 | return 0 |
mbligh | cdf02a4 | 2006-04-23 02:22:49 +0000 | [diff] [blame] | 183 | |
mbligh | 987071e | 2008-06-13 16:39:12 +0000 | [diff] [blame] | 184 | |
mbligh | 42b81ca | 2006-09-30 22:10:01 +0000 | [diff] [blame] | 185 | def get_os_vendor(): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 186 | """Try to guess what's the os vendor |
| 187 | """ |
mbligh | 90b97ff | 2009-03-10 20:29:01 +0000 | [diff] [blame] | 188 | if os.path.isfile('/etc/SuSE-release'): |
| 189 | return 'SUSE' |
| 190 | |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 191 | issue = '/etc/issue' |
mbligh | af4efc2 | 2008-01-25 16:33:59 +0000 | [diff] [blame] | 192 | |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 193 | if not os.path.isfile(issue): |
| 194 | return 'Unknown' |
mbligh | af4efc2 | 2008-01-25 16:33:59 +0000 | [diff] [blame] | 195 | |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 196 | if file_contains_pattern(issue, 'Red Hat'): |
| 197 | return 'Red Hat' |
mbligh | 2f29c19 | 2009-01-12 20:39:17 +0000 | [diff] [blame] | 198 | elif file_contains_pattern(issue, 'Fedora'): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 199 | return 'Fedora Core' |
| 200 | elif file_contains_pattern(issue, 'SUSE'): |
| 201 | return 'SUSE' |
| 202 | elif file_contains_pattern(issue, 'Ubuntu'): |
| 203 | return 'Ubuntu' |
| 204 | elif file_contains_pattern(issue, 'Debian'): |
| 205 | return 'Debian' |
| 206 | else: |
| 207 | return 'Unknown' |
mbligh | af4efc2 | 2008-01-25 16:33:59 +0000 | [diff] [blame] | 208 | |
mbligh | cdf02a4 | 2006-04-23 02:22:49 +0000 | [diff] [blame] | 209 | |
Eric Li | 8a12e80 | 2011-02-17 14:24:13 -0800 | [diff] [blame] | 210 | def get_cc(): |
| 211 | try: |
| 212 | return os.environ['CC'] |
| 213 | except KeyError: |
| 214 | return 'gcc' |
| 215 | |
| 216 | |
mbligh | f49d5cf | 2006-04-23 02:24:42 +0000 | [diff] [blame] | 217 | def get_vmlinux(): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 218 | """Return the full path to vmlinux |
mbligh | c86b0b4 | 2006-07-28 17:35:28 +0000 | [diff] [blame] | 219 | |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 220 | Ahem. This is crap. Pray harder. Bad Martin. |
| 221 | """ |
mbligh | 2da4d88 | 2009-01-21 19:05:40 +0000 | [diff] [blame] | 222 | vmlinux = '/boot/vmlinux-%s' % utils.system_output('uname -r') |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 223 | if os.path.isfile(vmlinux): |
| 224 | return vmlinux |
mbligh | 2da4d88 | 2009-01-21 19:05:40 +0000 | [diff] [blame] | 225 | vmlinux = '/lib/modules/%s/build/vmlinux' % utils.system_output('uname -r') |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 226 | if os.path.isfile(vmlinux): |
| 227 | return vmlinux |
| 228 | return None |
mbligh | f49d5cf | 2006-04-23 02:24:42 +0000 | [diff] [blame] | 229 | |
| 230 | |
| 231 | def get_systemmap(): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 232 | """Return the full path to System.map |
mbligh | c86b0b4 | 2006-07-28 17:35:28 +0000 | [diff] [blame] | 233 | |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 234 | Ahem. This is crap. Pray harder. Bad Martin. |
| 235 | """ |
mbligh | 2da4d88 | 2009-01-21 19:05:40 +0000 | [diff] [blame] | 236 | map = '/boot/System.map-%s' % utils.system_output('uname -r') |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 237 | if os.path.isfile(map): |
| 238 | return map |
mbligh | 2da4d88 | 2009-01-21 19:05:40 +0000 | [diff] [blame] | 239 | map = '/lib/modules/%s/build/System.map' % utils.system_output('uname -r') |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 240 | if os.path.isfile(map): |
| 241 | return map |
| 242 | return None |
mbligh | 67b5ece | 2006-04-23 02:53:12 +0000 | [diff] [blame] | 243 | |
| 244 | |
| 245 | def get_modules_dir(): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 246 | """Return the modules dir for the running kernel version""" |
mbligh | 2da4d88 | 2009-01-21 19:05:40 +0000 | [diff] [blame] | 247 | kernel_version = utils.system_output('uname -r') |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 248 | return '/lib/modules/%s/kernel' % kernel_version |
mbligh | f49d5cf | 2006-04-23 02:24:42 +0000 | [diff] [blame] | 249 | |
| 250 | |
David Sharp | eb5e7a3 | 2014-10-29 15:44:39 -0700 | [diff] [blame] | 251 | _CPUINFO_RE = re.compile(r'^(?P<key>[^\t]*)\t*: ?(?P<value>.*)$') |
| 252 | |
David Sharp | f948379 | 2015-03-06 13:56:39 -0800 | [diff] [blame] | 253 | |
David Sharp | eb5e7a3 | 2014-10-29 15:44:39 -0700 | [diff] [blame] | 254 | def get_cpuinfo(): |
| 255 | """Read /proc/cpuinfo and convert to a list of dicts.""" |
| 256 | cpuinfo = [] |
| 257 | with open('/proc/cpuinfo', 'r') as f: |
| 258 | cpu = {} |
| 259 | for line in f: |
| 260 | line = line.strip() |
| 261 | if not line: |
| 262 | cpuinfo.append(cpu) |
| 263 | cpu = {} |
| 264 | continue |
| 265 | match = _CPUINFO_RE.match(line) |
| 266 | cpu[match.group('key')] = match.group('value') |
| 267 | if cpu: |
| 268 | # cpuinfo usually ends in a blank line, so this shouldn't happen. |
| 269 | cpuinfo.append(cpu) |
| 270 | return cpuinfo |
| 271 | |
David Sharp | f948379 | 2015-03-06 13:56:39 -0800 | [diff] [blame] | 272 | |
mbligh | 5970cf0 | 2006-08-06 15:39:22 +0000 | [diff] [blame] | 273 | def get_cpu_arch(): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 274 | """Work out which CPU architecture we're running on""" |
| 275 | f = open('/proc/cpuinfo', 'r') |
| 276 | cpuinfo = f.readlines() |
| 277 | f.close() |
| 278 | if list_grep(cpuinfo, '^cpu.*(RS64|POWER3|Broadband Engine)'): |
| 279 | return 'power' |
| 280 | elif list_grep(cpuinfo, '^cpu.*POWER4'): |
| 281 | return 'power4' |
| 282 | elif list_grep(cpuinfo, '^cpu.*POWER5'): |
| 283 | return 'power5' |
| 284 | elif list_grep(cpuinfo, '^cpu.*POWER6'): |
| 285 | return 'power6' |
mbligh | 0758c82 | 2009-09-18 19:37:35 +0000 | [diff] [blame] | 286 | elif list_grep(cpuinfo, '^cpu.*POWER7'): |
| 287 | return 'power7' |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 288 | elif list_grep(cpuinfo, '^cpu.*PPC970'): |
| 289 | return 'power970' |
mbligh | f23fd92 | 2010-02-25 18:45:45 +0000 | [diff] [blame] | 290 | elif list_grep(cpuinfo, 'ARM'): |
| 291 | return 'arm' |
mbligh | 12e8b89 | 2008-09-08 21:39:41 +0000 | [diff] [blame] | 292 | elif list_grep(cpuinfo, '^flags.*:.* lm .*'): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 293 | return 'x86_64' |
HS Liao | d24bc85 | 2015-07-15 18:59:06 +0800 | [diff] [blame] | 294 | elif list_grep(cpuinfo, 'CPU.*implementer.*0x41'): |
| 295 | return 'arm' |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 296 | else: |
| 297 | return 'i386' |
mbligh | f4c3532 | 2006-03-13 01:01:10 +0000 | [diff] [blame] | 298 | |
David Sharp | f948379 | 2015-03-06 13:56:39 -0800 | [diff] [blame] | 299 | |
Haixia Shi | 82dd904 | 2016-09-27 18:10:53 -0700 | [diff] [blame] | 300 | def get_arm_soc_family_from_devicetree(): |
| 301 | """ |
| 302 | Work out which ARM SoC we're running on based on the 'compatible' property |
| 303 | of the base node of devicetree, if it exists. |
| 304 | """ |
| 305 | devicetree_compatible = '/sys/firmware/devicetree/base/compatible' |
| 306 | if not os.path.isfile(devicetree_compatible): |
| 307 | return None |
| 308 | f = open(devicetree_compatible, 'r') |
| 309 | compatible = f.readlines() |
| 310 | f.close() |
| 311 | if list_grep(compatible, 'rk3399'): |
| 312 | return 'rockchip' |
| 313 | elif list_grep(compatible, 'mt8173'): |
| 314 | return 'mediatek' |
| 315 | return None |
| 316 | |
| 317 | |
Daniel Kurtz | 7c6ee78 | 2014-03-03 18:14:33 -0800 | [diff] [blame] | 318 | def get_arm_soc_family(): |
| 319 | """Work out which ARM SoC we're running on""" |
Haixia Shi | 82dd904 | 2016-09-27 18:10:53 -0700 | [diff] [blame] | 320 | family = get_arm_soc_family_from_devicetree() |
| 321 | if family is not None: |
| 322 | return family |
| 323 | |
Daniel Kurtz | 7c6ee78 | 2014-03-03 18:14:33 -0800 | [diff] [blame] | 324 | f = open('/proc/cpuinfo', 'r') |
| 325 | cpuinfo = f.readlines() |
| 326 | f.close() |
| 327 | if list_grep(cpuinfo, 'EXYNOS5'): |
| 328 | return 'exynos5' |
| 329 | elif list_grep(cpuinfo, 'Tegra'): |
| 330 | return 'tegra' |
ZhengShunQian | aec3bf5 | 2014-09-24 15:14:41 +0800 | [diff] [blame] | 331 | elif list_grep(cpuinfo, 'Rockchip'): |
| 332 | return 'rockchip' |
Daniel Kurtz | 7c6ee78 | 2014-03-03 18:14:33 -0800 | [diff] [blame] | 333 | return 'arm' |
| 334 | |
David Sharp | f948379 | 2015-03-06 13:56:39 -0800 | [diff] [blame] | 335 | |
Daniel Kurtz | 1711374 | 2014-03-05 14:10:03 -0800 | [diff] [blame] | 336 | def get_cpu_soc_family(): |
Daniel Kurtz | 7c6ee78 | 2014-03-03 18:14:33 -0800 | [diff] [blame] | 337 | """Like get_cpu_arch, but for ARM, returns the SoC family name""" |
| 338 | family = get_cpu_arch() |
| 339 | if family == 'arm': |
Ilja H. Friedel | 59b3bc7 | 2015-05-18 13:53:28 -0700 | [diff] [blame] | 340 | family = get_arm_soc_family() |
Daniel Kurtz | 7c6ee78 | 2014-03-03 18:14:33 -0800 | [diff] [blame] | 341 | return family |
mbligh | f4c3532 | 2006-03-13 01:01:10 +0000 | [diff] [blame] | 342 | |
David Sharp | f948379 | 2015-03-06 13:56:39 -0800 | [diff] [blame] | 343 | |
David Sharp | eb5e7a3 | 2014-10-29 15:44:39 -0700 | [diff] [blame] | 344 | INTEL_UARCH_TABLE = { |
David Sharp | eb5e7a3 | 2014-10-29 15:44:39 -0700 | [diff] [blame] | 345 | '06_1C': 'Atom', |
Ilja H. Friedel | 59b3bc7 | 2015-05-18 13:53:28 -0700 | [diff] [blame] | 346 | '06_26': 'Atom', |
| 347 | '06_36': 'Atom', |
| 348 | '06_4C': 'Braswell', |
David Sharp | eb5e7a3 | 2014-10-29 15:44:39 -0700 | [diff] [blame] | 349 | '06_3D': 'Broadwell', |
David Sharp | eb5e7a3 | 2014-10-29 15:44:39 -0700 | [diff] [blame] | 350 | '06_0D': 'Dothan', |
Ilja H. Friedel | 59b3bc7 | 2015-05-18 13:53:28 -0700 | [diff] [blame] | 351 | '06_3A': 'IvyBridge', |
| 352 | '06_3E': 'IvyBridge', |
| 353 | '06_3C': 'Haswell', |
| 354 | '06_3F': 'Haswell', |
| 355 | '06_45': 'Haswell', |
| 356 | '06_46': 'Haswell', |
| 357 | '06_0F': 'Merom', |
| 358 | '06_16': 'Merom', |
| 359 | '06_17': 'Nehalem', |
| 360 | '06_1A': 'Nehalem', |
| 361 | '06_1D': 'Nehalem', |
| 362 | '06_1E': 'Nehalem', |
| 363 | '06_1F': 'Nehalem', |
| 364 | '06_2E': 'Nehalem', |
| 365 | '06_2A': 'SandyBridge', |
| 366 | '06_2D': 'SandyBridge', |
| 367 | '06_4E': 'Skylake', |
| 368 | '0F_03': 'Prescott', |
| 369 | '0F_04': 'Prescott', |
| 370 | '0F_06': 'Presler', |
| 371 | '06_25': 'Westmere', |
| 372 | '06_2C': 'Westmere', |
| 373 | '06_2F': 'Westmere', |
David Sharp | eb5e7a3 | 2014-10-29 15:44:39 -0700 | [diff] [blame] | 374 | } |
| 375 | |
David Sharp | f948379 | 2015-03-06 13:56:39 -0800 | [diff] [blame] | 376 | |
David Sharp | eb5e7a3 | 2014-10-29 15:44:39 -0700 | [diff] [blame] | 377 | def get_intel_cpu_uarch(numeric=False): |
| 378 | """Return the Intel microarchitecture we're running on, or None. |
| 379 | |
| 380 | Returns None if this is not an Intel CPU. Returns the family and model as |
| 381 | underscore-separated hex (per Intel manual convention) if the uarch is not |
| 382 | known, or if numeric is True. |
| 383 | """ |
| 384 | if not get_current_kernel_arch().startswith('x86'): |
| 385 | return None |
| 386 | cpuinfo = get_cpuinfo()[0] |
| 387 | if cpuinfo['vendor_id'] != 'GenuineIntel': |
| 388 | return None |
| 389 | family_model = '%02X_%02X' % (int(cpuinfo['cpu family']), |
| 390 | int(cpuinfo['model'])) |
| 391 | if numeric: |
| 392 | return family_model |
| 393 | return INTEL_UARCH_TABLE.get(family_model, family_model) |
| 394 | |
| 395 | |
mbligh | 548f29a | 2006-10-17 04:55:12 +0000 | [diff] [blame] | 396 | def get_current_kernel_arch(): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 397 | """Get the machine architecture, now just a wrap of 'uname -m'.""" |
| 398 | return os.popen('uname -m').read().rstrip() |
mbligh | cdf02a4 | 2006-04-23 02:22:49 +0000 | [diff] [blame] | 399 | |
| 400 | |
mbligh | fdbcaec | 2006-10-01 23:28:57 +0000 | [diff] [blame] | 401 | def get_file_arch(filename): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 402 | # -L means follow symlinks |
mbligh | 2da4d88 | 2009-01-21 19:05:40 +0000 | [diff] [blame] | 403 | file_data = utils.system_output('file -L ' + filename) |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 404 | if file_data.count('80386'): |
| 405 | return 'i386' |
| 406 | return None |
mbligh | fdbcaec | 2006-10-01 23:28:57 +0000 | [diff] [blame] | 407 | |
| 408 | |
mbligh | f4c3532 | 2006-03-13 01:01:10 +0000 | [diff] [blame] | 409 | def count_cpus(): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 410 | """number of CPUs in the local machine according to /proc/cpuinfo""" |
cychiang | 46589b1 | 2012-10-03 11:19:33 +0800 | [diff] [blame] | 411 | try: |
Ilja H. Friedel | 59b3bc7 | 2015-05-18 13:53:28 -0700 | [diff] [blame] | 412 | return multiprocessing.cpu_count() |
cychiang | 46589b1 | 2012-10-03 11:19:33 +0800 | [diff] [blame] | 413 | except Exception as e: |
Ilja H. Friedel | 59b3bc7 | 2015-05-18 13:53:28 -0700 | [diff] [blame] | 414 | logging.exception('can not get cpu count from' |
cychiang | 46589b1 | 2012-10-03 11:19:33 +0800 | [diff] [blame] | 415 | ' multiprocessing.cpu_count()') |
David Sharp | f948379 | 2015-03-06 13:56:39 -0800 | [diff] [blame] | 416 | cpuinfo = get_cpuinfo() |
cychiang | 46589b1 | 2012-10-03 11:19:33 +0800 | [diff] [blame] | 417 | # Returns at least one cpu. Check comment #1 in crosbug.com/p/9582. |
David Sharp | f948379 | 2015-03-06 13:56:39 -0800 | [diff] [blame] | 418 | return len(cpuinfo) or 1 |
| 419 | |
| 420 | |
| 421 | def cpu_online_map(): |
| 422 | """ |
| 423 | Check out the available cpu online map |
| 424 | """ |
| 425 | cpuinfo = get_cpuinfo() |
| 426 | cpus = [] |
| 427 | for cpu in cpuinfo: |
Ilja H. Friedel | 59b3bc7 | 2015-05-18 13:53:28 -0700 | [diff] [blame] | 428 | cpus.append(cpu['processor']) # grab cpu number |
David Sharp | f948379 | 2015-03-06 13:56:39 -0800 | [diff] [blame] | 429 | return cpus |
| 430 | |
| 431 | |
| 432 | def get_cpu_family(): |
| 433 | cpuinfo = get_cpuinfo()[0] |
| 434 | return int(cpuinfo['cpu_family']) |
| 435 | |
| 436 | |
| 437 | def get_cpu_vendor(): |
| 438 | cpuinfo = get_cpuinfo() |
| 439 | vendors = [cpu['vendor_id'] for cpu in cpuinfo] |
| 440 | for v in vendors[1:]: |
| 441 | if v != vendors[0]: |
| 442 | raise error.TestError('multiple cpu vendors found: ' + str(vendors)) |
| 443 | return vendors[0] |
| 444 | |
| 445 | |
| 446 | def probe_cpus(): |
| 447 | """ |
| 448 | This routine returns a list of cpu devices found under |
| 449 | /sys/devices/system/cpu. |
| 450 | """ |
| 451 | cmd = 'find /sys/devices/system/cpu/ -maxdepth 1 -type d -name cpu*' |
| 452 | return utils.system_output(cmd).splitlines() |
mbligh | f4c3532 | 2006-03-13 01:01:10 +0000 | [diff] [blame] | 453 | |
mbligh | e7a170f | 2006-12-05 07:48:18 +0000 | [diff] [blame] | 454 | |
| 455 | # Returns total memory in kb |
mbligh | 558885e | 2008-04-01 20:41:38 +0000 | [diff] [blame] | 456 | def read_from_meminfo(key): |
mbligh | 2da4d88 | 2009-01-21 19:05:40 +0000 | [diff] [blame] | 457 | meminfo = utils.system_output('grep %s /proc/meminfo' % key) |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 458 | return int(re.search(r'\d+', meminfo).group(0)) |
mbligh | 558885e | 2008-04-01 20:41:38 +0000 | [diff] [blame] | 459 | |
| 460 | |
mbligh | e7a170f | 2006-12-05 07:48:18 +0000 | [diff] [blame] | 461 | def memtotal(): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 462 | return read_from_meminfo('MemTotal') |
mbligh | 558885e | 2008-04-01 20:41:38 +0000 | [diff] [blame] | 463 | |
| 464 | |
| 465 | def freememtotal(): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 466 | return read_from_meminfo('MemFree') |
mbligh | 558885e | 2008-04-01 20:41:38 +0000 | [diff] [blame] | 467 | |
Puthikorn Voravootivat | b7f4c2e | 2014-04-03 11:03:39 -0700 | [diff] [blame] | 468 | def usable_memtotal(): |
Puthikorn Voravootivat | dca8dc6 | 2014-08-11 10:44:57 -0700 | [diff] [blame] | 469 | # Reserved 5% for OS use |
| 470 | return int(read_from_meminfo('MemFree') * 0.95) |
Puthikorn Voravootivat | b7f4c2e | 2014-04-03 11:03:39 -0700 | [diff] [blame] | 471 | |
mbligh | 558885e | 2008-04-01 20:41:38 +0000 | [diff] [blame] | 472 | |
mbligh | 8493be4 | 2008-11-20 00:55:11 +0000 | [diff] [blame] | 473 | def rounded_memtotal(): |
mbligh | 53da18e | 2009-01-05 21:13:26 +0000 | [diff] [blame] | 474 | # Get total of all physical mem, in kbytes |
| 475 | usable_kbytes = memtotal() |
| 476 | # usable_kbytes is system's usable DRAM in kbytes, |
mbligh | 8493be4 | 2008-11-20 00:55:11 +0000 | [diff] [blame] | 477 | # as reported by memtotal() from device /proc/meminfo memtotal |
| 478 | # after Linux deducts 1.5% to 5.1% for system table overhead |
| 479 | # Undo the unknown actual deduction by rounding up |
| 480 | # to next small multiple of a big power-of-two |
| 481 | # eg 12GB - 5.1% gets rounded back up to 12GB |
| 482 | mindeduct = 0.015 # 1.5 percent |
| 483 | maxdeduct = 0.055 # 5.5 percent |
| 484 | # deduction range 1.5% .. 5.5% supports physical mem sizes |
| 485 | # 6GB .. 12GB in steps of .5GB |
| 486 | # 12GB .. 24GB in steps of 1 GB |
| 487 | # 24GB .. 48GB in steps of 2 GB ... |
| 488 | # Finer granularity in physical mem sizes would require |
| 489 | # tighter spread between min and max possible deductions |
| 490 | |
| 491 | # increase mem size by at least min deduction, without rounding |
Puthikorn Voravootivat | b7f4c2e | 2014-04-03 11:03:39 -0700 | [diff] [blame] | 492 | min_kbytes = int(usable_kbytes / (1.0 - mindeduct)) |
mbligh | 8493be4 | 2008-11-20 00:55:11 +0000 | [diff] [blame] | 493 | # increase mem size further by 2**n rounding, by 0..roundKb or more |
mbligh | 53da18e | 2009-01-05 21:13:26 +0000 | [diff] [blame] | 494 | round_kbytes = int(usable_kbytes / (1.0 - maxdeduct)) - min_kbytes |
mbligh | 8493be4 | 2008-11-20 00:55:11 +0000 | [diff] [blame] | 495 | # find least binary roundup 2**n that covers worst-cast roundKb |
mbligh | 53da18e | 2009-01-05 21:13:26 +0000 | [diff] [blame] | 496 | mod2n = 1 << int(math.ceil(math.log(round_kbytes, 2))) |
| 497 | # have round_kbytes <= mod2n < round_kbytes*2 |
| 498 | # round min_kbytes up to next multiple of mod2n |
| 499 | phys_kbytes = min_kbytes + mod2n - 1 |
| 500 | phys_kbytes = phys_kbytes - (phys_kbytes % mod2n) # clear low bits |
| 501 | return phys_kbytes |
mbligh | 8493be4 | 2008-11-20 00:55:11 +0000 | [diff] [blame] | 502 | |
| 503 | |
jadmanski | f432516 | 2010-04-09 16:04:54 +0000 | [diff] [blame] | 504 | def sysctl(key, value=None): |
| 505 | """Generic implementation of sysctl, to read and write. |
| 506 | |
| 507 | @param key: A location under /proc/sys |
| 508 | @param value: If not None, a value to write into the sysctl. |
| 509 | |
| 510 | @return The single-line sysctl value as a string. |
| 511 | """ |
| 512 | path = '/proc/sys/%s' % key |
| 513 | if value is not None: |
| 514 | utils.write_one_line(path, str(value)) |
| 515 | return utils.read_one_line(path) |
| 516 | |
| 517 | |
mbligh | 558885e | 2008-04-01 20:41:38 +0000 | [diff] [blame] | 518 | def sysctl_kernel(key, value=None): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 519 | """(Very) partial implementation of sysctl, for kernel params""" |
jadmanski | f432516 | 2010-04-09 16:04:54 +0000 | [diff] [blame] | 520 | if value is not None: |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 521 | # write |
mbligh | 2da4d88 | 2009-01-21 19:05:40 +0000 | [diff] [blame] | 522 | utils.write_one_line('/proc/sys/kernel/%s' % key, str(value)) |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 523 | else: |
| 524 | # read |
mbligh | 2da4d88 | 2009-01-21 19:05:40 +0000 | [diff] [blame] | 525 | out = utils.read_one_line('/proc/sys/kernel/%s' % key) |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 526 | return int(re.search(r'\d+', out).group(0)) |
mbligh | e7a170f | 2006-12-05 07:48:18 +0000 | [diff] [blame] | 527 | |
| 528 | |
mbligh | 5285a2d | 2008-03-10 20:28:08 +0000 | [diff] [blame] | 529 | def _convert_exit_status(sts): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 530 | if os.WIFSIGNALED(sts): |
| 531 | return -os.WTERMSIG(sts) |
| 532 | elif os.WIFEXITED(sts): |
| 533 | return os.WEXITSTATUS(sts) |
| 534 | else: |
| 535 | # impossible? |
| 536 | raise RuntimeError("Unknown exit status %d!" % sts) |
mbligh | 5285a2d | 2008-03-10 20:28:08 +0000 | [diff] [blame] | 537 | |
| 538 | |
mbligh | f4c3532 | 2006-03-13 01:01:10 +0000 | [diff] [blame] | 539 | def where_art_thy_filehandles(): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 540 | """Dump the current list of filehandles""" |
| 541 | os.system("ls -l /proc/%d/fd >> /dev/tty" % os.getpid()) |
mbligh | f4c3532 | 2006-03-13 01:01:10 +0000 | [diff] [blame] | 542 | |
| 543 | |
| 544 | def print_to_tty(string): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 545 | """Output string straight to the tty""" |
| 546 | open('/dev/tty', 'w').write(string + '\n') |
mbligh | f4c3532 | 2006-03-13 01:01:10 +0000 | [diff] [blame] | 547 | |
| 548 | |
mbligh | b8a14e3 | 2006-05-06 00:17:35 +0000 | [diff] [blame] | 549 | def dump_object(object): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 550 | """Dump an object's attributes and methods |
mbligh | c86b0b4 | 2006-07-28 17:35:28 +0000 | [diff] [blame] | 551 | |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 552 | kind of like dir() |
| 553 | """ |
| 554 | for item in object.__dict__.iteritems(): |
| 555 | print item |
| 556 | try: |
Puthikorn Voravootivat | b7f4c2e | 2014-04-03 11:03:39 -0700 | [diff] [blame] | 557 | (key, value) = item |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 558 | dump_object(value) |
| 559 | except: |
| 560 | continue |
mbligh | b8a14e3 | 2006-05-06 00:17:35 +0000 | [diff] [blame] | 561 | |
| 562 | |
mbligh | 4b08966 | 2006-06-14 22:34:58 +0000 | [diff] [blame] | 563 | def environ(env_key): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 564 | """return the requested environment variable, or '' if unset""" |
| 565 | if (os.environ.has_key(env_key)): |
| 566 | return os.environ[env_key] |
| 567 | else: |
| 568 | return '' |
mbligh | 4b08966 | 2006-06-14 22:34:58 +0000 | [diff] [blame] | 569 | |
| 570 | |
| 571 | def prepend_path(newpath, oldpath): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 572 | """prepend newpath to oldpath""" |
| 573 | if (oldpath): |
| 574 | return newpath + ':' + oldpath |
| 575 | else: |
| 576 | return newpath |
mbligh | 4b08966 | 2006-06-14 22:34:58 +0000 | [diff] [blame] | 577 | |
| 578 | |
| 579 | def append_path(oldpath, newpath): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 580 | """append newpath to oldpath""" |
| 581 | if (oldpath): |
| 582 | return oldpath + ':' + newpath |
| 583 | else: |
| 584 | return newpath |
mbligh | 4b08966 | 2006-06-14 22:34:58 +0000 | [diff] [blame] | 585 | |
| 586 | |
David Sharp | 77e0121 | 2015-03-06 15:01:06 -0800 | [diff] [blame] | 587 | _TIME_OUTPUT_RE = re.compile( |
| 588 | r'([\d\.]*)user ([\d\.]*)system ' |
| 589 | r'(\d*):([\d\.]*)elapsed (\d*)%CPU') |
| 590 | |
| 591 | |
mbligh | 4e75b0d | 2006-08-29 15:22:44 +0000 | [diff] [blame] | 592 | def avgtime_print(dir): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 593 | """ Calculate some benchmarking statistics. |
| 594 | Input is a directory containing a file called 'time'. |
| 595 | File contains one-per-line results of /usr/bin/time. |
| 596 | Output is average Elapsed, User, and System time in seconds, |
| 597 | and average CPU percentage. |
| 598 | """ |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 599 | user = system = elapsed = cpu = count = 0 |
David Sharp | 77e0121 | 2015-03-06 15:01:06 -0800 | [diff] [blame] | 600 | with open(dir + "/time") as f: |
| 601 | for line in f: |
| 602 | try: |
| 603 | m = _TIME_OUTPUT_RE.match(line); |
| 604 | user += float(m.group(1)) |
| 605 | system += float(m.group(2)) |
| 606 | elapsed += (float(m.group(3)) * 60) + float(m.group(4)) |
| 607 | cpu += float(m.group(5)) |
| 608 | count += 1 |
| 609 | except: |
| 610 | raise ValueError("badly formatted times") |
mbligh | af4efc2 | 2008-01-25 16:33:59 +0000 | [diff] [blame] | 611 | |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 612 | return "Elapsed: %0.2fs User: %0.2fs System: %0.2fs CPU: %0.0f%%" % \ |
Puthikorn Voravootivat | b7f4c2e | 2014-04-03 11:03:39 -0700 | [diff] [blame] | 613 | (elapsed / count, user / count, system / count, cpu / count) |
mbligh | 4e75b0d | 2006-08-29 15:22:44 +0000 | [diff] [blame] | 614 | |
| 615 | |
David Sharp | 77e0121 | 2015-03-06 15:01:06 -0800 | [diff] [blame] | 616 | def to_seconds(time_string): |
| 617 | """Converts a string in M+:SS.SS format to S+.SS""" |
| 618 | elts = time_string.split(':') |
| 619 | if len(elts) == 1: |
| 620 | return time_string |
| 621 | return str(int(elts[0]) * 60 + float(elts[1])) |
| 622 | |
| 623 | |
| 624 | _TIME_OUTPUT_RE_2 = re.compile(r'(.*?)user (.*?)system (.*?)elapsed') |
| 625 | |
| 626 | |
| 627 | def extract_all_time_results(results_string): |
| 628 | """Extract user, system, and elapsed times into a list of tuples""" |
| 629 | results = [] |
| 630 | for result in _TIME_OUTPUT_RE_2.findall(results_string): |
| 631 | results.append(tuple([to_seconds(elt) for elt in result])) |
| 632 | return results |
| 633 | |
| 634 | |
mbligh | f06db0f | 2006-09-30 17:08:43 +0000 | [diff] [blame] | 635 | def running_config(): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 636 | """ |
| 637 | Return path of config file of the currently running kernel |
| 638 | """ |
mbligh | 2da4d88 | 2009-01-21 19:05:40 +0000 | [diff] [blame] | 639 | version = utils.system_output('uname -r') |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 640 | for config in ('/proc/config.gz', \ |
| 641 | '/boot/config-%s' % version, |
| 642 | '/lib/modules/%s/build/.config' % version): |
| 643 | if os.path.isfile(config): |
| 644 | return config |
| 645 | return None |
mbligh | 9ec8acc | 2006-10-05 06:52:33 +0000 | [diff] [blame] | 646 | |
| 647 | |
mbligh | a1bef1f | 2007-04-03 17:18:07 +0000 | [diff] [blame] | 648 | def check_for_kernel_feature(feature): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 649 | config = running_config() |
mbligh | a1bef1f | 2007-04-03 17:18:07 +0000 | [diff] [blame] | 650 | |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 651 | if not config: |
| 652 | raise TypeError("Can't find kernel config file") |
mbligh | a1bef1f | 2007-04-03 17:18:07 +0000 | [diff] [blame] | 653 | |
lmr | 959e816 | 2010-04-16 06:15:34 +0000 | [diff] [blame] | 654 | if magic.guess_type(config) == 'application/x-gzip': |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 655 | grep = 'zgrep' |
| 656 | else: |
| 657 | grep = 'grep' |
| 658 | grep += ' ^CONFIG_%s= %s' % (feature, config) |
mbligh | a1bef1f | 2007-04-03 17:18:07 +0000 | [diff] [blame] | 659 | |
mbligh | 2da4d88 | 2009-01-21 19:05:40 +0000 | [diff] [blame] | 660 | if not utils.system_output(grep, ignore_status=True): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 661 | raise ValueError("Kernel doesn't have a %s feature" % (feature)) |
mbligh | a1bef1f | 2007-04-03 17:18:07 +0000 | [diff] [blame] | 662 | |
| 663 | |
mbligh | 663e4f6 | 2006-10-11 05:03:40 +0000 | [diff] [blame] | 664 | def check_glibc_ver(ver): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 665 | glibc_ver = commands.getoutput('ldd --version').splitlines()[0] |
| 666 | glibc_ver = re.search(r'(\d+\.\d+(\.\d+)?)', glibc_ver).group() |
lmr | 0fab1e9 | 2010-05-21 18:25:36 +0000 | [diff] [blame] | 667 | if utils.compare_versions(glibc_ver, ver) == -1: |
| 668 | raise error.TestError("Glibc too old (%s). Glibc >= %s is needed." % |
| 669 | (glibc_ver, ver)) |
mbligh | 0763522 | 2007-07-09 21:29:00 +0000 | [diff] [blame] | 670 | |
| 671 | def check_kernel_ver(ver): |
mbligh | 2da4d88 | 2009-01-21 19:05:40 +0000 | [diff] [blame] | 672 | kernel_ver = utils.system_output('uname -r') |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 673 | kv_tmp = re.split(r'[-]', kernel_ver)[0:3] |
lmr | 42b7a5d | 2010-05-21 12:52:08 +0000 | [diff] [blame] | 674 | # In compare_versions, if v1 < v2, return value == -1 |
| 675 | if utils.compare_versions(kv_tmp[0], ver) == -1: |
| 676 | raise error.TestError("Kernel too old (%s). Kernel > %s is needed." % |
| 677 | (kernel_ver, ver)) |
mbligh | 60418bb | 2008-01-03 01:55:09 +0000 | [diff] [blame] | 678 | |
mbligh | 9061a27 | 2006-12-28 21:20:51 +0000 | [diff] [blame] | 679 | |
mbligh | 264cd8f | 2007-02-02 23:57:43 +0000 | [diff] [blame] | 680 | def human_format(number): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 681 | # Convert number to kilo / mega / giga format. |
| 682 | if number < 1024: |
| 683 | return "%d" % number |
| 684 | kilo = float(number) / 1024.0 |
| 685 | if kilo < 1024: |
| 686 | return "%.2fk" % kilo |
| 687 | meg = kilo / 1024.0 |
| 688 | if meg < 1024: |
| 689 | return "%.2fM" % meg |
| 690 | gig = meg / 1024.0 |
| 691 | return "%.2fG" % gig |
mbligh | 264cd8f | 2007-02-02 23:57:43 +0000 | [diff] [blame] | 692 | |
mbligh | 8eca3a9 | 2007-02-03 20:59:39 +0000 | [diff] [blame] | 693 | |
| 694 | def numa_nodes(): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 695 | node_paths = glob.glob('/sys/devices/system/node/node*') |
| 696 | nodes = [int(re.sub(r'.*node(\d+)', r'\1', x)) for x in node_paths] |
| 697 | return (sorted(nodes)) |
mbligh | 8eca3a9 | 2007-02-03 20:59:39 +0000 | [diff] [blame] | 698 | |
| 699 | |
| 700 | def node_size(): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 701 | nodes = max(len(numa_nodes()), 1) |
| 702 | return ((memtotal() * 1024) / nodes) |
mbligh | 8eca3a9 | 2007-02-03 20:59:39 +0000 | [diff] [blame] | 703 | |
mbligh | 32bcff3 | 2007-07-25 16:37:32 +0000 | [diff] [blame] | 704 | |
mbligh | c421164 | 2007-08-02 21:00:51 +0000 | [diff] [blame] | 705 | def pickle_load(filename): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 706 | return pickle.load(open(filename, 'r')) |
mbligh | c421164 | 2007-08-02 21:00:51 +0000 | [diff] [blame] | 707 | |
mbligh | 237bed3 | 2007-09-05 13:05:57 +0000 | [diff] [blame] | 708 | |
| 709 | # Return the kernel version and build timestamp. |
| 710 | def running_os_release(): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 711 | return os.uname()[2:4] |
mbligh | 237bed3 | 2007-09-05 13:05:57 +0000 | [diff] [blame] | 712 | |
| 713 | |
| 714 | def running_os_ident(): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 715 | (version, timestamp) = running_os_release() |
| 716 | return version + '::' + timestamp |
mbligh | b830e28 | 2007-10-02 16:35:03 +0000 | [diff] [blame] | 717 | |
| 718 | |
mbligh | 3bf79ca | 2009-01-21 19:02:40 +0000 | [diff] [blame] | 719 | def running_os_full_version(): |
| 720 | (version, timestamp) = running_os_release() |
| 721 | return version |
| 722 | |
| 723 | |
mbligh | 523a19b | 2007-12-04 22:50:14 +0000 | [diff] [blame] | 724 | # much like find . -name 'pattern' |
| 725 | def locate(pattern, root=os.getcwd()): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 726 | for path, dirs, files in os.walk(root): |
mbligh | 987071e | 2008-06-13 16:39:12 +0000 | [diff] [blame] | 727 | for f in files: |
| 728 | if fnmatch.fnmatch(f, pattern): |
mbligh | 7076b19 | 2008-06-13 17:53:49 +0000 | [diff] [blame] | 729 | yield os.path.abspath(os.path.join(path, f)) |
mbligh | 523a19b | 2007-12-04 22:50:14 +0000 | [diff] [blame] | 730 | |
| 731 | |
mbligh | 25bb1e1 | 2007-10-12 23:57:47 +0000 | [diff] [blame] | 732 | def freespace(path): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 733 | """Return the disk free space, in bytes""" |
| 734 | s = os.statvfs(path) |
| 735 | return s.f_bavail * s.f_bsize |
jadmanski | 8415f96 | 2008-05-06 20:38:53 +0000 | [diff] [blame] | 736 | |
| 737 | |
| 738 | def disk_block_size(path): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 739 | """Return the disk block size, in bytes""" |
| 740 | return os.statvfs(path).f_bsize |
mbligh | 6de9cdf | 2007-11-24 19:35:28 +0000 | [diff] [blame] | 741 | |
| 742 | |
David Sharp | 77e0121 | 2015-03-06 15:01:06 -0800 | [diff] [blame] | 743 | _DISK_PARTITION_3_RE = re.compile(r'^(/dev/hd[a-z]+)3', re.M) |
| 744 | |
mbligh | 2316e52 | 2007-11-24 19:39:52 +0000 | [diff] [blame] | 745 | def get_disks(): |
mbligh | 2da4d88 | 2009-01-21 19:05:40 +0000 | [diff] [blame] | 746 | df_output = utils.system_output('df') |
David Sharp | 77e0121 | 2015-03-06 15:01:06 -0800 | [diff] [blame] | 747 | return _DISK_PARTITION_3_RE.findall(df_output) |
mbligh | 6de9cdf | 2007-11-24 19:35:28 +0000 | [diff] [blame] | 748 | |
mbligh | 3e9062e | 2007-11-29 15:57:02 +0000 | [diff] [blame] | 749 | |
Puthikorn Voravootivat | 8b811e0 | 2014-06-02 14:13:45 -0700 | [diff] [blame] | 750 | def get_disk_size(disk_name): |
| 751 | """ |
| 752 | Return size of disk in byte. Return 0 in Error Case |
| 753 | |
| 754 | @param disk_name: disk name to find size |
| 755 | """ |
| 756 | device = os.path.basename(disk_name) |
| 757 | for line in file('/proc/partitions'): |
| 758 | try: |
Gwendal Grignou | 10e71e6 | 2014-06-12 11:25:19 -0700 | [diff] [blame] | 759 | _, _, blocks, name = re.split(r' +', line.strip()) |
Puthikorn Voravootivat | 8b811e0 | 2014-06-02 14:13:45 -0700 | [diff] [blame] | 760 | except ValueError: |
| 761 | continue |
| 762 | if name == device: |
| 763 | return 1024 * int(blocks) |
| 764 | return 0 |
| 765 | |
| 766 | |
| 767 | def get_disk_size_gb(disk_name): |
| 768 | """ |
| 769 | Return size of disk in GB (10^9). Return 0 in Error Case |
| 770 | |
| 771 | @param disk_name: disk name to find size |
| 772 | """ |
| 773 | return int(get_disk_size(disk_name) / (10.0 ** 9) + 0.5) |
| 774 | |
| 775 | |
| 776 | def get_disk_model(disk_name): |
| 777 | """ |
| 778 | Return model name for internal storage device |
| 779 | |
| 780 | @param disk_name: disk name to find model |
| 781 | """ |
| 782 | cmd1 = 'udevadm info --query=property --name=%s' % disk_name |
| 783 | cmd2 = 'grep -E "ID_(NAME|MODEL)="' |
| 784 | cmd3 = 'cut -f 2 -d"="' |
| 785 | cmd = ' | '.join([cmd1, cmd2, cmd3]) |
| 786 | return utils.system_output(cmd) |
| 787 | |
| 788 | |
Gwendal Grignou | a409c80 | 2016-10-13 09:41:08 -0700 | [diff] [blame] | 789 | _DISK_DEV_RE = re.compile(r'/dev/sd[a-z]|/dev/mmcblk[0-9]*|/dev/nvme[0-9]*') |
David Sharp | 77e0121 | 2015-03-06 15:01:06 -0800 | [diff] [blame] | 790 | |
| 791 | |
Gwendal Grignou | 10e71e6 | 2014-06-12 11:25:19 -0700 | [diff] [blame] | 792 | def get_disk_from_filename(filename): |
| 793 | """ |
| 794 | Return the disk device the filename is on. |
| 795 | If the file is on tmpfs or other special file systems, |
| 796 | return None. |
| 797 | |
| 798 | @param filename: name of file, full path. |
| 799 | """ |
Gwendal Grignou | 10e71e6 | 2014-06-12 11:25:19 -0700 | [diff] [blame] | 800 | |
Gwendal Grignou | 30dcb3b | 2014-06-20 10:48:21 -0700 | [diff] [blame] | 801 | if not os.path.exists(filename): |
Gwendal Grignou | 10e71e6 | 2014-06-12 11:25:19 -0700 | [diff] [blame] | 802 | raise error.TestError('file %s missing' % filename) |
| 803 | |
| 804 | if filename[0] != '/': |
| 805 | raise error.TestError('This code works only with full path') |
| 806 | |
David Sharp | 77e0121 | 2015-03-06 15:01:06 -0800 | [diff] [blame] | 807 | m = _DISK_DEV_RE.match(filename) |
Gwendal Grignou | 10e71e6 | 2014-06-12 11:25:19 -0700 | [diff] [blame] | 808 | while not m: |
| 809 | if filename[0] != '/': |
| 810 | return None |
| 811 | if filename == '/dev/root': |
| 812 | cmd = 'rootdev -d -s' |
| 813 | elif filename.startswith('/dev/mapper'): |
| 814 | cmd = 'dmsetup table "%s"' % os.path.basename(filename) |
| 815 | dmsetup_output = utils.system_output(cmd).split(' ') |
| 816 | if dmsetup_output[2] == 'verity': |
| 817 | maj_min = dmsetup_output[4] |
| 818 | elif dmsetup_output[2] == 'crypt': |
| 819 | maj_min = dmsetup_output[6] |
| 820 | cmd = 'realpath "/dev/block/%s"' % maj_min |
| 821 | elif filename.startswith('/dev/loop'): |
| 822 | cmd = 'losetup -O BACK-FILE "%s" | tail -1' % filename |
| 823 | else: |
| 824 | cmd = 'df "%s" | tail -1 | cut -f 1 -d" "' % filename |
| 825 | filename = utils.system_output(cmd) |
David Sharp | 77e0121 | 2015-03-06 15:01:06 -0800 | [diff] [blame] | 826 | m = _DISK_DEV_RE.match(filename) |
Gwendal Grignou | 10e71e6 | 2014-06-12 11:25:19 -0700 | [diff] [blame] | 827 | return m.group(0) |
| 828 | |
| 829 | |
Puthikorn Voravootivat | 8ba770d | 2014-06-10 14:44:27 -0700 | [diff] [blame] | 830 | def get_disk_firmware_version(disk_name): |
| 831 | """ |
| 832 | Return firmware version for internal storage device. (empty string for eMMC) |
| 833 | |
| 834 | @param disk_name: disk name to find model |
| 835 | """ |
| 836 | cmd1 = 'udevadm info --query=property --name=%s' % disk_name |
| 837 | cmd2 = 'grep -E "ID_REVISION="' |
| 838 | cmd3 = 'cut -f 2 -d"="' |
| 839 | cmd = ' | '.join([cmd1, cmd2, cmd3]) |
| 840 | return utils.system_output(cmd) |
| 841 | |
| 842 | |
| 843 | def is_disk_scsi(disk_name): |
| 844 | """ |
| 845 | Return true if disk is a scsi device, return false otherwise |
| 846 | |
| 847 | @param disk_name: disk name check |
| 848 | """ |
| 849 | return re.match('/dev/sd[a-z]+', disk_name) |
| 850 | |
| 851 | |
| 852 | def is_disk_harddisk(disk_name): |
| 853 | """ |
| 854 | Return true if disk is a harddisk, return false otherwise |
| 855 | |
| 856 | @param disk_name: disk name check |
| 857 | """ |
| 858 | cmd1 = 'udevadm info --query=property --name=%s' % disk_name |
| 859 | cmd2 = 'grep -E "ID_ATA_ROTATION_RATE_RPM="' |
| 860 | cmd3 = 'cut -f 2 -d"="' |
| 861 | cmd = ' | '.join([cmd1, cmd2, cmd3]) |
| 862 | |
| 863 | rtt = utils.system_output(cmd) |
| 864 | |
| 865 | # eMMC will not have this field; rtt == '' |
| 866 | # SSD will have zero rotation rate; rtt == '0' |
| 867 | # For harddisk rtt > 0 |
| 868 | return rtt and int(rtt) > 0 |
| 869 | |
| 870 | |
| 871 | def verify_hdparm_feature(disk_name, feature): |
| 872 | """ |
| 873 | Check for feature support for SCSI disk using hdparm |
| 874 | |
| 875 | @param disk_name: target disk |
| 876 | @param feature: hdparm output string of the feature |
| 877 | """ |
| 878 | cmd = 'hdparm -I %s | grep -q "%s"' % (disk_name, feature) |
| 879 | ret = utils.system(cmd, ignore_status=True) |
| 880 | if ret == 0: |
| 881 | return True |
| 882 | elif ret == 1: |
| 883 | return False |
| 884 | else: |
| 885 | raise error.TestFail('Error running command %s' % cmd) |
| 886 | |
| 887 | |
| 888 | def get_storage_error_msg(disk_name, reason): |
| 889 | """ |
| 890 | Get Error message for storage test which include disk model. |
| 891 | and also include the firmware version for the SCSI disk |
| 892 | |
| 893 | @param disk_name: target disk |
| 894 | @param reason: Reason of the error. |
| 895 | """ |
| 896 | |
| 897 | msg = reason |
| 898 | |
| 899 | model = get_disk_model(disk_name) |
| 900 | msg += ' Disk model: %s' % model |
| 901 | |
| 902 | if is_disk_scsi(disk_name): |
| 903 | fw = get_disk_firmware_version(disk_name) |
| 904 | msg += ' firmware: %s' % fw |
| 905 | |
| 906 | return msg |
| 907 | |
| 908 | |
Brian Norris | 570152b | 2015-12-07 16:52:19 -0800 | [diff] [blame] | 909 | def load_module(module_name, params=None): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 910 | # Checks if a module has already been loaded |
| 911 | if module_is_loaded(module_name): |
| 912 | return False |
mbligh | af4efc2 | 2008-01-25 16:33:59 +0000 | [diff] [blame] | 913 | |
Brian Norris | 570152b | 2015-12-07 16:52:19 -0800 | [diff] [blame] | 914 | cmd = '/sbin/modprobe ' + module_name |
| 915 | if params: |
| 916 | cmd += ' ' + params |
| 917 | utils.system(cmd) |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 918 | return True |
mbligh | 3e9062e | 2007-11-29 15:57:02 +0000 | [diff] [blame] | 919 | |
| 920 | |
| 921 | def unload_module(module_name): |
lmr | b923fc2 | 2009-06-08 17:27:59 +0000 | [diff] [blame] | 922 | """ |
| 923 | Removes a module. Handles dependencies. If even then it's not possible |
| 924 | to remove one of the modules, it will trhow an error.CmdError exception. |
| 925 | |
| 926 | @param module_name: Name of the module we want to remove. |
| 927 | """ |
Henrik Kjellander | abbd237 | 2013-04-04 14:06:57 +0200 | [diff] [blame] | 928 | l_raw = utils.system_output("/bin/lsmod").splitlines() |
lmr | b923fc2 | 2009-06-08 17:27:59 +0000 | [diff] [blame] | 929 | lsmod = [x for x in l_raw if x.split()[0] == module_name] |
| 930 | if len(lsmod) > 0: |
| 931 | line_parts = lsmod[0].split() |
| 932 | if len(line_parts) == 4: |
| 933 | submodules = line_parts[3].split(",") |
| 934 | for submodule in submodules: |
| 935 | unload_module(submodule) |
| 936 | utils.system("/sbin/modprobe -r %s" % module_name) |
Daniel Kurtz | f278e85 | 2014-03-04 21:57:30 -0800 | [diff] [blame] | 937 | logging.info("Module %s unloaded", module_name) |
lmr | b923fc2 | 2009-06-08 17:27:59 +0000 | [diff] [blame] | 938 | else: |
Daniel Kurtz | f278e85 | 2014-03-04 21:57:30 -0800 | [diff] [blame] | 939 | logging.info("Module %s is already unloaded", module_name) |
mbligh | 3e9062e | 2007-11-29 15:57:02 +0000 | [diff] [blame] | 940 | |
| 941 | |
| 942 | def module_is_loaded(module_name): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 943 | module_name = module_name.replace('-', '_') |
Henrik Kjellander | abbd237 | 2013-04-04 14:06:57 +0200 | [diff] [blame] | 944 | modules = utils.system_output('/bin/lsmod').splitlines() |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 945 | for module in modules: |
| 946 | if module.startswith(module_name) and module[len(module_name)] == ' ': |
| 947 | return True |
| 948 | return False |
mbligh | 3e9062e | 2007-11-29 15:57:02 +0000 | [diff] [blame] | 949 | |
| 950 | |
mbligh | 6b34c4c | 2008-01-10 16:32:04 +0000 | [diff] [blame] | 951 | def get_loaded_modules(): |
Henrik Kjellander | abbd237 | 2013-04-04 14:06:57 +0200 | [diff] [blame] | 952 | lsmod_output = utils.system_output('/bin/lsmod').splitlines()[1:] |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 953 | return [line.split(None, 1)[0] for line in lsmod_output] |
mbligh | 6b34c4c | 2008-01-10 16:32:04 +0000 | [diff] [blame] | 954 | |
| 955 | |
mbligh | 3e9062e | 2007-11-29 15:57:02 +0000 | [diff] [blame] | 956 | def get_huge_page_size(): |
mbligh | 2da4d88 | 2009-01-21 19:05:40 +0000 | [diff] [blame] | 957 | output = utils.system_output('grep Hugepagesize /proc/meminfo') |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 958 | return int(output.split()[1]) # Assumes units always in kB. :( |
mbligh | 3e9062e | 2007-11-29 15:57:02 +0000 | [diff] [blame] | 959 | |
| 960 | |
| 961 | def get_num_huge_pages(): |
mbligh | 2da4d88 | 2009-01-21 19:05:40 +0000 | [diff] [blame] | 962 | raw_hugepages = utils.system_output('/sbin/sysctl vm.nr_hugepages') |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 963 | return int(raw_hugepages.split()[2]) |
mbligh | 3e9062e | 2007-11-29 15:57:02 +0000 | [diff] [blame] | 964 | |
| 965 | |
| 966 | def set_num_huge_pages(num): |
mbligh | 2da4d88 | 2009-01-21 19:05:40 +0000 | [diff] [blame] | 967 | utils.system('/sbin/sysctl vm.nr_hugepages=%d' % num) |
mbligh | 3e9062e | 2007-11-29 15:57:02 +0000 | [diff] [blame] | 968 | |
| 969 | |
mbligh | 70c50ad | 2008-02-12 20:56:13 +0000 | [diff] [blame] | 970 | def ping_default_gateway(): |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 971 | """Ping the default gateway.""" |
mbligh | 70c50ad | 2008-02-12 20:56:13 +0000 | [diff] [blame] | 972 | |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 973 | network = open('/etc/sysconfig/network') |
| 974 | m = re.search('GATEWAY=(\S+)', network.read()) |
| 975 | |
| 976 | if m: |
| 977 | gw = m.group(1) |
| 978 | cmd = 'ping %s -c 5 > /dev/null' % gw |
mbligh | 2da4d88 | 2009-01-21 19:05:40 +0000 | [diff] [blame] | 979 | return utils.system(cmd, ignore_status=True) |
jadmanski | 0afbb63 | 2008-06-06 21:10:57 +0000 | [diff] [blame] | 980 | |
| 981 | raise error.TestError('Unable to find default gateway') |
mbligh | 70c50ad | 2008-02-12 20:56:13 +0000 | [diff] [blame] | 982 | |
| 983 | |
jadmanski | 115feb2 | 2008-07-23 21:36:22 +0000 | [diff] [blame] | 984 | def drop_caches(): |
| 985 | """Writes back all dirty pages to disk and clears all the caches.""" |
mbligh | 2da4d88 | 2009-01-21 19:05:40 +0000 | [diff] [blame] | 986 | utils.system("sync") |
jadmanski | 115feb2 | 2008-07-23 21:36:22 +0000 | [diff] [blame] | 987 | # We ignore failures here as this will fail on 2.6.11 kernels. |
mbligh | 2da4d88 | 2009-01-21 19:05:40 +0000 | [diff] [blame] | 988 | utils.system("echo 3 > /proc/sys/vm/drop_caches", ignore_status=True) |
mbligh | a3c17fc | 2009-08-24 22:34:41 +0000 | [diff] [blame] | 989 | |
| 990 | |
mbligh | e6bc5b9 | 2009-11-06 03:12:11 +0000 | [diff] [blame] | 991 | def process_is_alive(name_pattern): |
mbligh | a3c17fc | 2009-08-24 22:34:41 +0000 | [diff] [blame] | 992 | """ |
| 993 | 'pgrep name' misses all python processes and also long process names. |
| 994 | 'pgrep -f name' gets all shell commands with name in args. |
mbligh | e6bc5b9 | 2009-11-06 03:12:11 +0000 | [diff] [blame] | 995 | So look only for command whose initial pathname ends with name. |
| 996 | Name itself is an egrep pattern, so it can use | etc for variations. |
mbligh | a3c17fc | 2009-08-24 22:34:41 +0000 | [diff] [blame] | 997 | """ |
mbligh | e6bc5b9 | 2009-11-06 03:12:11 +0000 | [diff] [blame] | 998 | return utils.system("pgrep -f '^([^ /]*/)*(%s)([ ]|$)'" % name_pattern, |
mbligh | a3c17fc | 2009-08-24 22:34:41 +0000 | [diff] [blame] | 999 | ignore_status=True) == 0 |
mbligh | 88f602c | 2010-02-02 18:17:04 +0000 | [diff] [blame] | 1000 | |
| 1001 | |
Eric Li | a82dc35 | 2011-02-23 13:15:52 -0800 | [diff] [blame] | 1002 | def get_hwclock_seconds(utc=True): |
| 1003 | """ |
| 1004 | Return the hardware clock in seconds as a floating point value. |
| 1005 | Use Coordinated Universal Time if utc is True, local time otherwise. |
| 1006 | Raise a ValueError if unable to read the hardware clock. |
| 1007 | """ |
| 1008 | cmd = '/sbin/hwclock --debug' |
| 1009 | if utc: |
| 1010 | cmd += ' --utc' |
| 1011 | hwclock_output = utils.system_output(cmd, ignore_status=True) |
| 1012 | match = re.search(r'= ([0-9]+) seconds since .+ (-?[0-9.]+) seconds$', |
| 1013 | hwclock_output, re.DOTALL) |
| 1014 | if match: |
| 1015 | seconds = int(match.group(1)) + float(match.group(2)) |
Daniel Kurtz | f278e85 | 2014-03-04 21:57:30 -0800 | [diff] [blame] | 1016 | logging.debug('hwclock seconds = %f', seconds) |
Eric Li | a82dc35 | 2011-02-23 13:15:52 -0800 | [diff] [blame] | 1017 | return seconds |
| 1018 | |
| 1019 | raise ValueError('Unable to read the hardware clock -- ' + |
| 1020 | hwclock_output) |
| 1021 | |
| 1022 | |
| 1023 | def set_wake_alarm(alarm_time): |
| 1024 | """ |
| 1025 | Set the hardware RTC-based wake alarm to 'alarm_time'. |
| 1026 | """ |
| 1027 | utils.write_one_line('/sys/class/rtc/rtc0/wakealarm', str(alarm_time)) |
| 1028 | |
| 1029 | |
| 1030 | def set_power_state(state): |
| 1031 | """ |
| 1032 | Set the system power state to 'state'. |
| 1033 | """ |
| 1034 | utils.write_one_line('/sys/power/state', state) |
| 1035 | |
| 1036 | |
| 1037 | def standby(): |
| 1038 | """ |
| 1039 | Power-on suspend (S1) |
| 1040 | """ |
| 1041 | set_power_state('standby') |
| 1042 | |
| 1043 | |
| 1044 | def suspend_to_ram(): |
| 1045 | """ |
| 1046 | Suspend the system to RAM (S3) |
| 1047 | """ |
| 1048 | set_power_state('mem') |
| 1049 | |
| 1050 | |
| 1051 | def suspend_to_disk(): |
| 1052 | """ |
| 1053 | Suspend the system to disk (S4) |
| 1054 | """ |
| 1055 | set_power_state('disk') |