blob: 8e06e6582998a2ffe79f1119d974184873e8fbdf [file] [log] [blame]
#! /usr/bin/python
# Copyright 2016 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Chimera craft UI. Code lifted from catawampus diag and tech UI."""
__author__ = 'edjames@google.com (Ed James)'
import getopt
import json
import os
import sys
import urllib2
import tornado.ioloop
import tornado.web
class CraftUI(object):
"""A web server that configures and displays Chimera data."""
def __init__(self, wwwroot, port, sim):
"""initialize."""
self.wwwroot = wwwroot
self.port = port
self.sim = sim
self.data = {}
self.data['refreshCount'] = 0
def ReadFile(self, filepath):
text = ''
try:
with open(filepath) as fd:
text = fd.read().rstrip()
except IOError as e:
text = 'ReadFile failed: %s: %s' % (filepath, e.strerror)
return text
def GetData(self):
"""Get system data, return a json string."""
pj = self.GetPlatformData()
mj = self.GetModemData()
rj = self.GetRadioData()
js = '{"platform":' + pj + ',"modem":' + mj + ',"radio":' + rj + '}'
return js
def GetPlatformData(self):
"""Get platform data, return a json string."""
data = self.data
sim = self.sim
if data['refreshCount'] == 0:
data['version'] = self.ReadFile(sim + '/etc/version')
data['platform'] = self.ReadFile(sim + '/etc/platform')
data['softwaredate'] = self.ReadFile(sim + '/etc/softwaredate')
data['refreshCount'] += 1
data['uptime'] = self.ReadFile(sim + '/proc/uptime')
data['ledstate'] = self.ReadFile(sim + '/tmp/gpio/ledstate')
cs = '/config/settings/'
data['craft_ipaddr'] = self.ReadFile(sim + cs + 'craft_ipaddr')
data['local_ipaddr'] = self.ReadFile(sim + cs + 'local_ipaddr')
data['peer_ipaddr'] = self.ReadFile(sim + cs + 'peer_ipaddr')
data['vlan_inband'] = self.ReadFile(sim + cs + 'vlan_inband')
data['vlan_peer'] = self.ReadFile(sim + cs + 'vlan_peer')
return json.dumps(data)
def GetModemData(self):
"""Get modem data, return a json string."""
response = '{}'
if self.sim:
response = self.ReadFile(self.sim + '/tmp/glaukus/modem.json')
else:
try:
url = 'http://localhost:8080/api/modem'
handle = urllib2.urlopen(url, timeout=2)
response = handle.read()
except urllib2.URLError as ex:
print 'Connection to %s failed: %s' % (url, ex.reason)
return response
def GetRadioData(self):
"""Get radio data, return a json string."""
response = '{}'
if self.sim:
response = self.ReadFile(self.sim + '/tmp/glaukus/radio.json')
else:
try:
url = 'http://localhost:8080/api/radio'
handle = urllib2.urlopen(url, timeout=2)
response = handle.read()
except urllib2.URLError as ex:
print 'Connection to %s failed: %s' % (url, ex.reason)
return response
class MainHandler(tornado.web.RequestHandler):
"""Displays the UI."""
def get(self):
ui = self.settings['ui']
print 'GET craft HTML page'
self.render(ui.wwwroot + '/index.thtml', peerurl='http://TODO')
class RestartHandler(tornado.web.RequestHandler):
"""Restart the box."""
def get(self):
print 'displaying restart interstitial screen'
self.render('restarting.html')
def post(self):
print 'user requested restart'
self.redirect('/restart')
os.system('(sleep 5; reboot) &')
class JsonHandler(tornado.web.RequestHandler):
"""Provides JSON-formatted content to be displayed in the UI."""
@tornado.web.asynchronous
def get(self):
ui = self.settings['ui']
print 'GET JSON data for craft page'
jsonstring = ui.GetData()
self.set_header('Content-Type', 'application/json')
self.write(jsonstring)
self.finish()
def RunUI(self):
"""Create the web server and run forever."""
handlers = [
(r'/', CraftUI.MainHandler),
(r'/content.json', CraftUI.JsonHandler),
(r'/restart', CraftUI.RestartHandler),
(r'/static/([^/]*)$', tornado.web.StaticFileHandler,
{'path': self.wwwroot + '/static'}),
]
app = tornado.web.Application(handlers)
app.settings['ui'] = self
app.listen(self.port)
ioloop = tornado.ioloop.IOLoop.instance()
ioloop.start()
def Usage():
"""Show usage."""
print 'Usage: % [-p)ort 80] [-d)ir web] [-s)im top]'
print '\tUse -s to provide an alternate rootfs'
def main():
www = '/usr/craftui/www'
port = 80
sim = ''
try:
opts, args = getopt.getopt(sys.argv[1:], 's:p:w:',
['sim=', 'port=', 'www='])
except getopt.GetoptError as err:
# print help information and exit:
print str(err)
Usage()
sys.exit(1)
for o, a in opts:
if o in ('-s', '--sim'):
sim = a
elif o in ('-p', '--port'):
port = int(a)
elif o in ('-w', '--www'):
www = a
else:
assert False, 'unhandled option'
Usage()
sys.exit(1)
if args:
assert False, 'extra args'
Usage()
sys.exit(1)
craftui = CraftUI(www, port, sim)
craftui.RunUI()
if __name__ == '__main__':
main()