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
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)
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)
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
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')
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)
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)
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)
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)
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
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
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')
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) )
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')
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' )
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' )
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
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