Beispiel #1
0
    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())),
        )
Beispiel #2
0
    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())),
        )
Beispiel #3
0
def filesystem_entry(request, filesystem_id):
    """
    Process requests for a single `FilesystemModel`s.

    HTTP Methods
    ------------
        DELETE:
            Removes the specified entry (in the URL) from the database.
        PUT:
            Updates the specified entry (in the URL) in the database.

    Parameters
    ----------
        request: HttpRequest
            The request which should be processed.

    Returns
    -------
        HttpResponse:
            If the HTTP method is not supported, then an
            `HttpResponseForbidden` is returned.
    """

    if request.method == 'DELETE':
        try:
            filesystem = FilesystemModel.objects.get(id=filesystem_id)
            try:
                fs_delete(filesystem)
                return StatusResponse.ok("")
            except FsimError as err:
                return StatusResponse(err)
        except FilesystemModel.DoesNotExist as err:
            return StatusResponse(FilesystemNotExistError(err, filesystem_id))
    elif request.method == 'PUT':
        # create form from a new QueryDict made from the request body
        # (request.PUT is unsupported) as an update (instance) of the
        # existing slave
        try:
            model = FilesystemModel.objects.get(id=filesystem_id)

            form = FilesystemForm(QueryDict(request.body), instance=model)
            if form.is_valid():
                filesystem = form.save(commit=False)
                try:
                    filesystem.full_clean()
                    form.save()
                    return StatusResponse.ok('')
                except ValidationError as _:
                    error_dict = {
                        'name': [
                            'Filesystem with this Name already exists on this Client.'
                        ]
                    }
                    return StatusResponse(Status.err(error_dict))
            else:
                return StatusResponse(Status.err(form.errors))
        except FilesystemModel.DoesNotExist as err:
            return StatusResponse(FilesystemNotExistError(err, filesystem_id))
    else:
        return HttpResponseForbidden()
Beispiel #4
0
    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())),
        )
Beispiel #5
0
    def test_chain_command_success(self):
        if os.name == 'nt':
            prog = "C:\\Windows\\System32\\cmd.exe"
            args = ["/c", "ECHO %date%"]
        else:
            prog = "/bin/sh"
            args = ["-c", "echo $(date)"]

        result = self.loop.run_until_complete(
            client.command.chain_execution(commands=[{
                'method': 'execute',
                'uuid': 'thisisunique',
                'arguments': {
                    'pid': random.choice(string.digits),
                    'own_uuid': uuid4().hex,
                    'path': prog,
                    'arguments': args
                },
            }]))

        response = Status(
            Status.ID_OK,
            {
                'method': 'execute',
                'result': '0',
            },
            'thisisunique',
        )

        self.assertEqual(Status(**result[0]), response)
Beispiel #6
0
    def test_receive_filesystem_moved_success(self):
        filesystem = FileFactory()

        moved = MovedFileFactory.build()

        error_status = Status.ok({
            'method': 'filesystem_move',
            'result': moved.hash_value,
        })
        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.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())),
        )
Beispiel #7
0
    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())),
        )
Beispiel #8
0
    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())),
        )
Beispiel #9
0
    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())),
        )
Beispiel #10
0
    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())),
        )
class BilibiliBlock():
    """
    Bilibili文件块类
    
    Properties:
        index -- block序号
        path -- name_type.m4s.index
        block_size -- block大小,默认为10MB
    """

    def __init__(self, index, url, qn, path, spider, block_size=10*1024*1024):

        self.index = index
        self.url = url
        self.qn = qn
        self.path = "{}.{:03}".format(path, index)
        self.spider = spider
        self.block_size = 10*1024*1024

        self.name = os.path.split(self.path)[-1]
        self.status = Status()

    def download(self):
        stream = True
        chunk_size = 1024
        # 更改状态
        self.status.switch(Status.DOWNLOADING)

        if not os.path.exists(self.path):
            # 设置 headers
            headers = dict(self.spider.headers)
            headers["Range"] = "bytes={}-{}".format(
                self.index * self.block_size,
                (self.index + 1) * self.block_size - 1)
            # 尝试建立连接
            connected = False
            while not connected:
                try:
                    res = self.spider.get(
                        self.url, stream=stream, headers=headers)
                    connected = True
                except:
                    print("[Error] 下载出错,正在重新尝试...")

            # 写入文件
            with open(self.path, 'wb+') as f:
                if stream == True:
                    for chunk in res.iter_content(chunk_size=chunk_size):
                        if not chunk:
                            break
                        f.write(chunk)
                else:
                    f.write(res.content)
        self.status.switch(Status.DONE)

    def remove(self):
        """ 删除文件 """
        if os.path.exists(self.path):
            os.remove(self.path)
    def __init__(self, index, url, qn, path, spider, block_size=10*1024*1024):

        self.index = index
        self.url = url
        self.qn = qn
        self.path = "{}.{:03}".format(path, index)
        self.spider = spider
        self.block_size = 10*1024*1024

        self.name = os.path.split(self.path)[-1]
        self.status = Status()
