d4-core/server/lib/Sensor.py

276 lines
10 KiB
Python
Executable File

#!/usr/bin/env python3
# -*-coding:UTF-8 -*
import os
import sys
import time
import uuid
import redis
from flask import escape
sys.path.append(os.path.join(os.environ['D4_HOME'], 'lib/'))
import ConfigLoader
import d4_server
### Config ###
config_loader = ConfigLoader.ConfigLoader()
r_serv_db = config_loader.get_redis_conn("Redis_METADATA")
config_loader = None
### ###
def is_valid_uuid_v4(UUID):
UUID = UUID.replace('-', '')
try:
uuid_test = uuid.UUID(hex=UUID, version=4)
return uuid_test.hex == UUID
except:
return False
def get_time_sensor_last_seen(sensor_uuid):
res = r_serv_db.hget('metadata_uuid:{}'.format(sensor_uuid), 'last_seen')
if res:
return int(res)
else:
return 0
def _get_sensor_type(sensor_uuid, first_seen=True, last_seen=True, time_format='default'):
uuid_type = []
uuid_all_type = r_serv_db.smembers('all_types_by_uuid:{}'.format(sensor_uuid))
for type in uuid_all_type:
type_meta = {}
type_meta['type'] = type
if first_seen:
type_meta['first_seen'] = r_serv_db.hget('metadata_type_by_uuid:{}:{}'.format(sensor_uuid, type), 'first_seen')
if last_seen:
type_meta['last_seen'] = r_serv_db.hget('metadata_type_by_uuid:{}:{}'.format(sensor_uuid, type), 'last_seen')
# time format
if time_format=='gmt':
if type_meta['first_seen']:
type_meta['first_seen'] = datetime.datetime.fromtimestamp(float(type_meta['first_seen'])).strftime('%Y-%m-%d %H:%M:%S')
if type_meta['last_seen']:
type_meta['last_seen'] = datetime.datetime.fromtimestamp(float(type_meta['last_seen'])).strftime('%Y-%m-%d %H:%M:%S')
uuid_type.append(type_meta)
return uuid_type
def _get_sensor_metadata(sensor_uuid, first_seen=True, last_seen=True, time_format='default', sensor_types=False, mail=True, description=True):
meta_sensor = {}
meta_sensor['uuid'] = sensor_uuid
if first_seen:
meta_sensor['first_seen'] = r_serv_db.hget('metadata_uuid:{}'.format(sensor_uuid), 'first_seen')
if last_seen:
meta_sensor['last_seen'] = r_serv_db.hget('metadata_uuid:{}'.format(sensor_uuid), 'last_seen')
# time format
if time_format=='gmt':
if meta_sensor['first_seen']:
meta_sensor['first_seen'] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(int(meta_sensor['first_seen'])))
if meta_sensor['last_seen']:
meta_sensor['last_seen'] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(int(meta_sensor['last_seen'])))
if sensor_types:
meta_sensor['types'] = _get_sensor_type(sensor_uuid, first_seen=False, last_seen=False)
if description:
meta_sensor['description'] = r_serv_db.hget('metadata_uuid:{}'.format(sensor_uuid), 'description')
if mail:
meta_sensor['mail'] = r_serv_db.hget('metadata_uuid:{}'.format(sensor_uuid), 'user_mail')
return meta_sensor
### BEGIN - SENSOR REGISTRATION ###
## TODO: add description
def register_sensor(req_dict):
sensor_uuid = req_dict.get('uuid', None)
hmac_key = req_dict.get('hmac_key', None)
user_id = req_dict.get('mail', None)
third_party = req_dict.get('third_party', None)
# verify uuid
if not is_valid_uuid_v4(sensor_uuid):
return ({"status": "error", "reason": "Invalid uuid"}, 400)
sensor_uuid = sensor_uuid.replace('-', '')
# sensor already exist
if r_serv_db.exists('metadata_uuid:{}'.format(sensor_uuid)):
return ({"status": "error", "reason": "Sensor already registered"}, 409)
# hmac key
if not hmac_key:
return ({"status": "error", "reason": "Mandatory parameter(s) not provided"}, 400)
else:
hmac_key = escape(hmac_key)
if len(hmac_key)>100:
hmac_key=hmac_key[:100]
if third_party:
third_party = True
res = _register_sensor(sensor_uuid, hmac_key, user_id=user_id, third_party=third_party, description=None)
return res
def _register_sensor(sensor_uuid, secret_key, user_id=None, third_party=False, description=None):
r_serv_db.hset('metadata_uuid:{}'.format(sensor_uuid), 'hmac_key', secret_key)
if user_id:
r_serv_db.hset('metadata_uuid:{}'.format(sensor_uuid), 'user_mail', user_id)
if description:
r_serv_db.hset('metadata_uuid:{}'.format(sensor_uuid), 'description', description)
if third_party:
r_serv_db.hset('metadata_uuid:{}'.format(sensor_uuid), 'third_party', True)
r_serv_db.sadd('sensor_pending_registration', sensor_uuid)
return ({'uuid': sensor_uuid}, 200)
def get_pending_sensor():
return list(r_serv_db.smembers('sensor_pending_registration'))
def get_nb_pending_sensor():
return r_serv_db.scard('sensor_pending_registration')
def get_nb_registered_sensors():
return r_serv_db.scard('registered_uuid')
def get_registered_sensors():
return list(r_serv_db.smembers('registered_uuid'))
def approve_sensor(req_dict):
sensor_uuid = req_dict.get('uuid', None)
if not is_valid_uuid_v4(sensor_uuid):
return ({"status": "error", "reason": "Invalid uuid"}, 400)
sensor_uuid = sensor_uuid.replace('-', '')
# sensor not registred
#if r_serv_db.sismember('sensor_pending_registration', sensor_uuid):
# return ({"status": "error", "reason": "Sensor not registred"}, 404)
# sensor already approved
if r_serv_db.sismember('registered_uuid', sensor_uuid):
return ({"status": "error", "reason": "Sensor already approved"}, 409)
return _approve_sensor(sensor_uuid)
def _approve_sensor(sensor_uuid):
r_serv_db.sadd('registered_uuid', sensor_uuid)
r_serv_db.srem('sensor_pending_registration', sensor_uuid)
return ({'uuid': sensor_uuid}, 200)
def delete_pending_sensor(req_dict):
sensor_uuid = req_dict.get('uuid', None)
if not is_valid_uuid_v4(sensor_uuid):
return ({"status": "error", "reason": "Invalid uuid"}, 400)
sensor_uuid = sensor_uuid.replace('-', '')
# sensor not registred
#if r_serv_db.sismember('sensor_pending_registration', sensor_uuid):
# return ({"status": "error", "reason": "Sensor not registred"}, 404)
# sensor already approved
if not r_serv_db.sismember('sensor_pending_registration', sensor_uuid):
return ({"status": "error", "reason": "Not Pending Sensor"}, 409)
return _delete_pending_sensor(sensor_uuid)
def _delete_pending_sensor(sensor_uuid):
r_serv_db.srem('sensor_pending_registration', sensor_uuid)
return ({'uuid': sensor_uuid}, 200)
def delete_registered_sensor(req_dict):
sensor_uuid = req_dict.get('uuid', None)
if not is_valid_uuid_v4(sensor_uuid):
return ({"status": "error", "reason": "Invalid uuid"}, 400)
sensor_uuid = sensor_uuid.replace('-', '')
# sensor not registred
if not r_serv_db.sismember('registered_uuid', sensor_uuid):
return ({"status": "error", "reason": "Sensor not registered"}, 404)
return _delete_registered_sensor(sensor_uuid)
def _delete_registered_sensor(sensor_uuid):
r_serv_db.srem('registered_uuid', sensor_uuid)
return ({'uuid': sensor_uuid}, 200)
### --- END - SENSOR REGISTRATION --- ###
### BEGIN - SENSOR MONITORING ###
def get_sensors_monitoring_last_updated():
res = r_serv_db.get('sensors_monitoring:last_updated')
if res:
return int(res)
else:
return 0
def get_all_sensors_to_monitor():
return r_serv_db.smembers('to_monitor:sensors')
def get_to_monitor_delta_time_by_uuid(sensor_uuid):
return int(r_serv_db.hget('to_monitor:sensor:{}'.format(sensor_uuid), 'delta_time'))
def get_all_sensors_to_monitor_dict():
dict_to_monitor = {}
for sensor_uuid in get_all_sensors_to_monitor():
dict_to_monitor[sensor_uuid] = get_to_monitor_delta_time_by_uuid(sensor_uuid)
return dict_to_monitor
def _check_sensor_delta(sensor_uuid, sensor_delta):
last_d4_packet = get_time_sensor_last_seen(sensor_uuid)
# check sensor delta time between two D4 packets + check sensor connection
if int(time.time()) - last_d4_packet > sensor_delta or not d4_server.is_sensor_connected(sensor_uuid):
r_serv_db.sadd('sensors_monitoring:sensors_error', sensor_uuid)
handle_sensor_monitoring_error(sensor_uuid)
else:
r_serv_db.srem('sensors_monitoring:sensors_error', sensor_uuid)
def handle_sensor_monitoring_error(sensor_uuid):
print('sensor monitoring error: {}'.format(sensor_uuid))
## TODO: ##
# MAILS
# UI Notifications
# SNMP
# Syslog message
## ## ## ##
return None
def is_sensor_monitored(sensor_uuid):
return r_serv_db.sismember('to_monitor:sensors', sensor_uuid)
def get_all_sensors_connection_errors():
return r_serv_db.smembers('sensors_monitoring:sensors_error')
def api_get_all_sensors_connection_errors():
return list(get_all_sensors_connection_errors()), 200
def add_sensor_to_monitor(sensor_uuid, delta_time):
r_serv_db.sadd('to_monitor:sensors', sensor_uuid)
r_serv_db.hset('to_monitor:sensor:{}'.format(sensor_uuid), 'delta_time', delta_time)
r_serv_db.set('sensors_monitoring:last_updated', int(time.time()))
r_serv_db.srem('sensors_monitoring:sensors_error', sensor_uuid)
def delete_sensor_to_monitor(sensor_uuid):
r_serv_db.srem('to_monitor:sensors', sensor_uuid)
r_serv_db.delete('to_monitor:sensor:{}'.format(sensor_uuid))
r_serv_db.set('sensors_monitoring:last_updated', int(time.time()))
r_serv_db.srem('sensors_monitoring:sensors_error', sensor_uuid)
def api_add_sensor_to_monitor(data_dict):
sensor_uuid = data_dict.get('uuid', None)
delta_time = data_dict.get('delta_time', None)
if not is_valid_uuid_v4(sensor_uuid):
return ({"status": "error", "reason": "Invalid uuid"}, 400)
sensor_uuid = sensor_uuid.replace('-', '')
# hmac key
if not delta_time:
return ({"status": "error", "reason": "Mandatory parameter(s) not provided"}, 400)
else:
try:
delta_time = int(delta_time)
if delta_time < 1:
return ({"status": "error", "reason": "Invalid delta_time"}, 400)
except Exception:
return ({"status": "error", "reason": "Invalid delta_time"}, 400)
add_sensor_to_monitor(sensor_uuid, delta_time)
def api_delete_sensor_to_monitor(data_dict):
sensor_uuid = data_dict.get('uuid', None)
if not is_valid_uuid_v4(sensor_uuid):
return ({"status": "error", "reason": "Invalid uuid"}, 400)
sensor_uuid = sensor_uuid.replace('-', '')
if not is_sensor_monitored(sensor_uuid):
return ({"status": "error", "reason": "Sensor not monitored"}, 400)
delete_sensor_to_monitor(sensor_uuid)
### --- END - SENSOR REGISTRATION --- ###