]>
git.ipfire.org Git - people/stevee/pakfire.git/blob - src/pakfire/system.py
758a8d7ada57ab8aafbfa82024e5198238e7886e
2 ###############################################################################
4 # Pakfire - The IPFire package management system #
5 # Copyright (C) 2011 Pakfire development team #
7 # This program is free software: you can redistribute it and/or modify #
8 # it under the terms of the GNU General Public License as published by #
9 # the Free Software Foundation, either version 3 of the License, or #
10 # (at your option) any later version. #
12 # This program is distributed in the hope that it will be useful, #
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15 # GNU General Public License for more details. #
17 # You should have received a copy of the GNU General Public License #
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
20 ###############################################################################
22 from __future__
import division
24 import multiprocessing
32 from . import _pakfire
38 Class that grants access to several information about
39 the system this software is running on.
43 hn
= socket
.gethostname()
45 # If a host has got no domain part, we add one.
47 hn
= "%s.localdomain" % hn
53 if not hasattr(self
, "_distro"):
54 self
._distro
= distro
.Distribution()
59 def native_arch(self
):
61 Return the native architecture of the host we
69 Return the architecture of the host we are running on.
71 if self
.supported_arches
and not self
.native_arch
in self
.supported_arches
:
72 return self
.supported_arches
[0]
74 return self
.native_arch
77 def supported_arches(self
):
79 Check what architectures can be built on this host.
82 # Host arch : Can build these arches.
85 "x86_64" : ["x86_64", "i686",],
89 "armv5tel" : ["armv5tel",],
90 "armv5tejl" : ["armv5tel",],
91 "armv6l" : ["armv5tel",],
92 "armv7l" : ["armv7hl", "armv5tel",],
93 "armv7hl" : ["armv7hl", "armv5tel",],
95 "aarch64" : ["aarch64",],
99 return host_can_build
[self
.native_arch
]
103 def host_supports_arch(self
, arch
):
105 Check if this host can build for the target architecture "arch".
107 return arch
in self
.supported_arches
112 Count the number of CPU cores.
114 return multiprocessing
.cpu_count()
116 def parse_cpuinfo(self
):
119 with
open("/proc/cpuinfo") as f
:
120 for line
in f
.readlines():
122 # Split the lines by colons.
123 a
, b
= line
.split(":")
137 cpuinfo
= self
.parse_cpuinfo()
139 ret
= cpuinfo
.get("model name", None)
141 # Some ARM platforms do not provide "model name", so we
145 ret
= "%(Hardware)s - %(Processor)s" % cpuinfo
149 # Remove too many spaces.
151 ret
= " ".join(ret
.split())
153 return ret
or _("Could not be determined")
156 def cpu_bogomips(self
):
157 return _pakfire
.performance_index()
159 def get_loadavg(self
):
160 return os
.getloadavg()
164 return self
.get_loadavg()[0]
168 return self
.get_loadavg()[1]
172 return self
.get_loadavg()[2]
174 def has_overload(self
):
176 Checks, if the load average is not too high.
178 On this is to be decided if a new job is taken.
180 # If there are more than 2 processes in the process queue per CPU
181 # core we will assume that the system has heavy load and to not request
183 return self
.loadavg5
>= self
.cpu_count
* 2
185 def parse_meminfo(self
):
188 with
open("/proc/meminfo") as f
:
189 for line
in f
.readlines():
191 a
, b
, c
= line
.split()
194 a
= a
.replace(":", "")
204 def memory_total(self
):
205 meminfo
= self
.parse_meminfo()
207 return meminfo
.get("MemTotal", None)
210 memory
= memory_total
213 def memory_free(self
):
214 meminfo
= self
.parse_meminfo()
216 free
= meminfo
.get("MemFree", None)
218 buffers
= meminfo
.get("Buffers")
219 cached
= meminfo
.get("Cached")
221 return free
+ buffers
+ cached
224 def swap_total(self
):
225 meminfo
= self
.parse_meminfo()
227 return meminfo
.get("SwapTotal", None)
231 meminfo
= self
.parse_meminfo()
233 return meminfo
.get("SwapFree", None)
235 def get_mountpoint(self
, path
):
236 return Mountpoint(path
)
239 def parallelism(self
):
241 Calculates how many processes should be run
242 simulatneously when compiling.
244 # Check how many processes would fit into the
245 # memory when each process takes up to 192MB.
246 multiplicator
= self
.memory
/ (192 * 1024 * 1024)
247 multiplicator
= round(multiplicator
)
249 # Count the number of online CPU cores.
250 cpucount
= os
.sysconf("SC_NPROCESSORS_CONF") * 2
253 return min(multiplicator
, cpucount
)
256 # Create an instance of this class to only keep it once in memory.
259 class Mountpoints(object):
260 def __init__(self
, root
="/"):
261 self
._mountpoints
= []
263 # Scan for all mountpoints on the system.
267 return iter(self
._mountpoints
)
269 def _scan(self
, root
):
270 # Get the real path of root.
271 root
= os
.path
.realpath(root
)
273 # If root is not equal to /, we are in a chroot and
274 # our root must be a mountpoint to count files.
276 mp
= Mountpoint("/", root
=root
)
277 self
._mountpoints
.append(mp
)
279 f
= open("/proc/mounts")
281 for line
in f
.readlines():
284 # The mountpoint is the second argument.
287 # Skip all mountpoints that are not in our root directory.
288 if not mountpoint
.startswith(root
):
291 mountpoint
= os
.path
.relpath(mountpoint
, root
)
292 if mountpoint
== ".":
295 mountpoint
= os
.path
.join("/", mountpoint
)
297 mp
= Mountpoint(mountpoint
, root
=root
)
299 if not mp
in self
._mountpoints
:
300 self
._mountpoints
.append(mp
)
304 # Sort all mountpoints for better searching.
305 self
._mountpoints
.sort()
307 def add_pkg(self
, pkg
):
308 for file in pkg
.filelist
:
311 def rem_pkg(self
, pkg
):
312 for file in pkg
.filelist
:
316 for mp
in reversed(self
._mountpoints
):
317 # Check if the file is located on this mountpoint.
318 if not file.name
.startswith(mp
.path
):
321 # Add file to this mountpoint.
326 for mp
in reversed(self
._mountpoints
):
327 # Check if the file is located on this mountpoint.
328 if not file.name
.startswith(mp
.path
):
331 # Remove file from this mountpoint.
336 class Mountpoint(object):
337 def __init__(self
, path
, root
="/"):
341 # Cache the statvfs call of the mountpoint.
344 # Save the amount of data that is used or freed.
348 return "<%s %s>" % (self
.__class
__.__name
__, self
.fullpath
)
350 def __cmp__(self
, other
):
351 return cmp(self
.fullpath
, other
.fullpath
)
356 while path
.startswith("/"):
359 return os
.path
.join(self
.root
, path
)
363 if self
.__stat
is None:
364 # Find the next mountpoint, because we cannot
365 # statvfs any path in the FS.
366 path
= os
.path
.realpath(self
.fullpath
)
368 # Walk to root until we find a mountpoint.
369 while not os
.path
.ismount(path
):
370 path
= os
.path
.dirname(path
)
372 # See what we can get.
373 self
.__stat
= os
.statvfs(path
)
379 return self
.stat
.f_bavail
* self
.stat
.f_bsize
382 def space_needed(self
):
383 if self
.disk_usage
> 0:
384 return self
.disk_usage
389 def space_left(self
):
390 return self
.free
- self
.space_needed
393 assert file.name
.startswith(self
.path
)
395 # Round filesize to 4k blocks.
398 blocks
= file.size
// block_size
399 if file.size
% block_size
:
402 self
.disk_usage
+= blocks
* block_size
405 assert file.name
.startswith(self
.path
)
407 self
.disk_usage
-= file.size
409 def is_readonly(self
):
411 Returns True if the mountpoint is mounted read-only.
414 # Using the statvfs output does not really work, so we use
415 # a very naive approach here, were we just try to create a
416 # new file. If that works, it's writable.
419 handle
, path
= tempfile
.mkstemp(prefix
="ro-test-", dir=self
.fullpath
)
421 # Read-only file system.
425 # Raise all other exceptions.
428 # Close the file and remove it.
434 def remount(self
, rorw
=None):
436 if rorw
in ("ro", "rw"):
437 options
= "%s,%s" % (options
, rorw
)
440 shellenv
= shell
.ShellExecuteEnvironment(
441 ["mount", "-o", options
, self
.fullpath
],
445 except ShellEnvironmentError
, e
:
449 if __name__
== "__main__":
450 print "Hostname", system
.hostname
451 print "Arch", system
.arch
452 print "Supported arches", system
.supported_arches
454 print "CPU Model", system
.cpu_model
455 print "CPU count", system
.cpu_count
456 print "Memory", system
.memory