Beispiel #13
0
    def test_chain_command_one_failed(self):
        if os.name == 'nt':
            prog = "C:\\Windows\\System32\\cmd.exe"
            args = ["/c", "ECHO %date%"]
        else:
            prog = "/bin/sh"
            args = ["-c", "echo $(date)"]

        result = self.loop.run_until_complete(
            client.command.chain_execution(commands=[{
                'method': 'execute',
                'uuid': 0,
                'arguments': {
                    'pid': 1,
                    'own_uuid': 0,
                    'path': prog,
                },
            }, {
                'method': 'execute',
                'uuid': 1,
                'arguments': {
                    'pid': 1,
                    'own_uuid': 1,
                    'path': prog,
                    'arguments': args
                },
            }]))

        response1 = Status(
            Status.ID_ERR,
            {
                'method':
                'execute',
                'result':
                "execute() missing 1 required positional argument: 'arguments'",
            },
            'uniqueidforfirst',
        )

        response2 = Status(
            Status.ID_ERR,
            {
                'method':
                'execute',
                'result':
                'Could not execute because earlier command was not successful.',
            },
            'uniqueidforsecond',
        )

        self.assertEqual(Status(**result[0]), response1)
        self.assertEqual(Status(**result[1]), response2)
    def test_rpc_method_raise_exception(self):  # pylint: disable=R0201
        """
        Tests what happens if a rpc method raises an exception
        """
        @Rpc.method
        @asyncio.coroutine
        def raises_async():  # pylint: disable=R0201,W0612
            """
            Simple async rpc function, that raises an Exception.
            """
            raise Exception('foo')

        cmd = Command('raises_async')
        status = Status.err({
            'method': 'raises_async',
            'result': str(Exception('foo'))
        })
        status.uuid = cmd.uuid

        Server(
            [
                cmd.to_json(),
            ],
            [
                status.to_json(),
            ],
        ).run()
        def execute_call(cmd):
            """
            Handles an incoming message in a seperat task
            """
            callable_command = Rpc.get(cmd.method)
            logging.debug("Found correct function ... calling.")

            try:
                result = yield from asyncio.coroutine(callable_command)(
                    **cmd.arguments)
                status_code = Status.ID_OK
                logging.debug(
                    'method %s with args: %s returned %s.',
                    cmd.method,
                    cmd.arguments,
                    result,
                )
            except Exception as err:  # pylint: disable=W0703
                result = str(err)
                status_code = Status.ID_ERR
                logging.info('Function raise Exception(%s)', result)

            return Status(status_code, {
                'method': cmd.method,
                'result': result
            }, cmd.uuid)
Beispiel #16
0
    def test_receive_execute_slave_not_exists(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',
        )

        program.delete()

        ws_client = WSClient()
        ws_client.send_and_consume(
            'websocket.receive',
            path='/commands',
            content={'text': expected_status.to_json()},
        )

        self.assertFalse(
            ProgramStatusModel.objects.filter(program=program).exists())

        #  test if the webinterface gets the "finished" message
        self.assertIsNone(webinterface.receive())
    def test_rpc_method_cancel_method(self):  # pylint: disable=R0201
        """
        Tests what happens if you cancel a running method
        """
        @Rpc.method
        @asyncio.coroutine
        def sleep(sec):  # pylint: disable=R0201,W0612
            """
            Simple async rpc function, that raises an Exception.
            """
            try:
                yield from asyncio.sleep(sec)
            except asyncio.CancelledError:
                return -15

        sleep_cmd = Command(method='sleep', sec=1)
        cancel_cmd = Command(method='sleep')
        cancel_cmd.uuid = sleep_cmd.uuid
        status = Status.ok({'method': 'sleep', 'result': -15})
        status.uuid = sleep_cmd.uuid

        Server(
            [
                sleep_cmd.to_json(),
                cancel_cmd.to_json(),
            ],
            [
                status.to_json(),
            ],
        ).run()
