Esempio n. 1
0
 def test_email_user(self, mcs, smtp_mock):
     with self.__service.test_request_context(path="/test"):
         with mock.patch.object(pdm.userservicedesk.HRService.current_app,
                                'mail_token_service') as m_ts:
             m_ts.issue = mock.MagicMock(return_value='agfgffsgdf')
             HRService.email_user("*****@*****.**")
             assert mcs.call_args[0][0] == '*****@*****.**'
             assert mcs.call_args[0][1] == 'agfgffsgdf'
Esempio n. 2
0
 def test_compose_and_send_sendmail(self, smtp_mock, mail_mock):
     with self.__service.test_request_context(path="/test"):
         # sendmail errors
         mytoken = 'mytoken_abc'
         toaddr = "user@remotehost"
         body = os.path.join(self._conf['verification_url'], mytoken)
         smtp_mock.return_value.sendmail.side_effect = smtplib.SMTPException
         with self.assertRaises(RuntimeError):
             HRService.compose_and_send(toaddr, mytoken,
                                        datetime.datetime.utcnow())
         args = smtp_mock.return_value.sendmail.call_args
         assert args[0][0] == self._conf['smtp_server_login']
         assert args[0][1] == toaddr
         assert body in args[0][2]  # check the important part of the email
Esempio n. 3
0
 def get_job_status(job_id):
     """Get job status."""
     Job = request.db.tables.Job  # pylint: disable=invalid-name
     job = Job.query.filter_by(id=job_id, user_id=HRService.check_token())\
                    .first_or_404()
     # pylint: disable=no-member
     return jsonify({'jobid': job.id, 'status': JobStatus(job.status).name})
Esempio n. 4
0
 def post_job():
     """Add a job."""
     require_attrs('src_siteid')
     Job = request.db.tables.Job  # pylint: disable=invalid-name
     user_id = HRService.check_token()
     request.data['user_id'] = user_id
     request.data['src_credentials'] = current_app.site_client\
                                                  .get_cred(request.data['src_siteid'], user_id)
     if request.data['type'] == JobType.COPY:
         require_attrs('dst_siteid')
         request.data['dst_credentials'] = current_app.site_client\
                                                      .get_cred(request.data['dst_siteid'],
                                                                user_id)
     elif request.data['type'] == JobType.RENAME and\
             request.data.get('dst_siteid') != request.data['src_siteid']:
         current_app.log.warn("dst_siteid (%s) != src_siteid (%s)",
                              request.data.get('dst_siteid'),
                              request.data['src_siteid'])
         request.data['dst_siteid'] = request.data['src_siteid']
     try:
         job = Job(**request.data)
     except ValueError as err:
         abort(400, description=err.message)
     except Exception as err:  # pylint: disable=broad-except
         abort(500, description=err.message)
     try:
         job.add()
     except Exception as err:  # pylint: disable=broad-except
         abort(500, description=err.message)
     return jsonify(job)
Esempio n. 5
0
 def get_element(job_id, element_id):
     """Get all jobs for a user."""
     JobElement = request.db.tables.JobElement  # pylint: disable=invalid-name
     element = JobElement.query.filter_by(id=element_id, job_id=job_id)\
                               .join(JobElement.job)\
                               .filter_by(user_id=HRService.check_token())\
                               .first_or_404()
     return jsonify(element)
Esempio n. 6
0
    def test_compose_and_send(self, close_mock, connect_mock, mail_mock):
        with self.__service.test_request_context(path="/test"):
            # force connect to raise the SMTPException derived class. HRService wraps it into
            # RuntimeError
            connect_mock.return_value = (400, 'cannot connect message'
                                         )  # 220 is the success code
            with self.assertRaises(RuntimeError):
                HRService.compose_and_send("centos@localhost", 'mytoken_abc',
                                           datetime.datetime.utcnow()
                                           )  # timestamp does not matter here
            connect_mock.assert_called_with('localhost', None)  # from conf{}

            # now allow for connect() to raise a socket.error
            import socket
            connect_mock.side_effect = socket.error
            with self.assertRaises(RuntimeError):
                HRService.compose_and_send("centos@localhost", 'mytoken_abc',
                                           datetime.datetime.utcnow())
