OLD | NEW |
1 import glob, logging, os, re, time | 1 import glob, logging, os, re, time |
2 from autotest_lib.client.bin import utils | 2 from autotest_lib.client.bin import utils |
3 from autotest_lib.client.common_lib import error | 3 from autotest_lib.client.common_lib import error |
4 | 4 |
5 | 5 |
6 class DevStat(object): | 6 class DevStat(object): |
7 """ | 7 """ |
8 Device power status. This class implements generic status initialization | 8 Device power status. This class implements generic status initialization |
9 and parsing routines. | 9 and parsing routines. |
10 """ | 10 """ |
(...skipping 23 matching lines...) Expand all Loading... |
34 return field_type(0) | 34 return field_type(0) |
35 | 35 |
36 | 36 |
37 def read_all_vals(self): | 37 def read_all_vals(self): |
38 for field, prop in self.fields.iteritems(): | 38 for field, prop in self.fields.iteritems(): |
39 if prop[0]: | 39 if prop[0]: |
40 val = self.read_val(prop[0], prop[1]) | 40 val = self.read_val(prop[0], prop[1]) |
41 setattr(self, field, val) | 41 setattr(self, field, val) |
42 | 42 |
43 | 43 |
| 44 class ThermalStat(DevStat): |
| 45 """ |
| 46 Thermal status. |
| 47 |
| 48 Fields: |
| 49 (All temperatures are in millidegrees Celsius.) |
| 50 |
| 51 str enabled: Whether thermal zone is enabled |
| 52 int temp: Current temperature |
| 53 str type: Thermal zone type |
| 54 int num_trip_points: Number of thermal trip points that activate |
| 55 cooling devices |
| 56 int num_points_tripped: Temperature is above this many trip points |
| 57 str trip_point_N_type: Trip point #N's type |
| 58 int trip_point_N_temp: Trip point #N's temperature value |
| 59 int cdevX_trip_point: Trip point o cooling device #X (index) |
| 60 """ |
| 61 |
| 62 MAX_TRIP_POINTS = 20 |
| 63 |
| 64 thermal_fields = { |
| 65 'enabled': ['enabled', str], |
| 66 'temp': ['temp', int], |
| 67 'type': ['type', str], |
| 68 'num_points_tripped': ['', ''] |
| 69 } |
| 70 def __init__(self, path=None): |
| 71 # Browse the thermal folder for trip point fields. |
| 72 self.num_trip_points = 0 |
| 73 |
| 74 thermal_fields = glob.glob(path + '/*') |
| 75 for file in thermal_fields: |
| 76 field = file[len(path + '/'):] |
| 77 if field.find('trip_point') != -1: |
| 78 if field.find('temp'): |
| 79 field_type = int |
| 80 else: |
| 81 field_type = str |
| 82 self.thermal_fields[field] = [field, field_type] |
| 83 |
| 84 # Count the number of trip points. |
| 85 if field.find('_type') != -1: |
| 86 self.num_trip_points += 1 |
| 87 |
| 88 super(ThermalStat, self).__init__(self.thermal_fields, path) |
| 89 self.update() |
| 90 |
| 91 def update(self): |
| 92 if not os.path.exists(self.path): |
| 93 return |
| 94 |
| 95 self.read_all_vals() |
| 96 self.num_points_tripped = 0 |
| 97 |
| 98 for field in self.thermal_fields: |
| 99 if field.find('trip_point_') != -1 and field.find('_temp') != -1 \ |
| 100 and self.temp > self.read_val(field, int): |
| 101 self.num_points_tripped += 1 |
| 102 logging.info('Temperature trip point #' + \ |
| 103 field[len('trip_point_'):field.rfind('_temp')] + \ |
| 104 ' tripped.') |
| 105 |
| 106 |
| 107 |
44 class BatteryStat(DevStat): | 108 class BatteryStat(DevStat): |
45 """ | 109 """ |
46 Battery status. | 110 Battery status. |
47 | 111 |
48 Fields: | 112 Fields: |
49 | 113 |
50 float charge_full: Last full capacity reached [Ah] | 114 float charge_full: Last full capacity reached [Ah] |
51 float charge_full_design: Full capacity by design [Ah] | 115 float charge_full_design: Full capacity by design [Ah] |
52 float charge_now: Remaining charge [Ah] | 116 float charge_now: Remaining charge [Ah] |
53 float current_now: Battery discharge rate [A] | 117 float current_now: Battery discharge rate [A] |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 self.online = self.is_online == 1 | 192 self.online = self.is_online == 1 |
129 | 193 |
130 | 194 |
131 class SysStat(object): | 195 class SysStat(object): |
132 """ | 196 """ |
133 System power status for a given host. | 197 System power status for a given host. |
134 | 198 |
135 Fields: | 199 Fields: |
136 | 200 |
137 battery: A list of BatteryStat objects. | 201 battery: A list of BatteryStat objects. |
138 linepower: A list of LineStat opbjects. | 202 linepower: A list of LineStat objects. |
139 """ | 203 """ |
140 | 204 |
141 def __init__(self): | 205 def __init__(self): |
142 power_supply_path = '/sys/class/power_supply/*' | 206 power_supply_path = '/sys/class/power_supply/*' |
143 self.battery = None | 207 self.battery = None |
144 self.linepower = None | 208 self.linepower = None |
| 209 self.thermal = None |
145 battery_path = None | 210 battery_path = None |
146 linepower_path = None | 211 linepower_path = None |
| 212 thermal_path = '/sys/class/thermal/thermal_zone*' |
| 213 |
147 power_supplies = glob.glob(power_supply_path) | 214 power_supplies = glob.glob(power_supply_path) |
148 for path in power_supplies: | 215 for path in power_supplies: |
149 type_path = os.path.join(path,'type') | 216 type_path = os.path.join(path,'type') |
150 if not os.path.exists(type_path): | 217 if not os.path.exists(type_path): |
151 continue | 218 continue |
152 type = utils.read_one_line(type_path) | 219 type = utils.read_one_line(type_path) |
153 if type == 'Battery': | 220 if type == 'Battery': |
154 battery_path = path | 221 battery_path = path |
155 elif type == 'Mains': | 222 elif type == 'Mains': |
156 linepower_path = path | 223 linepower_path = path |
157 if battery_path and linepower_path: | 224 if battery_path and linepower_path: |
158 self.battery_path = battery_path | 225 self.battery_path = battery_path |
159 self.linepower_path = linepower_path | 226 self.linepower_path = linepower_path |
160 else: | 227 else: |
161 raise error.TestError('Battery or Linepower path not found') | 228 raise error.TestError('Battery or Linepower path not found') |
| 229 self.thermal_path = glob.glob(thermal_path)[0] |
162 | 230 |
| 231 self.min_temp = 999999999 |
| 232 self.max_temp = -999999999 |
| 233 self.temp_log = {} |
163 | 234 |
164 def refresh(self): | 235 def refresh(self): |
165 """ | 236 """ |
166 Initialize device power status objects for a single battery and a | 237 Initialize device power status objects for a single battery and a |
167 single power line by parsing the output of devkit-power -d. | 238 single power line by parsing the output of devkit-power -d. |
168 """ | 239 """ |
169 self.battery = [ BatteryStat(self.battery_path) ] | 240 self.battery = [ BatteryStat(self.battery_path) ] |
170 self.linepower = [ LineStat(self.linepower_path) ] | 241 self.linepower = [ LineStat(self.linepower_path) ] |
| 242 self.thermal = [ ThermalStat(self.thermal_path) ] |
| 243 |
| 244 try: |
| 245 if self.thermal[0].temp < self.min_temp * 1000: |
| 246 self.min_temp = float(self.thermal[0].temp) / 1000 |
| 247 if self.thermal[0].temp > self.max_temp * 1000: |
| 248 self.max_temp = float(self.thermal[0].temp) / 1000 |
| 249 logging.info('Temperature reading: ' + self.thermal[0].temp) |
| 250 except: |
| 251 logging.error('Could not read temperature, skipping.') |
171 | 252 |
172 | 253 |
173 def get_status(): | 254 def get_status(): |
174 """ | 255 """ |
175 Return a new power status object (SysStat). A new power status snapshot | 256 Return a new power status object (SysStat). A new power status snapshot |
176 for a given host can be obtained by either calling this routine again and | 257 for a given host can be obtained by either calling this routine again and |
177 constructing a new SysStat object, or by using the refresh method of the | 258 constructing a new SysStat object, or by using the refresh method of the |
178 SysStat object. | 259 SysStat object. |
179 """ | 260 """ |
180 status = SysStat() | 261 status = SysStat() |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
389 | 470 |
390 active = int(utils.read_file(active_duration_path)) | 471 active = int(utils.read_file(active_duration_path)) |
391 connected = int(utils.read_file(connected_duration_path)) | 472 connected = int(utils.read_file(connected_duration_path)) |
392 logging.debug('device %s active for %.2f%%', | 473 logging.debug('device %s active for %.2f%%', |
393 path, active * 100.0 / connected) | 474 path, active * 100.0 / connected) |
394 | 475 |
395 total_active += active | 476 total_active += active |
396 total_connected += connected | 477 total_connected += connected |
397 | 478 |
398 return total_active, total_connected | 479 return total_active, total_connected |
OLD | NEW |