Beispiel #18
0
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_math_add(self):  # pylint: disable=R0201
        """
        Testing simple math add function with async features.
        """
        @Rpc.method
        def math_add(integer1, integer2):  # pylint: disable=R0201,W0612
            """
            Simple add function with async.

            Arguments
            ---------
                integer1: first operand
                integer2: second operand
            """
            res = (integer1 + integer2)
            return res

        cmd = Command("math_add", integer1=1, integer2=2)
        status = Status.ok({'method': 'math_add', 'result': 3})
        status.uuid = cmd.uuid

        Server(
            [
                cmd.to_json(),
            ],
            [
                status.to_json(),
            ],
        ).run()
Beispiel #20
0
def filesystem_restore(request, filesystem_id):
    """
    Processes an method invocation (restore) for an `FilesystemModel`. (see
    @frontend.controller.filesystem_restore)

    HTTP Methods
    ------------
        POST:
            Invokes the method for the `FilesystemModel` (which is
            specified in the URL).

    Parameters
    ----------
        request: HttpRequest
            The request which should be processed.

    Returns
    -------
        HttpResponse:
            If the HTTP method is not supported, then an
            `HttpResponseForbidden` is returned.
    """
    if request.method == 'POST':
        try:
            filesystem = FilesystemModel.objects.get(id=filesystem_id)
            try:
                fs_restore(filesystem)
                return StatusResponse(Status.ok(""))
            except FsimError as err:
                return StatusResponse(err)
        except FilesystemModel.DoesNotExist as err:
            return StatusResponse(FilesystemNotExistError(err, filesystem_id))
    else:
        return HttpResponseForbidden()
Beispiel #21
0
    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())))
Beispiel #22
0
    def test_receive_unknown_message_type(self):
        ws_client = WSClient()
        ws_client.send_and_consume(
            'websocket.receive',
            path='/commands',
            content={'text': Status.ok({
                'method': ''
            }).to_json()},
        )

        self.assertIsNone(ws_client.receive())
Beispiel #23
0
def notify_err(message):
    """
    Sending the given `message` to the notification channel. Indicating that
    the message is an error message.

    Parameters
    ----------
        message: JSON object
            This message is send to the web interface with an Status.err()
            wrapped around.
    """
    Group('notifications').send({'text': Status.err(message).to_json()})
    def test_state_next_offline_filesystem(self):
        webinterface = WSClient()
        webinterface.join_group('notifications')

        self.prog1.delete()

        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.ERROR,
        )

        self.assertStatusRegex(
            Status.err(SlaveOfflineError),
            Status.err(self.sched._Scheduler__error_code),
        )
    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())),
        )
Beispiel #26
0
            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 __init__(self, page, name, path, cid, spider):

        self.page = page
        self.name = name
        self.path = path
        self.cid = cid
        self.spider = spider

        self.video = None
        self.audio = None
        self.total = 0
        self.status = Status()
Beispiel #28
0
    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())
Beispiel #29
0
    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())),
        )
Beispiel #30
0
    def enable_remote(self):
        """
        Enables remote logging to the websocket located on 'self.__url'. First
        the existing log gets send, then updates follow on every request
        (an empty message)by the receiver.
        """
        with self.__lock:
            self.__ws_connection = yield from websockets.connect(self.__url)
            log = self.__log_file.read()
            msg = {'log': log.decode(), 'pid': self.__pid_on_master}

        yield from self.__ws_connection.send(Status.ok(msg).to_json())
        yield from self.__ws_connection.recv()

        while True:
            yield from self.__ws_buffer_has_content.wait()

            with self.__lock:
                msg = {
                    'log': self.__ws_buffer.decode(),
                    'pid': self.__pid_on_master
                }
                self.__ws_buffer = b''
                self.__ws_buffer_has_content.clear()

            try:
                yield from self.__ws_connection.send(Status.ok(msg).to_json())
                yield from self.__ws_connection.recv()
            except websockets.exceptions.ConnectionClosed:
                break

            if msg['log'] == b''.decode():
                break

            # if the stream from tee has finished the buffer gets send and
            # cleared in the next iterations which terminates the loop
            if self.__ws_finished:
                self.__ws_buffer_has_content.set()