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.ADMIN;
|
||||||
import static org.cerberus.core.constant.RoleSecurity.MAINTAINER;
|
import static org.cerberus.core.constant.RoleSecurity.MAINTAINER;
|
||||||
|
import static org.cerberus.services.DaemonHandlingService.Action.*;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/applications")
|
@RequestMapping("/api/applications")
|
||||||
@@ -54,4 +55,31 @@ public class ApplicationController {
|
|||||||
securityService.checkHasAnyRole(connectedUser, id, ADMIN, MAINTAINER);
|
securityService.checkHasAnyRole(connectedUser, id, ADMIN, MAINTAINER);
|
||||||
service.delete(id);
|
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.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import static org.cerberus.core.constant.Role.MAINTAINER;
|
import static org.cerberus.core.constant.Role.MAINTAINER;
|
||||||
import static org.cerberus.core.utils.StringUtils.concat;
|
import static org.cerberus.core.utils.StringUtils.concat;
|
||||||
|
|
||||||
@@ -16,14 +18,17 @@ public class ApplicationService extends AbstractService<Application> {
|
|||||||
private ApplicationRepository repository;
|
private ApplicationRepository repository;
|
||||||
private ApplicationRoleService applicationRoleService;
|
private ApplicationRoleService applicationRoleService;
|
||||||
private ApplicationValidator validator;
|
private ApplicationValidator validator;
|
||||||
|
private DaemonHandlingService daemonHandlingService;
|
||||||
|
|
||||||
ApplicationService(ApplicationRepository repository,
|
ApplicationService(ApplicationRepository repository,
|
||||||
ApplicationRoleService applicationRoleService,
|
ApplicationRoleService applicationRoleService,
|
||||||
ApplicationValidator validator) {
|
ApplicationValidator validator,
|
||||||
|
DaemonHandlingService daemonHandlingService) {
|
||||||
super(repository);
|
super(repository);
|
||||||
this.repository = repository;
|
this.repository = repository;
|
||||||
this.applicationRoleService = applicationRoleService;
|
this.applicationRoleService = applicationRoleService;
|
||||||
this.validator = validator;
|
this.validator = validator;
|
||||||
|
this.daemonHandlingService = daemonHandlingService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@@ -63,4 +68,12 @@ public class ApplicationService extends AbstractService<Application> {
|
|||||||
|
|
||||||
return repository.save(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