forked from saltstack/salt
/
adb.py
135 lines (103 loc) · 4.44 KB
/
adb.py
1
2
3
4
5
6
7
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# -*- coding: utf-8 -*-
'''
Beacon to emit adb device state changes for Android devices
.. versionadded:: 2016.3.0
'''
# Import Python libs
from __future__ import absolute_import
import logging
# Salt libs
import salt.utils
log = logging.getLogger(__name__)
__virtualname__ = 'adb'
last_state = {}
last_state_extra = {'value': False, 'no_devices': False}
def __virtual__():
which_result = salt.utils.which('adb')
if which_result is None:
return False
else:
return __virtualname__
def __validate__(config):
'''
Validate the beacon configuration
'''
# Configuration for adb beacon should be a dictionary with states array
if not isinstance(config, dict):
log.info('Configuration for adb beacon must be a dict.')
return False, ('Configuration for adb beacon must be a dict.')
elif 'states' not in config.keys():
log.info('Configuration for adb beacon must include a states array.')
return False, ('Configuration for adb beacon must include a states array.')
else:
states = ['offline', 'bootloader', 'device', 'host', 'recovery', 'no permissions',
'sideload', 'unauthorized', 'unknown', 'missing']
if any(s not in states for s in config['states']):
log.info('Need a one of the following adb '
'states: {0}'.format(', '.join(states)))
return False, ('Need a one of the following adb '
'states: {0}'.format(', '.join(states)))
return True, 'Valid beacon configuration'
def beacon(config):
'''
Emit the status of all devices returned by adb
Specify the device states that should emit an event,
there will be an event for each device with the
event type and device specified.
.. code-block:: yaml
beacons:
adb:
- states:
- offline
- unauthorized
- missing
- no_devices_event: True
- battery_low: 25
'''
log.trace('adb beacon starting')
ret = []
_validate = __validate__(config)
if not _validate[0]:
return ret
out = __salt__['cmd.run']('adb devices', runas=config.get('user', None))
lines = out.split('\n')[1:]
last_state_devices = list(last_state.keys())
found_devices = []
for line in lines:
try:
device, state = line.split('\t')
found_devices.append(device)
if device not in last_state_devices or \
('state' in last_state[device] and last_state[device]['state'] != state):
if state in config['states']:
ret.append({'device': device, 'state': state, 'tag': state})
last_state[device] = {'state': state}
if 'battery_low' in config:
val = last_state.get(device, {})
cmd = 'adb -s {0} shell cat /sys/class/power_supply/*/capacity'.format(device)
battery_levels = __salt__['cmd.run'](cmd, runas=config.get('user', None)).split('\n')
for l in battery_levels:
battery_level = int(l)
if 0 < battery_level < 100:
if 'battery' not in val or battery_level != val['battery']:
if ('battery' not in val or val['battery'] > config['battery_low']) and \
battery_level <= config['battery_low']:
ret.append({'device': device, 'battery_level': battery_level, 'tag': 'battery_low'})
if device not in last_state:
last_state[device] = {}
last_state[device].update({'battery': battery_level})
except ValueError:
continue
# Find missing devices and remove them / send an event
for device in last_state_devices:
if device not in found_devices:
if 'missing' in config['states']:
ret.append({'device': device, 'state': 'missing', 'tag': 'missing'})
del last_state[device]
# Maybe send an event if we don't have any devices
if 'no_devices_event' in config and config['no_devices_event'] is True:
if len(found_devices) == 0 and not last_state_extra['no_devices']:
ret.append({'tag': 'no_devices'})
# Did we have no devices listed this time around?
last_state_extra['no_devices'] = len(found_devices) == 0
return ret