diff --git a/src/opengnsys/modules/server/ogAdmClient/__init__.py b/src/opengnsys/modules/server/ogAdmClient/__init__.py index b107431..19cec82 100644 --- a/src/opengnsys/modules/server/ogAdmClient/__init__.py +++ b/src/opengnsys/modules/server/ogAdmClient/__init__.py @@ -51,28 +51,28 @@ from opengnsys.log import logger from opengnsys.workers import ServerWorker # Check authorization header decorator -def check_secret(fnc): +def check_secret (fnc): """ Decorator to check for received secret key and raise exception if it isn't valid. """ - def wrapper(*args, **kwargs): - return fnc(*args, **kwargs) + def wrapper (*args, **kwargs): + return fnc (*args, **kwargs) #try: # this, path, get_params, post_params, server = args # # Accept "status" operation with no arguments or any function with Authorization header # if fnc.__name__ == 'process_status' and not get_params: - # return fnc(*args, **kwargs) + # return fnc (*args, **kwargs) # elif this.random == server.headers['Authorization']: - # return fnc(*args, **kwargs) + # return fnc (*args, **kwargs) # else: - # raise Exception('Unauthorized operation') + # raise Exception ('Unauthorized operation') #except Exception as e: - # logger.error(str(e)) - # raise Exception(e) + # logger.error (str (e)) + # raise Exception (e) return wrapper -class ogAdmClientWorker(ServerWorker): +class ogAdmClientWorker (ServerWorker): name = 'ogAdmClient' # Module name interface = None # Bound interface for OpenGnsys REST = None # REST object @@ -88,55 +88,55 @@ class ogAdmClientWorker(ServerWorker): idcentro = None idaula = None - def onDeactivation(self): + def onDeactivation (self): """ Sends OGAgent stopping notification to OpenGnsys server """ - logger.debug('onDeactivation') + logger.debug ('onDeactivation') - def processClientMessage(self, message, data): - logger.debug('Got OpenGnsys message from client: {}, data {}'.format(message, data)) + def processClientMessage (self, message, data): + logger.debug ('Got OpenGnsys message from client: {}, data {}'.format (message, data)) - def onLogin(self, data): - logger.warn('in onLogin, should not happen') + def onLogin (self, data): + logger.warn ('in onLogin, should not happen') - def onLogout(self, user): - logger.warn('in onLogout, should not happen') + def onLogout (self, user): + logger.warn ('in onLogout, should not happen') - def process_ogclient(self, path, get_params, post_params, server): - """ - This method can be overridden to provide your own message processor, or better you can - implement a method that is called exactly as "process_" + path[0] (module name has been removed from path - array) and this default processMessage will invoke it - * Example: - Imagine this invocation url (no matter if GET or POST): http://example.com:9999/Sample/mazinger/Z - The HTTP Server will remove "Sample" from path, parse arguments and invoke this method as this: - module.processMessage(["mazinger","Z"], get_params, post_params) + #def process_ogclient (self, path, get_params, post_params, server): + # """ + # This method can be overridden to provide your own message processor, or better you can + # implement a method that is called exactly as "process_" + path[0] (module name has been removed from path + # array) and this default processMessage will invoke it + # * Example: + # Imagine this invocation url (no matter if GET or POST): http://example.com:9999/Sample/mazinger/Z + # The HTTP Server will remove "Sample" from path, parse arguments and invoke this method as this: + # module.processMessage (["mazinger","Z"], get_params, post_params) - This method will process "mazinger", and look for a "self" method that is called "process_mazinger", - and invoke it this way: - return self.process_mazinger(["Z"], get_params, post_params) + # This method will process "mazinger", and look for a "self" method that is called "process_mazinger", + # and invoke it this way: + # return self.process_mazinger (["Z"], get_params, post_params) - In the case path is empty (that is, the path is composed only by the module name, like in - "http://example.com/Sample", the "process" method will be invoked directly + # In the case path is empty (that is, the path is composed only by the module name, like in + # "http://example.com/Sample", the "process" method will be invoked directly - The methods must return data that can be serialized to json (i.e. Objects are not serializable to json, - basic type are) - """ - if not path: - return "ok" - try: - operation = getattr(self, 'ogclient_' + path[0]) - except Exception: - raise Exception('Message processor for "{}" not found'.format(path[0])) - return operation(path[1:], get_params, post_params) + # The methods must return data that can be serialized to json (i.e. Objects are not serializable to json, + # basic type are) + # """ + # if not path: + # return "ok" + # try: + # operation = getattr (self, 'ogclient_' + path[0]) + # except Exception: + # raise Exception ('Message processor for "{}" not found'.format (path[0])) + # return operation (path[1:], get_params, post_params) @check_secret - def process_status(self, path, get_params, post_params, server): - return {'ogAdmClient': 'in process_status'} + def process_status (self, path, get_params, post_params, server): + return {'ogAdmClient': 'in process_status'} ## XXX @check_secret - def process_reboot(self, path, get_params, post_params, server): + def process_reboot (self, path, get_params, post_params, server): """ Launches a system reboot operation :param path: @@ -145,16 +145,16 @@ class ogAdmClientWorker(ServerWorker): :param server: authorization header :return: JSON object {"op": "launched"} """ - logger.debug('Received reboot operation') + logger.debug ('Received reboot operation') # Rebooting thread def rebt(): operations.reboot() - threading.Thread(target=rebt).start() + threading.Thread (target=rebt).start() return {'op': 'launched'} @check_secret - def process_poweroff(self, path, get_params, post_params, server): + def process_poweroff (self, path, get_params, post_params, server): """ Launches a system power off operation :param path: @@ -163,23 +163,24 @@ class ogAdmClientWorker(ServerWorker): :param server: authorization header :return: JSON object {"op": "launched"} """ - logger.debug('Received poweroff operation') + logger.debug ('Received poweroff operation') # Powering off thread def pwoff(): - time.sleep(2) + time.sleep (2) operations.poweroff() - threading.Thread(target=pwoff).start() + threading.Thread (target=pwoff).start() return {'op': 'launched'} - @check_secret - def process_logoff(self, path, get_params, post_params, server): - logger.warn('in process_logoff, should not happen') + #@check_secret + #def process_logoff (self, path, get_params, post_params, server): + # logger.warn ('in process_logoff, should not happen') + ## curl --insecure -X POST --data '{"nfn": "popup", "title": "my title", "message": "my message"}' https://192.168.1.249:8000/ogAdmClient/popup @check_secret - def process_popup(self, path, get_params, post_params, server): - logger.debug('in process_popup, path "{}" get_params "{}" post_params "{}" server "{}"'.format(path, get_params, post_params, server)) - logger.debug('type(post_params) "{}"'.format(type(post_params))) + def process_popup (self, path, get_params, post_params, server): + logger.debug ('in process_popup, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server)) + logger.debug ('type(post_params) "{}"'.format (type (post_params))) ## in process_popup, should not happen, path "[]" get_params "{}" post_params "{'title': 'mi titulo', 'message': 'mi mensaje'}" server "" ## type(post_params) "" return {'debug':'test'} @@ -191,12 +192,12 @@ class ogAdmClientWorker(ServerWorker): - #def process_client_popup(self, params): - # logger.warn('in process_client_popup') + #def process_client_popup (self, params): + # logger.warn ('in process_client_popup') - ## process_* are invoked from opengnsys/httpserver.py:99 "data = module.processServerMessage(path, get_params, post_params, self)" (via opengnsys/workers/server_worker.py) - ## process_client_* are invoked from opengnsys/service.py:123 "v.processClientMessage(message, json.loads(data))" (via opengnsys/workers/server_worker.py) + ## process_* are invoked from opengnsys/httpserver.py:99 "data = module.processServerMessage (path, get_params, post_params, self)" (via opengnsys/workers/server_worker.py) + ## process_client_* are invoked from opengnsys/service.py:123 "v.processClientMessage (message, json.loads (data))" (via opengnsys/workers/server_worker.py) def interfaceAdmin (self, method, parametros=[]): @@ -213,7 +214,7 @@ class ogAdmClientWorker(ServerWorker): logger.debug ('subprocess.run ("{}", capture_output=True)'.format (proc)) return subprocess.run (proc, capture_output=True).stdout.strip().decode ('utf-8') - def tomaIPlocal(self): + def tomaIPlocal (self): try: self.IPlocal = self.interfaceAdmin ('getIpAddress'); logger.info ('local IP is "{}"'.format (self.IPlocal)) @@ -226,9 +227,9 @@ class ogAdmClientWorker(ServerWorker): def LeeConfiguracion(self): parametroscfg = self.interfaceAdmin ('getConfiguration') ## Configuración de los Sistemas Operativos del cliente logger.debug ('parametroscfg ({})'.format (parametroscfg)) - return (parametroscfg) + return parametroscfg - def enviaMensajeServidor(self, path, obj={}): + def enviaMensajeServidor (self, path, obj={}): obj['iph'] = self.IPlocal ## Ip del ordenador obj['ido'] = self.idordenador ## Identificador del ordenador obj['npc'] = self.nombreordenador ## Nombre del ordenador @@ -237,7 +238,7 @@ class ogAdmClientWorker(ServerWorker): res = self.REST.sendMessage (path, obj) - if (type(res) is not dict): + if (type (res) is not dict): #logger.error ('No se ha podido establecer conexión con el Servidor de Administración') ## Error de conexión con el servidor logger.debug (f'res ({res})') logger.error ('Error al enviar trama ***send() fallo') @@ -245,7 +246,7 @@ class ogAdmClientWorker(ServerWorker): return res - def ejecutaArchivo(self,fn): + def ejecutaArchivo (self,fn): logger.debug ('fn ({})'.format (fn)) ## TODO need to understand this code (ogAdmClient.c:2111) before translating it to python @@ -271,15 +272,15 @@ class ogAdmClientWorker(ServerWorker): ## let's test something, assuming that in the "file" there's not just some bash, but a sequence of parameters such as "nfn=Function\rparam1=foo\rparam2=bar" buffer = subprocess.run (['cat', fn], capture_output=True).stdout.strip().decode ('utf-8') - logger.debug ('buffer ({})'.format (buffer.replace('\r', '\\r'))) ## change \r so as not to mess with the log + logger.debug ('buffer ({})'.format (buffer.replace ('\r', '\\r'))) ## change \r so as not to mess with the log if buffer: - for l in buffer.split('@'): - if not len(l): continue + for l in buffer.split ('@'): + if not len (l): continue logger.debug ('line ({})'.format (l)) ## at this point, an option would be fire up a curl to localhost, but we can also parse the params and locally call the desired function: post_params = {} - for param in l.split("\r"): - k, v = param.split('=') + for param in l.split ("\r"): + k, v = param.split ('=') post_params[k] = v logger.debug ('post_params "{}"'.format (post_params)) @@ -297,13 +298,13 @@ class ogAdmClientWorker(ServerWorker): logger.error ('Ha ocurrido algún problema al procesar la trama recibida') break - def inclusionCliente(self): + def inclusionCliente (self): cfg = self.LeeConfiguracion() res = self.enviaMensajeServidor ('InclusionCliente', { 'cfg': cfg }) logger.debug ('res ({})'.format (res)) ## RESPUESTA_InclusionCliente - if (type(res) is not dict or 0 == res['res']) : + if (type (res) is not dict or 0 == res['res']) : logger.error ('Ha ocurrido algún problema en el proceso de inclusión del cliente') return False @@ -320,34 +321,34 @@ class ogAdmClientWorker(ServerWorker): return True - def cuestionCache(self): + def cuestionCache (self): return True ## ogAdmClient.c:425 #>>>>>>>>>>>>>>>>>>>>>>>>>> #try: - # self.interfaceAdmin ('procesaCache', [ self.cache ]); + # self.interfaceAdmin ('procesaCache', [self.cache]); #except Exception as e: # logger.error ('Ha habido algún problerma al procesar la caché') # return False # #return True - def autoexecCliente(self): + def autoexecCliente (self): res = self.enviaMensajeServidor ('AutoexecCliente', { 'exe': self.idproautoexec }) logger.debug ('res ({})'.format (res)) - if (type(res) is not dict): + if (type (res) is not dict): logger.error ('Ha ocurrido algún problema al enviar una petición de comandos o tareas pendientes al Servidor de Administración') logger.error ('Ha ocurrido algún problema al recibir una petición de comandos o tareas pendientes desde el Servidor de Administración') return False ## RESPUESTA_AutoexecCliente - if (type(res) is not dict or 0 == res['res']) : + if (type (res) is not dict or 0 == res['res']) : logger.error ('Ha ocurrido algún problema al procesar la trama recibida') return False logger.info (res) res = self.enviaMensajeServidor ('enviaArchivo', { 'nfl': res['nfl'] }) - if (type(res) is not dict): + if (type (res) is not dict): logger.error ('Ha ocurrido algún problema al enviar una petición de comandos o tareas pendientes al Servidor de Administración') logger.error ('Ha ocurrido algún problema al recibir un archivo por la red') return False @@ -356,16 +357,16 @@ class ogAdmClientWorker(ServerWorker): fileautoexec = '/tmp/_autoexec_{}'.format (self.IPlocal) logger.debug ('fileautoexec ({})'.format (fileautoexec)) with open (fileautoexec, 'w') as fd: - fd.write (base64.b64decode (res['contents']).decode('utf-8')) + fd.write (base64.b64decode (res['contents']).decode ('utf-8')) self.ejecutaArchivo (fileautoexec); return True - def comandosPendientes(self): + def comandosPendientes (self): while (True): res = self.enviaMensajeServidor ('ComandosPendientes') ## receives just one command - if (type(res) is not dict): + if (type (res) is not dict): logger.error ('Ha ocurrido algún problema al enviar una petición de comandos o tareas pendientes al Servidor de Administración') logger.error ('Ha ocurrido algún problema al recibir una petición de comandos o tareas pendientes desde el Servidor de Administración') return False @@ -375,7 +376,7 @@ class ogAdmClientWorker(ServerWorker): break ## TODO manage the rest of cases... we might have to do something similar to ejecutaArchivo - #if(!gestionaTrama(ptrTrama)){ // Análisis de la trama + #if (!gestionaTrama (ptrTrama)){ // Análisis de la trama # logger.error ('Ha ocurrido algún problema al procesar la trama recibida') # return False #} @@ -384,7 +385,7 @@ class ogAdmClientWorker(ServerWorker): return True - def cargaPaginaWeb(url=None): + def cargaPaginaWeb (url=None): if (not url): url = self.urlMenu os.system ('pkill -9 browser'); @@ -401,14 +402,14 @@ class ogAdmClientWorker(ServerWorker): return True - def muestraMenu(self): + def muestraMenu (self): self.cargaPaginaWeb() - def procesaComandos(self): + def procesaComandos (self): res = self.enviaMensajeServidor ('DisponibilidadComandos', { 'tpc': 'OPG' }) ## Activar disponibilidad logger.debug ('res ({})'.format (res)) - if (type(res) is not dict): + if (type (res) is not dict): logger.error ('Ha ocurrido algún problema al enviar una petición de comandos interactivos al Servidor de Administración') return False @@ -417,42 +418,42 @@ class ogAdmClientWorker(ServerWorker): ## we now return true and the outer agent code gets to wait for requests from outside ## TODO thing is, ogAdmClient always calls comandosPendientes() after every received request. How do we do that here? # - #ptrTrama=recibeMensaje(&socket_c); - #if(!ptrTrama){ - # errorLog(modulo,46,FALSE); 'Ha ocurrido algún problema al recibir un comando interactivo desde el Servidor de Administración' + #ptrTrama=recibeMensaje (&socket_c); + #if (!ptrTrama){ + # errorLog (modulo,46,FALSE); 'Ha ocurrido algún problema al recibir un comando interactivo desde el Servidor de Administración' # return; #} - #close(socket_c); - #if(!gestionaTrama(ptrTrama)){ // Análisis de la trama - # errorLog(modulo,39,FALSE); 'Ha ocurrido algún problema al procesar la trama recibida' + #close (socket_c); + #if (!gestionaTrama (ptrTrama)){ // Análisis de la trama + # errorLog (modulo,39,FALSE); 'Ha ocurrido algún problema al procesar la trama recibida' # return; #} - #if(!comandosPendientes(ptrTrama)){ - # errorLog(modulo,42,FALSE); 'Ha ocurrido algún problema al enviar una petición de comandos o tareas pendientes al Servidor de Administración' + #if (!comandosPendientes (ptrTrama)){ + # errorLog (modulo,42,FALSE); 'Ha ocurrido algún problema al enviar una petición de comandos o tareas pendientes al Servidor de Administración' #} - def onActivation(self): + def onActivation (self): """ Sends OGAgent activation notification to OpenGnsys server """ # Generate random secret to send on activation - self.random = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(self.length)) + self.random = ''.join (random.choice (string.ascii_lowercase + string.digits) for _ in range (self.length)) # Ensure cfg has required configuration variables or an exception will be thrown try: - url = self.service.config.get('ogAdmClient', 'remote') - loglevel = self.service.config.get('ogAdmClient', 'log') - #servidorAdm = self.service.config.get('ogAdmClient', 'servidorAdm') - #puerto = self.service.config.get('ogAdmClient', 'puerto') - self.pathinterface = self.service.config.get('ogAdmClient', 'pathinterface') - urlMenu = self.service.config.get('ogAdmClient', 'urlMenu') - #urlMsg = self.service.config.get('ogAdmClient', 'urlMsg') - logger.setLevel(loglevel) + url = self.service.config.get ('ogAdmClient', 'remote') + loglevel = self.service.config.get ('ogAdmClient', 'log') + #servidorAdm = self.service.config.get ('ogAdmClient', 'servidorAdm') + #puerto = self.service.config.get ('ogAdmClient', 'puerto') + self.pathinterface = self.service.config.get ('ogAdmClient', 'pathinterface') + urlMenu = self.service.config.get ('ogAdmClient', 'urlMenu') + #urlMsg = self.service.config.get ('ogAdmClient', 'urlMsg') + logger.setLevel (loglevel) except NoOptionError as e: - logger.error("Configuration error: {}".format(e)) + logger.error ("Configuration error: {}".format (e)) raise e - self.REST = REST(url) + self.REST = REST (url) - if (not self.tomaIPlocal()): + if not self.tomaIPlocal(): raise Exception ('Se han generado errores. No se puede continuar la ejecución de este módulo') logger.info ('Inicio de sesion') @@ -462,16 +463,16 @@ class ogAdmClientWorker(ServerWorker): logger.info ('Cliente iniciado') logger.info ('Procesando caché') - if (not self.cuestionCache()): + if not self.cuestionCache(): raise Exception ('Se han generado errores. No se puede continuar la ejecución de este módulo') - if (self.idproautoexec > 0): + if self.idproautoexec > 0: logger.info ('Ejecución de archivo Autoexec') - if (not self.autoexecCliente()): + if not self.autoexecCliente(): raise Exception ('Se han generado errores. No se puede continuar la ejecución de este módulo') logger.info ('Procesa comandos pendientes') - if (not self.comandosPendientes()): + if not self.comandosPendientes(): raise Exception ('Se han generado errores. No se puede continuar la ejecución de este módulo') logger.info ('Acciones pendientes procesadas') @@ -482,59 +483,60 @@ class ogAdmClientWorker(ServerWorker): def process_NoComandosPtes(self, path, get_params, post_params, server): logger.warn('in process_NoComandosPtes') - def process_Actualizar(self, path, get_params, post_params, server): - logger.warn('in process_Actualizar') + ## curl --insecure https://192.168.1.249:8000/ogAdmClient/Actualizar + def process_Actualizar (self, path, get_params, post_params, server): + logger.warn ('in process_Actualizar') - def process_Purgar(self, path, get_params, post_params, server): - logger.warn('in process_Purgar') + def process_Purgar (self, path, get_params, post_params, server): + logger.warn ('in process_Purgar') - def process_ConsolaRemota(self, path, get_params, post_params, server): - logger.warn('in process_ConsolaRemota') + def process_ConsolaRemota (self, path, get_params, post_params, server): + logger.warn ('in process_ConsolaRemota') - def process_Sondeo(self, path, get_params, post_params, server): - logger.warn('in process_Sondeo') + def process_Sondeo (self, path, get_params, post_params, server): + logger.warn ('in process_Sondeo') - def process_Arrancar(self, path, get_params, post_params, server): - logger.warn('in process_Arrancar') + def process_Arrancar (self, path, get_params, post_params, server): + logger.warn ('in process_Arrancar') - def process_Apagar(self, path, get_params, post_params, server): - logger.warn('in process_Apagar') + def process_Apagar (self, path, get_params, post_params, server): + logger.warn ('in process_Apagar') - def process_Reiniciar(self, path, get_params, post_params, server): - logger.warn('in process_Reiniciar') + def process_Reiniciar (self, path, get_params, post_params, server): + logger.warn ('in process_Reiniciar') - def process_IniciarSesion(self, path, get_params, post_params, server): - logger.warn('in process_IniciarSesion') + def process_IniciarSesion (self, path, get_params, post_params, server): + logger.warn ('in process_IniciarSesion') - def process_CrearImagen(self, path, get_params, post_params, server): - logger.warn('in process_CrearImagen') + def process_CrearImagen (self, path, get_params, post_params, server): + logger.warn ('in process_CrearImagen') - def process_CrearImagenBasica(self, path, get_params, post_params, server): - logger.warn('in process_CrearImagenBasica') + def process_CrearImagenBasica (self, path, get_params, post_params, server): + logger.warn ('in process_CrearImagenBasica') - def process_CrearSoftIncremental(self, path, get_params, post_params, server): - logger.warn('in process_CrearSoftIncremental') + def process_CrearSoftIncremental (self, path, get_params, post_params, server): + logger.warn ('in process_CrearSoftIncremental') - def process_RestaurarImagen(self, path, get_params, post_params, server): - logger.warn('in process_RestaurarImagen') + def process_RestaurarImagen (self, path, get_params, post_params, server): + logger.warn ('in process_RestaurarImagen') - def process_RestaurarImagenBasica(self, path, get_params, post_params, server): - logger.warn('in process_RestaurarImagenBasica') + def process_RestaurarImagenBasica (self, path, get_params, post_params, server): + logger.warn ('in process_RestaurarImagenBasica') - def process_RestaurarSoftIncremental(self, path, get_params, post_params, server): - logger.warn('in process_RestaurarSoftIncremental') + def process_RestaurarSoftIncremental (self, path, get_params, post_params, server): + logger.warn ('in process_RestaurarSoftIncremental') - def process_Configurar(self, path, get_params, post_params, server): - logger.warn('in process_Configurar') + def process_Configurar (self, path, get_params, post_params, server): + logger.warn ('in process_Configurar') - def process_EjecutarScript(self, path, get_params, post_params, server): - logger.warn('in process_EjecutarScript') + def process_EjecutarScript (self, path, get_params, post_params, server): + logger.warn ('in process_EjecutarScript') - def process_InventarioHardware(self, path, get_params, post_params, server): - logger.warn('in process_InventarioHardware') + def process_InventarioHardware (self, path, get_params, post_params, server): + logger.warn ('in process_InventarioHardware') - def process_InventarioSoftware(self, path, get_params, post_params, server): - logger.warn('in process_InventarioSoftware') + def process_InventarioSoftware (self, path, get_params, post_params, server): + logger.warn ('in process_InventarioSoftware') - def process_EjecutaComandosPendientes(self, path, get_params, post_params, server): - logger.warn('in process_EjecutaComandosPendientes') + def process_EjecutaComandosPendientes (self, path, get_params, post_params, server): + logger.warn ('in process_EjecutaComandosPendientes')