Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Passive mode for project #2534

Merged
merged 11 commits into from Jun 20, 2017
Expand Up @@ -44,6 +44,7 @@ import rundeck.ScheduledExecution
import rundeck.services.ApiService
import rundeck.services.AuthorizationService
import rundeck.services.PasswordFieldsService
import rundeck.services.ScheduledExecutionService
import rundeck.services.framework.RundeckProjectConfigurable

import javax.servlet.http.HttpServletRequest
Expand Down Expand Up @@ -80,6 +81,7 @@ import rundeck.filters.ApiRequestFilters
class FrameworkController extends ControllerBase implements ApplicationContextAware {
FrameworkService frameworkService
ExecutionService executionService
ScheduledExecutionService scheduledExecutionService
UserService userService

PasswordFieldsService resourcesPasswordFieldsService
Expand Down Expand Up @@ -1090,6 +1092,17 @@ class FrameworkController extends ControllerBase implements ApplicationContextAw
projProps.putAll(inputProps)
def inputMap = new HashMap(inputProps)

def isExecutionDisabledNow = !scheduledExecutionService.isProjectExecutionEnabled(project)
def isScheduleDisabledNow = !scheduledExecutionService.isProjectScheduledEnabled(project)


def newExecutionDisabledStatus = (projProps['project.disable.executions'] && projProps['project.disable.executions'] == 'true')
def newScheduleDisabledStatus = (projProps['project.disable.schedule'] && projProps['project.disable.schedule'] == 'true')

def reschedule = ((isExecutionDisabledNow != newExecutionDisabledStatus)
|| (isScheduleDisabledNow != newScheduleDisabledStatus))
def active = (!newExecutionDisabledStatus && !newScheduleDisabledStatus)

final nodeExecType = frameworkService.getDefaultNodeExecutorService(projProps)
final nodeConfig = frameworkService.getNodeExecConfigurationForType(nodeExecType, projProps)

Expand Down Expand Up @@ -1180,6 +1193,13 @@ class FrameworkController extends ControllerBase implements ApplicationContextAw
if (!result.success) {
errors << result.error
}
if(reschedule){
if(active){
scheduledExecutionService.rescheduleJobs(frameworkService.isClusterModeEnabled()?frameworkService.getServerUUID():null, project)
}else{
scheduledExecutionService.unscheduleJobsForProject(project, frameworkService.isClusterModeEnabled()?frameworkService.getServerUUID():null, project)
}
}
}

if (!errors) {
Expand Down Expand Up @@ -1252,6 +1272,20 @@ class FrameworkController extends ControllerBase implements ApplicationContextAw
}else{
projProps['project.description']=''
}

def isExecutionDisabledNow = !scheduledExecutionService.isProjectExecutionEnabled(project)
def isScheduleDisabledNow = !scheduledExecutionService.isProjectScheduledEnabled(project)

def newExecutionDisabledStatus = (params.disableExecutionMode && params.disableExecutionMode == 'true')
def newScheduleDisabledStatus = (params.disableScheduleMode && params.disableScheduleMode == 'true')

projProps['project.disable.executions']=newExecutionDisabledStatus?'true':'false'
projProps['project.disable.schedule']=newScheduleDisabledStatus?'true':'false'

def reschedule = ((isExecutionDisabledNow != newExecutionDisabledStatus)
|| (isScheduleDisabledNow != newScheduleDisabledStatus))
def active = (!newExecutionDisabledStatus && !newScheduleDisabledStatus)

