use of org.eclipse.che.api.core.ConflictException in project che by eclipse.
the class CheEnvironmentEngine method initializeEnvironment.
private void initializeEnvironment(String namespace, String workspaceId, String envName, EnvironmentImpl envConfig, String networkId, MessageConsumer<MachineLogMessage> messageConsumer) throws ServerException, ConflictException, EnvironmentException {
CheServicesEnvironmentImpl internalEnv = environmentParser.parse(envConfig);
internalEnv.setWorkspaceId(workspaceId);
infrastructureProvisioner.provision(envConfig, internalEnv);
normalize(namespace, workspaceId, internalEnv);
List<String> servicesOrder = startStrategy.order(internalEnv);
normalizeNames(internalEnv);
EnvironmentHolder environmentHolder = new EnvironmentHolder(servicesOrder, internalEnv, envConfig, messageConsumer, EnvStatus.STARTING, envName, networkId);
try (@SuppressWarnings("unused") Unlocker u = stripedLocks.writeLock(workspaceId)) {
if (environments.putIfAbsent(workspaceId, environmentHolder) != null) {
throw new ConflictException(format("Environment of workspace '%s' already exists", workspaceId));
}
}
}
use of org.eclipse.che.api.core.ConflictException in project che by eclipse.
the class WorkspaceService method updateCommand.
@PUT
@Path("/{id}/command/{name}")
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
@ApiOperation(value = "Update the workspace command by replacing the command with a new one", notes = "This operation can be performed only by the workspace owner")
@ApiResponses({ @ApiResponse(code = 200, message = "The command successfully updated"), @ApiResponse(code = 400, message = "Missed required parameters, parameters are not valid"), @ApiResponse(code = 403, message = "The user does not have access to update the workspace"), @ApiResponse(code = 404, message = "The workspace or the command not found"), @ApiResponse(code = 409, message = "The Command with such name already exists"), @ApiResponse(code = 500, message = "Internal server error occurred") })
public WorkspaceDto updateCommand(@ApiParam("The workspace id") @PathParam("id") String id, @ApiParam("The name of the command") @PathParam("name") String cmdName, @ApiParam(value = "The command update", required = true) CommandDto update) throws ServerException, BadRequestException, NotFoundException, ConflictException, ForbiddenException {
requiredNotNull(update, "Command update");
final WorkspaceImpl workspace = workspaceManager.getWorkspace(id);
final List<CommandImpl> commands = workspace.getConfig().getCommands();
if (!commands.removeIf(cmd -> cmd.getName().equals(cmdName))) {
throw new NotFoundException(format("Workspace '%s' doesn't contain command '%s'", id, cmdName));
}
commands.add(new CommandImpl(update));
validator.validateConfig(workspace.getConfig());
return linksInjector.injectLinks(asDto(workspaceManager.updateWorkspace(workspace.getId(), workspace)), getServiceContext());
}
use of org.eclipse.che.api.core.ConflictException in project che by eclipse.
the class WorkspaceRuntimes method startAsync.
/**
* Asynchronously starts the environment of the workspace.
* Before executing start task checks whether all conditions
* are met and throws appropriate exceptions if not, so
* there is no way to start the same workspace twice.
*
* <p>Note that cancellation of resulting future won't
* interrupt workspace start, call {@link #stop(String)} directly instead.
*
* <p>If starting process is interrupted let's say within call
* to {@link #stop(String)} method, resulting future will
* be exceptionally completed(eventually) with an instance of
* {@link EnvironmentStartInterruptedException}. Note that clients
* don't have to cleanup runtime resources, the component
* will do necessary cleanup when interrupted.
*
* <p>Implementation notes:
* if thread which executes the task is interrupted, then the
* task is also eventually(depends on the environment engine implementation)
* interrupted as if {@link #stop(String)} is called directly.
* That helps to shutdown gracefully when thread pool is asked
* to {@link ExecutorService#shutdownNow()} and also reduces
* shutdown time when there are starting workspaces.
*
* @param workspace
* workspace containing target environment
* @param envName
* the name of the environment to start
* @param recover
* whether to recover from the snapshot
* @return completable future describing the instance of running environment
* @throws ConflictException
* when the workspace is already started
* @throws ConflictException
* when workspaces start refused {@link #refuseWorkspacesStart()} was called
* @throws ServerException
* when any other error occurs
* @throws IllegalArgumentException
* when the workspace doesn't contain the environment
* @throws NullPointerException
* when either {@code workspace} or {@code envName} is null
*/
public CompletableFuture<WorkspaceRuntimeImpl> startAsync(Workspace workspace, String envName, boolean recover) throws ConflictException, ServerException {
requireNonNull(workspace, "Non-null workspace required");
requireNonNull(envName, "Non-null environment name required");
EnvironmentImpl environment = copyEnv(workspace, envName);
String workspaceId = workspace.getId();
CompletableFuture<WorkspaceRuntimeImpl> cmpFuture;
StartTask startTask;
try (@SuppressWarnings("unused") Unlocker u = locks.writeLock(workspaceId)) {
checkIsNotTerminated("start the workspace");
if (isStartRefused.get()) {
throw new ConflictException(format("Start of the workspace '%s' is rejected by the system, " + "no more workspaces are allowed to start", workspace.getConfig().getName()));
}
RuntimeState state = states.get(workspaceId);
if (state != null) {
throw new ConflictException(format("Could not start workspace '%s' because its status is '%s'", workspace.getConfig().getName(), state.status));
}
startTask = new StartTask(workspaceId, envName, environment, recover, cmpFuture = new CompletableFuture<>());
states.put(workspaceId, new RuntimeState(WorkspaceStatus.STARTING, envName, startTask, sharedPool.submit(startTask)));
}
// publish event synchronously as the task may not be executed by
// executors service(due to legal cancellation), clients still have
// to receive STOPPED -> STARTING event
eventsService.publish(DtoFactory.newDto(WorkspaceStatusEvent.class).withWorkspaceId(workspaceId).withStatus(WorkspaceStatus.STARTING).withEventType(EventType.STARTING).withPrevStatus(WorkspaceStatus.STOPPED));
// so the start thread is free to go and start the environment
startTask.unlockStart();
return cmpFuture;
}
use of org.eclipse.che.api.core.ConflictException in project che by eclipse.
the class WorkspaceRuntimes method startEnvironmentAndPublishEvents.
/**
* Starts the environment publishing all the necessary events.
* Respects task interruption & stops the workspace if starting task is cancelled.
*/
private void startEnvironmentAndPublishEvents(EnvironmentImpl environment, String workspaceId, String envName, boolean recover) throws ServerException, EnvironmentException, ConflictException {
try {
envEngine.start(workspaceId, envName, environment, recover, new WebsocketMessageConsumer<>(format(ENVIRONMENT_OUTPUT_CHANNEL_TEMPLATE, workspaceId)), machineAgentsLauncher);
} catch (EnvironmentStartInterruptedException x) {
// environment start was interrupted, it's either shutdown or direct stop
// in the case of shutdown make sure the status is correct,
// otherwise workspace is already stopping
compareAndSetStatus(workspaceId, WorkspaceStatus.STARTING, WorkspaceStatus.STOPPING);
removeStateAndPublishStopEvents(workspaceId);
throw x;
} catch (EnvironmentException | ServerException | ConflictException x) {
// environment can't be started for some reason, STARTING -> STOPPED
removeState(workspaceId);
eventsService.publish(DtoFactory.newDto(WorkspaceStatusEvent.class).withWorkspaceId(workspaceId).withEventType(EventType.ERROR).withPrevStatus(WorkspaceStatus.STARTING).withStatus(WorkspaceStatus.STOPPED).withError("Start of environment '" + envName + "' failed. Error: " + x.getMessage()));
throw x;
}
// disallow direct start cancellation, STARTING -> RUNNING
WorkspaceStatus prevStatus;
try (@SuppressWarnings("unused") Unlocker u = locks.writeLock(workspaceId)) {
checkIsNotTerminated("finish workspace start");
RuntimeState state = states.get(workspaceId);
prevStatus = state.status;
if (state.status == WorkspaceStatus.STARTING) {
state.status = WorkspaceStatus.RUNNING;
state.startTask = null;
state.startFuture = null;
}
}
// or stop is called directly, anyway stop the environment
if (Thread.interrupted() || prevStatus != WorkspaceStatus.STARTING) {
try {
stopEnvironmentAndPublishEvents(workspaceId, WorkspaceStatus.STARTING);
} catch (Exception x) {
LOG.error("Couldn't stop the environment '{}' of the workspace '{}'. Error: {}", envName, workspaceId, x.getMessage());
}
throw new EnvironmentStartInterruptedException(workspaceId, envName);
}
// normally started, notify clients
eventsService.publish(DtoFactory.newDto(WorkspaceStatusEvent.class).withWorkspaceId(workspaceId).withStatus(WorkspaceStatus.RUNNING).withEventType(EventType.RUNNING).withPrevStatus(WorkspaceStatus.STARTING));
}
use of org.eclipse.che.api.core.ConflictException in project che by eclipse.
the class SystemManager method stopServices.
/**
* Stops some of the system services preparing system to lighter shutdown.
* System status is changed from {@link SystemStatus#RUNNING} to
* {@link SystemStatus#PREPARING_TO_SHUTDOWN}.
*
* @throws ConflictException
* when system status is different from running
*/
public void stopServices() throws ConflictException {
if (!statusRef.compareAndSet(RUNNING, PREPARING_TO_SHUTDOWN)) {
throw new ConflictException("System shutdown has been already called, system status: " + statusRef.get());
}
ExecutorService exec = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setDaemon(false).setNameFormat("ShutdownSystemServicesPool").setUncaughtExceptionHandler(LoggingUncaughtExceptionHandler.getInstance()).build());
exec.execute(ThreadLocalPropagateContext.wrap(this::doStopServices));
exec.shutdown();
}
Aggregations