Example #1
0
        async def process(self, req: Request['Abort_POST.Arguments'],
                          user: User) -> None:
            jobIds = req.args.jobId
            taskNames = req.args.taskName
            onlyWaiting = req.args.onlyWaiting
            jobDB = self.jobDB

            # Expect at least 1 jobId
            if not jobIds:
                raise InvalidRequest('No job IDs given; expected at least one')

            # Validate all jobId's
            invalidJobs = [jobId for jobId in jobIds if jobId not in jobDB]
            if invalidJobs:
                raise InvalidRequest('Non-existing jobs: %s' %
                                     ', '.join(sorted(invalidJobs)))

            def checkAbort(task: Task) -> bool:
                if onlyWaiting and not task.isWaiting():
                    return False
                elif taskNames and task.getName() not in taskNames:
                    return False
                else:
                    return True

            userName = user.name
            abortedTasks = {}
            for jobId in jobIds:
                job = jobDB[jobId]
                abortedTasks[jobId] = job.abortAll(checkAbort, userName)

            # pylint: disable=attribute-defined-outside-init
            self.abortedTasks = abortedTasks
Example #2
0
        async def process(self, req: Request['InspectDone_POST.Arguments'],
                          user: User) -> None:
            # Fetch and check job and task.
            self.initTask(req)
            job = self.job
            task = self.task
            taskName = task.getName()
            taskRun = task.getLatestRun()
            if not taskRun.isWaitingForInspection():
                raise InvalidRequest(
                    'Given task is not waiting for inspection')

            # Check result and summary.
            result = req.args.result
            if result not in (ResultCode.OK, ResultCode.WARNING,
                              ResultCode.ERROR):
                raise InvalidRequest(f'Invalid inspection result "{result}"')
            summary = req.args.summary

            # Check store permissions.
            checkPrivilegeForOwned(user, 't/m', job)

            # Store mid-level data, if any.
            data = cast(Mapping[str, str], req.args.data)
            if data:
                self.resultStorage.putData(taskName, taskRun.getId(), data)

            # Store inspection result.
            job.inspectDone(taskName, result, summary)
Example #3
0
    async def process(self, req: Request, user: User) -> None:
        # Determine navigation path.
        stepObjects = self.page.stepObjects
        requestedPath = []
        for name in self.args.path.split():
            try:
                requestedPath.append(stepObjects[name])
            except KeyError as ex:
                raise InvalidRequest(
                    f'non-existing dialog step "{name}" in navigation path'
                ) from ex
        if not requestedPath:
            raise InvalidRequest('Dialog state was lost')

        if self.args.error is not None:
            # User pressed back button on error page.
            self.walkSteps(requestedPath[:-1])
        elif self.args.back is not None:
            # User pressed back button on normal page.
            # We must go back to the previous step that will be shown;
            # we can't just go back two steps, since we might end up on
            # a non-shown step and then automatically advance to the same
            # step the user pressed the back button on.
            self.walkSteps(requestedPath, requestedPath[-1])
        else:
            self.walkSteps(requestedPath)
Example #4
0
        async def process(self,
                          req: Request['GetResourceInfo_GET.Arguments'],
                          user: User
                          ) -> None:
            resTypeNames = req.args.type
            resNames = req.args.name

            # Check validity of optional typenames
            resTypeDB = self.resTypeDB
            invalidTypeNames = sorted(
                name for name in resTypeNames if name not in resTypeDB
                )
            if invalidTypeNames:
                raise InvalidRequest(
                    'Non-existing resource types: ' +
                    ', '.join(invalidTypeNames)
                    )

            # Check validity of optional names
            resourceDB = self.resourceDB
            invalidNames = [
                name
                for name in resNames
                if name not in resourceDB
                ]
            if invalidNames:
                raise InvalidRequest(
                    'Non-existing resource names: ' +
                    ', '.join(sorted(invalidNames))
                    )

            # Determine set of resource types
            query: List[RecordProcessor] = []
            if resTypeNames:
                # TODO: Use SetFilter.create().
                query.append(SetFilter('type', resTypeNames, resourceDB))
            resources = runQuery(query, resourceDB)

            # Filter out resources with id's other than in 'resNames' if
            # filter is present
            # TODO: This could also be done using querylib.
            if resNames:
                resources = [
                    res
                    for res in resources
                    if res.getId() in resNames
                    ]

            # pylint: disable=attribute-defined-outside-init
            self.resources = resources
Example #5
0
 async def process(self, req: Request[JobIdArgs], user: User) -> None:
     jobId = req.args.jobId
     try:
         # pylint: disable=attribute-defined-outside-init
         self.job = self.jobDB[jobId]
     except KeyError:
         raise InvalidRequest(f'Job "{jobId}" does not exist')
