def start(self): """ Start the daemon """ logger.debug('Starting daemon') # Check for a pidfile to see if the daemon already runs try: pf = open(self.pidfile, 'r') pid = int(pf.read().strip()) pf.close() except IOError: pid = None if pid: message = "pidfile {} already exist. Daemon already running?\n".format( pid) logger.error(message) sys.stderr.write(message) sys.exit(1) # Start the daemon self.daemonize() try: self.run() except Exception as e: logger.error('Exception running process: {}'.format(e)) if os.path.exists(self.pidfile): os.remove(self.pidfile)
def run(self): if self.ipc is None: return self.running = True # Wait a bit so we ensure IPC thread is running... time.sleep(2) while self.running and self.ipc.running: try: msg = self.ipc.getMessage() if msg is None: break msgId, data = msg logger.debug('Got Message on User Space: {}:{}'.format( msgId, data)) if msgId == ipc.MSG_MESSAGE: module, message, data = data.split('\0') self.message.emit((module, message, data)) elif msgId == ipc.MSG_LOGOFF: self.logoff.emit() elif msgId == ipc.MSG_SCRIPT: self.script.emit(QtCore.QString.fromUtf8(data)) except Exception as e: try: logger.error('Got error on IPC thread {}'.format( utils.exceptionToMessage(e))) except: logger.error( 'Got error on IPC thread (an unicode error??)') if self.ipc.running is False and self.running is True: logger.warn('Lost connection with Service, closing program') self.exit.emit()
def run(self): self.running = True self.serverSocket.bind(('localhost', self.port)) self.serverSocket.setblocking(1) self.serverSocket.listen(4) while True: try: (clientSocket, address) = self.serverSocket.accept() # Stop processing if thread is mean to stop if self.running is False: break logger.debug('Got connection from {}'.format(address)) self.cleanupFinishedThreads() # House keeping logger.debug('Starting new thread, current: {}'.format( self.threads)) t = ClientProcessor(self, clientSocket) self.threads.append(t) t.start() except Exception as e: logger.error( 'Got an exception on Server ipc thread: {}'.format(e))
def getNetworkInfo(): ''' Obtains a list of network interfaces @return: A "generator" of elements, that are dict-as-object, with this elements: name: Name of the interface mac: mac of the interface ip: ip of the interface ''' obj = win32com.client.Dispatch("WbemScripting.SWbemLocator") wmobj = obj.ConnectServer("localhost", "root\cimv2") adapters = wmobj.ExecQuery( "Select * from Win32_NetworkAdapterConfiguration where IpEnabled=True") try: for obj in adapters: if obj.DefaultIPGateway is None: # Skip adapters without default router continue for ip in obj.IPAddress: if ':' in ip: # Is IPV6, skip this continue if ip is None or ip == '' or ip.startswith( '169.254') or ip.startswith( '0.'): # If single link ip, or no ip continue logger.debug('Net config found: {}=({}, {})'.format( obj.Caption, obj.MACAddress, ip)) yield utils.Bunch(name=obj.Caption, mac=obj.MACAddress, ip=ip) except Exception: return
def run(self): logger.debug('** Running Daemon **') set_proctitle('OGAgent') self.initialize() # Call modules initialization # They are called in sequence, no threading is done at this point, so ensure modules onActivate always returns # ********************* # * Main Service loop * # ********************* # Counter used to check ip changes only once every 10 seconds, for # example try: while self.isAlive: # In milliseconds, will break self.doWait(1000) except (KeyboardInterrupt, SystemExit) as e: logger.error('Requested exit of main loop') except Exception as e: logger.exception() logger.error('Caught exception on main loop: {}'.format(e)) self.terminate() self.notifyStop()
def rename(newName): ''' RH, Centos, Fedora Renamer Expects new host name on newName Host does not needs to be rebooted after renaming ''' logger.debug('using RH renamer') with open('/etc/hostname', 'w') as hostname: hostname.write(newName) # Force system new name os.system('/bin/hostname %s' % newName) # add name to "hosts" with open('/etc/hosts', 'r') as hosts: lines = hosts.readlines() with open('/etc/hosts', 'w') as hosts: hosts.write("127.0.1.1\t{}\n".format(newName)) for l in lines: if l[:9] != '127.0.1.1': # Skips existing 127.0.1.1. if it already exists hosts.write(l) with open('/etc/sysconfig/network', 'r') as net: lines = net.readlines() with open('/etc/sysconfig/network', 'w') as net: net.write('HOSTNAME={}\n'.format(newName)) for l in lines: if l[:8] != 'HOSTNAME': net.write(l) return True
def message(self, msg): ''' Processes the message sent asynchronously, msg is an QString ''' try: logger.debug('msg: {}, {}'.format(type(msg), msg)) module, message, data = msg except Exception as e: logger.error('Got exception {} processing message {}'.format( e, msg)) return for v in self.modules: if v.name == module: # Case Sensitive!!!! try: logger.debug( 'Notifying message {} to module {} with json data {}'. format(message, v.name, data)) v.processMessage(message, json.loads(data)) return except Exception as e: logger.error( 'Got exception {} processing generic message on {}'. format(e, v.name)) logger.error('Module {} not found, messsage {} not sent'.format( module, message))
def cleanup(self): logger.debug('Quit invoked') if self.stopped is False: self.stopped = True try: self.deinitialize() except Exception: logger.exception() logger.error('Got exception deinitializing modules') try: # If we close Client, send Logoff to Broker self.ipc.sendLogout(operations.getCurrentUser()) time.sleep(1) self.timer.stop() self.ipc.stop() except Exception: # May we have lost connection with server, simply log and exit in that case logger.exception() logger.exception("Got an exception, processing quit") try: # operations.logoff() # Uncomment this after testing to logoff user pass except Exception: pass
def process_popup(self, path, get_params, post_params, server): """ Shows a message popup on the user's session """ logger.debug('Received message operation') # Sending popup message to OGAgent client self.sendClientMessage('popup', post_params) return {'op': 'launched'}
def process_logoff(self, path, get_params, post_params, server): """ Closes user session """ logger.debug('Received logoff operation') # Sending log off message to OGAgent client self.sendClientMessage('logoff', {}) return {'op': 'sent to client'}
def process_popup(self, path, getParams, postParams, server): ''' Shows a message popup on the user's session. ''' logger.debug('Received message operation') self.checkSecret(server) # Sending popup message to OGAgent client. self.sendClientMessage('popup', postParams) return {'op': 'launched'}
def process_logoff(self, path, getParams, postParams, server): ''' Closes user session. ''' logger.debug('Received logoff operation') self.checkSecret(server) # Sending log off message to OGAgent client. self.sendClientMessage('logoff', {}) return {'op': 'sent to client'}
def cleanupFinishedThreads(self): ''' Cleans up current threads list ''' aliveThreads = [] for t in self.threads: if t.isAlive(): logger.debug('Thread {} is alive'.format(t)) aliveThreads.append(t) self.threads[:] = aliveThreads
def onLogout(self, user): ''' Sends session logout notification to OpenGnsys server ''' logger.debug('Received logout for {}'.format(user)) self.loggedin = False self.REST.sendMessage('ogagent/loggedout', { 'ip': self.interface.ip, 'user': user })
def deinitialize(self): for mod in reversed( self.modules): # Deinitialize reversed of initialization try: logger.debug('Deactivating module {}'.format(mod.name)) mod.deactivate() except Exception as e: logger.exception() logger.error("Deactivation of {} failed: {}".format( mod.name, utils.exceptionToMessage(e)))
def stop(self): logger.debug('Stopping Server IPC') self.running = False for t in self.threads: t.stop() socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect( ('localhost', self.port)) self.serverSocket.close() for t in self.threads: t.join()
def onActivation(self): ''' Sends OGAgent activation notification to OpenGnsys server ''' t = 0 # Generate random secret to send on activation 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 self.REST = REST(self.service.config.get('opengnsys', 'remote')) # Get network interfaces until they are active or timeout (5 minutes) for t in range(0, 300): try: self.interface = list(operations.getNetworkInfo())[ 0] # Get first network interface except Exception as e: # Wait 1 sec. and retry time.sleep(1) finally: # Exit loop if interface is active if self.interface: if t > 0: logger.debug( "Fetch connection data after {} tries".format(t)) break # Raise error after timeout if not self.interface: raise e # Loop to send initialization message for t in range(0, 100): try: self.REST.sendMessage( 'ogagent/started', { 'mac': self.interface.mac, 'ip': self.interface.ip, 'secret': self.random, 'ostype': operations.osType, 'osversion': operations.osVersion }) break except: time.sleep(3) if 0 < t < 100: logger.debug("Successful connection after {} tries".format(t)) elif t == 100: raise Exception( 'Initialization error: Cannot connect to remote server') # Delete marking files for f in ['ogboot.me', 'ogboot.firstboot', 'ogboot.secondboot']: try: os.remove(os.sep + f) except OSError: pass
def onDeactivation(self): ''' Sends OGAgent stopping notification to OpenGnsys server ''' logger.debug('onDeactivation') self.REST.sendMessage( 'ogagent/stopped', { 'mac': self.interface.mac, 'ip': self.interface.ip, 'ostype': operations.osType, 'osversion': operations.osVersion })
def sendRequestMessage(self, msg, data=None): logger.debug('Sending request for msg: {}({}), {}'.format( msg, REV_DICT.get(msg), data)) if data is None: data = b'' if isinstance(data, six.text_type): # Convert to bytes if necessary data = data.encode('utf-8') l = len(data) msg = six.int2byte(msg) + six.int2byte(l & 0xFF) + six.int2byte( l >> 8) + data self.clientSocket.sendall(msg)
def process_reboot(self, path, getParams, postParams, server): ''' Launches a system reboot operation. ''' logger.debug('Received reboot operation') self.checkSecret(server) # Rebooting thread. def rebt(): operations.reboot() threading.Thread(target=rebt).start() return {'op': 'launched'}
def __init__(self, port): super(self.__class__, self).__init__() # Retries connection for a while for _ in range(10): try: self.ipc = ipc.ClientIPC(port) self.ipc.start() break except Exception: logger.debug('IPC Server is not reachable') self.ipc = None time.sleep(2) self.running = False
def process_poweroff(self, path, getParams, postParams, server): ''' Launches a system power off operation. ''' logger.debug('Received poweroff operation') self.checkSecret(server) # Powering off thread. def pwoff(): time.sleep(2) operations.poweroff() threading.Thread(target=pwoff).start() return {'op': 'launched'}
def sendMessage(self, msgId, msgData): ''' Notify message to all listening threads ''' logger.debug('Sending message {}({}),{} to all clients'.format( msgId, REV_DICT.get(msgId), msgData)) # Convert to bytes so length is correctly calculated if isinstance(msgData, six.text_type): msgData = msgData.encode('utf8') for t in self.threads: if t.isAlive(): logger.debug('Sending to {}'.format(t)) t.messages.put((msgId, msgData))
def onLogin(self, userData): ''' Sends session login notification to OpenGnsys server ''' user, sep, language = userData.partition(',') logger.debug('Received login for {} with language {}'.format( user, language)) self.loggedin = True self.REST.sendMessage( 'ogagent/loggedin', { 'ip': self.interface.ip, 'user': user, 'language': language, 'ostype': operations.osType, 'osversion': operations.osVersion })
def process_reboot(self, path, get_params, post_params, server): """ Launches a system reboot operation :param path: :param get_params: :param post_params: :param server: authorization header :return: JSON object {"op": "launched"} """ logger.debug('Received reboot operation') # Rebooting thread def rebt(): operations.reboot() threading.Thread(target=rebt).start() return {'op': 'launched'}
def receiveBytes(self, number): msg = b'' while self.running and len(msg) < number: try: buf = self.clientSocket.recv(number - len(msg)) if buf == b'': logger.debug('Buf {}, msg {}({})'.format( buf, msg, REV_DICT.get(msg))) self.running = False break msg += buf except socket.timeout: pass if self.running is False: logger.debug('Not running, returning None') return None return msg
def process_script(self, path, getParams, postParams, server): ''' Processes an script execution (script should be encoded in base64) ''' logger.debug('Processing script request') self.checkSecret(server) # Decoding script. script = urllib.unquote( postParams.get('script').decode('base64')).decode('utf8') script = 'import subprocess; subprocess.check_output("""{}""",shell=True)'.format( script) # Executing script. if postParams.get('client', 'false') == 'false': thr = ScriptExecutorThread(script) thr.start() else: self.sendClientMessage('script', {'code': script}) return {'op': 'launched'}
def process_poweroff(self, path, get_params, post_params, server): """ Launches a system power off operation :param path: :param get_params: :param post_params: :param server: authorization header :return: JSON object {"op": "launched"} """ logger.debug('Received poweroff operation') # Powering off thread def pwoff(): time.sleep(2) operations.poweroff() threading.Thread(target=pwoff).start() return {'op': 'launched'}
def initialize(self): # Load modules and activate them # Also, sends "login" event to service self.modules = loadModules(self, client=True) logger.debug('Modules: {}'.format(list(v.name for v in self.modules))) # Send init to all modules validMods = [] for mod in self.modules: try: logger.debug('Activating module {}'.format(mod.name)) mod.activate() validMods.append(mod) except Exception as e: logger.exception() logger.error("Activation of {} failed: {}".format( mod.name, utils.exceptionToMessage(e))) self.modules[:] = validMods # copy instead of assignment # If this is running, it's because he have logged in, inform service of this fact self.ipc.sendLogin(operations.getCurrentUser(), operations.getSessionLanguage())
def process_script(self, path, get_params, post_params, server): """ Processes an script execution (script should be encoded in base64) :param path: :param get_params: :param post_params: JSON object {"script": "commands"} :param server: authorization header :return: JSON object {"op": "launched"} """ logger.debug('Processing script request') # Decoding script script = urllib.unquote( post_params.get('script').decode('base64')).decode('utf8') script = 'import subprocess;{0}'.format(';'.join([ 'subprocess.check_output({0},shell=True)'.format(repr(c)) for c in script.split('\n') ])) # Executing script. if post_params.get('client', 'false') == 'false': thr = ScriptExecutorThread(script) thr.start() else: self.sendClientMessage('script', {'code': script}) return {'op': 'launched'}