Esempio n. 1
0
    def __init__(self, scheduler, config):
        self.scheduler = scheduler
        self.config = config
        self.photo_capture = PhotoCapture(config["imagepath"])

        self.host = socket.gethostname()
        self.ip_address = socket.gethostbyname(self.host)

        # set up the routes manually
        bottle.route('/static/<filepath:path>', method='GET')(self.static)
        bottle.route('/', method='GET')(self.index)
        bottle.route('/meerkat/', method='GET')(self.meerkat)
        bottle.route('/meerkat/heartbeat.json', method='GET')(self.register_control_json)
        bottle.route('/meerkat/info.json', method='GET')(self.info_json)
        bottle.route('/meerkat/master.json', method='GET')(self.master_json)
        bottle.route('/meerkat/master.json', method='POST')(self.master_control_json)
        bottle.route('/meerkat/register.json', method='POST')(self.register_control_json)
        bottle.route('/meerkat/capture.json', method='POST')(self.capture_control_json)
        bottle.route('/meerkat/probes.json', method='GET')(self.probes_json)
        bottle.route('/meerkat/probe<p:int>.json', method='GET')(self.probe_json)
        bottle.route('/meerkat/probe<p:int>.json', method='POST')(self.probe_control_json)
        bottle.route('/meerkat/log.json', method='GET')(self.log_json)
