Example #1
0
    def test_create_and_check_for_request_rest(self):
        """ Request (REST): Test the creation, query, and deletion of a Request """
        host = get_rest_host()

        properties = get_request_properties()

        client = Client(host=host)

        request_id = client.add_request(**properties)

        requests = client.get_requests(request_id=request_id)
        assert_equal(len(requests), 1)
        assert_equal(request_id, requests[0]['request_id'])

        for key in properties:
            if key in ['lifetime']:
                continue
            assert_equal(requests[0][key], properties[key])

        client.update_request(request_id,
                              parameters={'status': RequestStatus.Failed})
        requests = client.get_requests(request_id=request_id)
        assert_equal(len(requests), 1)
        assert_equal(requests[0]['status'], RequestStatus.Failed)

        reqs = client.get_requests(request_id=999999)
        assert_equal(len(reqs), 0)
Example #2
0
class ClientManager:
    def __init__(self, host=None):
        self.host = host
        if self.host is None:
            self.host = get_rest_host()
        self.client = Client(host=self.host)

    @exception_handler
    def submit(self, workflow):
        """
        Submit the workflow as a request to iDDS server.

        :param workflow: The workflow to be submitted.
        """
        props = {
            'scope': 'workflow',
            'name': workflow.name,
            'requester': 'panda',
            'request_type': RequestType.Workflow,
            'transform_tag': 'workflow',
            'status': RequestStatus.New,
            'priority': 0,
            'lifetime': workflow.lifetime,
            'workload_id': workflow.get_workload_id(),
            'request_metadata': {
                'version': release_version,
                'workload_id': workflow.get_workload_id(),
                'workflow': workflow
            }
        }
        workflow.add_proxy()
        primary_init_work = workflow.get_primary_initial_collection()
        if primary_init_work:
            if type(primary_init_work) in [Collection]:
                props['scope'] = primary_init_work.scope
                props['name'] = primary_init_work.name
            else:
                props['scope'] = primary_init_work['scope']
                props['name'] = primary_init_work['name']

        # print(props)
        request_id = self.client.add_request(**props)
        return request_id

    @exception_handler
    def abort(self, request_id=None, workload_id=None):
        """
        Abort requests.

        :param workload_id: the workload id.
        :param request_id: the request.
        """
        if request_id is None and workload_id is None:
            logging.error(
                "Both request_id and workload_id are None. One of them should not be None"
            )
            return (
                -1,
                "Both request_id and workload_id are None. One of them should not be None"
            )

        reqs = self.client.get_requests(request_id=request_id,
                                        workload_id=workload_id)
        if reqs:
            rets = []
            for req in reqs:
                logging.info("Aborting request: %s" % req['request_id'])
                # self.client.update_request(request_id=req['request_id'], parameters={'substatus': RequestStatus.ToCancel})
                self.client.send_message(request_id=req['request_id'],
                                         msg={
                                             'command': 'update_request',
                                             'parameters': {
                                                 'status':
                                                 RequestStatus.ToCancel
                                             }
                                         })
                logging.info("Abort request registered successfully: %s" %
                             req['request_id'])
                ret = (0, "Abort request registered successfully: %s" %
                       req['request_id'])
                rets.append(ret)
            return rets
        else:
            return (-1, 'No matching requests')

    @exception_handler
    def suspend(self, request_id=None, workload_id=None):
        """
        Suspend requests.

        :param workload_id: the workload id.
        :param request_id: the request.
        """
        if request_id is None and workload_id is None:
            logging.error(
                "Both request_id and workload_id are None. One of them should not be None"
            )
            return (
                -1,
                "Both request_id and workload_id are None. One of them should not be None"
            )

        reqs = self.client.get_requests(request_id=request_id,
                                        workload_id=workload_id)
        if reqs:
            rets = []
            for req in reqs:
                logging.info("Suspending request: %s" % req['request_id'])
                # self.client.update_request(request_id=req['request_id'], parameters={'substatus': RequestStatus.ToSuspend})
                self.client.send_message(request_id=req['request_id'],
                                         msg={
                                             'command': 'update_request',
                                             'parameters': {
                                                 'status':
                                                 RequestStatus.ToSuspend
                                             }
                                         })
                logging.info("Suspend request registered successfully: %s" %
                             req['request_id'])
                ret = (0, "Suspend request registered successfully: %s" %
                       req['request_id'])
                rets.append(ret)
            return rets
        else:
            return (-1, 'No matching requests')

    @exception_handler
    def resume(self, request_id=None, workload_id=None):
        """
        Resume requests.

        :param workload_id: the workload id.
        :param request_id: the request.
        """
        if request_id is None and workload_id is None:
            logging.error(
                "Both request_id and workload_id are None. One of them should not be None"
            )
            return (
                -1,
                "Both request_id and workload_id are None. One of them should not be None"
            )

        reqs = self.client.get_requests(request_id=request_id,
                                        workload_id=workload_id)
        if reqs:
            rets = []
            for req in reqs:
                logging.info("Resuming request: %s" % req['request_id'])
                # self.client.update_request(request_id=req['request_id'], parameters={'substatus': RequestStatus.ToResume})
                self.client.send_message(request_id=req['request_id'],
                                         msg={
                                             'command': 'update_request',
                                             'parameters': {
                                                 'status':
                                                 RequestStatus.ToResume
                                             }
                                         })
                logging.info("Resume request registered successfully: %s" %
                             req['request_id'])
                ret = (0, "Resume request registered successfully: %s" %
                       req['request_id'])
                rets.append(ret)
            return rets
        else:
            return (-1, 'No matching requests')

    @exception_handler
    def retry(self, request_id=None, workload_id=None):
        """
        Retry requests.

        :param workload_id: the workload id.
        :param request_id: the request.
        """
        if request_id is None and workload_id is None:
            logging.error(
                "Both request_id and workload_id are None. One of them should not be None"
            )
            return (
                -1,
                "Both request_id and workload_id are None. One of them should not be None"
            )

        reqs = self.client.get_requests(request_id=request_id,
                                        workload_id=workload_id)
        if reqs:
            rets = []
            for req in reqs:
                logging.info("Retrying request: %s" % req['request_id'])
                # self.client.update_request(request_id=req['request_id'], parameters={'substatus': RequestStatus.ToResume})
                self.client.send_message(request_id=req['request_id'],
                                         msg={
                                             'command': 'update_request',
                                             'parameters': {
                                                 'status':
                                                 RequestStatus.ToResume
                                             }
                                         })
                logging.info("Retry request registered successfully: %s" %
                             req['request_id'])
                ret = (0, "Retry request registered successfully: %s" %
                       req['request_id'])
                rets.append(ret)
            return rets
        else:
            return (-1, 'No matching requests')

    @exception_handler
    def finish(self,
               request_id=None,
               workload_id=None,
               set_all_finished=False):
        """
        Retry requests.

        :param workload_id: the workload id.
        :param request_id: the request.
        """
        if request_id is None and workload_id is None:
            logging.error(
                "Both request_id and workload_id are None. One of them should not be None"
            )
            return (
                -1,
                "Both request_id and workload_id are None. One of them should not be None"
            )

        reqs = self.client.get_requests(request_id=request_id,
                                        workload_id=workload_id)
        if reqs:
            rets = []
            for req in reqs:
                logging.info("Finishing request: %s" % req['request_id'])
                if set_all_finished:
                    # self.client.update_request(request_id=req['request_id'], parameters={'substatus': RequestStatus.ToForceFinish})
                    self.client.send_message(
                        request_id=req['request_id'],
                        msg={
                            'command': 'update_request',
                            'parameters': {
                                'status': RequestStatus.ToForceFinish
                            }
                        })
                else:
                    # self.client.update_request(request_id=req['request_id'], parameters={'substatus': RequestStatus.ToFinish})
                    self.client.send_message(request_id=req['request_id'],
                                             msg={
                                                 'command': 'update_request',
                                                 'parameters': {
                                                     'status':
                                                     RequestStatus.ToFinish
                                                 }
                                             })
                logging.info("ToFinish request registered successfully: %s" %
                             req['request_id'])
                ret = (0, "ToFinish request registered successfully: %s" %
                       req['request_id'])
                rets.append(ret)
            return rets
        else:
            return (-1, 'No matching requests')

    @exception_handler
    def get_requests(self,
                     request_id=None,
                     workload_id=None,
                     with_detail=False,
                     with_metadata=False):
        """
        Get requests.

        :param workload_id: the workload id.
        :param request_id: the request.
        :param with_detail: Whether to show detail info.
        """
        reqs = self.client.get_requests(request_id=request_id,
                                        workload_id=workload_id,
                                        with_detail=with_detail,
                                        with_metadata=with_metadata)
        return reqs

    @exception_handler
    def get_status(self,
                   request_id=None,
                   workload_id=None,
                   with_detail=False,
                   with_metadata=False):
        """
        Get the status progress report of requests.

        :param workload_id: the workload id.
        :param request_id: the request.
        :param with_detail: Whether to show detail info.
        """
        reqs = self.client.get_requests(request_id=request_id,
                                        workload_id=workload_id,
                                        with_detail=with_detail,
                                        with_metadata=with_metadata)
        if with_detail:
            table = []
            for req in reqs:
                table.append([
                    req['request_id'], req['transform_id'], req['workload_id'],
                    req['transform_workload_id'],
                    "%s:%s" %
                    (req['output_coll_scope'], req['output_coll_name']),
                    "%s[%s/%s/%s]" %
                    (req['transform_status'].name, req['output_total_files'],
                     req['output_processed_files'],
                     req['output_processing_files']), req['errors']
                ])
            ret = tabulate.tabulate(table,
                                    tablefmt='simple',
                                    headers=[
                                        'request_id', 'transform_id',
                                        'request_workload_id',
                                        'transform_workload_id', 'scope:name',
                                        'status[Total/OK/Processing]', 'errors'
                                    ])
            # print(ret)
            return str(ret)
        else:
            table = []
            for req in reqs:
                table.append([
                    req['request_id'], req['workload_id'],
                    "%s:%s" % (req['scope'], req['name']), req['status'].name,
                    req['errors']
                ])
            ret = tabulate.tabulate(table,
                                    tablefmt='simple',
                                    headers=[
                                        'request_id', 'request_workload_id',
                                        'scope:name', 'status', 'errors'
                                    ])
            # print(ret)
            return str(ret)

    @exception_handler
    def download_logs(self,
                      request_id=None,
                      workload_id=None,
                      dest_dir='./',
                      filename=None):
        """
        Download logs for a request.

        :param workload_id: the workload id.
        :param request_id: the request.
        :param dest_dir: The destination directory.
        :param filename: The destination filename to be saved. If it's None, default filename will be saved.
        """
        filename = self.client.download_logs(request_id=request_id,
                                             workload_id=workload_id,
                                             dest_dir=dest_dir,
                                             filename=filename)
        if filename:
            logging.info("Logs are downloaded to %s" % filename)
            return (0, "Logs are downloaded to %s" % filename)
        else:
            logging.info(
                "Failed to download logs for workload_id(%s) and request_id(%s)"
                % (workload_id, request_id))
            return (
                -1,
                "Failed to download logs for workload_id(%s) and request_id(%s)"
                % (workload_id, request_id))

    @exception_handler
    def upload_to_cacher(self, filename):
        """
        Upload file to iDDS cacher: On the cacher, the filename will be the basename of the file.
        """
        return self.client.upload(filename)

    @exception_handler
    def download_from_cacher(self, filename):
        """
        Download file from iDDS cacher: On the cacher, the filename will be the basename of the file.
        """
        return self.client.download(filename)

    @exception_handler
    def get_hyperparameters(self,
                            workload_id,
                            request_id,
                            id=None,
                            status=None,
                            limit=None):
        """
        Get hyperparameters from the Head service.

        :param workload_id: the workload id.
        :param request_id: the request id.
        :param status: the status of the hyperparameters.
        :param limit: limit number of hyperparameters

        :raise exceptions if it's not got successfully.
        """
        return self.client.get_hyperparameters(workload_id=workload_id,
                                               request_id=request_id,
                                               id=id,
                                               status=status,
                                               limit=limit)

    @exception_handler
    def update_hyperparameter(self, workload_id, request_id, id, loss):
        """
        Update hyperparameter to the Head service.

        :param workload_id: the workload id.
        :param request_id: the request.
        :param id: id of the hyper parameter.
        :param loss: the loss.

        :raise exceptions if it's not updated successfully.
        """
        return self.client.update_hyperparameter(workload_id=workload_id,
                                                 request_id=request_id,
                                                 id=id,
                                                 loss=loss)

    @exception_handler
    def get_messages(self, request_id=None, workload_id=None):
        """
        Get messages.

        :param workload_id: the workload id.
        :param request_id: the request.
        """
        if request_id is None and workload_id is None:
            logging.error(
                "Both request_id and workload_id are None. One of them should not be None"
            )
            return (
                -1,
                "Both request_id and workload_id are None. One of them should not be None"
            )

        logging.info(
            "Retrieving messages for request_id: %s, workload_id: %s" %
            (request_id, workload_id))
        msgs = self.client.get_messages(request_id=request_id,
                                        workload_id=workload_id)
        logging.info(
            "Retrieved %s messages for request_id: %s, workload_id: %s" %
            (len(msgs), request_id, workload_id))
        return (0, msgs)