1# 2# pystatgrab 3# https://libstatgrab.org/pystatgrab/ 4# Copyright (C) 2004-2019 Tim Bishop 5# Copyright (C) 2005-2013 Adam Sampson 6# 7# This library is free software; you can redistribute it and/or 8# modify it under the terms of the GNU Lesser General Public 9# License as published by the Free Software Foundation; either 10# version 2.1 of the License, or (at your option) any later version. 11# 12# This library 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 GNU 15# Lesser General Public License for more details. 16# 17# You should have received a copy of the GNU Lesser General Public 18# License along with this library; if not, write to the Free Software 19# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20# 02110-1301, USA. 21# 22# $Id$ 23# 24 25from libc.stdlib cimport malloc, free 26from sys import version_info 27 28cimport libstatgrab as sg 29 30# Helper code 31 32class StatgrabError(Exception): 33 """Exception representing a libstatgrab error.""" 34 def __init__(self): 35 cdef sg.sg_error_details details 36 sg.sg_get_error_details(&details) 37 self.error = details.error 38 self.errno_value = details.errno_value 39 self.error_arg = details.error_arg 40 41 cdef char *msg = NULL 42 sg.sg_strperror(&msg, &details) 43 super(StatgrabError, self).__init__("statgrab error: " + msg) 44 free(msg) 45 46cdef int _not_error(sg.sg_error code) except -1: 47 """Raise StatgrabError if code is not SG_ERROR_NONE.""" 48 if code != sg.SG_ERROR_NONE: 49 raise StatgrabError() 50 return 0 51 52cdef int _not_null(const void *value) except -1: 53 """Raise StatgrabError if value is NULL.""" 54 if value == NULL: 55 raise StatgrabError() 56 return 0 57 58cdef int _vector_not_null(const void *value, size_t entries) except -1: 59 """Check the return value from a vector-returning function. 60 Raise StatgrabError if: 61 - entries > 0 and value is NULL, or 62 - entries == 0 and sg_get_error indicates an error has occurred.""" 63 # FIXME: this is an API oddity; libstatgrab issue #17 discusses it 64 if entries > 0 and value == NULL: 65 raise StatgrabError() 66 elif entries == 0 and sg.sg_get_error() != sg.SG_ERROR_NONE: 67 raise StatgrabError() 68 return 0 69 70class Result(dict): 71 def __init__(self, attrs): 72 super(Result, self).__init__(attrs) 73 74 # For compatibility with older pystatgrab. 75 self.attrs = attrs 76 77 def __getattr__(self, item): 78 try: 79 return self.__getitem__(item) 80 except KeyError: 81 raise AttributeError(item) 82 83def _str_to_bytes(s): 84 if version_info[0] >= 3 and isinstance(s, str): 85 return bytes(s, 'utf-8') 86 else: 87 return s 88 89def _bytes_to_str(b): 90 if version_info[0] >= 3 and isinstance(b, bytes): 91 return str(b, 'utf-8') 92 else: 93 return b 94 95# libstatgrab constants exported 96 97ERROR_NONE = sg.SG_ERROR_NONE 98ERROR_INVALID_ARGUMENT = sg.SG_ERROR_INVALID_ARGUMENT 99ERROR_ASPRINTF = sg.SG_ERROR_ASPRINTF 100ERROR_SPRINTF = sg.SG_ERROR_SPRINTF 101ERROR_DEVICES = sg.SG_ERROR_DEVICES 102ERROR_DEVSTAT_GETDEVS = sg.SG_ERROR_DEVSTAT_GETDEVS 103ERROR_DEVSTAT_SELECTDEVS = sg.SG_ERROR_DEVSTAT_SELECTDEVS 104ERROR_DISKINFO = sg.SG_ERROR_DISKINFO 105ERROR_ENOENT = sg.SG_ERROR_ENOENT 106ERROR_GETIFADDRS = sg.SG_ERROR_GETIFADDRS 107ERROR_GETMNTINFO = sg.SG_ERROR_GETMNTINFO 108ERROR_GETPAGESIZE = sg.SG_ERROR_GETPAGESIZE 109ERROR_HOST = sg.SG_ERROR_HOST 110ERROR_KSTAT_DATA_LOOKUP = sg.SG_ERROR_KSTAT_DATA_LOOKUP 111ERROR_KSTAT_LOOKUP = sg.SG_ERROR_KSTAT_LOOKUP 112ERROR_KSTAT_OPEN = sg.SG_ERROR_KSTAT_OPEN 113ERROR_KSTAT_READ = sg.SG_ERROR_KSTAT_READ 114ERROR_KVM_GETSWAPINFO = sg.SG_ERROR_KVM_GETSWAPINFO 115ERROR_KVM_OPENFILES = sg.SG_ERROR_KVM_OPENFILES 116ERROR_MALLOC = sg.SG_ERROR_MALLOC 117ERROR_MEMSTATUS = sg.SG_ERROR_MEMSTATUS 118ERROR_OPEN = sg.SG_ERROR_OPEN 119ERROR_OPENDIR = sg.SG_ERROR_OPENDIR 120ERROR_READDIR = sg.SG_ERROR_READDIR 121ERROR_PARSE = sg.SG_ERROR_PARSE 122ERROR_PDHADD = sg.SG_ERROR_PDHADD 123ERROR_PDHCOLLECT = sg.SG_ERROR_PDHCOLLECT 124ERROR_PDHOPEN = sg.SG_ERROR_PDHOPEN 125ERROR_PDHREAD = sg.SG_ERROR_PDHREAD 126ERROR_PERMISSION = sg.SG_ERROR_PERMISSION 127ERROR_PSTAT = sg.SG_ERROR_PSTAT 128ERROR_SETEGID = sg.SG_ERROR_SETEGID 129ERROR_SETEUID = sg.SG_ERROR_SETEUID 130ERROR_SETMNTENT = sg.SG_ERROR_SETMNTENT 131ERROR_SOCKET = sg.SG_ERROR_SOCKET 132ERROR_SWAPCTL = sg.SG_ERROR_SWAPCTL 133ERROR_SYSCONF = sg.SG_ERROR_SYSCONF 134ERROR_SYSCTL = sg.SG_ERROR_SYSCTL 135ERROR_SYSCTLBYNAME = sg.SG_ERROR_SYSCTLBYNAME 136ERROR_SYSCTLNAMETOMIB = sg.SG_ERROR_SYSCTLNAMETOMIB 137ERROR_SYSINFO = sg.SG_ERROR_SYSINFO 138ERROR_MACHCALL = sg.SG_ERROR_MACHCALL 139ERROR_IOKIT = sg.SG_ERROR_IOKIT 140ERROR_UNAME = sg.SG_ERROR_UNAME 141ERROR_UNSUPPORTED = sg.SG_ERROR_UNSUPPORTED 142ERROR_XSW_VER_MISMATCH = sg.SG_ERROR_XSW_VER_MISMATCH 143ERROR_GETMSG = sg.SG_ERROR_GETMSG 144ERROR_PUTMSG = sg.SG_ERROR_PUTMSG 145ERROR_INITIALISATION = sg.SG_ERROR_INITIALISATION 146ERROR_MUTEX_LOCK = sg.SG_ERROR_MUTEX_LOCK 147ERROR_MUTEX_UNLOCK = sg.SG_ERROR_MUTEX_UNLOCK 148 149entire_cpu_percent = sg.sg_entire_cpu_percent 150last_diff_cpu_percent = sg.sg_last_diff_cpu_percent 151new_diff_cpu_percent = sg.sg_new_diff_cpu_percent 152 153IFACE_DUPLEX_FULL = sg.SG_IFACE_DUPLEX_FULL 154IFACE_DUPLEX_HALF = sg.SG_IFACE_DUPLEX_HALF 155IFACE_DUPLEX_UNKNOWN = sg.SG_IFACE_DUPLEX_UNKNOWN 156 157IFACE_DOWN = sg.SG_IFACE_DOWN 158IFACE_UP = sg.SG_IFACE_UP 159 160PROCESS_STATE_RUNNING = sg.SG_PROCESS_STATE_RUNNING 161PROCESS_STATE_SLEEPING = sg.SG_PROCESS_STATE_SLEEPING 162PROCESS_STATE_STOPPED = sg.SG_PROCESS_STATE_STOPPED 163PROCESS_STATE_ZOMBIE = sg.SG_PROCESS_STATE_ZOMBIE 164PROCESS_STATE_UNKNOWN = sg.SG_PROCESS_STATE_UNKNOWN 165 166entire_process_count = sg.sg_entire_process_count 167last_process_count = sg.sg_last_process_count 168 169# libstatgrab functions exported 170 171# FIXME: docstrings 172 173def init(ignore_init_errors=False): 174 _not_error(sg.sg_init(ignore_init_errors)) 175 176def snapshot(): 177 _not_error(sg.sg_snapshot()) 178 179def shutdown(): 180 _not_error(sg.sg_shutdown()) 181 182def drop_privileges(): 183 _not_error(sg.sg_drop_privileges()) 184 185def get_host_info(): 186 cdef const sg.sg_host_info *s = sg.sg_get_host_info(NULL) 187 _not_null(s) 188 return Result({ 189 'os_name': s.os_name, 190 'os_release': s.os_release, 191 'os_version': s.os_version, 192 'platform': s.platform, 193 'hostname': s.hostname, 194 'bitwidth': s.bitwidth, 195 'host_state': s.host_state, 196 'ncpus': s.ncpus, 197 'maxcpus': s.maxcpus, 198 'uptime': s.uptime, 199 'systime': s.systime, 200 }) 201 202cdef _make_cpu_stats(const sg.sg_cpu_stats *s): 203 return Result({ 204 'user': s.user, 205 'kernel': s.kernel, 206 'idle': s.idle, 207 'iowait': s.iowait, 208 'swap': s.swap, 209 'nice': s.nice, 210 'total': s.total, 211 'context_switches': s.context_switches, 212 'voluntary_context_switches': s.voluntary_context_switches, 213 'involuntary_context_switches': s.involuntary_context_switches, 214 'syscalls': s.syscalls, 215 'interrupts': s.interrupts, 216 'soft_interrupts': s.soft_interrupts, 217 'systime': s.systime, 218 }) 219 220def get_cpu_stats(): 221 cdef const sg.sg_cpu_stats *s = sg.sg_get_cpu_stats(NULL) 222 _not_null(s) 223 return _make_cpu_stats(s) 224 225def get_cpu_stats_diff(): 226 cdef const sg.sg_cpu_stats *s = sg.sg_get_cpu_stats_diff(NULL) 227 _not_null(s) 228 return _make_cpu_stats(s) 229 230def get_cpu_percents(cps=new_diff_cpu_percent): 231 cdef const sg.sg_cpu_percents *s = sg.sg_get_cpu_percents(NULL) 232 _not_null(s) 233 return Result({ 234 'user': s.user, 235 'kernel': s.kernel, 236 'idle': s.idle, 237 'iowait': s.iowait, 238 'swap': s.swap, 239 'nice': s.nice, 240 'time_taken': s.time_taken, 241 }) 242 243def get_mem_stats(): 244 cdef const sg.sg_mem_stats *s = sg.sg_get_mem_stats(NULL) 245 _not_null(s) 246 return Result({ 247 'total': s.total, 248 'free': s.free, 249 'used': s.used, 250 'cache': s.cache, 251 'systime': s.systime, 252 }) 253 254def get_load_stats(): 255 cdef const sg.sg_load_stats *s = sg.sg_get_load_stats(NULL) 256 _not_null(s) 257 return Result({ 258 'min1': s.min1, 259 'min5': s.min5, 260 'min15': s.min15, 261 'systime': s.systime, 262 }) 263 264cdef _make_user_stats(const sg.sg_user_stats *s): 265 return Result({ 266 'login_name': s.login_name, 267 # Note special handling for record_id. 268 'record_id': s.record_id[:s.record_id_size], 269 'device': s.device, 270 'hostname': s.hostname, 271 'pid': s.pid, 272 'login_time': s.login_time, 273 'systime': s.systime, 274 }) 275 276def get_user_stats(): 277 cdef size_t n 278 cdef const sg.sg_user_stats *s = sg.sg_get_user_stats(&n) 279 _vector_not_null(s, n) 280 return [_make_user_stats(&s[i]) for i in range(n)] 281 282def get_swap_stats(): 283 cdef const sg.sg_swap_stats *s = sg.sg_get_swap_stats(NULL) 284 _not_null(s) 285 return Result({ 286 'total': s.total, 287 'used': s.used, 288 'free': s.free, 289 'systime': s.systime, 290 }) 291 292def get_valid_filesystems(): 293 cdef size_t n 294 cdef const char **s = sg.sg_get_valid_filesystems(&n) 295 _vector_not_null(s, n) 296 return [_bytes_to_str(s[i]) for i in range(n)] 297 298def set_valid_filesystems(valid_fs): 299 cdef int num_fs = len(valid_fs) 300 cdef const char **vs 301 vs = <const char **>malloc((num_fs + 1) * sizeof(const char *)) 302 if vs == NULL: 303 raise MemoryError("malloc failed") 304 valid_fs = [_str_to_bytes(x) for x in valid_fs] 305 for i in range(num_fs): 306 vs[i] = valid_fs[i] 307 vs[num_fs] = NULL 308 _not_error(sg.sg_set_valid_filesystems(vs)) 309 free(vs) 310 311cdef _make_fs_stats(const sg.sg_fs_stats *s): 312 return Result({ 313 'device_name': s.device_name, 314 'device_canonical': s.device_canonical, 315 'fs_type': s.fs_type, 316 'mnt_point': s.mnt_point, 317 'device_type': s.device_type, 318 'size': s.size, 319 'used': s.used, 320 'free': s.free, 321 'avail': s.avail, 322 'total_inodes': s.total_inodes, 323 'used_inodes': s.used_inodes, 324 'free_inodes': s.free_inodes, 325 'avail_inodes': s.avail_inodes, 326 'io_size': s.io_size, 327 'block_size': s.block_size, 328 'total_blocks': s.total_blocks, 329 'free_blocks': s.free_blocks, 330 'used_blocks': s.used_blocks, 331 'avail_blocks': s.avail_blocks, 332 'systime': s.systime, 333 }) 334 335def get_fs_stats(): 336 cdef size_t n 337 cdef const sg.sg_fs_stats *s = sg.sg_get_fs_stats(&n) 338 _vector_not_null(s, n) 339 return [_make_fs_stats(&s[i]) for i in range(n)] 340 341def get_fs_stats_diff(): 342 cdef size_t n 343 cdef const sg.sg_fs_stats *s = sg.sg_get_fs_stats_diff(&n) 344 _vector_not_null(s, n) 345 return [_make_fs_stats(&s[i]) for i in range(n)] 346 347cdef _make_disk_io_stats(const sg.sg_disk_io_stats *s): 348 return Result({ 349 'disk_name': s.disk_name, 350 'read_bytes': s.read_bytes, 351 'write_bytes': s.write_bytes, 352 'systime': s.systime, 353 }) 354 355def get_disk_io_stats(): 356 cdef size_t n 357 cdef const sg.sg_disk_io_stats *s = sg.sg_get_disk_io_stats(&n) 358 _vector_not_null(s, n) 359 return [_make_disk_io_stats(&s[i]) for i in range(n)] 360 361def get_disk_io_stats_diff(): 362 cdef size_t n 363 cdef const sg.sg_disk_io_stats *s = sg.sg_get_disk_io_stats_diff(&n) 364 _vector_not_null(s, n) 365 return [_make_disk_io_stats(&s[i]) for i in range(n)] 366 367cdef _make_network_io_stats(const sg.sg_network_io_stats *s): 368 return Result({ 369 'interface_name': s.interface_name, 370 'tx': s.tx, 371 'rx': s.rx, 372 'ipackets': s.ipackets, 373 'opackets': s.opackets, 374 'ierrors': s.ierrors, 375 'oerrors': s.oerrors, 376 'collisions': s.collisions, 377 'systime': s.systime, 378 }) 379 380def get_network_io_stats(): 381 cdef size_t n 382 cdef const sg.sg_network_io_stats *s = sg.sg_get_network_io_stats(&n) 383 _vector_not_null(s, n) 384 return [_make_network_io_stats(&s[i]) for i in range(n)] 385 386def get_network_io_stats_diff(): 387 cdef size_t n 388 cdef const sg.sg_network_io_stats *s = sg.sg_get_network_io_stats_diff(&n) 389 _vector_not_null(s, n) 390 return [_make_network_io_stats(&s[i]) for i in range(n)] 391 392cdef _make_network_iface_stats(const sg.sg_network_iface_stats *s): 393 return Result({ 394 'interface_name': s.interface_name, 395 'speed': s.speed, 396 'factor': s.factor, 397 'duplex': s.duplex, 398 'up': s.up, 399 'systime': s.systime, 400 }) 401 402def get_network_iface_stats(): 403 cdef size_t n 404 cdef const sg.sg_network_iface_stats *s = sg.sg_get_network_iface_stats(&n) 405 _vector_not_null(s, n) 406 return [_make_network_iface_stats(&s[i]) for i in range(n)] 407 408cdef _make_page_stats(const sg.sg_page_stats *s): 409 return Result({ 410 'pages_pagein': s.pages_pagein, 411 'pages_pageout': s.pages_pageout, 412 'systime': s.systime, 413 }) 414 415def get_page_stats(): 416 cdef const sg.sg_page_stats *s = sg.sg_get_page_stats(NULL) 417 _not_null(s) 418 return _make_page_stats(s) 419 420def get_page_stats_diff(): 421 cdef const sg.sg_page_stats *s = sg.sg_get_page_stats_diff(NULL) 422 _not_null(s) 423 return _make_page_stats(s) 424 425cdef _make_process_stats(const sg.sg_process_stats *s): 426 return Result({ 427 'process_name': s.process_name, 428 'proctitle': s.proctitle, 429 'pid': s.pid, 430 'parent': s.parent, 431 'pgid': s.pgid, 432 'sessid': s.sessid, 433 'uid': s.uid, 434 'euid': s.euid, 435 'gid': s.gid, 436 'egid': s.egid, 437 'context_switches': s.context_switches, 438 'voluntary_context_switches': s.voluntary_context_switches, 439 'involuntary_context_switches': s.involuntary_context_switches, 440 'proc_size': s.proc_size, 441 'proc_resident': s.proc_resident, 442 'start_time': s.start_time, 443 'time_spent': s.time_spent, 444 'cpu_percent': s.cpu_percent, 445 'nice': s.nice, 446 'state': s.state, 447 'systime': s.systime, 448 }) 449 450def get_process_stats(): 451 cdef size_t n 452 cdef const sg.sg_process_stats *s = sg.sg_get_process_stats(&n) 453 _vector_not_null(s, n) 454 return [_make_process_stats(&s[i]) for i in range(n)] 455 456def get_process_count(pcs=entire_process_count): 457 cdef const sg.sg_process_count *s = sg.sg_get_process_count_of(pcs) 458 _not_null(s) 459 return Result({ 460 'total': s.total, 461 'running': s.running, 462 'sleeping': s.sleeping, 463 'stopped': s.stopped, 464 'zombie': s.zombie, 465 'unknown': s.unknown, 466 'systime': s.systime, 467 }) 468 469# Backwards compatibility with pystatgrab <= 0.5 470 471SG_ERROR_NONE = ERROR_NONE 472SG_ERROR_INVALID_ARGUMENT = ERROR_INVALID_ARGUMENT 473SG_ERROR_ASPRINTF = ERROR_ASPRINTF 474SG_ERROR_SPRINTF = ERROR_SPRINTF 475SG_ERROR_DEVICES = ERROR_DEVICES 476SG_ERROR_DEVSTAT_GETDEVS = ERROR_DEVSTAT_GETDEVS 477SG_ERROR_DEVSTAT_SELECTDEVS = ERROR_DEVSTAT_SELECTDEVS 478SG_ERROR_DISKINFO = ERROR_DISKINFO 479SG_ERROR_ENOENT = ERROR_ENOENT 480SG_ERROR_GETIFADDRS = ERROR_GETIFADDRS 481SG_ERROR_GETMNTINFO = ERROR_GETMNTINFO 482SG_ERROR_GETPAGESIZE = ERROR_GETPAGESIZE 483SG_ERROR_HOST = ERROR_HOST 484SG_ERROR_KSTAT_DATA_LOOKUP = ERROR_KSTAT_DATA_LOOKUP 485SG_ERROR_KSTAT_LOOKUP = ERROR_KSTAT_LOOKUP 486SG_ERROR_KSTAT_OPEN = ERROR_KSTAT_OPEN 487SG_ERROR_KSTAT_READ = ERROR_KSTAT_READ 488SG_ERROR_KVM_GETSWAPINFO = ERROR_KVM_GETSWAPINFO 489SG_ERROR_KVM_OPENFILES = ERROR_KVM_OPENFILES 490SG_ERROR_MALLOC = ERROR_MALLOC 491SG_ERROR_MEMSTATUS = ERROR_MEMSTATUS 492SG_ERROR_OPEN = ERROR_OPEN 493SG_ERROR_OPENDIR = ERROR_OPENDIR 494SG_ERROR_READDIR = ERROR_READDIR 495SG_ERROR_PARSE = ERROR_PARSE 496SG_ERROR_PDHADD = ERROR_PDHADD 497SG_ERROR_PDHCOLLECT = ERROR_PDHCOLLECT 498SG_ERROR_PDHOPEN = ERROR_PDHOPEN 499SG_ERROR_PDHREAD = ERROR_PDHREAD 500SG_ERROR_PERMISSION = ERROR_PERMISSION 501SG_ERROR_PSTAT = ERROR_PSTAT 502SG_ERROR_SETEGID = ERROR_SETEGID 503SG_ERROR_SETEUID = ERROR_SETEUID 504SG_ERROR_SETMNTENT = ERROR_SETMNTENT 505SG_ERROR_SOCKET = ERROR_SOCKET 506SG_ERROR_SWAPCTL = ERROR_SWAPCTL 507SG_ERROR_SYSCONF = ERROR_SYSCONF 508SG_ERROR_SYSCTL = ERROR_SYSCTL 509SG_ERROR_SYSCTLBYNAME = ERROR_SYSCTLBYNAME 510SG_ERROR_SYSCTLNAMETOMIB = ERROR_SYSCTLNAMETOMIB 511SG_ERROR_SYSINFO = ERROR_SYSINFO 512SG_ERROR_MACHCALL = ERROR_MACHCALL 513SG_ERROR_IOKIT = ERROR_IOKIT 514SG_ERROR_UNAME = ERROR_UNAME 515SG_ERROR_UNSUPPORTED = ERROR_UNSUPPORTED 516SG_ERROR_XSW_VER_MISMATCH = ERROR_XSW_VER_MISMATCH 517SG_ERROR_GETMSG = ERROR_GETMSG 518SG_ERROR_PUTMSG = ERROR_PUTMSG 519SG_ERROR_INITIALISATION = ERROR_INITIALISATION 520SG_ERROR_MUTEX_LOCK = ERROR_MUTEX_LOCK 521SG_ERROR_MUTEX_UNLOCK = ERROR_MUTEX_UNLOCK 522 523SG_IFACE_DUPLEX_FULL = IFACE_DUPLEX_FULL 524SG_IFACE_DUPLEX_HALF = IFACE_DUPLEX_HALF 525SG_IFACE_DUPLEX_UNKNOWN = IFACE_DUPLEX_UNKNOWN 526 527SG_IFACE_DOWN = IFACE_DOWN 528SG_IFACE_UP = IFACE_UP 529 530SG_PROCESS_STATE_RUNNING = PROCESS_STATE_RUNNING 531SG_PROCESS_STATE_SLEEPING = PROCESS_STATE_SLEEPING 532SG_PROCESS_STATE_STOPPED = PROCESS_STATE_STOPPED 533SG_PROCESS_STATE_ZOMBIE = PROCESS_STATE_ZOMBIE 534SG_PROCESS_STATE_UNKNOWN = PROCESS_STATE_UNKNOWN 535 536# Some functions returned True/False for success/failure. 537def _wrap_success(func, *args): 538 try: 539 func(*args) 540 return True 541 except StatgrabError: 542 return False 543 544def sg_init(): 545 return _wrap_success(init) 546def sg_snapshot(): 547 return _wrap_success(snapshot) 548def sg_shutdown(): 549 return _wrap_success(shutdown) 550def sg_drop_privileges(): 551 return _wrap_success(drop_privileges) 552 553# The error-handling functions just wrapped those from libstatgrab. 554def sg_get_error(): 555 return sg.sg_get_error() 556def sg_get_error_arg(): 557 return sg.sg_get_error_arg() 558def sg_get_error_errno(): 559 return sg.sg_get_error_errno() 560def sg_str_error(code): 561 return _bytes_to_str(sg.sg_str_error(code)) 562 563# Some functions work the same way, just with a different name. 564sg_get_host_info = get_host_info 565sg_get_cpu_stats = get_cpu_stats 566sg_get_cpu_stats_diff = get_cpu_stats_diff 567sg_get_cpu_percents = get_cpu_percents 568sg_get_mem_stats = get_mem_stats 569sg_get_load_stats = get_load_stats 570sg_get_swap_stats = get_swap_stats 571sg_get_fs_stats = get_fs_stats 572sg_get_disk_io_stats = get_disk_io_stats 573sg_get_disk_io_stats_diff = get_disk_io_stats_diff 574sg_get_network_io_stats = get_network_io_stats 575sg_get_network_io_stats_diff = get_network_io_stats_diff 576sg_get_network_iface_stats = get_network_iface_stats 577sg_get_page_stats = get_page_stats 578sg_get_page_stats_diff = get_page_stats_diff 579sg_get_process_stats = get_process_stats 580sg_get_process_count = get_process_count 581 582# User stats used to be a single result rather than a list. 583def sg_get_user_stats(): 584 cdef size_t n 585 cdef const sg.sg_user_stats *s = sg.sg_get_user_stats(&n) 586 _vector_not_null(s, n) 587 return Result({ 588 'name_list': " ".join([_bytes_to_str(s[i].login_name) for i in range(n)]), 589 'num_entries': n, 590 }) 591