helpers.py 5.75 KB
Newer Older
Mario Hock's avatar
Mario Hock committed
1
#!/usr/bin/env python3
2
3
4
5
# -*- coding:utf-8 -*-

from collections import namedtuple
import os
Mario Hock's avatar
Mario Hock committed
6
import netifaces
7
import operator
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

_ptime_cpu_perc_nt = None


### Copied from »psutil« source code and adapted to calculate percentage on two input values rather than "live"
#     see: psutil/__init__.py:1282  (Version: 1.2.1-1ubuntu2)
def calculate_cpu_times_percent(cpu_times_older, cpu_times_younger, percpu=False):
    """Same as cpu_percent() but provides utilization percentages
    for each specific CPU time as is returned by cpu_times().
    For instance, on Linux we'll get:

      >>> cpu_times_percent()
      cpupercent(user=4.8, nice=0.0, system=4.8, idle=90.5, iowait=0.0,
                 irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0)
      >>>

    interval and percpu arguments have the same meaning as in
    cpu_percent().
    """
    #global _last_cpu_times_2
    #global _last_per_cpu_times_2
#    blocking = interval is not None and interval > 0.0
    WINDOWS = os.name == 'nt'

    def calculate(t1, t2):
        global _ptime_cpu_perc_nt
        nums = []
        all_delta = sum(t2) - sum(t1)
        for field in t1._fields:
            field_delta = getattr(t2, field) - getattr(t1, field)
            try:
                field_perc = (100 * field_delta) / all_delta
            except ZeroDivisionError:
                field_perc = 0.0
            field_perc = round(field_perc, 1)
            if WINDOWS:
                # XXX
                # Work around:
                # https://code.google.com/p/psutil/issues/detail?id=392
                # CPU times are always supposed to increase over time
                # or at least remain the same and that's because time
                # cannot go backwards.
                # Surprisingly sometimes this might not be the case on
                # Windows where 'system' CPU time can be smaller
                # compared to the previous call, resulting in corrupted
                # percentages (< 0 or > 100).
                # I really don't know what to do about that except
                # forcing the value to 0 or 100.
                if field_perc > 100.0:
                    field_perc = 100.0
                elif field_perc < 0.0:
                    field_perc = 0.0
            nums.append(field_perc)
        if _ptime_cpu_perc_nt is None:
            _ptime_cpu_perc_nt = namedtuple('cpupercent', ' '.join(t1._fields))
        return _ptime_cpu_perc_nt(*nums)

    # system-wide usage
    if not percpu:
        #if blocking:
            #t1 = cpu_times()
            #time.sleep(interval)
        #else:
            #t1 = _last_cpu_times_2
        #_last_cpu_times_2 = cpu_times()
        #return calculate(t1, _last_cpu_times_2)
        return calculate(cpu_times_older, cpu_times_younger)
    # per-cpu usage
    else:
        ret = []
        #if blocking:
            #tot1 = cpu_times(percpu=True)
            #time.sleep(interval)
        #else:
            #tot1 = _last_per_cpu_times_2
        #_last_per_cpu_times_2 = cpu_times(percpu=True)
        for t1, t2 in zip(cpu_times_older, cpu_times_younger):
            ret.append(calculate(t1, t2))
        return ret
Mario Hock's avatar
Mario Hock committed
87
88
89
90
91
92
93
94
95
96
97
98



def get_nics():
    return netifaces.interfaces()

def get_nic_speeds():
    ret = dict()

    for nic in get_nics():
        try:
            with open("/sys/class/net/" + nic + "/speed", "r") as f:
Mario Hock's avatar
Mario Hock committed
99
                speed = int( f.read().strip() ) * 1000 * 1000
Mario Hock's avatar
Mario Hock committed
100
101
102
103
104
105
106

            ret[nic] = speed
        except OSError:
            speed = 0

    return ret

Mario Hock's avatar
Mario Hock committed
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

def split_proprtionally(text, weights, size=0, fill=" "):
    """
    Split a string proportional to a given weight-distribution.

    If a |size| is specified, that string is filled with |fill| at the end to match that length.
    (NOTE: len(fill) must be 1)
    """

    if ( size > 0 ):
        ## Fill text with spaces.
        if ( len(text) < size ):
            text += fill * (size-len(text))
        ## Truncate text if it's too long.
        elif ( len(text) > size ):
            text = text[size]
    else:
        size = len(text)

    # sum of all weights
    total_weights = float( sum(weights) )

    ## Calculate an int for each weight so that they sum appropriately to |size|.
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
    float_lengths = [ (w / total_weights)*size for w in weights ]
    weighted_lengths = [ int(round( f )) for f in float_lengths ]

    ## Compensate rounding-related inconsistencies.
        # XXX I hope this actually does what's supposed to do...
        # (Increase/decrease the fields with the biggest rounding differences in order to fit the size)
    diff = size - sum(weighted_lengths)
    while( diff != 0 ):
        sign = -1 if diff < 0 else 1

        ## Calculate index where the rounding produced the biggest difference.
        #    (On equality, the latter one wins.)
        max_diff = 0
        index_of_max_diff = None
        for i in range( len(weighted_lengths) ):
            cur_diff = ( float_lengths[i] - weighted_lengths[i] ) * sign

            if ( cur_diff >= max_diff ):
                max_diff = cur_diff
                index_of_max_diff = i

        ## Increase the just found index by 1.
        weighted_lengths[i] += sign
        diff -= sign

    assert( sum(weighted_lengths) == size )
Mario Hock's avatar
Mario Hock committed
156
157
158
159
160
161
162
163
164
165
166



    ## * split *
    ret = list()
    last_pos = 0
    for pos in weighted_lengths:
        ret.append( text[last_pos:last_pos + pos] )
        last_pos += pos

    return ret
167
168
169
170
171
172
173
174
175
176
177
178
179


def get_sysinfo():
    #uname = os.uname()
    #input_fields = ("sysname", "nodename", "release", "version", "machine")

    output_fields = ("sysname", "hostname", "kernel", "version", "machine")

    ret = dict()
    for out_field, value in zip(output_fields, os.uname()):
        ret[out_field] = value

    return ret
180
181
182
183


def sort_named_tuple(data):
    return sorted( data._asdict().items() , key=operator.itemgetter(1), reverse=True)