Esempio n. 2
0
class HttpServer(object):
    def __init__(self, scheduler, config):
        self.scheduler = scheduler
        self.config = config
        self.photo_capture = PhotoCapture(config["imagepath"])

        self.host = socket.gethostname()
        self.ip_address = socket.gethostbyname(self.host)

        # set up the routes manually
        bottle.route('/static/<filepath:path>', method='GET')(self.static)
        bottle.route('/', method='GET')(self.index)
        bottle.route('/meerkat/', method='GET')(self.meerkat)
        bottle.route('/meerkat/heartbeat.json', method='GET')(self.register_control_json)
        bottle.route('/meerkat/info.json', method='GET')(self.info_json)
        bottle.route('/meerkat/master.json', method='GET')(self.master_json)
        bottle.route('/meerkat/master.json', method='POST')(self.master_control_json)
        bottle.route('/meerkat/register.json', method='POST')(self.register_control_json)
        bottle.route('/meerkat/capture.json', method='POST')(self.capture_control_json)
        bottle.route('/meerkat/probes.json', method='GET')(self.probes_json)
        bottle.route('/meerkat/probe<p:int>.json', method='GET')(self.probe_json)
        bottle.route('/meerkat/probe<p:int>.json', method='POST')(self.probe_control_json)
        bottle.route('/meerkat/log.json', method='GET')(self.log_json)


    def start(self):
        self.http_thread = Thread(target=bottle.run,
                                  kwargs=dict(host=self.config['http_host'], port=self.config['http_port'], server='wsgiref', debug=False, quiet=True),
                                  name='http-thread')
        self.http_thread.setDaemon(True)
        self.http_thread.start()
        logging.info("Http server started on port %s." % self.config["http_port"])


    def index(self):
        redirect('/meerkat/')


    def meerkat(self):
        return template('index', scheduler=self.scheduler)


    def probes_json(self):
        probes = []
        i = 0
        for p in self.scheduler.probes:
            probes.append(self.helper_get_probe_struct(p))
            i = i + 1

        ret = {"status": "OK",
                "body": {
                    "probes": probes
                }
              }
        response.set_header('Cache-Control', 'No-store')
        return json.dumps(ret)


    def probe_json(self, p):
        ret = {"status": "OK",
                "body": self.helper_get_probe_struct(self.scheduler.probes[p])
              }
        response.set_header('Cache-Control', 'No-store')
        return json.dumps(ret)


    def probe_control_json(self, p):
        command = request.forms.command
        if command == 'ON':
            self.scheduler.start_probe(p)
            #self.scheduler.queue.put( (COMMAND_EXEC, 'start_probe', p) )
        elif command == 'OFF':
            self.scheduler.stop_probe(p)
            #self.scheduler.queue.put( (COMMAND_EXEC, 'stop_probe', p) )

        time.sleep(0.5)
        response.set_header('Cache-Control', 'No-store')
        return self.probe_json(p)


    def info_json(self):
        probes = []
        i = 0
        for p in self.scheduler.probes:
            probes.append(self.helper_get_probe_struct(p))
            i = i + 1

        ret = {"status": "OK",
                "body": {
                    "id": None,
                    "info": self.helper_get_master_struct(),
                    "probes": probes
                }
              }
        ret["body"]["id"] = ret["body"]["info"]["host"]

        response.set_header('Cache-Control', 'No-store')
        return json.dumps(ret)


    def master_json(self):
        ret = {"status": "OK",
                "body": self.helper_get_master_struct()
        }

        response.set_header('Cache-Control', 'No-store')
        return json.dumps(ret)

    
    def master_control_json(self):
        command = request.forms.command
        if command == 'ON':
            self.scheduler.start_probes()
            #self.scheduler.queue.put( (COMMAND_EXEC, 'start_probes') )
        elif command == 'OFF':
            self.scheduler.stop_probes()
            #self.scheduler.queue.put( (COMMAND_EXEC, 'stop_probes') )

        time.sleep(1)
        response.set_header('Cache-Control', 'No-store')
        return self.master_json()

    
    def register_control_json(self):
        ret = {"status": "OK",
                "body": ""
              }
        try:
            r = requests.post(self.config["mission_control"]["register_url"], data=self.info_json())
            ret = r.text
        except Exception as ex:
            ret["status"] = "ERROR"
            ret["body"] = str(ex)

        response.set_header('Cache-Control', 'No-store')
        return json.dumps(ret)

    
    def capture_control_json(self):
        ret = {"status": "OK",
                "body": None
              }
        try:
            ret["body"] = self.photo_capture.capture()
        except Exception as ex:
            ret["status"] = "ERROR"
            ret["body"] = str(ex)

        response.set_header('Cache-Control', 'No-store')
        return json.dumps(ret)


    def log_json(self):
        lines = request.query.n or 10
        stdin,stdout = os.popen2("tail -n %s %s" % (lines, self.config['logfile']))
        stdin.close()
        log = stdout.readlines()
        stdout.close()

        ret = {"status": "OK",
               "body": {
                    "log": log,
                }
              }

        response.set_header('Cache-Control', 'No-store')
        return json.dumps(ret)  


    def static(self, filepath):
        if 'latest' in filepath:
            response.set_header('Cache-Control', 'No-store')

        return static_file(filepath, root=STATIC_ROOT)


    ######### HELPERS ########################################################
    def helper_get_probe_data(self, probe):
        ret = []
        records = 1
        storage = Storage(self.config["datafile"])
        for r in storage.get_records_by_probe_id(probe.id, records):
            record = {
                "metadata": {
                    "probe_id": r[0],
                    "timestamp": r[2],
                    "length": r[3],
                },
                "data": str(r[4]).encode('utf-8')
            }
            if (record["data"].startswith('{') or record["data"].startswith('[')):
                try:
                    record["data"] = json.loads(record["data"])
                    if type(record["data"]) == dict:
                        record["data"] = [record["data"]]
                except:
                    pass

            ret.append(record)

        storage.close()
        return ret


    def helper_get_probe_filters(self, filters):
        ret = []
        for f in filters:
            ret.append(f.id)
        return ret


    def helper_get_probe_struct(self, probe):
        ret = {
            "id": "probe%s" % probe.index,
            "index": probe.index,
            "label": probe.id,
            "status": "OFF",
            "command": ' '.join(probe.command),
            "data": self.helper_get_probe_data(probe),
            "filters": self.helper_get_probe_filters(probe.filters),
            "error_filters": self.helper_get_probe_filters(probe.error_filters),
            "interval": probe.interval,
            "duration": probe.duration,
            "dummy": probe.dummy,
            "last_error": probe.last_error
        }
        if probe.running:
            ret["status"] = "ON"

        return ret


    def helper_get_master_struct(self):
        ret = {
            "timestamp": time.time() * 1000,
            "status": "OFF",
            "ip_address": self.ip_address,
            "net_interfaces": self.helper_get_net_interfaces(),
            "host": self.host,
            "heartbeat_url": "https://%s/meerkat/heartbeat.json" % (self.host),
            "info_url": "https://%s/meerkat/info.json" % (self.host),
            "dashboard_url": "https://%s/meerkat/" % (self.host),
            "latest_img_url": "https://%s/static/img/latest.jpg?%s" % (self.host, time.time()),
            "uptime_secs": self.helper_get_uptime_secs(),
            "load_average": self.helper_get_load_average(),
            "sys_temperature": self.helper_get_sys_temperature(),
            "gpu_temperature": self.helper_get_gpu_temperature(),
            "data_size_kb": self.helper_get_data_size_kb(),
            "free_space_b": self.helper_get_free_space(),
            "has_camera": self.config["has_camera"],
            "available_memory_kb": 0,
            "free_memory_kb": 0,
            "mission_control_url": self.config['mission_control']['url'],
            "mission_control_register_url": self.config['mission_control']['register_url']
        }

        if self.scheduler.active:
            ret["status"] = "ON"

        available_mem, free_mem = self.helper_get_memory_info()
        ret["available_memory_kb"] = available_mem
        ret["free_memory_kb"] = free_mem

        return ret

    def helper_get_free_space(self):
        # TODO: should this be the where the data file is, not just '/'?
        stat = os.statvfs('/')
        return stat.f_bsize * stat.f_bavail


    def helper_get_net_interfaces(self):
        net_interfaces = '?'
        cmd = 'ifconfig -s -a | sed 1d | cut -d " " -f1 | tr "\\\\n" ,'
        try:
            net_interfaces = check_output(cmd, shell=True).split(',')
            net_interfaces.pop()
            net_interfaces.pop()
        except IOError:
            pass

        return net_interfaces


    def helper_get_uptime_secs(self):
        uptime = '?'
        try:
            with open('/proc/uptime', 'r') as f:
                secs = f.readline()

            uptime = float(secs.split()[0])
        except IOError:
            pass

        return uptime


    def helper_get_gpu_temperature(self):
        gpu_temperature = '?'
        cmd = '/opt/vc/bin/vcgencmd measure_temp | egrep "[0-9.]{4,}" -o'
        try:
            gpu_temperature = check_output(cmd, shell=True)
        except IOError:
            pass

        return float(gpu_temperature)


    def helper_get_sys_temperature(self):
        sys_temperature = '?'
        try:
            with open('/sys/class/thermal/thermal_zone0/temp', 'r') as f:
                sys_temperature = f.readline()

            sys_temperature = float(sys_temperature) / 1000
        except IOError:
            pass

        return sys_temperature


    def helper_get_load_average(self):
        load_average = '?'
        try:
            with open('/proc/loadavg', 'r') as f:
                loadavg = f.readline()

            loadavg = loadavg.split(' ')
            loadavg = loadavg[:-2]
        except IOError:
            pass

        return loadavg


    def helper_get_memory_info(self):
        meminfo = ('?', '?')
        try:
            with open('/proc/meminfo', 'r') as f:
                available_mem = f.readline()
                free_mem = f.readline()

            meminfo = (int(available_mem.split()[1]), int(free_mem.split()[1]))
        except IOError:
            pass

        return meminfo


    def helper_get_data_size_kb(self):
        bytes = os.path.getsize(self.config['datafile'])
        return bytes / 1024