def prepareServerForNewUser(self, user): username = '' if user is None: user = None elif isinstance(user, User): user = self.getUserCreateIfNotExistent(user.name) elif isinstance(user, basestring): user = self.getUserCreateIfNotExistent(user) else: raise ValueError('User must be either None, a User Class or a string') if self.activeUser: self.log.info('Logging current user out: %s' % self.activeUser.name) self.terminateAllComponents( self.activeUser ) if user: self.log.info('Preparing the Server for new user: %s' % username) # Clear the eventHistory EventHistory.clear() self.activeUser = user
def screenReaderStopped(self, reader): self.log.debug( 'Screenreader stopped %s' % reader.name ) if not self.component: raise AttributeError('Component is not set') if not self.isAlive(): EventHistory.actionStopped(self, self.component)
def lostConnection(self): self.log.warning('Lost connection to %s' % str(self)) self.log.info ('Informing all components assigned to this host') EventHistory.hostOffline(self) self.ctrlChannel = None self.screenReader = None self.ssh.disconnect()
def killStateChannel( self ): self.log.debug('Killing state channel for Action "%s"' % ( self.name )) if self.stateChannel: self.stateChannel.send(chr(3)) self.stateChannel.send( 'exit\n' ) if self.stateCommand: # non blocking commands, so only one shell required # kill both screens for start and stop command channel = self.component.host.invokeShell() cmd = self.createKillCmd( self.stateCommand ) channel.send(cmd) self.state = None EventHistory.newState( self, self.component, self.state )
def screenReaderStopped(self, reader): self.log.debug( 'Action %s\'s ScreenReader stopped %s. Still alive: %s' % ( self.name, reader.name, self.isAlive() )) if not self.component: raise AttributeError('Component is not set') if not self.isAlive(): EventHistory.actionStopped(self, self.component) for s in self.screenReaders['show']: if s.isAlive(): self.log.debug( 'Action %s\'s Show-ScreenReader %s is alive' % ( self.name, s.name )) for s in self.screenReaders['hide']: if s.isAlive(): self.log.debug( 'Action %s\'s Hide-ScreenReader %s is alive' % ( self.name, s.name ))
def start(self, globalVars=None): if not self.component or not self.component.host: raise AttributeError('Host is not set for %s' % str(self)) if not self.isAlive(): self.clearScreenReaders() if not self.canStart(): self.log.info('Cannot start Action "%s", no commands found' % (self.name)) return self.log.info('Starting Action "%s". "%d" Commands / "%d" dependencies found' % (self.name, len(self._startCommands), len(self.dependencies))) if len(self.dependencies): self.log.info('Action depends on: %s' % list('%s>%s' % (item.component.getName(), item.name) for item in self.dependencies)) for dep in self.dependencies: dep.start() for cmd in self._startCommands.values(): channel = self.component.host.invokeShell() command = self.createScreenCmd( cmd, globalVars ) hideLog = cmd.hideLog self.startChannels.append(channel) screen_name = self.name + '_run' screenReader = ScreenReader( screen_name, channel, self.log, notifyStop=self.screenReaderStopped) self.screenReaders['hide' if hideLog else 'show'].append(screenReader) screenReader.start() self.log.debug('Running start command "%s" by Action "%s"' % (command.replace('\n','\\n'), self.name)) channel.send(command) self.constantlyCheckState( globalVars ) # if blocking is enabled for this command, wait for the screenreader to quit if cmd.blocking and screenReader and screenReader.isAlive(): self.log.debug('Command requires blocking. Action "%s" joined the screenReader Thread. Waiting for it to finish' % self.name) screenReader.join( 5.0 ) # notify EventHandler after all cmds run if self.isAlive(): EventHistory.actionRun(self, self.component) return True else: self.log.debug('Could not start action "%s", Action still active' % self.name) return False
def connect(self): if not self.isConnected(): try: self.ssh.connect() except socket.timeout as e: self.log.debug('Connection to %s timed out' % str(self)) return False except Exception as e: self.log.debug('Could not connect to %s' % str(self)) return False try: self.log.info('Connected to %s' % str(self)) EventHistory.hostOnline(self) return True except Exception as e: self.log.exception('Could open control. Clossing %s' % str(self)) self.screenReader = None self.disconnect() return False
def notifyNewStatusLine( self, screen, line ): configurationStart = line.rfind( '<configuration>' ) configurationEnd = line.rfind( '</configuration' ) if configurationStart < 0 or configurationEnd < 0: return configTxt = line[ configurationStart : configurationEnd ] code = '' codeStart = configTxt.find( '<code>' ) codeEnd = configTxt.find( '</code>' ) if codeStart >= 0 and codeEnd >= 0: code = configTxt[ codeStart+len( '<code>' ) : codeEnd ] message = '' messageStart = configTxt.find( '<message>' ) messageEnd = configTxt.find( '</message>' ) if messageStart >= 0 and messageEnd >= 0: message = configTxt[ messageStart+len( '<message>' ) : messageEnd ] if not self.state or self.state[ 'code' ] != code or self.state[ 'message' ] != message: print 'CODE: "%s", MESSGAGE: "%s"' % ( code, message ) self.state = { 'code': code, 'message': message } EventHistory.newState( self, self.component, self.state )
def do_GET(self): serverThread = self.server.serverThread activeUser = serverThread.activeUser try: responseCode = 200 args = {} options = {} output = None try: auth = None if self.headers.has_key('Authorization'): userPass = None auth = {'token': str(self.headers['Authorization'])} if auth[ 'token' ].lower().startswith( 'basic' ): # remove the leading "Basic " before splitting into user/pass userPass = base64.b64decode(auth['token'][6:]).split(':') elif auth[ 'token' ].lower().startswith( 'localhost' ): host, port = self.client_address if host != 'localhost' and host != '127.0.0.1': raise UnauthorizedRequestError( 'Only allowed by localhost', self.path ) name = auth[ 'token' ][ 10: ] userPass = [ name, '' ] else: raise UnauthorizedRequestError( 'Illegal token: %s' % auth[ 'token' ], self.path) if len(userPass) != 2: auth = None self.server.log.warn('Invalid Authorization Header: %s', str(self.headers['Authorization'])) else: # important: always process names in lowercase auth['user'] = userPass[0].lower() auth['pass'] = userPass[1] if not activeUser: auth['status'] = WebServer.SERVER_AVAILABLE elif activeUser and activeUser.name == auth['user']: auth['status'] = WebServer.SERVER_IN_CHARGE else: auth['status'] = WebServer.SERVER_NOT_AVAILABLE # if no auth was sent, return an 401 Unauthorized if not auth: raise UnauthorizedRequestError('No Auth-Token received', self.path) # get the request user requestUser = serverThread.getUserCreateIfNotExistent(auth['user']) # split the path by the first ? argsString, optionsString = self.path.split('?', 1) if self.path.find('?') > 0 else (self.path, '') # parse the request (remove the leading and trailing / , then split by /) args = argsString.strip('/').split("/") # parse the options string temp = optionsString.split('&') for t in temp: key, value = t.split('=',1) if t.find('=') > 0 else (t, '') if key: value = urllib2.unquote( urllib2.unquote(value)).replace( '+', ' ' ) if value else None options[key] = value # action is the first argument action = args[0] # Status Command must be available even if no user is logged in if action == 'status': output = '{"status": %d}' % auth['status'] elif action == 'info': output = '[Path]<br>%s<br>' % str(self.path) output += '<br>' output += '[Args]<br>%s<br>' % str(args) output += '<br>' output += '[Options]<br>%s<br>' % str(options) output += '<br>' output += '[ActiveUser]<br>' if activeUser: output += 'name:%s<br>' % activeUser.name else: output += 'None<br>' output += '<br>' output += '[RequestUser]<br>name:%s<br>' % requestUser.name output += '<br>' output += '[Components]<br>' output += "<table>" output += "<tr><th>Name</th><th>Active</th><th>Online ScreenReader Show</th><th>Online ScreenReader Hide</th></tr>" for comp in requestUser.components(): ma = comp.mainAction output += '<tr>' output += '<td>%s</td>' % ma.name output += '<td>%s</td>' % ma.isAlive() output += '<td>' for s in ma.screenReaders[ 'show' ]: if s.isAlive(): output += str( s.name ) output += '</td><td>' for s in ma.screenReaders[ 'hide' ]: if s.isAlive(): output += str( s.name ) output += '</td>' output += '</tr>' output += '</table>' output += '<br>' * 3 output += '[Hosts]<br>' for host in serverThread.hosts.values(): output += '%s<br>' % str(host) output += '<br>' output += '[Auth]<br>' if not auth: output += 'None' else: output += 'token: %s<br>' % auth['token'] output += 'user: %s<br>' % auth['user'] output += '<br>' output += '[Permission]<br>' output += "Bitmask: %s<br>" % str(requestUser.getPrivileges()) output += "ACTION_RUN: %s<br>" % str(requestUser.hasPrivilege(privileges.ACTION_RUN)) output += "ACTION_STOP: %s<br>" % str(requestUser.hasPrivilege(privileges.ACTION_STOP)) output += "ACTION_STATUS: %s<br>" % str(requestUser.hasPrivilege(privileges.ACTION_STATUS)) output += "COMP_ADMIN: %s<br>" % str(requestUser.hasPrivilege(privileges.COMP_ADMIN)) output += "HOST_ADMIN: %s<br>" % str(requestUser.hasPrivilege(privileges.HOST_ADMIN)) output += "START_SERVER: %s<br>" % str(requestUser.hasPrivilege(privileges.START_SERVER)) output += "PRIV_ADMIN: %s<br>" % str(requestUser.hasPrivilege(privileges.PRIV_ADMIN)) # privileges elif action == 'privileges': if len(args) < 2: raise ArgumentRequestError('Wrong argument count for "privileges". %s found, at least 2 Required.' % str(args), self.path) if args[1] == 'my': output = str(requestUser.getPrivileges()) elif args[1] == 'all': if not requestUser.hasPrivilege(privileges.PRIV_ADMIN): raise UnauthorizedRequestError('Insufficient rights.', self.path) allUsersPermission = serverThread.allUsersPermission(); output = json.dumps({'labels': privileges.dict(), 'users': allUsersPermission}) elif args[1] == 'submit': if not requestUser.hasPrivilege(privileges.PRIV_ADMIN): raise UnauthorizedRequestError('Insufficient rights.', self.path) serverThread.savePermissions(options) output = "Ok." else: raise ArgumentRequestError('Invalid Argument for privileges "%s". ' % str(args[1]), self.path) # Request host / component data elif action == 'data': # data/(host|comp) if len(args) < 2: raise ArgumentRequestError('Wrong argument count for "data". %s found, at least 2 Required.' % str(args), self.path) if args[1] == 'host': JSONObj = {} for host in serverThread.hosts.values(): JSONObj[host.id] = host.createJSONObj() output = json.dumps(JSONObj) #TODO: use json dump a la json.dump(comp.webInformation)! elif args[1] == 'comp': JSONObj = {} for comp in requestUser.components(): JSONObj[comp.id] = comp.createJSONObj(); output = json.dumps(JSONObj) # Events elif args[1] == 'eventHistory': # you must be in charge if not auth['status'] == WebServer.SERVER_IN_CHARGE: raise UnauthorizedRequestError('You are not in charge.', self.path) if len(args) != 3: raise ArgumentRequestError('Wrong argument count for "data/eventHistory". %s found, 3 Required.' % str(args), self.path) if not args[2].isdigit(): raise ArgumentRequestError('Invalid argument for timestamp "%s". timestamp must be numerical.' % args[2], self.path) timestamp = int(args[2]) data = EventHistory.getEventData(timestamp) #TODO: use json dump outputObject = { "timestamp": time.time(), "events": data } output = json.dumps( outputObject ) else: raise ArgumentRequestError('Invalid Argument for data "%s". ' % str(args[1]), self.path) elif action == 'parameters': # you must be in charge if not auth['status'] == WebServer.SERVER_IN_CHARGE: raise UnauthorizedRequestError('You are not in charge.', self.path) try: command = args[ 1 ] compId = int( args[ 2 ]) actionId = int( args[ 3 ]) except ( ValueError, KeyError, IndexError ) as e: raise ArgumentRequestError( 'Wrong format for parameter', self.path ) if command not in ( 'load', 'save' ): raise ArgumentRequestError( 'Wrong command type', self.path ) comp = activeUser.get(compId) if not comp: raise ArgumentRequestError('Component with id "%d" not found' % compId, self.path) action = comp.getAction(actionId) if not action: raise ArgumentRequestError('Action "%d" for component "%d, %s" not found.' % (actionId, compId, comp.getName()), self.path) if command == 'load': parameters = serverThread.loadParameters( comp, action ) output = parameters if command == 'save': try: print options[ 'json' ] data = json.loads( options['json'] ) print data except KeyError, e: raise ArgumentRequestError( 'Data Field missing', self.path ) except ValueError, e: raise ArgumentRequestError('Could not decode json Object:\n%s' % options['json'], self.path) if serverThread.saveParameters( comp, action, data ): output = '{"success": true}' else: output = '{"success": false}'