Esempio n. 7
0
    def get_output(job_id):
        """Get job output."""
        Job = request.db.tables.Job  # pylint: disable=invalid-name
        job = Job.query.filter_by(id=job_id, user_id=HRService.check_token())\
                       .first_or_404()

        log_filebase = os.path.join(current_app.workqueueservice_workerlogs,
                                    job.log_uid[:2], job.log_uid)

        elements_list = []
        for element in job.elements:
            # pylint: disable=no-member
            attempt_output = {
                'jobid': job_id,
                'elementid': element.id,
                'type': JobType(element.type).name
            }
            attempt_list = []
            attempts = element.attempts
            element_log_filebase = os.path.join(log_filebase, str(element.id))
            for attempt in xrange(
                    1, attempts):  # previous attempts, presumably failed ones
                failed_output = dict(attempt_output,
                                     attempt=attempt,
                                     status=JobStatus.FAILED.name)
                log_filename = os.path.join(element_log_filebase,
                                            "attempt%i.log" % attempt)
                log = "log directory/file %s not found for job.element %s.%s."\
                      % (log_filename, job_id, element.id)
                if os.path.exists(log_filename):
                    with open(log_filename, 'rb') as logfile:
                        log = logfile.read()
                failed_output.update(log=log)
                attempt_list.append(failed_output)

            if attempts:
                status = JobStatus.FAILED
                if element.status == JobStatus.DONE:
                    status = JobStatus.DONE
                last_output = dict(attempt_output,
                                   attempt=attempts,
                                   status=status.name)
                log_filename = os.path.join(element_log_filebase,
                                            "attempt%i.log" % attempts)
                log = "log directory/file %s not found for job.element %s.%s."\
                      % (log_filename, job_id, element.id)
                if os.path.exists(log_filename):
                    with open(log_filename, 'rb') as logfile:
                        log = logfile.read()
                last_output.update(log=log)
                if status == JobStatus.DONE and element.type == JobType.LIST:
                    last_output.update(listing=element.listing)
                attempt_list.append(last_output)
            elements_list.append(attempt_list)
        return jsonify(elements_list)
Esempio n. 8
0
 def get_jobs():
     """Get all jobs for a user."""
     Job = request.db.tables.Job  # pylint: disable=invalid-name
     jobs = []
     for job in Job.query.filter_by(user_id=HRService.check_token()).all():
         elements = job.elements
         status_counter = Counter(element.status for element in elements)
         new_job = job.encode_for_json()
         new_job.update(num_elements=len(elements),
                        num_new=status_counter[JobStatus.NEW],
                        num_done=status_counter[JobStatus.DONE],
                        num_failed=status_counter[JobStatus.FAILED],
                        num_submitted=status_counter[JobStatus.SUBMITTED],
                        num_running=status_counter[JobStatus.RUNNING])
         jobs.append(new_job)
     return jsonify(jobs)
Esempio n. 9
0
    def __init__(self, user_token):
        """
        Constructor initialises all service clients involved in the transfer management:
        EndpointService, CredService and finally the WorkqueueService.

        :param user_token: user token
        """

        self.__user_token = user_token
        # endpoint
        self.__site_client = SiteClient()
        self.__site_client.set_token(user_token)
        self.__sitelist = self.__site_client.get_sites()
        # get user id
        self.__user_id = HRService.get_token_userid(user_token)
        # work queue client
        self.__wq_client = WorkqueueClient()
        self.__wq_client.set_token(user_token)
Esempio n. 10
0
 def get_element_status(job_id, element_id):
     """Get element status."""
     JobElement = request.db.tables.JobElement  # pylint: disable=invalid-name
     element = JobElement.query.filter_by(id=element_id, job_id=job_id)\
                               .join(JobElement.job)\
                               .filter_by(user_id=HRService.check_token())\
                               .first_or_404()
     # pylint: disable=no-member
     monitoring_info = element.monitoring_info
     if monitoring_info is None:
         monitoring_info = {}
     return jsonify({
         'jobid': element.job_id,
         'elementid': element.id,
         'status': JobStatus(element.status).name,
         'attempts': element.attempts,
         'transferred': monitoring_info.get('transferred', 'N/A'),
         'instant': monitoring_info.get('instant', 'N/A'),
         'average': monitoring_info.get('average', 'N/A'),
         'elapsed': monitoring_info.get('elapsed', 'N/A')
     })
