blob: bcfd5b5d278112297ed09ce4f5847e7956e904fe [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):
74 result = adb.shell_command(command)
75 if adb.lastFailed():
76 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
83def get_control_plane_state():
84 '''
85 check aether control plane works by toggling airplane mode
86 '''
87 adb = ADB()
88 if adb.set_adb_path(CONF.adb.path) is False:
89 err = "[ERROR]: " + CONF.adb.path + " not found"
90 return State.error, err
91
92 # get the current airplane mode
93 success, result = _run_adb_shell(adb, ADB_GET_COMMANDS['apn_mode'])
94 if not success or result is None:
95 return State.error, result
96 apn_mode_on = True if result == "1" else False
97
98 # toggle the airplane mode
99 for command in ADB_APN_COMMANDS.values():
100 success, result = _run_adb_shell(adb, command)
101 if not success:
102 return State.error, result
103 if not apn_mode_on:
104 success, result = _run_adb_shell(adb, ADB_APN_COMMANDS['toggle'])
105 if not success:
106 return State.error, result
107
108 # additional wait for UE to fully attach
109 time.sleep(3)
110
111 # get connection state
112 state = State.connecting.value
113 while state == State.connecting.value:
114 success, result = _run_adb_shell(adb, ADB_GET_COMMANDS['lte_state'])
115 if not success or result is None:
116 return State.error, result
117 state = result.split("=")[1]
118
119 if not State.has_value(state):
120 return State.error, None
121 return State(state), None
122
123
124def get_user_plane_state():
125 '''
126 checks aether user plane connectivity with ping to 8.8.8.8
127 '''
128 adb = ADB()
129 if adb.set_adb_path(CONF.adb.path) is False:
130 err = "[ERROR]: " + CONF.adb.path + " not found"
131 return State.error, err
132
133 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 '''
145 response = requests.post(CONF.report_url, json=edge_status)
146 return requests.codes.ok,
147 if response == requests.codes.ok:
148 print("[INFO]: reported the status")
149 else:
150 response.raise_for_status()
151
152
153def run():
154 while True:
155 cp_state, err = get_control_plane_state()
156 up_state, err = get_user_plane_state()
157
158 edge_status['status']['control_plane'] = cp_state.name
159 edge_status['status']['user_plane'] = up_state.name
160
161 report_aether_network_state()
162 time.sleep(600)
163
164
165def main():
166 with daemon.DaemonContext():
167 run()
168
169
170if __name__ == "__main__":
171 main()