def put(self, id_report): """ Configuración para la ejecución del reporte """ request_data = dict(request.json) state_report = TemporalProcessingStateReport.objects(id_report=id_report).first() if state_report is not None: state_report.update(info=request_data) else: state_report = TemporalProcessingStateReport(id_report=id_report, info=request_data, msg="Rutina configurada") state_report.save() return dict(success=True, msg="Parámetros configurados de manera correcta"), 200
def get(ini_date: str = "yyyy-mm-dd H:M:S", end_date: str = "yyyy-mm-dd H:M:S"): """ Obtiene el estado del cálculo de los reportes de disponibilidad existentes en el periodo especificado Nota: Este servicio es válido solamente al momento de consultar el estado de un cálculo en proceso en otro contexto, este servicio no garantiza un comportamiento correcto Fecha inicial formato: <b>yyyy-mm-dd H:M:S</b> Fecha final formato: <b>yyyy-mm-dd H:M:S</b> """ success1, ini_date = u.check_date_yyyy_mm_dd_hh_mm_ss(ini_date) success2, end_date = u.check_date_yyyy_mm_dd_hh_mm_ss(end_date) if not success1 or not success2: msg = "No se puede convertir. " + (ini_date if not success1 else end_date) return dict(success=False, msg=msg), 400 # check the existing nodes: all_nodes = SRNode.objects() all_nodes = [n for n in all_nodes if n.activado] if len(all_nodes) == 0: msg = f"No se encuentran nodos que procesar" return dict(success=False, msg=msg), 404 # scan reports within this date range: to_send = list() for node in all_nodes: if u.isTemporal(ini_date, end_date): v_report = SRNodeDetailsTemporal(nodo=node, nombre=node.nombre, tipo=node.tipo, fecha_inicio=ini_date, fecha_final=end_date) else: v_report = SRNodeDetailsPermanente(nodo=node, nombre=node.nombre, tipo=node.tipo, fecha_inicio=ini_date, fecha_final=end_date) tmp_report = TemporalProcessingStateReport.objects( id_report=v_report.id_report).first() if tmp_report is None: for i in range(20): tmp_report = TemporalProcessingStateReport.objects( id_report=v_report.id_report).first() if tmp_report is not None: break else: time.sleep(2) to_send.append(tmp_report.to_summary()) if len(all_nodes) == len(to_send): return dict(success=True, status=to_send), 200 else: return dict(success=False, status=None), 409
def run_all_nodes(report_ini_date: dt.datetime, report_end_date: dt.datetime, save_in_db=False, force=False): # corre todos los nodos que se encuentran activos: global start_time_script start_time_script = dt.datetime.now() mongo_config = init.MONGOCLIENT_SETTINGS try: connect(**mongo_config) except Exception as e: pass """ Buscando los nodos con los que se va a trabajar """ all_nodes = SRNode.objects() all_nodes = [n for n in all_nodes if n.activado] if len(all_nodes) == 0: msg = f"No hay nodos a procesar en db:[{mongo_config['db']}]" return False, [], msg name_list = [n.nombre for n in all_nodes] for sR_node in all_nodes: report_node = SRNodeDetailsBase(nodo=sR_node, nombre=sR_node.nombre, tipo=sR_node.tipo, fecha_inicio=report_ini_date, fecha_final=report_end_date) status_node = TemporalProcessingStateReport.objects( id_report=report_node.id_report).first() if status_node is not None: status_node.delete() return run_node_list(name_list, report_ini_date, report_end_date, save_in_db, force)
def delete(ini_date: str = "yyyy-mm-dd H:M:S", end_date: str = "yyyy-mm-dd H:M:S"): """ Elimina si existe la disponibilidad de los nodos especificados en la lista Fecha inicial formato: <b>yyyy-mm-dd H:M:S</b> Fecha final formato: <b>yyyy-mm-dd H:M:S</b> """ success1, ini_date = u.check_date_yyyy_mm_dd_hh_mm_ss(ini_date) success2, end_date = u.check_date_yyyy_mm_dd_hh_mm_ss(end_date) if not success1 or not success2: msg = "No se puede convertir. " + (ini_date if not success1 else end_date) return dict(success=False, msg=msg), 400 node_list_name = request.json["nodos"] not_found = list() deleted = list() for node in node_list_name: sR_node = SRNode.objects(nombre=node).first() if sR_node is None: not_found.append(node) continue report_v = SRNodeDetailsBase(nodo=sR_node, nombre=sR_node.nombre, tipo=sR_node.tipo, fecha_inicio=ini_date, fecha_final=end_date) # delete status report if exists status_report = TemporalProcessingStateReport.objects( id_report=report_v.id_report).first() if status_report is not None: status_report.delete() if u.isTemporal(ini_date, end_date): report = SRNodeDetailsTemporal.objects( id_report=report_v.id_report).first() else: report_v = SRNodeDetailsPermanente(nodo=sR_node, nombre=sR_node.nombre, tipo=sR_node.tipo, fecha_inicio=ini_date, fecha_final=end_date) report = SRNodeDetailsPermanente.objects( id_report=report_v.id_report).first() if report is None: not_found.append(node) continue report.delete() deleted.append(node) if len(deleted) == 0: return dict(success=False, deleted=deleted, not_found=not_found), 404 success, _, msg = run_summary(ini_date, end_date, save_in_db=True, force=True) if not success: return dict(success=False, deleted=[], not_found=not_found), 400 return dict(success=True, deleted=deleted, not_found=not_found), 200
def save(self, msg=None): info = dict(trigger=dict(seconds=self.trigger.seconds, days=self.trigger.days), mail_config=self.mail_config, parameters=self.parameters) state = TemporalProcessingStateReport.objects(id_report=self.name).first() if state is None: state = TemporalProcessingStateReport(id_report=self.name, info=info, msg=msg) state.save() else: state.update(info=info, created=dt.datetime.now(), msg=msg)
def post(self, id_report): """ Corre de manera rutinaria el reporte con el id """ th = get_thread_by_name(id_report) if th is None: if id_report == 'rutina_de_reporte_diario': state = TemporalProcessingStateReport.objects(id_report=id_report).first() if state is None: return dict(success=False, msg="La rutina aún no ha sido configurada"), 404 trigger = dt.timedelta(**state.info["trigger"]) th_v = StoppableThreadDailyReport(trigger=trigger, name=id_report) th_v.start() return dict(success=True, msg="La rutina ha sido inicializada"), 200 if id_report == 'rutina_correo_electronico': state = TemporalProcessingStateReport.objects(id_report=id_report).first() if state is None: return dict(success=False, msg="La rutina aún no ha sido configurada"), 404 trigger = dt.timedelta(**state.info["trigger"]) mail_config = state.info["mail_config"] parameters = state.info["parameters"] th_v = StoppableThreadMailReport(name=id_report, trigger=trigger, mail_config=mail_config, parameters=parameters) th_v.start() return dict(success=True, msg="La rutina ha sido inicializada"), 200 return dict(success=False, msg="La rutina ya se encuentra en ejecución"), 409
def test(): mongo_config = init.MONGOCLIENT_SETTINGS connect(**mongo_config) rutine_name = "rutina_de_reporte_diario" trigger = dict(hours=7, minutes=29, seconds=0) th_v = StoppableThreadDailyReport(trigger=dt.timedelta(**trigger), name=rutine_name) th_v.save(msg="Configuración guardada") state = TemporalProcessingStateReport.objects( id_report=rutine_name).first() trigger = dt.timedelta(**state.info["trigger"]) th = get_thread_by_name(rutine_name) if th is None: th = StoppableThreadDailyReport(trigger=trigger, name=rutine_name) th.start() else: th.stop()
def test(): mongo_config = init.MONGOCLIENT_SETTINGS connect(**mongo_config) rutine_name = "rutina_correo_electronico" trigger = dict(hours=7, minutes=40, seconds=0) mail_config = dict(from_email="*****@*****.**", users=["*****@*****.**"], admin=["*****@*****.**"]) parameters = dict(disp_utr_umbral=0.9, disp_tag_umbral=0.9) ini_date, end_date = get_dates_by_default() ini_date, end_date = dt.datetime(year=2021, month=3, day=1), dt.datetime(year=2021, month=3, day=30) th_v = StoppableThreadMailReport(trigger=dt.timedelta(**trigger), name=rutine_name, mail_config=mail_config, parameters=parameters, ini_date=ini_date, end_date=end_date) th_v.save(msg="Configuración guardada") state = TemporalProcessingStateReport.objects(id_report=rutine_name).first() trigger = dt.timedelta(**state.info["trigger"]) mail_config = state.info["mail_config"] th = get_thread_by_name(rutine_name) if th is None: th = StoppableThreadMailReport(name=rutine_name, trigger=trigger, mail_config=mail_config, parameters=parameters, ini_date=ini_date, end_date=end_date) th.start() else: th.stop()
def processing_node(nodo, ini_date: dt.datetime, end_date: dt.datetime, save_in_db=False, force=False): """ Procesa un nodo :param force: Indica si debe forzar el guardado del reporte :param nodo: [str, SRNode] Nombre del nodo, o su respectivo objeto SRNode :param ini_date: fecha inicial de reporte :param end_date: fecha final de reporte :param save_in_db: indica si se guardará en base de datos :return: Success, NodeReport or None, (int msg, str msg) """ global sR_node_name global report_ini_date global report_end_date global minutos_en_periodo reporte_ya_existe = False if isinstance(nodo, str): connect(**mongo_config) print(mongo_config) sR_node = SRNode.objects(nombre=nodo).first() if sR_node is None: return False, None, (_2_no_existe[0], f'No se encontro el nodo {nodo}') elif isinstance(nodo, SRNode): sR_node = nodo else: return False, None, (_3_no_reconocido[0], f'Objeto nodo no reconocido: {nodo}') """ Actualizar fecha y fin de reporte """ sR_node_name = sR_node.nombre report_ini_date = ini_date report_end_date = end_date t_delta = report_end_date - report_ini_date minutos_en_periodo = t_delta.days * (60 * 24) + t_delta.seconds // 60 + ( t_delta.seconds % 60) / 60 """ Creando reporte de nodo """ if u.isTemporal(ini_date, end_date): report_node = SRNodeDetailsTemporal(nodo=sR_node, nombre=sR_node.nombre, tipo=sR_node.tipo, fecha_inicio=report_ini_date, fecha_final=report_end_date) else: report_node = SRNodeDetailsPermanente(nodo=sR_node, nombre=sR_node.nombre, tipo=sR_node.tipo, fecha_inicio=report_ini_date, fecha_final=report_end_date) status_node = TemporalProcessingStateReport( id_report=report_node.id_report, msg=f"Empezando cálculo del nodo: {sR_node_name}", finish=False, percentage=0) status_node.info["nombre"] = report_node.nombre status_node.info["tipo"] = report_node.tipo status_node.update_now() """ Examinar si existe reporte asociado al nodo en este periodo de tiempo """ # si el reporte va ser re-escrito, entonces se elimina el existente de base de datos # caso contrario no se puede continuar al ya existir un reporte asociado a este nodo success, node_report_db, msg = delete_report_if_exists( save_in_db, force, report_node, status_node) if not success: # ya existe un reporte asociado, por lo que no se continúa return False, node_report_db, msg """ verificar si existe conexión con el servidor PI: """ success, status = verify_pi_server_connection(status_node) if not success: # si no existe conexión con el servidor no se puede continuar: return False, node_report, status """ Seleccionando las entidades a trabajar (estado: activado) """ """ entities es una lista de SREntity """ success, entities, status = get_active_entities(sR_node, status_node) if not success: # si no hay entidades en el nodo, no se puede continuar return False, node_report, status """ Trabajando con cada entity_list, cada entity_list tiene utrs que tienen tags a calcular """ # la cola que permitirá recibir los resultados de cada hilo out_queue = queue.Queue() # cronometrar el tiempo de cálculo start_time = dt.datetime.now() # Procesando cada utr dentro de un hilo: structure, out_queue, n_threads = processing_each_utr_in_threads( entities, out_queue) """ Recuperando los resultados de los informes provenientes de cada hilo """ report_node, status_node, in_memory_reports = collecting_report_from_threads( entities, out_queue, n_threads, report_node, status_node, structure) """ Calculando tiempo de ejecución """ run_time = dt.datetime.now() - start_time """ Calculando reporte en cada entidad """ [in_memory_reports[k].calculate() for k in in_memory_reports.keys()] [ in_memory_reports[k].reportes_utrs.sort( key=lambda x: x.disponibilidad_promedio_porcentage) for k in in_memory_reports.keys() ] report_node.reportes_entidades = [ in_memory_reports[k] for k in in_memory_reports.keys() ] report_node.reportes_entidades.sort( key=lambda x: x.disponibilidad_promedio_ponderada_porcentage) report_node.entidades_fallidas = [ r.entidad_nombre for r in report_node.reportes_entidades if r.numero_tags == 0 ] report_node.calculate_all() report_node.tiempo_calculo_segundos = run_time.total_seconds() if report_node.numero_tags_total == 0: status_node.failed() status_node.msg = _6_no_existe_entidades[1] status_node.update_now() # guardar los resultados del nodo a pesar de no tener tags válidas report_node.save(force=True) return False, report_node, ( _6_no_existe_entidades[0], f"El nodo {sR_node_name} no contiene entidades válidas para procesar" ) msg_save = (0, str()) try: if force or save_in_db: if reporte_ya_existe: msg_save = (_10_sobrescrito[0], "Reporte sobrescrito en base de datos") else: msg_save = (_9_guardado[0], "Reporte escrito en base de datos") print("reporte:", report_node.to_summary()) report_node.save(force=True) except Exception as e: status_node.failed() status_node.msg = _7_no_es_posible_guardar[1] status_node.update_now() return False, report_node, ( _7_no_es_posible_guardar[0], f"No se ha podido guardar el reporte del nodo {sR_node_name} debido a: \n {str(e)}" ) msg = f"{msg_save[1]}\nNodo [{sR_node_name}] procesado en: \t\t{run_time} \n" \ f"Numero de tags procesadas: \t{report_node.numero_tags_total}" status_node.finished() status_node.msg = msg_save[1] status_node.info["run_time_seconds"] = run_time.total_seconds() status_node.update_now() return True, report_node, (msg_save[0], msg)
def update_from_db(self): state = TemporalProcessingStateReport.objects( id_report=self.name).first() if state is not None: self.trigger = dt.timedelta(**state.info["trigger"])
def update_from_db(self): state = TemporalProcessingStateReport.objects(id_report=self.name).first() if state is not None: self.trigger = dt.timedelta(**state.info["trigger"]) self.mail_config = state.info["mail_config"] self.parameters = state.info["parameters"]