def Set<String> removePrefixes=[]
removePrefixes<< FrameworkProject.PROJECT_RESOURCES_URL_PROPERTY
if (params.defaultNodeExec) {
Expand Down Expand Up @@ -1384,6 +1418,13 @@ class FrameworkController extends ControllerBase implements ApplicationContextAw
if (!errors) {

def result = frameworkService.updateFrameworkProjectConfig(project, projProps, removePrefixes)
if(reschedule){
if(active){
scheduledExecutionService.rescheduleJobs(frameworkService.isClusterModeEnabled()?frameworkService.getServerUUID():null, project)
}else{
scheduledExecutionService.unscheduleJobsForProject(project,frameworkService.isClusterModeEnabled()?frameworkService.getServerUUID():null)
}
}
if (!result.success) {
errors << result.error
}
Expand Down Expand Up @@ -1499,6 +1540,8 @@ class FrameworkController extends ControllerBase implements ApplicationContextAw
[
project: project,
projectDescription:fwkProject.getProjectProperties().get("project.description"),
disableExecutionMode:fwkProject.getProjectProperties().get("project.disable.executions"),
disableScheduleMode:fwkProject.getProjectProperties().get("project.disable.schedule"),
resourceModelConfigDescriptions: resourceDescs,
configs: resourceConfig,
nodeexecconfig:nodeConfig,
Expand Down
Expand Up @@ -785,6 +785,8 @@ class MenuController extends ControllerBase implements ApplicationContextAware{
nodeErrorsMap:nodeErrorsMap,
resourceModelConfigDescriptions:descriptions,
nodeexecconfig:nodeexec,
disableExecutionMode:fproject.getProjectProperties().get("project.disable.executions"),
disableScheduleMode:fproject.getProjectProperties().get("project.disable.schedule"),
fcopyconfig:fcopy,
defaultNodeExec: defaultNodeExec,
defaultFileCopy: defaultFileCopy,
Expand Down
Expand Up @@ -2344,11 +2344,17 @@ class ScheduledExecutionController extends ControllerBase{
return [success:false,error:'unauthorized',message:msg]
}


if(!executionService.executionsAreActive){
def msg=g.message(code:'disabled.execution.run')
return [success:false,failed:true,error:'disabled',message:msg]
}

if(!scheduledExecutionService.isProjectExecutionEnabled(scheduledExecution.project)){
def msg=g.message(code:'project.execution.disabled')
return [success:false,failed:true,error:'disabled',message:msg]
}

if (!scheduledExecution.hasExecutionEnabled()) {
def msg=g.message(code:'scheduleExecution.execution.disabled')
return [success:false,failed:true,error:'disabled',message:msg]
Expand Down Expand Up @@ -2888,6 +2894,11 @@ class ScheduledExecutionController extends ControllerBase{
return [success:false,failed:true,error:'disabled',message: msg]
}

if(!scheduledExecutionService.isProjectExecutionEnabled(scheduledExecution.project)){
def msg=g.message(code:'project.execution.disabled')
return [success:false,failed:true,error:'disabled',message:msg]
}

if (!scheduledExecution.hasExecutionEnabled()) {
def msg = g.message(code: 'scheduleExecution.execution.disabled')
return [success: false, failed: true, error: 'disabled', message: msg]
Expand Down
3 changes: 3 additions & 0 deletions rundeckapp/grails-app/domain/rundeck/Execution.groovy
Expand Up @@ -144,6 +144,9 @@ class Execution extends ExecutionContext {
withServerNodeUUID { uuid ->
eq 'serverNodeUUID', uuid
}
withProject{ project ->
eq 'project', project
}
}


Expand Down
11 changes: 10 additions & 1 deletion rundeckapp/grails-app/domain/rundeck/ScheduledExecution.groovy
Expand Up @@ -45,6 +45,8 @@ class ScheduledExecution extends ExecutionContext {

Workflow workflow

def scheduledExecutionService

Date nextExecution
boolean scheduled = false
Boolean nodesSelectedByDefault = true
Expand Down Expand Up @@ -183,6 +185,9 @@ class ScheduledExecution extends ExecutionContext {
eq 'status', 'scheduled'
}
}
withProject { project ->
eq 'project', project
}
}


Expand Down Expand Up @@ -530,8 +535,12 @@ class ScheduledExecution extends ExecutionContext {
return (null == scheduleEnabled || scheduleEnabled)
}

def shouldScheduleExecutionProject(){
return scheduledExecutionService.shouldScheduleInThisProject(project)
}

def boolean shouldScheduleExecution() {
return scheduled && hasExecutionEnabled() && hasScheduleEnabled();
return scheduled && hasExecutionEnabled() && hasScheduleEnabled()
}

def boolean hasExecutionEnabled() {
Expand Down
5 changes: 4 additions & 1 deletion rundeckapp/grails-app/i18n/messages.properties
Expand Up @@ -1450,4 +1450,7 @@ form.option.multivalueAllSelected.label=Select All Values by Default
project.configuration.extra.category.gui.description=Additional configuration for the user interface for this project
project.configuration.extra.category.gui.title=User Interface
api.error.project.archive.failure=Project export request {0} failed: {1}
scheduledExecution.action.duplicate.other.button.label=Duplicate this Job to other Project&hellip;
project.passive.mode.description=Job execution and schedule configuration at project level.
project.execution.disabled=Project execution is disabled
project.schedule.disabled=Project schedule is disabled
scheduledExecution.action.duplicate.other.button.label=Duplicate this Job to other Project&hellip;
6 changes: 4 additions & 2 deletions rundeckapp/grails-app/i18n/messages_es_419.properties
Expand Up @@ -909,7 +909,7 @@ page.admin.EditProjectConfigFile.button=Editar Archivo de Configuración
page.admin.EditProjectConfigFile.title=Advanced\: Editar archivo de conf directamente
invalid.resource.model.source.configuration.provider.not.found=Configuración de Modelo Fuente de Recursos no Válido\: Proveedor no encontrado\: {0}
framework.service.NodeExecutor.default.label=Nodo Ejecutor por Defecto
framework.service.FileCopier.default.label=Copiadora de Archvivo Por Defecto
framework.service.FileCopier.default.label=Copiadora de Archivo Por Defecto
configuration.not.available=Configuración no disponible.
download.an.archive.of.project.named.prompt=Descargar un archivo del proyecto <strong>{0}</strong>
export.project.jar.button=Exportar {0}.rdproject.jar &hellip;
Expand Down Expand Up @@ -1446,4 +1446,6 @@ form.option.multivalueAllSelected.label=Select All Values by Default
project.configuration.extra.category.gui.description=Additional configuration for the Jobs for this project
project.configuration.extra.category.gui.title=User Interface
api.error.project.archive.failure=Project export request {0} failed: {1}
scheduledExecution.action.duplicate.other.button.label=Duplicar TRabajo a otro Projecto&hellip;
project.passive.mode.description=Configuracion de ejecucion y programacion de tareas a nivel de proyecto.
project.execution.disabled=Ejecucion deshabilitada a nivel de projecto.1
scheduledExecution.action.duplicate.other.button.label=Duplicar Trabajo a otro Projecto&hellip;
15 changes: 15 additions & 0 deletions rundeckapp/grails-app/jobs/rundeck/quartzjobs/ExecutionJob.groovy
Expand Up @@ -292,7 +292,22 @@ class ExecutionJob implements InterruptableJob {
}
}
}

FrameworkService frameworkService = initMap.frameworkService
def project = initMap.scheduledExecution.project
def fwProject = frameworkService.getFrameworkProject(project)
def disableEx = fwProject.getProjectProperties().get("project.disable.executions")
def disableSe = fwProject.getProjectProperties().get("project.disable.schedule")
def isProjectExecutionEnabled = ((!disableEx)||disableEx.toLowerCase()!='true')
def isProjectScheduledEnabled = ((!disableSe)||disableSe.toLowerCase()!='true')

if(!(isProjectExecutionEnabled && isProjectScheduledEnabled)){
initMap.jobShouldNotRun = "Job ${initMap.scheduledExecution.extid} schedule has been disabled, removing schedule on this project (${initMap.scheduledExecution.project})."
context.getScheduler().deleteJob(context.jobDetail.key)
return initMap
}


initMap.framework = frameworkService.rundeckFramework
def rolelist = initMap.scheduledExecution.userRoles
initMap.authContext = frameworkService.getAuthContextForUserAndRoles(initMap.scheduledExecution.user, rolelist)
Expand Down
Expand Up @@ -1682,6 +1682,10 @@ class ExecutionService implements ApplicationContextAware, StepExecutor, NodeSte
return [success:false,failed:true,error:'disabled',message:lookupMessage('disabled.execution.run',null)]
}

if(!scheduledExecutionService.isProjectExecutionEnabled(scheduledExecution.project)){
return [success:false,failed:true,error:'disabled',message:lookupMessage('project.execution.disabled',null)]
}

if (!scheduledExecution.hasExecutionEnabled()) {
return [success:false,failed:true,error:'disabled',message:lookupMessage('scheduleExecution.execution.disabled',null)]
}
Expand Down