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