blob: f26f5d1526721b3841c35c28d9dd7981e9878fcb [file] [log] [blame]
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -07001#!/usr/bin/env python
2
3# Copyright 2020-present Open Networking Foundation
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License
16
17import os
18import time
19import requests
20import json
21import enum
22import daemon
23from collections import namedtuple
24from pyadb import ADB
25
26'''
27Check Aether network operational status and report it to
28central monitoring server
29
301) check mobile connctivity after toggling the airplane mode
312) check if ping to 8.8.8.8 works
32'''
33
34CONF = json.loads(
35 open(os.getenv('CONFIG_FILE', "./config.json")).read(),
36 object_hook=lambda d: namedtuple('X', d.keys())(*d.values())
37)
38
39ADB_GET_COMMANDS = {
40 "apn_mode": "settings get global airplane_mode_on",
41 "lte_state": "dumpsys telephony.registry | grep -m1 mDataConnectionState",
42 "ping_result": "ping -c 3 8.8.8.8&>/dev/null; echo $?"
43}
44ADB_APN_COMMANDS = {
45 "home": "input keyevent 3",
46 "setting": "am start -a android.settings.AIRPLANE_MODE_SETTINGS",
47 "toggle": "input tap " + \
48 CONF.adb.apn_mode_toggle_location.x + " " + \
49 CONF.adb.apn_mode_toggle_location.y
50}
51
52
53class State(enum.Enum):
54 error = "-1"
55 disconnected = "0"
56 connecting = "1"
57 connected = "2"
58
59 @classmethod
60 def has_value(cls, value):
61 return value in cls._value2member_map_
62
63
64edge_status = {
65 'name': CONF.edge_name,
66 'status': {
67 'control_plane': None,
68 'user_plane': 'connected'
69 }
70}
71
72
73def _run_adb_shell(adb, command):
Hyunsun Moon53097ea2020-09-04 17:20:29 -070074 result, error = adb.shell_command(command)
75 if error is not None:
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -070076 err = "[ERROR]: " + command + " failed"
77 return False, err
78 time.sleep(2)
79 result = result[0] if result is not None else None
80 return True, result
81
82
Hyunsun Moon53097ea2020-09-04 17:20:29 -070083def get_control_plane_state(adb):
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -070084 '''
85 check aether control plane works by toggling airplane mode
86 '''
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -070087 # get the current airplane mode
88 success, result = _run_adb_shell(adb, ADB_GET_COMMANDS['apn_mode'])
89 if not success or result is None:
90 return State.error, result
91 apn_mode_on = True if result == "1" else False
92
93 # toggle the airplane mode
94 for command in ADB_APN_COMMANDS.values():
95 success, result = _run_adb_shell(adb, command)
96 if not success:
97 return State.error, result
98 if not apn_mode_on:
99 success, result = _run_adb_shell(adb, ADB_APN_COMMANDS['toggle'])
100 if not success:
101 return State.error, result
102
103 # additional wait for UE to fully attach
104 time.sleep(3)
105
106 # get connection state
107 state = State.connecting.value
108 while state == State.connecting.value:
109 success, result = _run_adb_shell(adb, ADB_GET_COMMANDS['lte_state'])
110 if not success or result is None:
111 return State.error, result
112 state = result.split("=")[1]
113
114 if not State.has_value(state):
115 return State.error, None
116 return State(state), None
117
118
Hyunsun Moon53097ea2020-09-04 17:20:29 -0700119def get_user_plane_state(adb):
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700120 '''
121 checks aether user plane connectivity with ping to 8.8.8.8
122 '''
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700123 success, result = _run_adb_shell(adb, ADB_GET_COMMANDS['ping_result'])
124 if not success or result is None:
125 return State.error, result
126
127 state = State.connected if result == "0" else State.disconnected
128 return state, None
129
130
131def report_aether_network_state():
132 '''
133 report the aether network state to the monitoring server
134 '''
Hyunsun Moon53097ea2020-09-04 17:20:29 -0700135 try:
136 result = requests.post(CONF.report_url, json=edge_status)
137 except requests.exceptions.ConnectionError:
138 pass
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700139
140
141def run():
Hyunsun Moon53097ea2020-09-04 17:20:29 -0700142 adb = ADB()
143 if adb.set_adb_path(CONF.adb.path) is False:
144 err = "[ERROR]: " + CONF.adb.path + " not found"
145 return State.error, err
146
147 dev = adb.get_devices()
148 if len(dev) == 0:
149 return State.error, "Device not found"
150 adb.set_target_device(dev[0])
151
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700152 while True:
Hyunsun Moon53097ea2020-09-04 17:20:29 -0700153 cp_state, err = get_control_plane_state(adb)
154 up_state, err = get_user_plane_state(adb)
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700155
156 edge_status['status']['control_plane'] = cp_state.name
157 edge_status['status']['user_plane'] = up_state.name
158
159 report_aether_network_state()
Hyunsun Moon53097ea2020-09-04 17:20:29 -0700160 time.sleep(CONF.report_interval)
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700161
162
163def main():
164 with daemon.DaemonContext():
165 run()
166
167
168if __name__ == "__main__":
169 main()