Example #6
0
        async def process(self,
                          req: Request[ControlPage.Arguments],
                          user: User
                          ) -> None:
            # pylint: disable=attribute-defined-outside-init

            # Parse posted XML request.
            rawReq = req.rawInput()
            request = cast(TaskRunnerData, parse(RequestFactory(), rawReq))

            # Sync Task Runner database.
            assert isinstance(user, TokenUser), user
            try:
                taskRunner = self.resourceDB.runnerFromToken(user)
            except KeyError as ex:
                raise InvalidRequest(*ex.args) from ex
            self.taskRunner = taskRunner
            self.abort = taskRunner.sync(self.jobDB, request)

            # Try to assign a new run if the Task Runner is available.
            # Or exit if the Task Runner exit flag is set.
            self.exit = False
            self.newRun = None
            if not taskRunner.isReserved():
                if taskRunner.shouldExit():
                    self.exit = True
                    taskRunner.setExitFlag(False)
                elif not taskRunner.isSuspended():
                    self.newRun = assignExecutionRun(taskRunner,
                                                     self.unfinishedJobs)
Example #7
0
 async def process(self, req: Request[TaskRunnerIdArgs],
                   user: User) -> None:
     runnerId = req.args.runnerId
     try:
         runner = self.resourceDB.getTaskRunner(runnerId)
     except KeyError as ex:
         raise InvalidRequest(str(ex)) from ex
     runner.setExitFlag(True)
Example #8
0
        async def process(self, req: Request['TaskAlert_POST.Arguments'],
                          user: User) -> None:
            self.initTask(req)

            alert = req.args.alert
            if alert != '' and alert not in alertList:
                raise InvalidRequest(f'Invalid alert status "{alert}"')

            self.task.setAlert(alert)
Example #9
0
        async def process(self, req: Request['TaskDone_POST.Arguments'],
                          user: User) -> None:
            # Verify arguments.
            try:
                result = req.args.result
                if result is not None and result not in defaultSummaries:
                    raise InvalidRequest(
                        f'Result code "{result}" is for internal use only')
                summary = req.args.summary
                reports = req.args.report
                outputs = cast(Mapping[str, str], req.args.output)

                # Find Task Runner.
                assert isinstance(user, TokenUser), user
                try:
                    taskRunner = self.resourceDB.runnerFromToken(user)
                except KeyError as ex:
                    raise InvalidRequest(*ex.args) from ex

                jobId = req.args.id
                runningTask = taskRunner.getRun()
                if runningTask is None:
                    raise InvalidRequest(f'Task Runner "{taskRunner.getId()}" '
                                         f'is not running a task')
                try:
                    job = self.jobDB[jobId]
                except KeyError:
                    raise InvalidRequest(f'No job exists with ID "{jobId}"')
                taskName = req.args.name
                task = job.getTask(taskName)
                if task is None:
                    raise InvalidRequest(
                        f'No task "{taskName}" in job "{jobId}"')
                runId = cast(str, task['run'])
                if runningTask.getId() != runId:
                    raise InvalidRequest(
                        f'Task Runner "{taskRunner.getId()}" '
                        f'is running task {runningTask.getId()} '
                        f'but wants to set {runId} as done')

                for report in reports:
                    # Reject anything that looks like a path separator.
                    for tabooChar in ('/', '\\', ':'):
                        if tabooChar in report:
                            raise InvalidRequest(
                                f'Invalid character "{tabooChar}" in '
                                f'report name "{report}"')

                extracted = cast(Mapping[str, str], req.args.data)

            except InvalidRequest as ex:
                logging.warning('Invalid TaskDone request: %s', ex)
                raise

            # Start making changes.
            if extracted:
                self.resultStorage.putData(taskName, runId, extracted)
            job.taskDone(taskName, result, summary, reports, outputs)
Example #10
0
    def initTask(self, req: Request[TaskIdArgs]) -> None:
        self.initJob(req)

        taskName = req.args.taskName
        task = self.job.getTask(taskName)
        if task is None:
            raise InvalidRequest(
                f'There is no task named "{taskName}" in job {req.args.jobId}')

        self.task = task
Example #11
0
    def initJob(self, req: Request[JobIdArgs]) -> None:
        jobId = req.args.jobId

        try:
            job = self.jobDB[jobId]
        except KeyError:
            raise InvalidRequest(f'No job exists with ID "{jobId}"')
        job.updateSummaries(tuple(self.resourceDB.iterTaskRunners()))

        self.job = job
Example #12
0
 def _initArgs(self,
               element: Optional[TaskRunner]) -> Mapping[str, object]:
     if element is None:
         return {'resetpass': True}
     elif isinstance(element, TaskRunner):
         return dict(capabilities=' '.join(element.capabilities),
                     description=element['description'])
     else:
         raise InvalidRequest(
             f'Resource "{element.getId()}" is not a Task Runner')
