def test_handle_request_2_e(self):
        """
        Test that the ``handle_request()`` method returns a success response has a valid serialized
        :class:`SchedulerRequestResponse` embedded in the data attribute, and that this scheduler response is also set
        as successful, when the session and authorization are good, and the request to the scheduler is appropriate and
        successful (simulated in testing via a dummy scheduler client).
        """
        ip_addr = self._session_ip_1
        user = self._user_1
        session = self.session_manager.create_session(ip_address=ip_addr,
                                                      username=user)
        request = NWMRequest(session_secret=session.session_secret,
                             version=2.0)

        dummy_scheduler_client = DummySchedulerClient(test_successful=True)
        self.handler._scheduler_client = dummy_scheduler_client

        response = asyncio.run(self.handler.handle_request(request=request),
                               debug=True)

        data_key = NWMRequestResponse.get_data_dict_key_for_scheduler_response(
        )
        deserialized_json_dict = response.data[data_key]
        scheduler_response = SchedulerRequestResponse.factory_init_from_deserialized_json(
            deserialized_json_dict)

        self.assertTrue(scheduler_response.success)
Example #2
0
    def _deserialize_model_request(self, model_request_hash: dict, parameters_hash: dict, **kwargs) -> MaaSRequest:
        """
        Deserialized the serialized data for a model request, in the form of Redis hashes/mappings, into a
        ::class:`MaaSRequest` object.

        Essentially, this performs the reverse of ::method:`serialize_model_request`.

        The method supports optional keyword arguments.  In particular, these are intended to provide future support for
        controlling the specific subtype of ::class:`MaaSRequest` that is created.  For now, only ::class:`NWMRequest`
        objects are supported.

        Parameters
        ----------
        model_request_hash : dict
            The Redis hash value for the inner ::class:`MaaSRequest` object of the scheduler request.

        parameters_hash : dict
            The ``parameters`` of the inner ::class:`MaaSRequest` object of the request.

        kwargs
            Optional keyword arguments.

        Returns
        -------
        MaaSRequest
            The deserialize model request object.
        """
        # TODO: consider whether there needs to be any conversion done to values (e.g., integer string to actual int)
        parameters = parameters_hash

        return NWMRequest(session_secret=model_request_hash['session_secret'],
                          version=float(model_request_hash['version']),
                          output=model_request_hash['output'],
                          parameters=parameters)
