blob: af81d5e777b4be78f20ebb759347344e143be681 [file] [log] [blame]
Hyunsun Moon4506e3e2020-10-07 01:27:12 +00001#!/usr/bin/env python3
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -07002
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
Hyunsun Moon4506e3e2020-10-07 01:27:12 +000017import sys
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -070018import os
19import time
20import requests
21import json
22import enum
Hyunsun Moon4506e3e2020-10-07 01:27:12 +000023import logging
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -070024from collections import namedtuple
25from pyadb import ADB
26
27'''
28Check Aether network operational status and report it to
29central monitoring server
30
311) check mobile connctivity after toggling the airplane mode
322) check if ping to 8.8.8.8 works
33'''
34
35CONF = json.loads(
36 open(os.getenv('CONFIG_FILE', "./config.json")).read(),
37 object_hook=lambda d: namedtuple('X', d.keys())(*d.values())
38)
39
Hyunsun Moon4506e3e2020-10-07 01:27:12 +000040logging.basicConfig(
41 filename=CONF.log_file,
42 format='%(asctime)s [%(levelname)s] %(message)s',
43 level=logging.WARN
44)
45
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -070046ADB_GET_COMMANDS = {
47 "apn_mode": "settings get global airplane_mode_on",
48 "lte_state": "dumpsys telephony.registry | grep -m1 mDataConnectionState",
49 "ping_result": "ping -c 3 8.8.8.8&>/dev/null; echo $?"
50}
51ADB_APN_COMMANDS = {
52 "home": "input keyevent 3",
53 "setting": "am start -a android.settings.AIRPLANE_MODE_SETTINGS",
54 "toggle": "input tap " + \
55 CONF.adb.apn_mode_toggle_location.x + " " + \
56 CONF.adb.apn_mode_toggle_location.y
57}
58
59
60class State(enum.Enum):
61 error = "-1"
62 disconnected = "0"
63 connecting = "1"
64 connected = "2"
65
66 @classmethod
67 def has_value(cls, value):
68 return value in cls._value2member_map_
69
70
71edge_status = {
72 'name': CONF.edge_name,
73 'status': {
74 'control_plane': None,
75 'user_plane': 'connected'
76 }
77}
78
79
80def _run_adb_shell(adb, command):
Hyunsun Moon53097ea2020-09-04 17:20:29 -070081 result, error = adb.shell_command(command)
Hyunsun Moon4506e3e2020-10-07 01:27:12 +000082 # error is returned even when succeeded
83 # so ignore error value here
84 if result:
85 logging.debug(result)
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -070086 time.sleep(2)
87 result = result[0] if result is not None else None
88 return True, result
89
90
Hyunsun Moon53097ea2020-09-04 17:20:29 -070091def get_control_plane_state(adb):
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -070092 '''
93 check aether control plane works by toggling airplane mode
94 '''
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -070095 # get the current airplane mode
96 success, result = _run_adb_shell(adb, ADB_GET_COMMANDS['apn_mode'])
97 if not success or result is None:
98 return State.error, result
99 apn_mode_on = True if result == "1" else False
100
101 # toggle the airplane mode
102 for command in ADB_APN_COMMANDS.values():
103 success, result = _run_adb_shell(adb, command)
104 if not success:
105 return State.error, result
106 if not apn_mode_on:
107 success, result = _run_adb_shell(adb, ADB_APN_COMMANDS['toggle'])
108 if not success:
109 return State.error, result
110
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700111 # get connection state
112 state = State.connecting.value
Hyunsun Moona40bda52021-01-21 12:04:43 -0800113 retry_count = 10
114 while retry_count > 0:
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700115 success, result = _run_adb_shell(adb, ADB_GET_COMMANDS['lte_state'])
116 if not success or result is None:
Hyunsun Moona40bda52021-01-21 12:04:43 -0800117 continue
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700118 state = result.split("=")[1]
Hyunsun Moona40bda52021-01-21 12:04:43 -0800119 if state == State.connected.value:
120 break
Hyunsun Moon659f2812021-01-21 13:43:49 -0800121 time.sleep(1)
Hyunsun Moona40bda52021-01-21 12:04:43 -0800122 retry_count -= 1
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700123
124 if not State.has_value(state):
125 return State.error, None
126 return State(state), None
127
128
Hyunsun Moon53097ea2020-09-04 17:20:29 -0700129def get_user_plane_state(adb):
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700130 '''
131 checks aether user plane connectivity with ping to 8.8.8.8
132 '''
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700133 success, result = _run_adb_shell(adb, ADB_GET_COMMANDS['ping_result'])
134 if not success or result is None:
135 return State.error, result
136
137 state = State.connected if result == "0" else State.disconnected
138 return state, None
139
140
141def report_aether_network_state():
142 '''
143 report the aether network state to the monitoring server
144 '''
Hyunsun Moon4506e3e2020-10-07 01:27:12 +0000145 logging.info("Sending report %s", edge_status)
Hyunsun Moon53097ea2020-09-04 17:20:29 -0700146 try:
147 result = requests.post(CONF.report_url, json=edge_status)
148 except requests.exceptions.ConnectionError:
Hyunsun Moon4506e3e2020-10-07 01:27:12 +0000149 logging.error("Failed to report for %s", e)
150 pass
151 try:
152 result.raise_for_status()
153 except requests.exceptions.HTTPError as e:
154 logging.error("Failed to report for %s", e)
Hyunsun Moon53097ea2020-09-04 17:20:29 -0700155 pass
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700156
157
Hyunsun Moon4506e3e2020-10-07 01:27:12 +0000158def main():
Hyunsun Moon53097ea2020-09-04 17:20:29 -0700159 adb = ADB()
160 if adb.set_adb_path(CONF.adb.path) is False:
Hyunsun Moon4506e3e2020-10-07 01:27:12 +0000161 logging.error(CONF.adb.path + " not found")
162 sys.exit(1)
Hyunsun Moon53097ea2020-09-04 17:20:29 -0700163
164 dev = adb.get_devices()
165 if len(dev) == 0:
Hyunsun Moon4506e3e2020-10-07 01:27:12 +0000166 logging.error("No device found")
167 sys.exit(1)
168
Hyunsun Moon53097ea2020-09-04 17:20:29 -0700169 adb.set_target_device(dev[0])
Hyunsun Moon4506e3e2020-10-07 01:27:12 +0000170 success, result = _run_adb_shell(adb, "svc data enable")
171 if not success:
172 logging.error("Failed to turn data on")
173 sys.exit(1)
Hyunsun Moon53097ea2020-09-04 17:20:29 -0700174
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700175 while True:
Hyunsun Moonda22c762021-01-22 13:00:24 -0800176 _run_adb_shell(adb, "svc power stayon true")
Hyunsun Moon53097ea2020-09-04 17:20:29 -0700177 cp_state, err = get_control_plane_state(adb)
178 up_state, err = get_user_plane_state(adb)
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700179
180 edge_status['status']['control_plane'] = cp_state.name
181 edge_status['status']['user_plane'] = up_state.name
182
183 report_aether_network_state()
Hyunsun Moonda22c762021-01-22 13:00:24 -0800184 _run_adb_shell(adb, "svc power stayon false")
185
Hyunsun Moon53097ea2020-09-04 17:20:29 -0700186 time.sleep(CONF.report_interval)
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700187
188
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700189if __name__ == "__main__":
190 main()