Add daemon handling service and associated routes.
This commit is contained in:
@@ -14,6 +14,7 @@ import java.util.UUID;
|
||||
|
||||
import static org.cerberus.core.constant.RoleSecurity.ADMIN;
|
||||
import static org.cerberus.core.constant.RoleSecurity.MAINTAINER;
|
||||
import static org.cerberus.services.DaemonHandlingService.Action.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/applications")
|
||||
@@ -54,4 +55,31 @@ public class ApplicationController {
|
||||
securityService.checkHasAnyRole(connectedUser, id, ADMIN, MAINTAINER);
|
||||
service.delete(id);
|
||||
}
|
||||
|
||||
@PostMapping("/{id}/start")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
public void start(@PathVariable("id") UUID id, Principal connectedUser) {
|
||||
securityService.checkHasAnyRole(connectedUser, id, ADMIN, MAINTAINER);
|
||||
service.doServiceAction(id, START);
|
||||
}
|
||||
|
||||
@PostMapping("/{id}/stop")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
public void stop(@PathVariable("id") UUID id, Principal connectedUser) {
|
||||
securityService.checkHasAnyRole(connectedUser, id, ADMIN, MAINTAINER);
|
||||
service.doServiceAction(id, STOP);
|
||||
}
|
||||
|
||||
@PostMapping("/{id}/restart")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
public void restart(@PathVariable("id") UUID id, Principal connectedUser) {
|
||||
securityService.checkHasAnyRole(connectedUser, id, ADMIN, MAINTAINER);
|
||||
service.doServiceAction(id, RESTART);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}/status")
|
||||
public int status(@PathVariable("id") UUID id, Principal connectedUser) {
|
||||
securityService.checkHasAnyRole(connectedUser, id, ADMIN, MAINTAINER);
|
||||
return service.getStatus(id);
|
||||
}
|
||||
}
|
||||
|
||||
18
src/main/java/org/cerberus/core/constant/ResultCode.java
Normal file
18
src/main/java/org/cerberus/core/constant/ResultCode.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package org.cerberus.core.constant;
|
||||
|
||||
public enum ResultCode {
|
||||
SUCCESS(0),
|
||||
FAILED(1),
|
||||
STATE_UNCHANGED(2),
|
||||
ILLEGAL_ARGUMENT(3);
|
||||
|
||||
private int val;
|
||||
|
||||
private ResultCode(final int pVal) {
|
||||
val = pVal;
|
||||
}
|
||||
|
||||
public final int val() {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.cerberus.core.exceptions;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
@ResponseStatus(value = HttpStatus.SERVICE_UNAVAILABLE)
|
||||
public class ServiceUnavailableException extends BusinessException {
|
||||
public ServiceUnavailableException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ServiceUnavailableException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package org.cerberus.entities.business;
|
||||
|
||||
/**
|
||||
* Object that contains the results of a system command.
|
||||
*
|
||||
* @author takiguchi
|
||||
*
|
||||
*/
|
||||
public class SystemResult {
|
||||
/** The result code of the command. */
|
||||
private int resultCode;
|
||||
/** The standard output of the command. */
|
||||
private StringBuilder stdOut;
|
||||
/** The standard errors output of the command. */
|
||||
private StringBuilder stdErr;
|
||||
|
||||
public SystemResult() {
|
||||
super();
|
||||
stdOut = new StringBuilder();
|
||||
stdErr = new StringBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the result code.
|
||||
*
|
||||
* @return the result code
|
||||
*/
|
||||
public int getResultCode() {
|
||||
return resultCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the result code.
|
||||
*
|
||||
* @param resultCode
|
||||
* the new result code
|
||||
*/
|
||||
public void setResultCode(int resultCode) {
|
||||
this.resultCode = resultCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the std out.
|
||||
*
|
||||
* @return the std out
|
||||
*/
|
||||
public String getStdOut() {
|
||||
return stdOut.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an output line to the {@code stdOut}.
|
||||
*
|
||||
* @param pLine
|
||||
* The output line to append.
|
||||
*/
|
||||
public void addOutputLine(final String pLine) {
|
||||
stdOut.append(pLine);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the std out.
|
||||
*
|
||||
* @param stdOut
|
||||
* the new std out
|
||||
*/
|
||||
public void setStdOut(String stdOut) {
|
||||
this.stdOut = new StringBuilder(stdOut);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the std err.
|
||||
*
|
||||
* @return the std err
|
||||
*/
|
||||
public String getStdErr() {
|
||||
return stdErr.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an error line to the {@code stdErr}.
|
||||
*
|
||||
* @param pLine
|
||||
* The error line to append.
|
||||
*/
|
||||
public void addErrorLine(final String pLine) {
|
||||
stdErr.append(pLine);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the std err.
|
||||
*
|
||||
* @param stdErr
|
||||
* the new std err
|
||||
*/
|
||||
public void setStdErr(String stdErr) {
|
||||
this.stdErr = new StringBuilder(stdErr);
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,8 @@ import org.cerberus.validators.ApplicationValidator;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.cerberus.core.constant.Role.MAINTAINER;
|
||||
import static org.cerberus.core.utils.StringUtils.concat;
|
||||
|
||||
@@ -16,14 +18,17 @@ public class ApplicationService extends AbstractService<Application> {
|
||||
private ApplicationRepository repository;
|
||||
private ApplicationRoleService applicationRoleService;
|
||||
private ApplicationValidator validator;
|
||||
private DaemonHandlingService daemonHandlingService;
|
||||
|
||||
ApplicationService(ApplicationRepository repository,
|
||||
ApplicationRoleService applicationRoleService,
|
||||
ApplicationValidator validator) {
|
||||
ApplicationValidator validator,
|
||||
DaemonHandlingService daemonHandlingService) {
|
||||
super(repository);
|
||||
this.repository = repository;
|
||||
this.applicationRoleService = applicationRoleService;
|
||||
this.validator = validator;
|
||||
this.daemonHandlingService = daemonHandlingService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -63,4 +68,12 @@ public class ApplicationService extends AbstractService<Application> {
|
||||
|
||||
return repository.save(application);
|
||||
}
|
||||
|
||||
public void doServiceAction(UUID applicationId, DaemonHandlingService.Action action) {
|
||||
daemonHandlingService.doServiceAction(findByIdOrElseThrow(applicationId), action);
|
||||
}
|
||||
|
||||
public int getStatus(UUID applicationId) {
|
||||
return daemonHandlingService.getStatus(findByIdOrElseThrow(applicationId));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package org.cerberus.services;
|
||||
|
||||
import org.cerberus.core.exceptions.BadRequestException;
|
||||
import org.cerberus.core.exceptions.ServiceUnavailableException;
|
||||
import org.cerberus.entities.business.SystemResult;
|
||||
import org.cerberus.entities.persistence.Application;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import static org.cerberus.core.constant.ResultCode.SUCCESS;
|
||||
import static org.cerberus.core.utils.StringUtils.concat;
|
||||
|
||||
@Service
|
||||
public class DaemonHandlingService {
|
||||
public enum Action {
|
||||
START,
|
||||
STOP,
|
||||
RESTART
|
||||
}
|
||||
|
||||
private SystemService systemService;
|
||||
|
||||
DaemonHandlingService(SystemService systemService) {
|
||||
this.systemService = systemService;
|
||||
}
|
||||
|
||||
public int getStatus(Application application) {
|
||||
return systemService.executeCommand("sudo service", application.getServiceName(), "status")
|
||||
.getResultCode();
|
||||
}
|
||||
|
||||
public void doServiceAction(Application application, Action action) {
|
||||
int applicationStatus = getStatus(application);
|
||||
|
||||
if((Action.START == action && applicationStatus == 0)
|
||||
|| (Action.STOP == action && applicationStatus != 0)) {
|
||||
throw new BadRequestException(concat("Service is already ", action.name().toLowerCase(), "ed."));
|
||||
}
|
||||
|
||||
SystemResult commandResult = systemService.executeCommand("sudo service",
|
||||
application.getServiceName(),
|
||||
action.name().toLowerCase());
|
||||
|
||||
if(commandResult.getResultCode() != SUCCESS.val()) {
|
||||
throw new ServiceUnavailableException(commandResult.getStdErr());
|
||||
}
|
||||
}
|
||||
}
|
||||
74
src/main/java/org/cerberus/services/SystemService.java
Normal file
74
src/main/java/org/cerberus/services/SystemService.java
Normal file
@@ -0,0 +1,74 @@
|
||||
package org.cerberus.services;
|
||||
|
||||
import org.cerberus.entities.business.SystemResult;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
import static org.cerberus.core.utils.StringUtils.concat;
|
||||
|
||||
/**
|
||||
* Business service to execute unix commands.
|
||||
*/
|
||||
@Service
|
||||
public class SystemService {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SystemService.class);
|
||||
|
||||
public SystemResult executeCommand(final String pCommand, final String... arguments) {
|
||||
final String commandWithArgs = buildCommand(pCommand, arguments);
|
||||
|
||||
final SystemResult commandResults = new SystemResult();
|
||||
|
||||
try {
|
||||
// Process creation and execution of the command.
|
||||
final Process process = Runtime.getRuntime().exec(commandWithArgs);
|
||||
|
||||
// Waiting the end of the command execution.
|
||||
process.waitFor();
|
||||
|
||||
// Getting of the stantard command output, and the standard error output.
|
||||
BufferedReader outputReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
|
||||
|
||||
String tempLine;
|
||||
while((tempLine = outputReader.readLine()) != null) {
|
||||
commandResults.addOutputLine(tempLine);
|
||||
}
|
||||
|
||||
while((tempLine = errorReader.readLine()) != null) {
|
||||
commandResults.addErrorLine(tempLine);
|
||||
}
|
||||
|
||||
commandResults.setResultCode(process.exitValue());
|
||||
} catch(IOException | InterruptedException ex) {
|
||||
LOG.error(concat("Error during command execution of: \"", commandWithArgs, "\"."), ex);
|
||||
}
|
||||
|
||||
return commandResults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the command in form of one string from the parameters.
|
||||
*
|
||||
* @param command
|
||||
* The command to execute.
|
||||
* @param arguments
|
||||
* The command arguments, could be {@code null}.
|
||||
* @return The command built.
|
||||
*/
|
||||
private String buildCommand(final String command, final Object... arguments) {
|
||||
final StringBuilder commandBuilder = new StringBuilder(command);
|
||||
|
||||
if (arguments != null) {
|
||||
for (final Object arg : arguments) {
|
||||
commandBuilder.append(" ").append(arg);
|
||||
}
|
||||
}
|
||||
|
||||
return commandBuilder.toString();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user