base_utils.py revision a1bef1f2774b539df11c134d9a9a177304c34f3c
1c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh"""Convenience functions for use by tests or whomever.
2c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh"""
3c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh
48eca3a98728afabc7fc761c08dbb8e91260c7de4mblighimport os,os.path,shutil,urllib,sys,signal,commands,pickle,glob
5bc2867dae46688cf0f6481a2190da7f32e08a3c7apwfrom error import *
64e75b0d3b020f901456217fb8ff0d7d4391fa869mblighimport re,string
7f4c35322b200d65f41a8332b4f3503beb497840dmbligh
8f4c35322b200d65f41a8332b4f3503beb497840dmblighdef grep(pattern, file):
97bdbfbdf088f9c2a72c199d5a530194bb2ac257fmbligh	"""
107bdbfbdf088f9c2a72c199d5a530194bb2ac257fmbligh	This is mainly to fix the return code inversion from grep
117bdbfbdf088f9c2a72c199d5a530194bb2ac257fmbligh	Also handles compressed files.
127bdbfbdf088f9c2a72c199d5a530194bb2ac257fmbligh
137bdbfbdf088f9c2a72c199d5a530194bb2ac257fmbligh	returns 1 if the pattern is present in the file, 0 if not.
147bdbfbdf088f9c2a72c199d5a530194bb2ac257fmbligh	"""
157bdbfbdf088f9c2a72c199d5a530194bb2ac257fmbligh	command = 'grep "%s" > /dev/null' % pattern
167bdbfbdf088f9c2a72c199d5a530194bb2ac257fmbligh	ret = cat_file_to_cmd(file, command, ignorestatus = 1)
177bdbfbdf088f9c2a72c199d5a530194bb2ac257fmbligh	return not ret
18f4c35322b200d65f41a8332b4f3503beb497840dmbligh
19f4c35322b200d65f41a8332b4f3503beb497840dmbligh
20c86b0b45cd0198d99d271a79f8b6de29feb98cd5mblighdef difflist(list1, list2):
21c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""returns items in list2 that are not in list1"""
22f4c35322b200d65f41a8332b4f3503beb497840dmbligh	diff = [];
23f4c35322b200d65f41a8332b4f3503beb497840dmbligh	for x in list2:
24f4c35322b200d65f41a8332b4f3503beb497840dmbligh		if x not in list1:
25f4c35322b200d65f41a8332b4f3503beb497840dmbligh			diff.append(x)
26f4c35322b200d65f41a8332b4f3503beb497840dmbligh	return diff
27f4c35322b200d65f41a8332b4f3503beb497840dmbligh
28c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh
297bdbfbdf088f9c2a72c199d5a530194bb2ac257fmblighdef cat_file_to_cmd(file, command, ignorestatus = 0):
307bdbfbdf088f9c2a72c199d5a530194bb2ac257fmbligh	"""
317bdbfbdf088f9c2a72c199d5a530194bb2ac257fmbligh	equivalent to 'cat file | command' but knows to use
327bdbfbdf088f9c2a72c199d5a530194bb2ac257fmbligh	zcat or bzcat if appropriate
337bdbfbdf088f9c2a72c199d5a530194bb2ac257fmbligh	"""
34712cd145672c0033a55173717787c54cd68e6b83mbligh	if not os.path.isfile(file):
35712cd145672c0033a55173717787c54cd68e6b83mbligh		raise NameError, 'invalid file %s to cat to command %s' % file, command
36f4c35322b200d65f41a8332b4f3503beb497840dmbligh	if file.endswith('.bz2'):
377bdbfbdf088f9c2a72c199d5a530194bb2ac257fmbligh		return system('bzcat ' + file + ' | ' + command, ignorestatus)
383d914919f7c22adae7c54e4a6d2378b1fc6efaf3mbligh	elif (file.endswith('.gz') or file.endswith('.tgz')):
397bdbfbdf088f9c2a72c199d5a530194bb2ac257fmbligh		return system('zcat ' + file + ' | ' + command, ignorestatus)
40f4c35322b200d65f41a8332b4f3503beb497840dmbligh	else:
417bdbfbdf088f9c2a72c199d5a530194bb2ac257fmbligh		return system('cat ' + file + ' | ' + command, ignorestatus)
42712cd145672c0033a55173717787c54cd68e6b83mbligh
43c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh
44712cd145672c0033a55173717787c54cd68e6b83mblighdef extract_tarball_to_dir(tarball, dir):
45c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""
46c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	Extract a tarball to a specified directory name instead of whatever
47c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	the top level of a tarball is - useful for versioned directory names, etc
48c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""
49712cd145672c0033a55173717787c54cd68e6b83mbligh	if os.path.exists(dir):
50712cd145672c0033a55173717787c54cd68e6b83mbligh		raise NameError, 'target %s already exists' % dir
51712cd145672c0033a55173717787c54cd68e6b83mbligh	pwd = os.getcwd()
52712cd145672c0033a55173717787c54cd68e6b83mbligh	os.chdir(os.path.dirname(os.path.abspath(dir)))
53712cd145672c0033a55173717787c54cd68e6b83mbligh	newdir = extract_tarball(tarball)
54712cd145672c0033a55173717787c54cd68e6b83mbligh	os.rename(newdir, dir)
55712cd145672c0033a55173717787c54cd68e6b83mbligh	os.chdir(pwd)
56712cd145672c0033a55173717787c54cd68e6b83mbligh
57f4c35322b200d65f41a8332b4f3503beb497840dmbligh
58712cd145672c0033a55173717787c54cd68e6b83mblighdef extract_tarball(tarball):
59c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""Returns the first found newly created directory by the tarball extraction"""
60712cd145672c0033a55173717787c54cd68e6b83mbligh	oldlist = os.listdir('.')
61712cd145672c0033a55173717787c54cd68e6b83mbligh	cat_file_to_cmd(tarball, 'tar xf -')
62712cd145672c0033a55173717787c54cd68e6b83mbligh	newlist = os.listdir('.')
63712cd145672c0033a55173717787c54cd68e6b83mbligh	newfiles = difflist(oldlist, newlist)   # what is new dir ?
64712cd145672c0033a55173717787c54cd68e6b83mbligh	new_dir = None
65712cd145672c0033a55173717787c54cd68e6b83mbligh	for newfile in newfiles:
66712cd145672c0033a55173717787c54cd68e6b83mbligh		if (os.path.isdir(newfile)):
67712cd145672c0033a55173717787c54cd68e6b83mbligh			return newfile
68712cd145672c0033a55173717787c54cd68e6b83mbligh	raise NameError, "extracting tarball produced no dir"
69712cd145672c0033a55173717787c54cd68e6b83mbligh
70cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh
71c69530b170d60b913131a2a65cf0e3c8b81bc700mblighdef update_version(srcdir, preserve_srcdir, new_version, install, *args, **dargs):
72c69530b170d60b913131a2a65cf0e3c8b81bc700mbligh	"""
73c69530b170d60b913131a2a65cf0e3c8b81bc700mbligh	Make sure srcdir is version new_version
74c69530b170d60b913131a2a65cf0e3c8b81bc700mbligh
75c69530b170d60b913131a2a65cf0e3c8b81bc700mbligh	If not, delete it and install() the new version.
76c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh
77c69530b170d60b913131a2a65cf0e3c8b81bc700mbligh	In the preserve_srcdir case, we just check it's up to date,
78c69530b170d60b913131a2a65cf0e3c8b81bc700mbligh	and if not, we rerun install, without removing srcdir
79c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""
807290556f1f826a79acf6f76ca3f5a04264fc521dmbligh	versionfile = srcdir + '/.version'
81c69530b170d60b913131a2a65cf0e3c8b81bc700mbligh	install_needed = True
82c69530b170d60b913131a2a65cf0e3c8b81bc700mbligh
83ff88e4eac1757a065f2c69f48ac3c63831fe4f04mbligh	if os.path.exists(srcdir):
84ff88e4eac1757a065f2c69f48ac3c63831fe4f04mbligh		if os.path.exists(versionfile):
85ff88e4eac1757a065f2c69f48ac3c63831fe4f04mbligh			old_version = pickle.load(open(versionfile, 'r'))
86c69530b170d60b913131a2a65cf0e3c8b81bc700mbligh			if (old_version == new_version):
87c69530b170d60b913131a2a65cf0e3c8b81bc700mbligh				install_needed = False
88c69530b170d60b913131a2a65cf0e3c8b81bc700mbligh
89c69530b170d60b913131a2a65cf0e3c8b81bc700mbligh	if install_needed:
90c69530b170d60b913131a2a65cf0e3c8b81bc700mbligh		if not preserve_srcdir:
917290556f1f826a79acf6f76ca3f5a04264fc521dmbligh			system('rm -rf ' + srcdir)
9278e17027dd041ed8ff7fb2736201a6146a3b93a9mbligh		install(*args, **dargs)
937290556f1f826a79acf6f76ca3f5a04264fc521dmbligh		if os.path.exists(srcdir):
947290556f1f826a79acf6f76ca3f5a04264fc521dmbligh			pickle.dump(new_version, open(versionfile, 'w'))
957290556f1f826a79acf6f76ca3f5a04264fc521dmbligh
967290556f1f826a79acf6f76ca3f5a04264fc521dmbligh
97ea30c8a19ee292ee57b5223ca079f7a311195b41mblighdef is_url(path):
98c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""true if path is a url
99c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""
100c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	# should cope with other url types here, but we only handle http and ftp
101ea30c8a19ee292ee57b5223ca079f7a311195b41mbligh	if (path.startswith('http://')) or (path.startswith('ftp://')):
102ea30c8a19ee292ee57b5223ca079f7a311195b41mbligh		return 1
103ea30c8a19ee292ee57b5223ca079f7a311195b41mbligh	return 0
104ea30c8a19ee292ee57b5223ca079f7a311195b41mbligh
105cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh
1068eca3a98728afabc7fc761c08dbb8e91260c7de4mblighdef get_file(src, dest, permissions = None):
107c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""get a file, either from url or local"""
1083118661bc4d4d57438013bb47ac63e78c7bca03dmbligh	if (src == dest):      # no-op here allows clean overrides in tests
1093118661bc4d4d57438013bb47ac63e78c7bca03dmbligh		return
110ea30c8a19ee292ee57b5223ca079f7a311195b41mbligh	if (is_url(src)):
111f4c35322b200d65f41a8332b4f3503beb497840dmbligh		print 'PWD: ' + os.getcwd()
112f4c35322b200d65f41a8332b4f3503beb497840dmbligh		print 'Fetching \n\t', src, '\n\t->', dest
113f4c35322b200d65f41a8332b4f3503beb497840dmbligh		try:
114f4c35322b200d65f41a8332b4f3503beb497840dmbligh			urllib.urlretrieve(src, dest)
115f4c35322b200d65f41a8332b4f3503beb497840dmbligh		except IOError:
116f4c35322b200d65f41a8332b4f3503beb497840dmbligh			sys.stderr.write("Unable to retrieve %s (to %s)\n" % (src, dest))
117f4c35322b200d65f41a8332b4f3503beb497840dmbligh			sys.exit(1)
1188eca3a98728afabc7fc761c08dbb8e91260c7de4mbligh	else:
1198eca3a98728afabc7fc761c08dbb8e91260c7de4mbligh		shutil.copyfile(src, dest)
1208eca3a98728afabc7fc761c08dbb8e91260c7de4mbligh	if permissions:
1218eca3a98728afabc7fc761c08dbb8e91260c7de4mbligh		os.chmod(permissions)
122f4c35322b200d65f41a8332b4f3503beb497840dmbligh	return dest
123f4c35322b200d65f41a8332b4f3503beb497840dmbligh
124ea30c8a19ee292ee57b5223ca079f7a311195b41mbligh
1258264186be2d5531ca903fe34a87bd5c79cce5f80mblighdef unmap_url(srcdir, src, destdir = '.'):
12652508630c5a7511c452bfd94c7ab1c0e1d588d00mbligh	"""
12752508630c5a7511c452bfd94c7ab1c0e1d588d00mbligh	Receives either a path to a local file or a URL.
12852508630c5a7511c452bfd94c7ab1c0e1d588d00mbligh	returns either the path to the local file, or the fetched URL
12952508630c5a7511c452bfd94c7ab1c0e1d588d00mbligh
13052508630c5a7511c452bfd94c7ab1c0e1d588d00mbligh	unmap_url('/usr/src', 'foo.tar', '/tmp')
13152508630c5a7511c452bfd94c7ab1c0e1d588d00mbligh				= '/usr/src/foo.tar'
13252508630c5a7511c452bfd94c7ab1c0e1d588d00mbligh	unmap_url('/usr/src', 'http://site/file', '/tmp')
13352508630c5a7511c452bfd94c7ab1c0e1d588d00mbligh				= '/tmp/file'
13452508630c5a7511c452bfd94c7ab1c0e1d588d00mbligh				(after retrieving it)
13552508630c5a7511c452bfd94c7ab1c0e1d588d00mbligh	"""
136ea30c8a19ee292ee57b5223ca079f7a311195b41mbligh	if is_url(src):
137ea30c8a19ee292ee57b5223ca079f7a311195b41mbligh		dest = destdir + '/' + os.path.basename(src)
138ea30c8a19ee292ee57b5223ca079f7a311195b41mbligh		get_file(src, dest)
139ea30c8a19ee292ee57b5223ca079f7a311195b41mbligh		return dest
1408264186be2d5531ca903fe34a87bd5c79cce5f80mbligh	else:
1418264186be2d5531ca903fe34a87bd5c79cce5f80mbligh		return srcdir + '/' + src
142ea30c8a19ee292ee57b5223ca079f7a311195b41mbligh
143ea30c8a19ee292ee57b5223ca079f7a311195b41mbligh
144f4c35322b200d65f41a8332b4f3503beb497840dmblighdef basename(path):
145f4c35322b200d65f41a8332b4f3503beb497840dmbligh	i = path.rfind('/');
146f4c35322b200d65f41a8332b4f3503beb497840dmbligh	return path[i+1:]
147f4c35322b200d65f41a8332b4f3503beb497840dmbligh
148f4c35322b200d65f41a8332b4f3503beb497840dmbligh
149f4c35322b200d65f41a8332b4f3503beb497840dmblighdef force_copy(src, dest):
150c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""Replace dest with a new copy of src, even if it exists"""
151f4c35322b200d65f41a8332b4f3503beb497840dmbligh	if os.path.isfile(dest):
152f4c35322b200d65f41a8332b4f3503beb497840dmbligh		os.remove(dest)
1531e8858e6f825fb9eba4a87b921911c6f398ca727mbligh	if os.path.isdir(dest):
1541e8858e6f825fb9eba4a87b921911c6f398ca727mbligh		dest = os.path.join(dest, os.path.basename(src))
155f4c35322b200d65f41a8332b4f3503beb497840dmbligh	return shutil.copyfile(src, dest)
156f4c35322b200d65f41a8332b4f3503beb497840dmbligh
157f4c35322b200d65f41a8332b4f3503beb497840dmbligh
158fdbcaec15092d8b4af80970c495038bdf9b0e63fmblighdef force_link(src, dest):
159fdbcaec15092d8b4af80970c495038bdf9b0e63fmbligh	"""Link src to dest, overwriting it if it exists"""
160fdbcaec15092d8b4af80970c495038bdf9b0e63fmbligh	return system("ln -sf %s %s" % (src, dest))
161fdbcaec15092d8b4af80970c495038bdf9b0e63fmbligh
162fdbcaec15092d8b4af80970c495038bdf9b0e63fmbligh
163cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmblighdef file_contains_pattern(file, pattern):
164c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""Return true if file contains the specified egrep pattern"""
165cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh	if not os.path.isfile(file):
166cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh		raise NameError, 'file %s does not exist' % file
1675c1e26aa615e5a2587fce3a7d093bc05f2d1dc94mbligh	return not system('egrep -q "' + pattern + '" ' + file, ignorestatus = 1)
168cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh
169cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh
170cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmblighdef list_grep(list, pattern):
171c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""True if any item in list matches the specified pattern."""
172cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh	compiled = re.compile(pattern)
173cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh	for line in list:
174cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh		match = compiled.search(line)
175cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh		if (match):
176cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh			return 1
177cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh	return 0
178cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh
17942b81ca63a0ab336b844e9c5cce6fe30dae85357mblighdef get_os_vendor():
18042b81ca63a0ab336b844e9c5cce6fe30dae85357mbligh	"""Try to guess what's the os vendor
18142b81ca63a0ab336b844e9c5cce6fe30dae85357mbligh	"""
18242b81ca63a0ab336b844e9c5cce6fe30dae85357mbligh	issue = '/etc/issue'
18342b81ca63a0ab336b844e9c5cce6fe30dae85357mbligh
18442b81ca63a0ab336b844e9c5cce6fe30dae85357mbligh	if not os.path.isfile(issue):
18542b81ca63a0ab336b844e9c5cce6fe30dae85357mbligh		return 'Unknown'
18642b81ca63a0ab336b844e9c5cce6fe30dae85357mbligh
18742b81ca63a0ab336b844e9c5cce6fe30dae85357mbligh	if file_contains_pattern(issue, 'Red Hat'):
18842b81ca63a0ab336b844e9c5cce6fe30dae85357mbligh		return 'Red Hat'
18942b81ca63a0ab336b844e9c5cce6fe30dae85357mbligh	elif file_contains_pattern(issue, 'Fedora Core'):
19042b81ca63a0ab336b844e9c5cce6fe30dae85357mbligh		return 'Fedora Core'
19142b81ca63a0ab336b844e9c5cce6fe30dae85357mbligh	elif file_contains_pattern(issue, 'SUSE'):
19242b81ca63a0ab336b844e9c5cce6fe30dae85357mbligh		return 'SUSE'
19342b81ca63a0ab336b844e9c5cce6fe30dae85357mbligh	elif file_contains_pattern(issue, 'Ubuntu'):
19442b81ca63a0ab336b844e9c5cce6fe30dae85357mbligh		return 'Ubuntu'
19539f9cac86babcf828c81c17650bda85e2ef4c1c3apw	elif file_contains_pattern(issue, 'Debian'):
19639f9cac86babcf828c81c17650bda85e2ef4c1c3apw		return 'Debian'
19742b81ca63a0ab336b844e9c5cce6fe30dae85357mbligh	else:
19842b81ca63a0ab336b844e9c5cce6fe30dae85357mbligh		return 'Unknown'
19942b81ca63a0ab336b844e9c5cce6fe30dae85357mbligh
200cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh
201f49d5cfa9fc49a34b3b5e5e1cb97ce2c0a77dd0cmblighdef get_vmlinux():
202c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""Return the full path to vmlinux
203c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh
204c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	Ahem. This is crap. Pray harder. Bad Martin.
205c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""
206ad849eea0958e6fae31dbc6ca46c0fd10ef72fcambligh	vmlinux = '/boot/vmlinux-%s' % system_output('uname -r')
207662a2a2695f7f1b492e8dbd7f60db242f81e7cb2mbligh	if os.path.isfile(vmlinux):
208662a2a2695f7f1b492e8dbd7f60db242f81e7cb2mbligh		return vmlinux
20917dbf0564f5aaf66820a000f14e3006125b303f9mbligh	vmlinux = '/lib/modules/%s/build/vmlinux' % system_output('uname -r')
21017dbf0564f5aaf66820a000f14e3006125b303f9mbligh	if os.path.isfile(vmlinux):
21117dbf0564f5aaf66820a000f14e3006125b303f9mbligh		return vmlinux
212662a2a2695f7f1b492e8dbd7f60db242f81e7cb2mbligh	return None
213f49d5cfa9fc49a34b3b5e5e1cb97ce2c0a77dd0cmbligh
214f49d5cfa9fc49a34b3b5e5e1cb97ce2c0a77dd0cmbligh
215f49d5cfa9fc49a34b3b5e5e1cb97ce2c0a77dd0cmblighdef get_systemmap():
216c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""Return the full path to System.map
217c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh
218c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	Ahem. This is crap. Pray harder. Bad Martin.
219c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""
220ad849eea0958e6fae31dbc6ca46c0fd10ef72fcambligh	map = '/boot/System.map-%s' % system_output('uname -r')
221662a2a2695f7f1b492e8dbd7f60db242f81e7cb2mbligh	if os.path.isfile(map):
222662a2a2695f7f1b492e8dbd7f60db242f81e7cb2mbligh		return map
22317dbf0564f5aaf66820a000f14e3006125b303f9mbligh	map = '/lib/modules/%s/build/System.map' % system_output('uname -r')
22417dbf0564f5aaf66820a000f14e3006125b303f9mbligh	if os.path.isfile(map):
22517dbf0564f5aaf66820a000f14e3006125b303f9mbligh		return map
226662a2a2695f7f1b492e8dbd7f60db242f81e7cb2mbligh	return None
22767b5ece7667fc71429ee05b07ac7654ed5a05df7mbligh
22867b5ece7667fc71429ee05b07ac7654ed5a05df7mbligh
22967b5ece7667fc71429ee05b07ac7654ed5a05df7mblighdef get_modules_dir():
230c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""Return the modules dir for the running kernel version"""
23167b5ece7667fc71429ee05b07ac7654ed5a05df7mbligh	kernel_version = system_output('uname -r')
23267b5ece7667fc71429ee05b07ac7654ed5a05df7mbligh	return '/lib/modules/%s/kernel' % kernel_version
233f49d5cfa9fc49a34b3b5e5e1cb97ce2c0a77dd0cmbligh
234f49d5cfa9fc49a34b3b5e5e1cb97ce2c0a77dd0cmbligh
2355970cf057674accdb00a7742eae50e40c57e52d0mblighdef get_cpu_arch():
236c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""Work out which CPU architecture we're running on"""
237cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh	f = open('/proc/cpuinfo', 'r')
238cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh	cpuinfo = f.readlines()
239cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh	f.close()
240cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh	if list_grep(cpuinfo, '^cpu.*(RS64|POWER3|Broadband Engine)'):
241cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh		return 'power'
242cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh	elif list_grep(cpuinfo, '^cpu.*POWER4'):
243cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh		return 'power4'
244cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh	elif list_grep(cpuinfo, '^cpu.*POWER5'):
245cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh		return 'power5'
246cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh	elif list_grep(cpuinfo, '^cpu.*POWER6'):
247cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh		return 'power6'
248cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh	elif list_grep(cpuinfo, '^cpu.*PPC970'):
249cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh		return 'power970'
250cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh	elif list_grep(cpuinfo, 'Opteron'):
251cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh		return 'x86_64'
252cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh	elif list_grep(cpuinfo, 'GenuineIntel') and list_grep(cpuinfo, '48 bits virtual'):
253f4c35322b200d65f41a8332b4f3503beb497840dmbligh		return 'x86_64'
254f4c35322b200d65f41a8332b4f3503beb497840dmbligh	else:
255f4c35322b200d65f41a8332b4f3503beb497840dmbligh		return 'i386'
256f4c35322b200d65f41a8332b4f3503beb497840dmbligh
257f4c35322b200d65f41a8332b4f3503beb497840dmbligh
258548f29af9e38f87c3609838f5aabeac94bb69f13mblighdef get_current_kernel_arch():
259548f29af9e38f87c3609838f5aabeac94bb69f13mbligh	"""Get the machine architecture, now just a wrap of 'uname -m'."""
260548f29af9e38f87c3609838f5aabeac94bb69f13mbligh	return os.popen('uname -m').read().rstrip()
261cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh
262cdf02a40b97d0570b0e8f8a74a2ede7a868bb1edmbligh
263fdbcaec15092d8b4af80970c495038bdf9b0e63fmblighdef get_file_arch(filename):
264fdbcaec15092d8b4af80970c495038bdf9b0e63fmbligh	# -L means follow symlinks
265fdbcaec15092d8b4af80970c495038bdf9b0e63fmbligh	file_data = system_output('file -L ' + filename)
266fdbcaec15092d8b4af80970c495038bdf9b0e63fmbligh	if file_data.count('80386'):
267fdbcaec15092d8b4af80970c495038bdf9b0e63fmbligh		return 'i386'
268fdbcaec15092d8b4af80970c495038bdf9b0e63fmbligh	return None
269fdbcaec15092d8b4af80970c495038bdf9b0e63fmbligh
270fdbcaec15092d8b4af80970c495038bdf9b0e63fmbligh
271548f29af9e38f87c3609838f5aabeac94bb69f13mblighdef kernelexpand(kernel, args=None):
272f4c35322b200d65f41a8332b4f3503beb497840dmbligh	# if not (kernel.startswith('http://') or kernel.startswith('ftp://') or os.path.isfile(kernel)):
2735629af0f98d4f1f90c58e7ed81b130702271915ambligh	if kernel.find('/') < 0:     # contains no path.
274534015f5590bce2348413c02ec119936ee9e1a80mbligh		autodir = os.environ['AUTODIR']
275534015f5590bce2348413c02ec119936ee9e1a80mbligh		kernelexpand = os.path.join(autodir, 'tools/kernelexpand')
276548f29af9e38f87c3609838f5aabeac94bb69f13mbligh		if args:
277548f29af9e38f87c3609838f5aabeac94bb69f13mbligh			kernelexpand += ' ' + args
2785629af0f98d4f1f90c58e7ed81b130702271915ambligh		w, r = os.popen2(kernelexpand + ' ' + kernel)
279f4c35322b200d65f41a8332b4f3503beb497840dmbligh
280f4c35322b200d65f41a8332b4f3503beb497840dmbligh		kernel = r.readline().strip()
281f4c35322b200d65f41a8332b4f3503beb497840dmbligh		r.close()
282f4c35322b200d65f41a8332b4f3503beb497840dmbligh		w.close()
283534015f5590bce2348413c02ec119936ee9e1a80mbligh	return kernel.split()
284f4c35322b200d65f41a8332b4f3503beb497840dmbligh
285f4c35322b200d65f41a8332b4f3503beb497840dmbligh
286f4c35322b200d65f41a8332b4f3503beb497840dmblighdef count_cpus():
287c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""number of CPUs in the local machine according to /proc/cpuinfo"""
288f4c35322b200d65f41a8332b4f3503beb497840dmbligh	f = file('/proc/cpuinfo', 'r')
289f4c35322b200d65f41a8332b4f3503beb497840dmbligh	cpus = 0
290f4c35322b200d65f41a8332b4f3503beb497840dmbligh	for line in f.readlines():
291f4c35322b200d65f41a8332b4f3503beb497840dmbligh		if line.startswith('processor'):
292f4c35322b200d65f41a8332b4f3503beb497840dmbligh			cpus += 1
293f4c35322b200d65f41a8332b4f3503beb497840dmbligh	return cpus
294f4c35322b200d65f41a8332b4f3503beb497840dmbligh
295e7a170fb097da48af81ca598e29643f3e7cca584mbligh
296e7a170fb097da48af81ca598e29643f3e7cca584mbligh# Returns total memory in kb
297e7a170fb097da48af81ca598e29643f3e7cca584mblighdef memtotal():
298e7a170fb097da48af81ca598e29643f3e7cca584mbligh	memtotal = system_output('grep MemTotal /proc/meminfo')
299e7a170fb097da48af81ca598e29643f3e7cca584mbligh	return int(re.search(r'\d+', memtotal).group(0))
300e7a170fb097da48af81ca598e29643f3e7cca584mbligh
301e7a170fb097da48af81ca598e29643f3e7cca584mbligh
302a975fb6b4cb50f5d48b06d84aba97ca67c0adea4mblighdef system(cmd, ignorestatus = 0):
303c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""os.system replacement
304c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh
305c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	We have our own definition of system here, as the stock os.system doesn't
306c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	correctly handle sigpipe
307c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	(ie things like "yes | head" will hang because yes doesn't get the SIGPIPE).
308c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh
309c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	Also the stock os.system didn't raise errors based on exit status, this
310c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	version does unless you explicitly specify ignorestatus=1
311c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""
312f4c35322b200d65f41a8332b4f3503beb497840dmbligh	signal.signal(signal.SIGPIPE, signal.SIG_DFL)
313f4c35322b200d65f41a8332b4f3503beb497840dmbligh	try:
314bc2867dae46688cf0f6481a2190da7f32e08a3c7apw		status = os.system(cmd)
315f4c35322b200d65f41a8332b4f3503beb497840dmbligh	finally:
316f4c35322b200d65f41a8332b4f3503beb497840dmbligh		signal.signal(signal.SIGPIPE, signal.SIG_IGN)
317f4c35322b200d65f41a8332b4f3503beb497840dmbligh
31867b5ece7667fc71429ee05b07ac7654ed5a05df7mbligh	if ((status != 0) and not ignorestatus):
319a975fb6b4cb50f5d48b06d84aba97ca67c0adea4mbligh		raise CmdError(cmd, status)
320a975fb6b4cb50f5d48b06d84aba97ca67c0adea4mbligh	return status
3213d914919f7c22adae7c54e4a6d2378b1fc6efaf3mbligh
3223d914919f7c22adae7c54e4a6d2378b1fc6efaf3mbligh
32367b5ece7667fc71429ee05b07ac7654ed5a05df7mblighdef system_output(command, ignorestatus = 0):
324c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""Run command and return its output
325c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh
326c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	ignorestatus
327c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh		whether to raise a CmdError if command has a nonzero exit status
328c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""
32967b5ece7667fc71429ee05b07ac7654ed5a05df7mbligh	(result, data) = commands.getstatusoutput(command)
33067b5ece7667fc71429ee05b07ac7654ed5a05df7mbligh	if ((result != 0) and not ignorestatus):
33167b5ece7667fc71429ee05b07ac7654ed5a05df7mbligh		raise CmdError, 'command failed: ' + command
33267b5ece7667fc71429ee05b07ac7654ed5a05df7mbligh	return data
33367b5ece7667fc71429ee05b07ac7654ed5a05df7mbligh
33467b5ece7667fc71429ee05b07ac7654ed5a05df7mbligh
335f4c35322b200d65f41a8332b4f3503beb497840dmblighdef where_art_thy_filehandles():
336c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""Dump the current list of filehandles"""
337f4c35322b200d65f41a8332b4f3503beb497840dmbligh	os.system("ls -l /proc/%d/fd >> /dev/tty" % os.getpid())
338f4c35322b200d65f41a8332b4f3503beb497840dmbligh
339f4c35322b200d65f41a8332b4f3503beb497840dmbligh
340f4c35322b200d65f41a8332b4f3503beb497840dmblighdef print_to_tty(string):
341c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""Output string straight to the tty"""
342e80ff5a7ae2600b9ddffc2724764854c6a721101mbligh	open('/dev/tty', 'w').write(string + '\n')
343f4c35322b200d65f41a8332b4f3503beb497840dmbligh
344f4c35322b200d65f41a8332b4f3503beb497840dmbligh
345b8a14e358b611f2d97c06e863be9b53ab2bedeefmblighdef dump_object(object):
346c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""Dump an object's attributes and methods
347c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh
348c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	kind of like dir()
349c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""
350b8a14e358b611f2d97c06e863be9b53ab2bedeefmbligh	for item in object.__dict__.iteritems():
351b8a14e358b611f2d97c06e863be9b53ab2bedeefmbligh		print item
352b8a14e358b611f2d97c06e863be9b53ab2bedeefmbligh		try:
353b8a14e358b611f2d97c06e863be9b53ab2bedeefmbligh			(key,value) = item
354b8a14e358b611f2d97c06e863be9b53ab2bedeefmbligh			dump_object(value)
355b8a14e358b611f2d97c06e863be9b53ab2bedeefmbligh		except:
356b8a14e358b611f2d97c06e863be9b53ab2bedeefmbligh			continue
357b8a14e358b611f2d97c06e863be9b53ab2bedeefmbligh
358b8a14e358b611f2d97c06e863be9b53ab2bedeefmbligh
3594b089663460063b638124ff665f38d2fe7427648mblighdef environ(env_key):
360c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""return the requested environment variable, or '' if unset"""
3614b089663460063b638124ff665f38d2fe7427648mbligh	if (os.environ.has_key(env_key)):
362d931a5894a9cd50909ec5aabf7133ea944992b5dmbligh		return os.environ[env_key]
3634b089663460063b638124ff665f38d2fe7427648mbligh	else:
3644b089663460063b638124ff665f38d2fe7427648mbligh		return ''
3654b089663460063b638124ff665f38d2fe7427648mbligh
3664b089663460063b638124ff665f38d2fe7427648mbligh
3674b089663460063b638124ff665f38d2fe7427648mblighdef prepend_path(newpath, oldpath):
368c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""prepend newpath to oldpath"""
3694b089663460063b638124ff665f38d2fe7427648mbligh	if (oldpath):
3704b089663460063b638124ff665f38d2fe7427648mbligh		return newpath + ':' + oldpath
3714b089663460063b638124ff665f38d2fe7427648mbligh	else:
3724b089663460063b638124ff665f38d2fe7427648mbligh		return newpath
3734b089663460063b638124ff665f38d2fe7427648mbligh
3744b089663460063b638124ff665f38d2fe7427648mbligh
3754b089663460063b638124ff665f38d2fe7427648mblighdef append_path(oldpath, newpath):
376c86b0b45cd0198d99d271a79f8b6de29feb98cd5mbligh	"""append newpath to oldpath"""
3774b089663460063b638124ff665f38d2fe7427648mbligh	if (oldpath):
3784b089663460063b638124ff665f38d2fe7427648mbligh		return oldpath + ':' + newpath
3794b089663460063b638124ff665f38d2fe7427648mbligh	else:
3804b089663460063b638124ff665f38d2fe7427648mbligh		return newpath
3814b089663460063b638124ff665f38d2fe7427648mbligh
3824b089663460063b638124ff665f38d2fe7427648mbligh
3834e75b0d3b020f901456217fb8ff0d7d4391fa869mblighdef avgtime_print(dir):
3844e75b0d3b020f901456217fb8ff0d7d4391fa869mbligh	""" Calculate some benchmarking statistics.
3854e75b0d3b020f901456217fb8ff0d7d4391fa869mbligh	    Input is a directory containing a file called 'time'.
3864e75b0d3b020f901456217fb8ff0d7d4391fa869mbligh	    File contains one-per-line results of /usr/bin/time.
3874e75b0d3b020f901456217fb8ff0d7d4391fa869mbligh	    Output is average Elapsed, User, and System time in seconds,
3884e75b0d3b020f901456217fb8ff0d7d4391fa869mbligh	      and average CPU percentage.
3894e75b0d3b020f901456217fb8ff0d7d4391fa869mbligh	"""
3904e75b0d3b020f901456217fb8ff0d7d4391fa869mbligh	f = open(dir + "/time")
3914e75b0d3b020f901456217fb8ff0d7d4391fa869mbligh	user = system = elapsed = cpu = count = 0
3924e75b0d3b020f901456217fb8ff0d7d4391fa869mbligh	r = re.compile('([\d\.]*)user ([\d\.]*)system (\d*):([\d\.]*)elapsed (\d*)%CPU')
3934e75b0d3b020f901456217fb8ff0d7d4391fa869mbligh	for line in f.readlines():
3944e75b0d3b020f901456217fb8ff0d7d4391fa869mbligh		try:
3954e75b0d3b020f901456217fb8ff0d7d4391fa869mbligh			s = r.match(line);
396e1ee267d3c02ceba3b6168ad34d4b27d0bbc626ambligh			user += float(s.group(1))
397e1ee267d3c02ceba3b6168ad34d4b27d0bbc626ambligh			system += float(s.group(2))
398e1ee267d3c02ceba3b6168ad34d4b27d0bbc626ambligh			elapsed += (float(s.group(3)) * 60) + float(s.group(4))
399e1ee267d3c02ceba3b6168ad34d4b27d0bbc626ambligh			cpu += float(s.group(5))
4004e75b0d3b020f901456217fb8ff0d7d4391fa869mbligh			count += 1
4014e75b0d3b020f901456217fb8ff0d7d4391fa869mbligh		except:
4024e75b0d3b020f901456217fb8ff0d7d4391fa869mbligh			raise ValueError("badly formatted times")
4034e75b0d3b020f901456217fb8ff0d7d4391fa869mbligh
4044e75b0d3b020f901456217fb8ff0d7d4391fa869mbligh	f.close()
4054e75b0d3b020f901456217fb8ff0d7d4391fa869mbligh	return "Elapsed: %0.2fs User: %0.2fs System: %0.2fs CPU: %0.0f%%" % \
4064e75b0d3b020f901456217fb8ff0d7d4391fa869mbligh	      (elapsed/count, user/count, system/count, cpu/count)
4074e75b0d3b020f901456217fb8ff0d7d4391fa869mbligh
4084e75b0d3b020f901456217fb8ff0d7d4391fa869mbligh
409f06db0f9b381737b9c85bef1c23ea1a1ca73c559mblighdef running_config():
410f06db0f9b381737b9c85bef1c23ea1a1ca73c559mbligh	"""
411f06db0f9b381737b9c85bef1c23ea1a1ca73c559mbligh	Return path of config file of the currently running kernel
412f06db0f9b381737b9c85bef1c23ea1a1ca73c559mbligh	"""
413a1bef1f2774b539df11c134d9a9a177304c34f3cmbligh	version = system_output('uname -r')
414f06db0f9b381737b9c85bef1c23ea1a1ca73c559mbligh	for config in ('/proc/config.gz', \
415a1bef1f2774b539df11c134d9a9a177304c34f3cmbligh		       '/boot/config-%s' % version,
416a1bef1f2774b539df11c134d9a9a177304c34f3cmbligh		       '/lib/modules/%s/build/.config' % version):
417f06db0f9b381737b9c85bef1c23ea1a1ca73c559mbligh		if os.path.isfile(config):
418f06db0f9b381737b9c85bef1c23ea1a1ca73c559mbligh			return config
419f06db0f9b381737b9c85bef1c23ea1a1ca73c559mbligh	return None
4209ec8acc50c0fe06a40353db0df8e135cebb2ec58mbligh
4219ec8acc50c0fe06a40353db0df8e135cebb2ec58mbligh
422a1bef1f2774b539df11c134d9a9a177304c34f3cmblighdef check_for_kernel_feature(feature):
423a1bef1f2774b539df11c134d9a9a177304c34f3cmbligh	config = running_config()
424a1bef1f2774b539df11c134d9a9a177304c34f3cmbligh
425a1bef1f2774b539df11c134d9a9a177304c34f3cmbligh	if not config:
426a1bef1f2774b539df11c134d9a9a177304c34f3cmbligh		raise "Can't find kernel config file"
427a1bef1f2774b539df11c134d9a9a177304c34f3cmbligh
428a1bef1f2774b539df11c134d9a9a177304c34f3cmbligh	if config.endswith('.gz'):
429a1bef1f2774b539df11c134d9a9a177304c34f3cmbligh		grep = 'zgrep'
430a1bef1f2774b539df11c134d9a9a177304c34f3cmbligh	else:
431a1bef1f2774b539df11c134d9a9a177304c34f3cmbligh		grep = 'grep'
432a1bef1f2774b539df11c134d9a9a177304c34f3cmbligh	grep += ' ^CONFIG_%s= %s' % (feature, config)
433a1bef1f2774b539df11c134d9a9a177304c34f3cmbligh
434a1bef1f2774b539df11c134d9a9a177304c34f3cmbligh	if not system_output(grep, ignorestatus = 1):
435a1bef1f2774b539df11c134d9a9a177304c34f3cmbligh		raise "Kernel doesn't have a %s feature" % (feature)
436a1bef1f2774b539df11c134d9a9a177304c34f3cmbligh
437a1bef1f2774b539df11c134d9a9a177304c34f3cmbligh
4389ec8acc50c0fe06a40353db0df8e135cebb2ec58mblighdef cpu_online_map():
4399ec8acc50c0fe06a40353db0df8e135cebb2ec58mbligh	"""
4409ec8acc50c0fe06a40353db0df8e135cebb2ec58mbligh	Check out the available cpu online map
4419ec8acc50c0fe06a40353db0df8e135cebb2ec58mbligh	"""
4429ec8acc50c0fe06a40353db0df8e135cebb2ec58mbligh	cpus = []
4439ec8acc50c0fe06a40353db0df8e135cebb2ec58mbligh	for line in open('/proc/cpuinfo', 'r').readlines():
4449ec8acc50c0fe06a40353db0df8e135cebb2ec58mbligh		if line.startswith('processor'):
4459ec8acc50c0fe06a40353db0df8e135cebb2ec58mbligh			cpus.append(line.split()[2]) # grab cpu number
4469ec8acc50c0fe06a40353db0df8e135cebb2ec58mbligh	return cpus
447663e4f664465dbaa9e86c5c20d035ad9bd1e65edmbligh
448663e4f664465dbaa9e86c5c20d035ad9bd1e65edmbligh
449663e4f664465dbaa9e86c5c20d035ad9bd1e65edmblighdef check_glibc_ver(ver):
450663e4f664465dbaa9e86c5c20d035ad9bd1e65edmbligh	glibc_ver = commands.getoutput('ldd --version').splitlines()[0]
451cabfdafe37abd042e3b347735d3535b282ee4a51mbligh	glibc_ver = re.search(r'(\d+\.\d+(\.\d+)?)', glibc_ver).group()
452ea97ab8d339c659a3269037f19788954a98e704cmbligh	if glibc_ver.split('.') < ver.split('.'):
453ea97ab8d339c659a3269037f19788954a98e704cmbligh		raise "Glibc is too old (%s). Glibc >= %s is needed." % \
454ea97ab8d339c659a3269037f19788954a98e704cmbligh							(glibc_ver, ver)
4559061a273dfd2e522c15f6dd77cfed1e2815e4e9embligh
4569061a273dfd2e522c15f6dd77cfed1e2815e4e9emblighdef read_one_line(filename):
4579061a273dfd2e522c15f6dd77cfed1e2815e4e9embligh	return open(filename, 'r').readline().strip()
4589061a273dfd2e522c15f6dd77cfed1e2815e4e9embligh
4599061a273dfd2e522c15f6dd77cfed1e2815e4e9embligh
4609061a273dfd2e522c15f6dd77cfed1e2815e4e9emblighdef write_one_line(filename, str):
4619061a273dfd2e522c15f6dd77cfed1e2815e4e9embligh	str.rstrip()
4629061a273dfd2e522c15f6dd77cfed1e2815e4e9embligh	open(filename, 'w').write(str.rstrip() + "\n")
463264cd8f4889cea73fa5fb7873e3243c1c770a1bcmbligh
464264cd8f4889cea73fa5fb7873e3243c1c770a1bcmbligh
465264cd8f4889cea73fa5fb7873e3243c1c770a1bcmblighdef human_format(number):
466264cd8f4889cea73fa5fb7873e3243c1c770a1bcmbligh	# Convert number to kilo / mega / giga format.
467264cd8f4889cea73fa5fb7873e3243c1c770a1bcmbligh	if number < 1024:
468264cd8f4889cea73fa5fb7873e3243c1c770a1bcmbligh		return "%d" % number
469264cd8f4889cea73fa5fb7873e3243c1c770a1bcmbligh	kilo = float(number) / 1024.0
470264cd8f4889cea73fa5fb7873e3243c1c770a1bcmbligh	if kilo < 1024:
471264cd8f4889cea73fa5fb7873e3243c1c770a1bcmbligh		return "%.2fk" % kilo
472264cd8f4889cea73fa5fb7873e3243c1c770a1bcmbligh	meg = kilo / 1024.0
473264cd8f4889cea73fa5fb7873e3243c1c770a1bcmbligh	if meg < 1024:
474264cd8f4889cea73fa5fb7873e3243c1c770a1bcmbligh		return "%.2fM" % meg
475264cd8f4889cea73fa5fb7873e3243c1c770a1bcmbligh	gig = meg / 1024.0
476264cd8f4889cea73fa5fb7873e3243c1c770a1bcmbligh	return "%.2fG" % gig
477264cd8f4889cea73fa5fb7873e3243c1c770a1bcmbligh
4788eca3a98728afabc7fc761c08dbb8e91260c7de4mbligh
4798eca3a98728afabc7fc761c08dbb8e91260c7de4mblighdef numa_nodes():
4808eca3a98728afabc7fc761c08dbb8e91260c7de4mbligh	node_paths = glob.glob('/sys/devices/system/node/node*')
4818eca3a98728afabc7fc761c08dbb8e91260c7de4mbligh	nodes = [int(re.sub(r'.*node(\d+)', r'\1', x)) for x in node_paths]
4828eca3a98728afabc7fc761c08dbb8e91260c7de4mbligh	return (sorted(nodes))
4838eca3a98728afabc7fc761c08dbb8e91260c7de4mbligh
4848eca3a98728afabc7fc761c08dbb8e91260c7de4mbligh
4858eca3a98728afabc7fc761c08dbb8e91260c7de4mblighdef node_size():
4868eca3a98728afabc7fc761c08dbb8e91260c7de4mbligh	nodes = max(len(numa_nodes()), 1)
4878eca3a98728afabc7fc761c08dbb8e91260c7de4mbligh	return ((memtotal() * 1024) / nodes)
4888eca3a98728afabc7fc761c08dbb8e91260c7de4mbligh
489