#!/usr/bin/env python3 # -*- coding: utf-8 -*- # # Copyright (c) 2014 Virtual Cable S.L. # Copyright (c) 2024-2025 Qindel Formación y Servicios S.L. # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # * Neither the name of Virtual Cable S.L. nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """ @author: Ramón M. Gómez, ramongomez at us dot es @author: Natalia Serrano, nserrano at qindel dot com """ import base64 import os import signal import string import random import subprocess from pathlib import Path from urllib.parse import unquote from opengnsys import VERSION from opengnsys.log import logger from opengnsys.workers import ogLiveWorker # Check authorization header decorator def check_secret (fnc): """ Decorator to check for received secret key and raise exception if it isn't valid. """ def wrapper (*args, **kwargs): try: this, path, get_params, post_params, server = args if not server: ## this happens on startup, eg. onActivation->autoexecCliente->ejecutaArchivo->popup->check_secret return fnc (*args, **kwargs) if this.random == server.headers['Authorization']: return fnc (*args, **kwargs) else: raise Exception ('Unauthorized operation') except Exception as e: logger.error (str (e)) raise Exception (e) return wrapper # Check if operation is permitted def execution_level(level): def check_permitted(fnc): def wrapper(*args, **kwargs): levels = ['status', 'halt', 'full'] this = args[0] try: if levels.index(level) <= levels.index(this.exec_level): return fnc(*args, **kwargs) else: raise Exception('Unauthorized operation') except Exception as e: logger.debug (str(e)) raise Exception(e) return wrapper return check_permitted class ogAdmClientWorker (ogLiveWorker): name = 'ogAdmClient' # Module name REST = None # REST object def onDeactivation (self): """ Sends OGAgent stopping notification to OpenGnsys server """ logger.debug ('onDeactivation') self.REST.sendMessage ('ogagent/stopped', {'mac': self.mac, 'ip': self.IPlocal, 'idcentro': self.idcentro, 'idaula': self.idaula, 'idordenador': self.idordenador, 'nombreordenador': self.nombreordenador}) def InventariandoSoftware (self, dsk, par, nfn): sft_src = f'/tmp/CSft-{self.IPlocal}-{par}' try: self.interfaceAdmin (nfn, [dsk, par, sft_src]) herror = 0 except: herror = 1 if herror: logger.warning ('Error al ejecutar el comando') b64 = '' self.muestraMensaje (20) else: if not os.path.exists (sft_src): raise Exception (f'interfaceAdmin({nfn}) returned success but did not create file ({sft_src})') sft_src_contents = Path (sft_src).read_bytes() b64 = base64.b64encode (sft_src_contents).decode ('utf-8') self.muestraMensaje (19) cmd = { 'nfn': 'RESPUESTA_InventarioSoftware', 'dsk': dsk, ## not in the original C code, around ogAdmClient.c:1944 'par': par, 'contents': b64, } return self.respuestaEjecucionComando (cmd, herror, 0) def ejecutaArchivo (self,fn): logger.debug ('fn ({})'.format (fn)) ## 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 if buffer: for l in buffer.split ('@'): if not len (l): continue logger.debug ('line ({})'.format (l.replace ('\r', '\\r'))) ## change \r so as not to mess with the log ## 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 ('=') post_params[k] = v logger.debug ('post_params "{}"'.format (post_params)) func_name = post_params.pop ('nfn', None) if func_name is None: logger.error ('Ha ocurrido algún problema al procesar la trama recibida') break func = getattr (self, 'process_' + func_name) ## func is already a ref to self.func, so we don't have to call self.func(...) or func(self, ...) logger.debug ('calling function "{}" with post_params "{}"'.format (func_name, post_params)) output = func ([], {}, post_params, None) logger.debug ('output "{}"'.format (output)) if not output: logger.error ('Ha ocurrido algún problema al procesar la trama recibida') break def inclusionCliente (self): cfg = self.LeeConfiguracion() if not cfg: logger.warning ('No se ha podido recuperar la configuración de las particiones del disco') logger.warning ('Ha ocurrido algún problema en el proceso de inclusión del cliente') logger.error ('LeeConfiguracion() failed') return False res = self.enviaMensajeServidor ('InclusionCliente', { 'cfg': self.cfg2obj (cfg), 'secret': self.random, 'agent_version': VERSION }) logger.debug ('res ({})'.format (res)) ## RESPUESTA_InclusionCliente 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 if (not res['ido'] or not res['npc']): logger.error ('Se han recibido parámetros con valores no válidos') return False self.idordenador = res['ido'] ## Identificador del ordenador self.nombreordenador = res['npc'] ## Nombre del ordenador self.cache = res['che'] ## Tamaño de la caché reservada al cliente self.idproautoexec = res['exe'] ## Procedimento de inicio (Autoexec) self.idcentro = res['idc'] ## Identificador de la Unidad Organizativa self.idaula = res['ida'] ## Identificador del aula return True def cuestionCache (self): return True ## ogAdmClient.c:425 def autoexecCliente (self): res = self.enviaMensajeServidor ('AutoexecCliente', { 'exe': self.idproautoexec }) logger.debug ('res ({})'.format (res)) 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']) : 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): 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 logger.debug (f'res ({res})') 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')) self.ejecutaArchivo (fileautoexec) return True def comandosPendientes (self): while (True): res = self.enviaMensajeServidor ('ComandosPendientes') ## receives just one command 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 logger.info (res) if ('NoComandosPtes' == res['nfn']): break ## TODO manage the rest of cases... we might have to do something similar to ejecutaArchivo #if (!gestionaTrama (ptrTrama)){ // Análisis de la trama # logger.error ('Ha ocurrido algún problema al procesar la trama recibida') # return False #} ## ATM let's just return false to avoid a possible infinite loop return False return True def procesaComandos (self): res = self.enviaMensajeServidor ('DisponibilidadComandos', { 'tpc': 'OPG' }) ## Activar disponibilidad logger.debug ('res ({})'.format (res)) 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 logger.info ('Disponibilidad de comandos activada') ## Disponibilidad de cliente activada ## 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' # 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' # 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' #} def onActivation (self): super().onActivation() self.exec_level = 'full' self.random = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(32)) logger.info ('Inicio de sesion') logger.info ('Abriendo sesión en el servidor de Administración') if (not self.inclusionCliente()): raise Exception ('Se han generado errores. No se puede continuar la ejecución de este módulo') logger.info ('Cliente iniciado') logger.info ('Procesando caché') 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: logger.info ('Ejecución de archivo Autoexec') 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(): raise Exception ('Se han generado errores. No se puede continuar la ejecución de este módulo') logger.info ('Acciones pendientes procesadas') self.muestraMenu() self.procesaComandos() logger.info ('onActivation ok') def do_CrearImagen (self, post_params): for k in ['dsk', 'par', 'cpt', 'idi', 'nci', 'ipr', 'nfn', 'ids']: if k not in post_params: logger.error (f'required parameter ({k}) not in POST params') return {} dsk = post_params['dsk'] ## Disco par = post_params['par'] ## Número de partición cpt = post_params['cpt'] ## Código de la partición idi = post_params['idi'] ## Identificador de la imagen nci = post_params['nci'] ## Nombre canónico de la imagen ipr = post_params['ipr'] ## Ip del repositorio nfn = post_params['nfn'] ids = post_params['ids'] self.muestraMensaje (7) try: res = self.InventariandoSoftware (dsk, par, 'InventarioSoftware') ## Crea inventario Software previamente except: logger.warning ('Error al ejecutar el comando') return {} if res['contents']: self.muestraMensaje (2) inv_sft = res['contents'] try: self.interfaceAdmin (nfn, [dsk, par, nci, ipr]) self.muestraMensaje (9) herror = 0 except: logger.warning ('Error al ejecutar el comando') self.muestraMensaje (10) herror = 1 else: logger.warning ('Error al ejecutar el comando') herror = 1 inv_sft = '' self.muestraMenu() cmd = { 'nfn': 'RESPUESTA_CrearImagen', 'idi': idi, ## Identificador de la imagen 'dsk': dsk, ## Número de disco 'par': par, ## Número de partición de donde se creó 'cpt': cpt, ## Tipo o código de partición 'ipr': ipr, ## Ip del repositorio donde se alojó 'inv_sft': inv_sft, } return self.respuestaEjecucionComando (cmd, herror, ids) def do_RestaurarImagen (self, post_params): for k in ['dsk', 'par', 'idi', 'ipr', 'nci', 'ifs', 'ptc', 'nfn', 'ids']: if k not in post_params: logger.error (f'required parameter ({k}) not in POST params') return {} dsk = post_params['dsk'] par = post_params['par'] idi = post_params['idi'] ipr = post_params['ipr'] nci = post_params['nci'] ifs = post_params['ifs'] ptc = post_params['ptc'] ## Protocolo de clonación: Unicast, Multicast, Torrent nfn = post_params['nfn'] ids = post_params['ids'] self.muestraMensaje (3) try: ## the ptc.split() is useless right now, since interfaceAdmin() does ' '.join(params) in order to spawn a shell ## however we're going to need it in the future (when everything gets translated into python), plus it's harmless now. So let's do it #self.interfaceAdmin (nfn, [dsk, par, nci, ipr, ptc]) self.interfaceAdmin (nfn, [dsk, par, nci, ipr] + ptc.split()) self.muestraMensaje (11) herror = 0 except: logger.warning ('Error al ejecutar el comando') self.muestraMensaje (12) herror = 1 cfg = self.LeeConfiguracion() if not cfg: logger.warning ('No se ha podido recuperar la configuración de las particiones del disco') self.muestraMenu() cmd = { 'nfn': 'RESPUESTA_RestaurarImagen', 'idi': idi, ## Identificador de la imagen 'dsk': dsk, ## Número de disco 'par': par, ## Número de partición 'ifs': ifs, ## Identificador del perfil software 'cfg': self.cfg2obj(cfg), ## Configuración de discos } return self.respuestaEjecucionComando (cmd, herror, ids) def do_Configurar (self, post_params): for k in ['nfn', 'dsk', 'cfg', 'ids']: if k not in post_params: logger.error (f'required parameter ({k}) not in POST params') return {} nfn = post_params['nfn'] dsk = post_params['dsk'] cfg = post_params['cfg'] ids = post_params['ids'] self.muestraMensaje (4) params = [] disk_info = cfg.pop (0) logger.debug (f'disk_info ({disk_info})') for k in ['dis', 'tch']: params.append (f'{k}={disk_info[k]}') disk_info_str = '*'.join (params) partitions = [] for entry in cfg: logger.debug (f'entry ({entry})') params = [] for k in ['par', 'cpt', 'sfi', 'tam', 'ope']: params.append (f'{k}={entry[k]}') partitions.append ('*'.join (params)) part_info_str = '%'.join (partitions) cfg_str = f'{disk_info_str}!{part_info_str}%' try: self.interfaceAdmin (nfn, ['ignored', cfg_str]) self.muestraMensaje (14) herror = 0 except: logger.warning ('Error al ejecutar el comando') self.muestraMensaje (13) herror = 1 cfg = self.LeeConfiguracion() if not cfg: logger.warning ('No se ha podido recuperar la configuración de las particiones del disco') return {} cmd = { 'nfn': 'RESPUESTA_Configurar', 'cfg': self.cfg2obj (cfg), } self.muestraMenu() return self.respuestaEjecucionComando (cmd, herror, ids) def do_InventarioHardware (self, post_params): for k in ['nfn', 'ids']: if k not in post_params: logger.error (f'required parameter ({k}) not in POST params') return {} nfn = post_params['nfn'] ids = post_params['ids'] self.muestraMensaje (6) hrdsrc = f'/tmp/Chrd-{self.IPlocal}' ## Nombre que tendra el archivo de inventario hrddst = f'/tmp/Shrd-{self.IPlocal}' ## Nombre que tendra el archivo en el Servidor try: self.interfaceAdmin (nfn, [hrdsrc]) hrdsrc_contents = Path (hrdsrc).read_bytes() logger.debug (f'hrdsrc_contents 1 ({hrdsrc_contents})') herror = 0 except: logger.warning ('Error al ejecutar el comando') self.muestraMensaje (18) herror = 1 if herror: hrddst = '' else: logger.debug (f'hrdsrc_contents 2 ({hrdsrc_contents})') ## Envía fichero de inventario al servidor res = self.enviaMensajeServidor ('recibeArchivo', { 'nfl': hrddst, 'contents': base64.b64encode (hrdsrc_contents).decode ('utf-8') }) logger.debug (res) if not res: logger.error ('Ha ocurrido algún problema al enviar un archivo por la red') herror = 12 ## Error de envío de fichero por la red self.muestraMensaje (17) ## Envia respuesta de ejecución de la función de interface cmd = { 'nfn': 'RESPUESTA_InventarioHardware', 'hrd': hrddst, } self.muestraMenu() return self.respuestaEjecucionComando (cmd, herror, ids) def do_InventarioSoftware (self, post_params): for k in ['nfn', 'dsk', 'par', 'ids']: if k not in post_params: logger.error (f'required parameter ({k}) not in POST params') return {} nfn = post_params['nfn'] dsk = post_params['dsk'] par = post_params['par'] ids = post_params['ids'] self.muestraMensaje (7) try: cmd = self.InventariandoSoftware (dsk, par, 'InventarioSoftware') herror = 0 except: logger.warning ('Error al ejecutar el comando') cmd = { 'nfn': 'RESPUESTA_InventarioSoftware' } herror = 1 self.muestraMenu() return self.respuestaEjecucionComando (cmd, herror, ids) def do_Actualizar (self, post_params): self.muestraMensaje (1) #if !comandosPendientes: error 84 'Ha ocurrido algún problema al reiniciar la sesión del cliente' cfg = self.LeeConfiguracion() if not cfg: logger.warning ('No se ha podido recuperar la configuración de las particiones del disco') logger.error ('LeeConfiguracion() failed') return {} cmd = { 'nfn': 'RESPUESTA_Actualizar', 'cfg': self.cfg2obj (cfg), } self.muestraMenu() return self.respuestaEjecucionComando (cmd, 0) def do_Comando (self, post_params): for k in ['nfn', 'ids']: if k not in post_params: logger.error (f'required parameter ({k}) not in POST params') return {} nfn = post_params['nfn'] ids = post_params['ids'] try: self.interfaceAdmin (nfn) herror = 0 except: logger.warning ('Error al ejecutar el comando') herror = 1 cmd = { 'nfn': 'RESPUESTA_Comando', } return self.respuestaEjecucionComando (cmd, herror, ids) def do_ConsolaRemota (self, post_params): for k in ['nfn', 'scp']: if k not in post_params: logger.error (f'required parameter ({k}) not in POST params') return {} nfn = post_params['nfn'] scp = base64.b64decode (unquote (post_params['scp'])).decode ('utf-8') filescript = f'/tmp/_script_{self.IPlocal}' ecosrc = f'/tmp/_econsola_{self.IPlocal}' ecodst = f'/tmp/_Seconsola_{self.IPlocal}' ## Nombre que tendra el archivo en el Servidor with open (filescript, 'w') as fd: fd.write (scp) try: self.interfaceAdmin (nfn, [filescript, ecosrc]) ecosrc_contents = Path (ecosrc).read_bytes() except: logger.error ('Error al ejecutar el comando') return {} logger.debug ('sending recibeArchivo to server') res = self.enviaMensajeServidor ('recibeArchivo', { 'nfl': ecodst, 'contents': base64.b64encode (ecosrc_contents).decode ('utf-8') }) logger.debug (res) if not res: logger.error ('Ha ocurrido algún problema al enviar un archivo por la red') return {} def do_Apagar (self, post_params): for k in ['nfn', 'ids']: if k not in post_params: logger.error (f'required parameter ({k}) not in POST params') return {} nfn = post_params['nfn'] ids = post_params['ids'] try: self.interfaceAdmin (nfn) herror = 0 except: logger.warning ('Error al ejecutar el comando') herror = 1 cmd = { 'nfn': 'RESPUESTA_Apagar', } return self.respuestaEjecucionComando (cmd, herror, ids) def do_Reiniciar (self, post_params): for k in ['nfn', 'ids']: if k not in post_params: logger.error (f'required parameter ({k}) not in POST params') return {} nfn = post_params['nfn'] ids = post_params['ids'] try: self.interfaceAdmin (nfn) herror = 0 except: logger.warning ('Error al ejecutar el comando') herror = 1 cmd = { 'nfn': 'RESPUESTA_Reiniciar', } return self.respuestaEjecucionComando (cmd, herror, ids) def do_IniciarSesion (self, post_params): for k in ['nfn', 'dsk', 'par', 'ids']: if k not in post_params: logger.error (f'required parameter ({k}) not in POST params') return {} nfn = post_params['nfn'] dsk = post_params['dsk'] par = post_params['par'] ids = post_params['ids'] try: self.interfaceAdmin (nfn, [dsk, par]) herror = 0 except: logger.warning ('Error al ejecutar el comando') herror = 1 cmd = { 'nfn': 'RESPUESTA_IniciarSesion', } return self.respuestaEjecucionComando (cmd, herror, ids) def do_EjecutarScript (self, post_params): for k in ['nfn', 'scp', 'ids']: if k not in post_params: logger.error (f'required parameter ({k}) not in POST params') return {} nfn = post_params['nfn'] scp = base64.b64decode (unquote (post_params['scp'])).decode ('utf-8') ids = post_params['ids'] self.muestraMensaje (8) filescript = f'/tmp/_script_{self.IPlocal}' ## Nombre del archivo de script with open (filescript, 'w') as fd: fd.write (scp) try: self.interfaceAdmin (nfn, [filescript]) self.muestraMensaje (22) herror = 0 except: logger.warning ('Error al ejecutar el comando') self.muestraMensaje (21) herror = 1 ## Toma configuración de particiones cfg = self.LeeConfiguracion() if not cfg: logger.warning ('No se ha podido recuperar la configuración de las particiones del disco') herror = 36 #herror=ejecutarCodigoBash(scp); ## ogAdmClient.c:2004 cmd = { 'nfn': 'RESPUESTA_EjecutarScript', 'cfg': self.cfg2obj (cfg), } self.muestraMenu() return self.respuestaEjecucionComando (cmd, herror, ids) @execution_level('status') def process_status (self, path, get_params, post_params, server): logger.debug ('in process_status, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server)) full_config = 'full-config' in post_params and post_params['full-config'] thr_status = {} for k in self.thread_list: thr_status[k] = { 'running': self.thread_list[k]['running'], 'result': self.thread_list[k]['result'], } ret = { 'nfn': 'RESPUESTA_status', 'mac': self.mac, 'st': 'OGL', 'ip': self.IPlocal, 'threads': thr_status, } if full_config: cfg = self.LeeConfiguracion() ret['cfg'] = self.cfg2obj (cfg) return ret @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))) ## in process_popup, should not happen, path "[]" get_params "{}" post_params "{'title': 'mi titulo', 'message': 'mi mensaje'}" server "" ## type(post_params) "" return {'debug':'test'} @execution_level('full') @check_secret def process_Actualizar (self, path, get_params, post_params, server): logger.debug ('in process_Actualizar, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server)) return self._long_running_job ('Actualizar', self.do_Actualizar, args=(post_params,)) @execution_level('full') @check_secret def process_Purgar (self, path, get_params, post_params, server): logger.debug ('in process_Purgar, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server)) os.kill (os.getpid(), signal.SIGTERM) return {} #exit (0) ## ogAdmClient.c:905 @execution_level('full') @check_secret def process_Comando (self, path, get_params, post_params, server): logger.debug ('in process_Comando, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server)) return self._long_running_job ('Comando', self.do_Comando, args=(post_params,)) def process_Sondeo (self, path, get_params, post_params, server): logger.debug ('in process_Sondeo, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server)) return {} ## ogAdmClient.c:920 @execution_level('full') @check_secret def process_ConsolaRemota (self, path, get_params, post_params, server): logger.debug ('in process_ConsolaRemota, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server)) return self._long_running_job ('ConsolaRemota', self.do_ConsolaRemota, args=(post_params,)) @execution_level('full') @check_secret def process_Arrancar (self, path, get_params, post_params, server): logger.debug ('in process_Arrancar, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server)) for k in ['ids']: if k not in post_params: logger.error (f'required parameter ({k}) not in POST params') return {} ids = post_params['ids'] cmd = { 'nfn': 'RESPUESTA_Arrancar', 'tpc': 'OPG', } return self.respuestaEjecucionComando (cmd, 0, ids) @execution_level('halt') @check_secret def process_Apagar (self, path, get_params, post_params, server): logger.debug ('in process_Apagar, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server)) return self._long_running_job ('Apagar', self.do_Apagar, args=(post_params,)) @execution_level('halt') @check_secret def process_Reiniciar (self, path, get_params, post_params, server): logger.debug ('in process_Reiniciar, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server)) return self._long_running_job ('Reiniciar', self.do_Reiniciar, args=(post_params,)) @execution_level('full') @check_secret def process_IniciarSesion (self, path, get_params, post_params, server): logger.debug ('in process_IniciarSesion, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server)) return self._long_running_job ('IniciarSesion', self.do_IniciarSesion, args=(post_params,)) @execution_level('full') @check_secret def process_EjecutarScript (self, path, get_params, post_params, server): logger.debug ('in process_EjecutarScript, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server)) return self._long_running_job ('EjecutarScript', self.do_EjecutarScript, args=(post_params,)) @execution_level('full') @check_secret def process_EjecutaComandosPendientes (self, path, get_params, post_params, server): logger.debug ('in process_EjecutaComandosPendientes, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server)) return {'true':'true'} ## ogAdmClient.c:2138 @execution_level('full') @check_secret def process_CrearImagen (self, path, get_params, post_params, server): logger.debug ('in process_CrearImagen, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server)) logger.debug ('type(post_params) "{}"'.format (type (post_params))) return self._long_running_job ('CrearImagen', self.do_CrearImagen, args=(post_params,)) #def process_CrearImagenBasica (self, path, get_params, post_params, server): # logger.debug ('in process_CrearImagenBasica, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server)) # logger.warning ('this method has been removed') # raise Exception ({ '_httpcode': 404, '_msg': 'This method has been removed' }) #def process_CrearSoftIncremental (self, path, get_params, post_params, server): # logger.debug ('in process_CrearSoftIncremental, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server)) # logger.warning ('this method has been removed') # raise Exception ({ '_httpcode': 404, '_msg': 'This method has been removed' }) @execution_level('full') @check_secret def process_RestaurarImagen (self, path, get_params, post_params, server): logger.debug ('in process_RestaurarImagen, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server)) logger.debug ('type(post_params) "{}"'.format (type (post_params))) return self._long_running_job ('RestaurarImagen', self.do_RestaurarImagen, args=(post_params,)) #def process_RestaurarImagenBasica (self, path, get_params, post_params, server): # logger.debug ('in process_RestaurarImagenBasica, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server)) # logger.warning ('this method has been removed') # raise Exception ({ '_httpcode': 404, '_msg': 'This method has been removed' }) #def process_RestaurarSoftIncremental (self, path, get_params, post_params, server): # logger.warning ('in process_RestaurarSoftIncremental') # logger.debug ('in process_RestaurarSoftIncremental, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server)) # logger.warning ('this method has been removed') # raise Exception ({ '_httpcode': 404, '_msg': 'This method has been removed' }) ## una partición + cache en disco de 30 Gb: @execution_level('full') @check_secret def process_Configurar (self, path, get_params, post_params, server): logger.debug ('in process_Configurar, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server)) return self._long_running_job ('Configurar', self.do_Configurar, args=(post_params,)) @execution_level('full') @check_secret def process_InventarioHardware (self, path, get_params, post_params, server): logger.debug ('in process_InventarioHardware, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server)) return self._long_running_job ('InventarioHardware', self.do_InventarioHardware, args=(post_params,)) @execution_level('full') @check_secret def process_InventarioSoftware (self, path, get_params, post_params, server): logger.debug ('in process_InventarioSoftware, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server)) return self._long_running_job ('InventarioSoftware', self.do_InventarioSoftware, args=(post_params,)) @execution_level('full') @check_secret def process_KillJob (self, path, get_params, post_params, server): logger.debug ('in process_KillJob, path "{}" get_params "{}" post_params "{}" server "{}"'.format (path, get_params, post_params, server)) jid = post_params['job_id'] r = self.killer (jid) logger.debug (f'r bef ({r})') r.update ({ 'nfn':'RESPUESTA_KillJob', 'job':jid }) logger.debug (f'r aft ({r})') return r