def test_receive_chain_commands_success(self): filesystem = FileFactory() moved = MovedFileFactory.build() error_status1 = Status.ok({ 'method': 'filesystem_move', 'result': moved.hash_value, }) error_status1.uuid = filesystem.command_uuid error_status2 = Status.ok({ 'method': 'filesystem_move', 'result': moved.hash_value, }) error_status2.uuid = filesystem.command_uuid error_chain = Status.ok({ 'method': 'chain_execution', 'result': [dict(error_status1), dict(error_status2)], }) # connect webinterface webinterface = WSClient() webinterface.join_group('notifications') ws_client = WSClient() ws_client.send_and_consume( 'websocket.receive', path='/commands', content={'text': error_chain.to_json()}, ) query = FilesystemModel.objects.get(id=filesystem.id) self.assertEqual(query.hash_value, moved.hash_value) self.assertEqual(query.error_code, "") self.assertEqual( Status.ok({ 'filesystem_status': 'moved', 'fid': str(filesystem.id), }), Status.from_json(json.dumps(webinterface.receive())), ) self.assertEqual( Status.ok({ 'filesystem_status': 'moved', 'fid': str(filesystem.id), }), Status.from_json(json.dumps(webinterface.receive())), ) self.assertIsNone(webinterface.receive())
def test_receive_execute_success(self): program_status = ProgramStatusFactory(running=True) program = program_status.program expected_status = Status.ok({'method': 'execute', 'result': 0}) expected_status.uuid = program_status.command_uuid # connect webinterface webinterface = WSClient() webinterface.send_and_consume( 'websocket.connect', path='/notifications', ) ws_client = WSClient() ws_client.send_and_consume( 'websocket.receive', path='/commands', content={'text': expected_status.to_json()}, ) query = ProgramStatusModel.objects.filter(program=program, code=0) self.assertTrue(query.count() == 1) self.assertFalse(query.first().running) # test if the webinterface gets the "finished" message self.assertEqual( Status.ok({ 'program_status': 'finished', 'pid': str(program.id), 'code': 0, }), Status.from_json(json.dumps(webinterface.receive())), )
def ws_rpc_receive(message): """ Handles incoming requests on the websocket `/commands`. The incoming message will be parsed to a `Status` object. The appropriate handler is called with `select_method`. Parameters ---------- message: channels.message.Message Contains a message which needs to be JSON encoded string. """ try: try: status = Status.from_json(message.content['text']) except ValueError as err: LOGGER.error( "Error while parsing json. (cause: %s)", str(err), ) return select_method(status) except FormatError as err: LOGGER.error( "Could not parse Status from incoming request. (cause: %s)", str(err), ) except KeyError: LOGGER.error("No content['text'] in received message.")
def test_receive_online_success(self): slave = SlaveOnlineFactory(online=False) expected_status = Status.ok({'method': 'online'}) expected_status.uuid = slave.command_uuid # connect webinterface on /notifications webinterface = WSClient() webinterface.join_group('notifications') # send online answer ws_client = WSClient() ws_client.send_and_consume( 'websocket.receive', path='/commands', content={'text': expected_status.to_json()}, ) self.assertTrue(SlaveModel.objects.get(id=slave.id).is_online) # test if a connected message was send on /notifications self.assertEqual( Status.ok({ 'slave_status': 'connected', 'sid': str(slave.id), }), Status.from_json(json.dumps(webinterface.receive())), )
def test_receive_online_with_error_status(self): slave = SlaveOnlineFactory(online=False) error_status = Status.err({ 'method': 'online', 'result': str(Exception('foobar')) }) error_status.uuid = slave.command_uuid # connect webinterface on /notifications webinterface = WSClient() webinterface.join_group('notifications') # send online answer ws_client = WSClient() ws_client.send_and_consume('websocket.receive', path='/commands', content={'text': error_status.to_json()}) self.assertFalse(SlaveModel.objects.get(id=slave.id).is_online) # test if a connected message was send on /notifications self.assertEqual( Status.err( 'An error occurred while connecting to client {}!'.format( slave.name)), Status.from_json(json.dumps(webinterface.receive())), )
def test_receive_get_log_program_not_exists(self): error_status = Status.ok({ 'method': 'get_log', 'result': { 'log': '', 'uuid': '0' }, }) # connect webinterface webinterface = WSClient() webinterface.join_group('notifications') ws_client = WSClient() ws_client.send_and_consume( 'websocket.receive', path='/commands', content={'text': error_status.to_json()}, ) # test if the webinterface gets the error message self.assertEqual( Status.err('Received log from unknown program!'), Status.from_json(json.dumps(webinterface.receive())), )
def test_receive_filesystem_restore_with_error_code(self): filesystem = MovedFileFactory() error_code = 'any kind of string' error_status = Status.err({ 'method': 'filesystem_restore', 'result': error_code, }) error_status.uuid = filesystem.command_uuid # connect webinterface webinterface = WSClient() webinterface.join_group('notifications') ws_client = WSClient() ws_client.send_and_consume( 'websocket.receive', path='/commands', content={'text': error_status.to_json()}, ) query = FilesystemModel.objects.get(id=filesystem.id) self.assertEqual(query.error_code, error_code) self.assertEqual( Status.ok({ 'filesystem_status': 'error', 'fid': str(filesystem.id), 'error_code': error_code, }), Status.from_json(json.dumps(webinterface.receive())), )
def test_receive_get_log_success(self): program_status = ProgramStatusFactory(running=True) program = program_status.program error_status = Status.ok({ 'method': 'get_log', 'result': { 'log': 'this is the content of a logfile', 'uuid': program_status.command_uuid, }, }) # connect webinterface webinterface = WSClient() webinterface.join_group('notifications') ws_client = WSClient() ws_client.send_and_consume( 'websocket.receive', path='/commands', content={'text': error_status.to_json()}, ) # test if the webinterface gets the error message self.assertEqual( Status.ok({ 'log': 'this is the content of a logfile', 'pid': str(program.id), }), Status.from_json(json.dumps(webinterface.receive())), )
def test_receive_execute_with_error_status(self): program_status = ProgramStatusFactory(running=True) program = program_status.program error_status = Status.err({ 'method': 'execute', 'result': str(Exception('foobar')), }) error_status.uuid = program_status.command_uuid # connect webinterface webinterface = WSClient() webinterface.join_group('notifications') ws_client = WSClient() ws_client.send_and_consume( 'websocket.receive', path='/commands', content={'text': error_status.to_json()}, ) query = ProgramStatusModel.objects.get(program=program) self.assertFalse(query.running) self.assertEqual(query.code, 'foobar') # test if the webinterface gets the error message self.assertEqual( Status.ok({ 'program_status': 'finished', 'pid': str(program.id), 'code': 'foobar', }), Status.from_json(json.dumps(webinterface.receive())), )
def test_state_init(self): webinterface = WSClient() webinterface.join_group('notifications') ScriptModel.objects.filter(id=self.script.id).update( is_running=True, is_initialized=True, current_index=-1, ) self.sched._Scheduler__index = -1 self.sched._Scheduler__script = self.script.id self.sched._Scheduler__event = asyncio.Event(loop=self.sched.loop) self.sched._Scheduler__state = SchedulerStatus.INIT self.sched._Scheduler__state_init() self.assertEqual( self.sched._Scheduler__state, SchedulerStatus.WAITING_FOR_SLAVES, ) msg1 = Status.from_json(json.dumps(webinterface.receive())) msg2 = Status.from_json(json.dumps(webinterface.receive())) msg3 = Status.from_json(json.dumps(webinterface.receive())) expct1 = Status.ok({ 'script_status': 'waiting_for_slaves', 'script_id': self.script.id, }) expct2 = Status.ok({ 'message': "Send start command to client `{}`".format(self.prog1.slave.name), }) expct3 = Status.ok({ 'message': "Send start command to client `{}`".format(self.prog2.slave.name), }) self.assertStatusSet( [msg1, msg2, msg3], [expct1, expct2, expct3], )
def websocket_handler(websocket, path): self.assertEqual('/logs', path) # receive log from file json = yield from websocket.recv() log = Status.from_json(json).payload['log'].encode() # ack yield from websocket.send('') #receive dynamic log while True: json = yield from websocket.recv() # ack msg = Status.from_json(json).payload['log'].encode() log += msg if msg == b'': break else: yield from websocket.send('') self.assertIn(expected_log, log) print('finished server') finished.set_result(None)
def test_disconnect_success(self): slave = SlaveOnlineFactory() program_status = ProgramStatusFactory(program__slave=slave) program = program_status.program # connect client on /commands ws_client = WSClient() ws_client.send_and_consume( 'websocket.connect', path='/commands', content={'client': [slave.ip_address, slave.mac_address]}) # connect webinterface on /notifications webinterface = WSClient() webinterface.send_and_consume( 'websocket.connect', path='/notifications', ) # throw away connect repsonse ws_client.receive() ws_client.send_and_consume('websocket.disconnect', path='/commands') # test if SlaveStatus was to offline self.assertFalse(SlaveModel.objects.get(id=slave.id).is_online) Group('client_{}'.format(slave.id)).send( {'text': 'ok'}, immediately=True, ) self.assertIsNone(ws_client.receive()) # test if program status was removed self.assertFalse( ProgramStatusModel.objects.filter(program=program).exists()) # test if a "disconnected" message has been send to the webinterface self.assertEqual( Status.ok({ 'slave_status': 'disconnected', 'sid': str(slave.id) }), Status.from_json(json.dumps(webinterface.receive())))
def test_state_success(self): webinterface = WSClient() webinterface.join_group('notifications') self.sched._Scheduler__event = asyncio.Event(loop=self.sched.loop) self.sched._Scheduler__script = self.script.id self.sched._Scheduler__state = SchedulerStatus.SUCCESS self.sched._Scheduler__state_success() self.assertEqual( self.sched._Scheduler__state, SchedulerStatus.SUCCESS, ) self.assertEqual( Status.ok({ 'script_status': 'success', 'script_id': self.script.id, }), Status.from_json(json.dumps(webinterface.receive())), )
def test_connect_and_disconnect_success(self): ws_client = WSClient() ws_client.send_and_consume( 'websocket.connect', path='/notifications', ) # test if ws_client is part of 'notifications' Group('notifications').send({'text': Status.ok('').to_json()}) self.assertEqual( Status.ok(''), Status.from_json(json.dumps(ws_client.receive())), ) ws_client.send_and_consume( 'websocket.disconnect', path='/notifications', ) # test if ws_client was removed from 'notifications' Group('notifications').send({'text': Status.ok('').to_json()}) self.assertIsNone(ws_client.receive())
def test_receive_get_log_with_error_status(self): error_status = Status.err({ 'method': 'get_log', 'result': str(Exception('foobar')), }) # connect webinterface webinterface = WSClient() webinterface.join_group('notifications') ws_client = WSClient() ws_client.send_and_consume( 'websocket.receive', path='/commands', content={'text': error_status.to_json()}, ) # test if the webinterface gets the error message self.assertEqual( Status.err('An error occured while reading a log file!'), Status.from_json(json.dumps(webinterface.receive())), )
def test_state_next_offline_program(self): webinterface = WSClient() webinterface.join_group('notifications') self.slave1.online = True self.slave1.save() self.sched._Scheduler__index = -1 self.sched._Scheduler__event = asyncio.Event(loop=self.sched.loop) self.sched._Scheduler__script = self.script.id self.sched._Scheduler__state = SchedulerStatus.NEXT_STEP self.sched._Scheduler__state_next() self.assertEqual( Status.ok({ 'program_status': 'started', 'pid': self.prog1.id, }), Status.from_json(json.dumps(webinterface.receive())), ) self.assertEqual( self.sched._Scheduler__state, SchedulerStatus.WAITING_FOR_PROGRAMS_FILESYSTEMS, ) self.sched._Scheduler__state = SchedulerStatus.NEXT_STEP self.sched._Scheduler__state_next() self.assertEqual( self.sched._Scheduler__state, SchedulerStatus.ERROR, ) self.assertStatusRegex( Status.err(SlaveOfflineError), Status.err(self.sched._Scheduler__error_code), )
def test_connect_and_disconnect_success(self): webinterface = WSClient() webinterface.join_group('notifications') ws_client = WSClient() ws_client.send_and_consume('websocket.connect', path='/logs') self.assertIsNone(ws_client.receive()) msg = Status.ok({ 'log': ''.join([ choice(string.ascii_letters + string.digits) for _ in range(500) ]), 'pid': choice(string.digits) }) ws_client.send_and_consume('websocket.receive', path='/logs', content={'text': msg.to_json()}) self.assertEqual(msg, Status.from_json(json.dumps(webinterface.receive())))
def test_state_error(self): webinterface = WSClient() webinterface.join_group('notifications') self.sched._Scheduler__event = asyncio.Event(loop=self.sched.loop) self.sched._Scheduler__script = self.script.id self.sched._Scheduler__error_code = "Wow an error occurred." self.sched._Scheduler__state = SchedulerStatus.ERROR self.sched._Scheduler__state_error() self.assertEqual( self.sched._Scheduler__state, SchedulerStatus.ERROR, ) self.assertEqual( Status.ok({ 'script_status': 'error', 'error_code': 'Wow an error occurred.', 'script_id': self.script.id, }), Status.from_json(json.dumps(webinterface.receive())), )
def test_state_next_finished(self): webinterface = WSClient() webinterface.join_group('notifications') self.slave1.online = True self.slave1.save() self.slave2.online = True self.slave2.save() ProgramStatusModel.objects.create(program=self.prog1, code='0', command_uuid='0', start_time=now()) self.sched._Scheduler__index = -1 self.sched._Scheduler__event = asyncio.Event(loop=self.sched.loop) self.sched._Scheduler__script = self.script.id self.sched._Scheduler__state = SchedulerStatus.NEXT_STEP self.sched._Scheduler__state_next() self.assertEqual( self.sched._Scheduler__state, SchedulerStatus.WAITING_FOR_PROGRAMS_FILESYSTEMS, ) if self.prog1.start_time > 0: start_time = self.prog1.start_time else: start_time = 0 msg1 = Status.from_json(json.dumps(webinterface.receive())) expct1 = Status.ok({ 'script_status': 'next_step', 'index': 0, 'last_index': -1, 'start_time': start_time, 'script_id': self.script.id, }) self.assertStatusSet([msg1], [expct1]) ProgramStatusModel.objects.create(program=self.prog2, code='0', command_uuid='1', start_time=now()) self.sched._Scheduler__state = SchedulerStatus.NEXT_STEP self.sched._Scheduler__state_next() self.assertEqual( self.sched._Scheduler__state, SchedulerStatus.WAITING_FOR_PROGRAMS_FILESYSTEMS, ) if self.prog2.start_time > 0: start_time = self.prog2.start_time else: start_time = 0 msg1 = Status.from_json(json.dumps(webinterface.receive())) expct1 = Status.ok({ 'script_status': 'next_step', 'index': 2, 'last_index': 0, 'start_time': start_time, 'script_id': self.script.id, }) self.assertStatusSet([msg1], [expct1]) self.sched._Scheduler__state = SchedulerStatus.NEXT_STEP self.sched._Scheduler__state_next() self.assertEqual( self.sched._Scheduler__state, SchedulerStatus.SUCCESS, ) self.assertEqual( Status.ok({ 'script_status': 'next_step', 'index': -1, 'last_index': 2, 'start_time': 0, 'script_id': self.script.id, }), Status.from_json(json.dumps(webinterface.receive())), )
def test_state_next(self): webinterface = WSClient() webinterface.join_group('notifications') self.slave1.online = True self.slave1.save() self.slave2.online = True self.slave2.save() self.sched._Scheduler__index = -1 self.sched._Scheduler__event = asyncio.Event(loop=self.sched.loop) self.sched._Scheduler__script = self.script.id self.sched._Scheduler__state = SchedulerStatus.NEXT_STEP self.sched._Scheduler__state_next() self.assertEqual( self.sched._Scheduler__state, SchedulerStatus.WAITING_FOR_PROGRAMS_FILESYSTEMS, ) if self.prog1.start_time > 0: start_time = self.prog1.start_time else: start_time = 0 msg1 = Status.from_json(json.dumps(webinterface.receive())) msg2 = Status.from_json(json.dumps(webinterface.receive())) expct1 = Status.ok({ 'script_status': 'next_step', 'index': 0, 'last_index': -1, 'start_time': start_time, 'script_id': self.script.id, }) expct2 = Status.ok({ 'program_status': 'started', 'pid': self.prog1.id, }) self.assertStatusSet([msg1, msg2], [expct1, expct2]) self.sched._Scheduler__state = SchedulerStatus.NEXT_STEP self.sched._Scheduler__state_next() self.assertEqual( self.sched._Scheduler__state, SchedulerStatus.WAITING_FOR_PROGRAMS_FILESYSTEMS, ) if self.prog2.start_time > 0: start_time = self.prog2.start_time else: start_time = 0 msg1 = Status.from_json(json.dumps(webinterface.receive())) msg2 = Status.from_json(json.dumps(webinterface.receive())) expct1 = Status.ok({ 'script_status': 'next_step', 'index': 2, 'last_index': 0, 'start_time': start_time, 'script_id': self.script.id, }) expct2 = Status.ok({ 'program_status': 'started', 'pid': self.prog2.id, }) self.assertStatusSet([msg1, msg2], [expct1, expct2]) self.sched._Scheduler__state = SchedulerStatus.NEXT_STEP self.sched._Scheduler__state_next() self.assertEqual( self.sched._Scheduler__state, SchedulerStatus.SUCCESS, ) self.assertEqual( Status.ok({ 'script_status': 'next_step', 'index': -1, 'last_index': 2, 'start_time': 0, 'script_id': self.script.id, }), Status.from_json(json.dumps(webinterface.receive())), )