Example #3
0
    async def handle_request(self, request: NWMRequest, **kwargs) -> NWMRequestResponse:
        """
        Handle the given request for a new NWM job execution and return the resulting response.

        Parameters
        ----------
        request: NWMRequest
            A ``NWMRequest`` message instance with details of the job being requested.

        Returns
        -------
        response: NWMRequestResponse
            An appropriate ``NWMRequestResponse`` object.
        """
        session = self._session_manager.lookup_session_by_secret(request.session_secret)
        if session is None:
            reason = InitRequestResponseReason.UNRECOGNIZED_SESSION_SECRET
            msg = 'Request {} does not correspond to a known authenticated session'.format(request.to_json())
        elif not await self._is_authorized(request=request, session=session):
            reason = InitRequestResponseReason.UNAUTHORIZED
            msg = 'User {} in session [{}] not authorized for NWM job request {}'.format(
                session.user, str(session.session_id), request.to_json())
            logging.debug("*************" + msg)
        else:
            # TODO: push to redis stream, associating with this session somehow, and getting some kind of id back
            #The context manager manages a SINGLE connection to the scheduler server
            #Adhoc calls to the scheduler can be made for this connection via the scheduler_client
            #These adhoc calls will use the SAME connection the context was initialized with
            logging.debug("************* Preparing scheduler request message")
            scheduler_message = SchedulerRequestMessage(model_request=request, user_id=session.user)
            logging.debug("************* Scheduler request message ready:\n{}".format(str(scheduler_message)))
            #async with SchedulerClient(scheduler_url, self.scheduler_client_ssl_dir) as scheduler_client:
            # Should be able to do this to reuse same object/context/connection across tasks, even from other methods
            async with self._scheduler_client as scheduler_client:
                initial_response = await scheduler_client.async_make_request(scheduler_message)
                logging.debug("************* Scheduler client received response:\n{}".format(str(initial_response)))
                if initial_response.success:
                    job_id = initial_response.job_id
                    # TODO: maybe here, formalize responses to a degree containing data
                    #async for response in scheduler_client.get_results():
                    #    logging.debug("************* Results:\n{}".format(str(response)))
                    #    print(response)
                # TODO loop here to receive multiple requests, try while execpt connectionClosed,
                #   let server tell us when to stop listening
            # TODO: consider registering the job and relationship with session, etc.
            success = initial_response.success
            success_str = 'Success' if success else 'Failure'
            reason = InitRequestResponseReason.ACCEPTED if success else InitRequestResponseReason.REJECTED
            mesg = '{} submitting job to scheduler (returned id {})'.format(success_str, str(initial_response.job_id))
            # TODO: right now, the only supported MaaSRequest we will see is a NWMRequest, but account for other things
            return NWMRequestResponse(success=success, reason=reason.name, message=mesg, scheduler_response=initial_response)

        # If we didn't just return by executing 'else' condition above (i.e., we don't have an authorized session) ...
        return NWMRequestResponse(success=False, reason=reason.name, message=msg)
    def test_handle_request_1_a(self):
        """
        Test that the ``handle_request()`` method returns a failure response if the session for the secret cannot be
        found.
        """
        ip_addr = self._session_ip_1
        user = self._user_1
        session = self.session_manager.create_session(ip_address=ip_addr,
                                                      username=user)
        request = NWMRequest(session_secret=session.session_secret,
                             version=2.0)

        # Now, remove the session from the manager
        self.session_manager.remove_session(session)

        response = asyncio.run(self.handler.handle_request(request=request),
                               debug=True)
        self.assertFalse(response.success)
    def test_handle_request_3_c(self):
        """
        Test that the ``handle_request()`` method returns a failure response with the error job_id value when the
        session and authorization are good, but the request to the scheduler is not successful (simulated in testing via
        a dummy scheduler client).
        """
        ip_addr = self._session_ip_1
        user = self._user_1
        session = self.session_manager.create_session(ip_address=ip_addr,
                                                      username=user)
        request = NWMRequest(session_secret=session.session_secret,
                             version=2.0)

        dummy_scheduler_client = DummySchedulerClient(test_successful=False)
        self.handler._scheduler_client = dummy_scheduler_client

        response = asyncio.run(self.handler.handle_request(request=request),
                               debug=True)
        self.assertEquals(response.job_id, -1)
    def test_handle_request_2_a(self):
        """
        Test that the ``handle_request()`` method returns a success response when the session and authorization are
        good, and the request to the scheduler is appropriate and successful (simulated in testing via a dummy scheduler
        client).
        """
        ip_addr = self._session_ip_1
        user = self._user_1
        session = self.session_manager.create_session(ip_address=ip_addr,
                                                      username=user)
        request = NWMRequest(session_secret=session.session_secret,
                             version=2.0)

        dummy_scheduler_client = DummySchedulerClient(test_successful=True)
        self.handler._scheduler_client = dummy_scheduler_client

        response = asyncio.run(self.handler.handle_request(request=request),
                               debug=True)
        self.assertTrue(response.success)
    def test_handle_request_1_c(self):
        """
        Test that the ``handle_request()`` method returns an appropriate failure response with the correct failure
        reason if the user is not authorized.
        """
        ip_addr = self._session_ip_1
        user = self._user_1
        session = self.session_manager.create_session(ip_address=ip_addr,
                                                      username=user)
        request = NWMRequest(session_secret=session.session_secret,
                             version=2.0)

        #self.session_manager._authorizer = self.fail_authorizer
        self.handler._authorizer = self.fail_authorizer

        response = asyncio.run(self.handler.handle_request(request=request),
                               debug=True)
        self.assertEquals(response.reason,
                          InitRequestResponseReason.UNAUTHORIZED.name)
    def test_handle_request_1_b(self):
        """
        Test that the ``handle_request()`` method returns an appropriate failure response with the correct failure
        reason if the session for the secret cannot be found.
        """
        ip_addr = self._session_ip_1
        user = self._user_1
        session = self.session_manager.create_session(ip_address=ip_addr,
                                                      username=user)
        request = NWMRequest(session_secret=session.session_secret,
                             version=2.0)

        # Now, remove the session from the manager
        self.session_manager.remove_session(session)

        response = asyncio.run(self.handler.handle_request(request=request),
                               debug=True)
        self.assertEqual(
            response.reason,
            InitRequestResponseReason.UNRECOGNIZED_SESSION_SECRET.name)
    def test_handle_request_3_d(self):
        """
        Test that the ``handle_request()`` method returns a failure response with a valid serialized
        :class:`SchedulerRequestResponse` embedded in the data attribute, when the session and authorization are good,
        but the request to the scheduler are not successful (simulated in testing via a dummy scheduler client).
        """
        ip_addr = self._session_ip_1
        user = self._user_1
        session = self.session_manager.create_session(ip_address=ip_addr,
                                                      username=user)
        request = NWMRequest(session_secret=session.session_secret,
                             version=2.0)

        dummy_scheduler_client = DummySchedulerClient(test_successful=False)
        self.handler._scheduler_client = dummy_scheduler_client

        response = asyncio.run(self.handler.handle_request(request=request),
                               debug=True)
        sched_resp = SchedulerRequestResponse.factory_init_from_deserialized_json(
            response.data['scheduler_response'])
        self.assertTrue(isinstance(sched_resp, SchedulerRequestResponse))