Example #13
0
 async def process(self,
                   req: Request['TriggerSchedule_POST.Arguments'],
                   user: User
                   ) -> None:
     scheduleId = req.args.scheduleId
     try:
         schedule = self.scheduleDB[scheduleId]
     except KeyError:
         raise InvalidRequest(
             f'Schedule "{scheduleId}" does not exist'
             )
     checkPrivilegeForOwned(
         user, 's/m', schedule,
         ( f'trigger schedule "{scheduleId}" that is not owned by you',
           'trigger schedules' )
         )
     try:
         schedule.setTrigger()
     except ValueError as ex:
         raise InvalidRequest( str(ex) )
Example #14
0
        async def process(self, req: Request['ResourceControl_POST.Arguments'],
                          user: User) -> None:
            resNames = req.args.name
            suspend = req.args.action is Actions.SUSPEND

            if not resNames:
                raise InvalidRequest('No resources given')

            invalidNames = []
            resources = []
            resourceDB = self.resourceDB
            for name in resNames:
                try:
                    resources.append(resourceDB[name])
                except KeyError:
                    invalidNames.append(name)
            if invalidNames:
                raise InvalidRequest('Non-existing resource names: ' +
                                     ', '.join(sorted(invalidNames)))

            userName = user.name
            for res in resources:
                res.setSuspend(suspend, userName or 'anonymous')
Example #15
0
 def _initArgs(self, element: Optional[Resource]) -> Mapping[str, str]:
     if element is None:
         return {}
     elif isinstance(element, Resource):
         locator = element.getParameter('locator')
         assert locator is not None
         return dict(
             restype=element.typeName,
             capabilities=' '.join(element.capabilities),
             description=element.description,
             locator=locator
             )
     else:
         raise InvalidRequest(
             f'Resource "{element.getId()}" is of a pre-defined type'
             )
Example #16
0
 def _initArgs(self,
               element: Optional[Resource]
               ) -> Mapping[str, object]:
     if element is None:
         return dict(secret=genword(length=20))
     elif element.typeName == repoResourceTypeName:
         return dict(
             locator = element.getParameter('locator') or '',
             secret = element.getParameter('secret') or '',
             capabilities = ' '.join(element.capabilities),
             description = element['description']
             )
     else:
         raise InvalidRequest(
             f'Resource "{element.getId()}" is not a repository'
             )
Example #17
0
        async def process(self, req: Request['GetTagged_GET.Arguments'],
                          user: User) -> None:
            # Determine subject and access rights.
            try:
                db = self.subjectToDB(req.args.subject)
            except KeyError:
                raise InvalidRequest(
                    f'Invalid subject type "{req.args.subject}"')
            checkPrivilege(user, db.privilegeObject + '/l',
                           f'list {db.description}s')

            # Determine keys and values.
            keys = req.args.key
            values = req.args.value
            tagCache = db.tagCache
            if tagCache is not None:
                # Restrict keys to those that actually exist.
                if keys:
                    keys = keys & set(tagCache.getKeys())
                else:
                    keys = set(tagCache.getKeys())

            # Filter records.
            matches = []
            for record in db.values():
                tags = record.tags
                for key in keys:
                    if tags.hasTagKey(key):
                        recordId = record.getId()
                        if values:
                            for value in values:
                                if tags.hasTagValue(key, value):
                                    matches.append((recordId, key, value))
                        else:
                            for value in tags.getTagValues(key):
                                matches.append((recordId, key, value))

            # pylint: disable=attribute-defined-outside-init
            self.matches = matches
Example #18
0
        async def process(self, req: Request[TaskReportArgs],
                          user: User) -> None:
            self.initTask(req)
            run = self.task.getLatestRun()

            reports: Dict[str, Optional[str]] = OrderedDict()
            reports['Overview'] = None
            reports['Data'] = None
            taskReports = tuple(run.reports)
            reports.update(taskReports)

            # Find report to display.
            report = req.args.report
            if report is None:
                active = taskReports[0][0] if taskReports else 'Overview'
            else:
                report = report.casefold()
                for label in reports:
                    if label.casefold() == report:
                        active = label
                        break
                else:
                    raise InvalidRequest(f'unknown report: "{report}"')
            if report != active.casefold():
                raise ArgsCorrected(
                    req.args.override(report=active.casefold()))

            presenter: Optional[ReportPresenter] = None
            if reports[active] is not None:
                opener = run.reportOpener(active)
                if opener is not None:
                    presenter = createPresenter(opener, active)

            # pylint: disable=attribute-defined-outside-init
            self.reports = reports
            self.active = active
            self.presenter = presenter