Esempio n. 11
0
    def get_element_output(job_id, element_id, attempt=None):  # pylint: disable=too-many-branches
        """Get job element output."""
        Job = request.db.tables.Job  # pylint: disable=invalid-name
        JobElement = request.db.tables.JobElement  # pylint: disable=invalid-name
        log_uid, element = Job.query.with_entities(Job.log_uid, JobElement)\
                              .filter_by(id=job_id, user_id=HRService.check_token())\
                              .join(Job.elements)\
                              .filter_by(id=element_id)\
                              .first_or_404()

        log_filebase = os.path.join(current_app.workqueueservice_workerlogs,
                                    log_uid[:2], log_uid, str(element_id))

        if element.attempts == 0:
            abort(404,
                  description=
                  "No attempts have yet been recorded for element %d of "
                  "job %d. Please try later." % (element_id, job_id))
        # pylint: disable=no-member
        attempt_output = {
            'jobid': job_id,
            'elementid': element_id,
            'type': JobType(element.type).name
        }

        if attempt is not None:
            try:
                attempt = int(
                    attempt
                )  # can't use the flask <int:attempt> converter with negatives
            except ValueError:
                abort(400, description="bad attempt, expected an integer.")
            if attempt < 0:
                attempt = element.attempts + attempt + 1
            if attempt not in xrange(1, element.attempts + 1):
                abort(
                    404,
                    description=
                    "Invalid attempt '%s', job.element %s.%s has been tried %s "
                    "time(s)" %
                    (attempt, job_id, element_id, element.attempts))

            log_filename = os.path.join(log_filebase,
                                        "attempt%i.log" % attempt)
            if not os.path.exists(log_filename):
                abort(
                    500,
                    description=
                    "log directory/file %s not found for job.element %s.%s." %
                    (log_filename, job_id, element_id))
            status = JobStatus.FAILED
            if attempt == element.attempts and element.status == JobStatus.DONE:
                status = JobStatus.DONE
            attempt_output.update(attempt=attempt, status=status.name)
            with open(log_filename, 'rb') as logfile:
                attempt_output.update(log=logfile.read())
            if status == JobStatus.DONE and element.type == JobType.LIST:
                attempt_output.update(listing=element.listing)
            return jsonify(attempt_output)

        attempt_list = []
        attempts = element.attempts
        for attempt_ in xrange(
                1, attempts):  # previous attempts, presumably failed ones
            failed_output = dict(attempt_output,
                                 attempt=attempt_,
                                 status=JobStatus.FAILED.name)
            log_filename = os.path.join(log_filebase,
                                        "attempt%i.log" % attempt_)
            log = "log directory/file %s not found for job.element %s.%s."\
                  % (log_filename, job_id, element.id)
            if os.path.exists(log_filename):
                with open(log_filename, 'rb') as logfile:
                    log = logfile.read()
            failed_output.update(log=log)
            attempt_list.append(failed_output)

        if attempts:
            status = JobStatus.FAILED
            if element.status == JobStatus.DONE:
                status = JobStatus.DONE
            last_output = dict(attempt_output,
                               attempt=attempts,
                               status=status.name)
            log_filename = os.path.join(log_filebase,
                                        "attempt%i.log" % attempts)
            log = "log directory/file %s not found for job.element %s.%s."\
                  % (log_filename, job_id, element.id)
            if os.path.exists(log_filename):
                with open(log_filename, 'rb') as logfile:
                    log = logfile.read()
            last_output.update(log=log)
            if status == JobStatus.DONE and element.type == JobType.LIST:
                last_output.update(listing=element.listing)
            attempt_list.append(last_output)
        return jsonify(attempt_list)
Esempio n. 12
0
 def get_job(job_id):
     """Get job."""
     Job = request.db.tables.Job  # pylint: disable=invalid-name
     job = Job.query.filter_by(id=job_id, user_id=HRService.check_token())\
                    .first_or_404()
     return jsonify(job)