diff --git a/.gitignore b/.gitignore index ed439f2..015127e 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ test-output/ .classpath .settings/ .metadata/ +**TestingPivotalClient.java .idea/ *.iml @@ -30,3 +31,4 @@ brooklyn*.log.* *brooklyn-persisted-state/ ignored +**pivotal.properties diff --git a/README.md b/README.md index 0b07061..25ed90c 100644 --- a/README.md +++ b/README.md @@ -5,3 +5,4 @@ - Integrate TOSCA-based object model. - Integrate Lombok - Dockerized testing + diff --git a/core/pom.xml b/core/pom.xml index 3ad71bf..c21b35c 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -65,7 +65,41 @@ test + + + + + org.apache.commons + commons-math3 + 3.6 + test + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core/src/main/java/org/scenic/orchestrator/Application.java b/core/src/main/java/org/scenic/orchestrator/Application.java index cd2d451..cb124e6 100644 --- a/core/src/main/java/org/scenic/orchestrator/Application.java +++ b/core/src/main/java/org/scenic/orchestrator/Application.java @@ -3,6 +3,7 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; +import org.springframework.context.annotation.PropertySource; import org.springframework.scheduling.annotation.EnableScheduling; /** diff --git a/core/src/main/java/org/scenic/orchestrator/config/PivotalClientConfiguration.java b/core/src/main/java/org/scenic/orchestrator/config/PivotalClientConfiguration.java new file mode 100644 index 0000000..c67eac1 --- /dev/null +++ b/core/src/main/java/org/scenic/orchestrator/config/PivotalClientConfiguration.java @@ -0,0 +1,26 @@ +package org.scenic.orchestrator.config; + +import org.scenic.orchestrator.core.pivotal.PivotalClient; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +/** + * Created by Jose on 10/12/19. + */ +@Configuration +@PropertySource("classpath:pivotal.properties") +public class PivotalClientConfiguration { + + @Value("${pivotalUser}") + private String pivotalUser; + + @Value("${pivotalPass}") + private String pivotalPass; + + @Bean + public PivotalClient pivotalClient() { + return new PivotalClient(pivotalUser, pivotalPass); + } +} diff --git a/core/src/main/java/org/scenic/orchestrator/config/ThreadPoolExecutorConfig.java b/core/src/main/java/org/scenic/orchestrator/config/ThreadPoolExecutorConfig.java new file mode 100644 index 0000000..6afff10 --- /dev/null +++ b/core/src/main/java/org/scenic/orchestrator/config/ThreadPoolExecutorConfig.java @@ -0,0 +1,53 @@ +package org.scenic.orchestrator.config; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import org.scenic.orchestrator.core.service.plan.PlanStepExecutor; +import org.scenic.orchestrator.core.service.plan.strategy.ParallelStepExecutorStrategy; +import org.scenic.orchestrator.core.service.plan.strategy.SingleStepExecutorStrategy; +import org.scenic.orchestrator.manager.ManagerAnalyzerClient; +import org.scenic.orchestrator.manager.SecuentialManagerAnalyzerClient; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.web.client.RestTemplate; + +/** + * Created by Jose on 01/10/19. + */ +@Configuration +public class ThreadPoolExecutorConfig { + + @Bean(destroyMethod = "shutdown") + public ExecutorService executorService() { + return Executors.newFixedThreadPool(10); + } + + @Bean + @Profile("!secuential") + ParallelStepExecutorStrategy parallelStepExecutorStrategy(PlanStepExecutor planStepExecutor, + ExecutorService executorService) { + return new ParallelStepExecutorStrategy(planStepExecutor, executorService); + } + + @Bean + @Profile("!secuential") + ManagerAnalyzerClient managerAnalyzerClient(RestTemplate restTemplate){ + return new ManagerAnalyzerClient(restTemplate); + } + + @Bean + @Profile("secuential") + SingleStepExecutorStrategy singleStepExecutorStrategy(PlanStepExecutor planStepExecutor) { + return new SingleStepExecutorStrategy(planStepExecutor); + } + + + @Bean + @Profile("secuential") + ManagerAnalyzerClient secuentialManagerAnalyzerClient(RestTemplate restTemplate){ + return new SecuentialManagerAnalyzerClient(restTemplate); + } +} diff --git a/core/src/main/java/org/scenic/orchestrator/core/UpdateStatusScheduler.java b/core/src/main/java/org/scenic/orchestrator/core/UpdateStatusScheduler.java new file mode 100644 index 0000000..5fd6a69 --- /dev/null +++ b/core/src/main/java/org/scenic/orchestrator/core/UpdateStatusScheduler.java @@ -0,0 +1,25 @@ +package org.scenic.orchestrator.core; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +/** + * Created by Jose on 17/10/19. + */ +@ConditionalOnProperty(name="scheduleUpdating") +@Component +public class UpdateStatusScheduler { + + private final UpdaterManagement updaterManagement; + + public UpdateStatusScheduler(UpdaterManagement updaterManagement) { + this.updaterManagement = updaterManagement; + } + + @Scheduled(fixedRateString = "${instructionSchedularTime}") + public void deployApp() throws InterruptedException { + updaterManagement.updateApplication(); + } + +} diff --git a/core/src/main/java/org/scenic/orchestrator/core/UpdaterManagement.java b/core/src/main/java/org/scenic/orchestrator/core/UpdaterManagement.java index 124b89c..a1f13ca 100644 --- a/core/src/main/java/org/scenic/orchestrator/core/UpdaterManagement.java +++ b/core/src/main/java/org/scenic/orchestrator/core/UpdaterManagement.java @@ -15,7 +15,6 @@ @Component public class UpdaterManagement { - private final ManagementContext managementContext; private PlanManager planManager; @@ -24,8 +23,7 @@ public UpdaterManagement(ManagementContext managementContext, PlanManager planMa this.planManager = planManager; } - - @Scheduled(fixedRateString = "${instructionSchedularTime}") + //@Scheduled(fixedRateString = "${instructionSchedularTime}") public void updateApplication() { List applicationsToUpdate = MutableList.of(); @@ -41,6 +39,7 @@ public void updateApplication() { @Async("threadPoolTaskExecutor") public void manageApplication(RunningAppContext appContext){ + System.out.println("Checking updating"); planManager.update(appContext); managementContext.addRunningAppContext(appContext); } diff --git a/core/src/main/java/org/scenic/orchestrator/core/deployer/DeployerProxy.java b/core/src/main/java/org/scenic/orchestrator/core/deployer/DeployerProxy.java index ac70aeb..4b02f00 100644 --- a/core/src/main/java/org/scenic/orchestrator/core/deployer/DeployerProxy.java +++ b/core/src/main/java/org/scenic/orchestrator/core/deployer/DeployerProxy.java @@ -27,9 +27,14 @@ public class DeployerProxy { private static final String START_EFFECTOR_NAME = "start"; private static final String STOP_EFFECTOR_NAME = "stop"; + private static final String RESTART_EFFECTOR_NAME = "restart"; + private static final String STOP_MACHINE_MODE = "stopMachineMode"; private static final String STOP_MACHINE_IF_NOT_STOPPED = "IF_NOT_STOPPED"; + private static final String STOP_PROCESS_MODE = "stopProcessMode"; + private static final String STOP_PROCESS_MODE_NEVER = "NEVER"; + private final BrooklynApi brooklynApi; private final ApplicationApi applicationApi; @@ -74,6 +79,19 @@ public void stopEffector(RunningAppContext app, String entityId) { executeEffector(effectorTemplate); } + public void restartEffector(RunningAppContext app, String entityId) { + EffectorTemplate effectorTemplate = + new EffectorTemplate(app, entityId, RESTART_EFFECTOR_NAME, getRestartBody()); + executeEffector(effectorTemplate); + } + + + public void releaseEffector(RunningAppContext app, String entityId) { + EffectorTemplate effectorTemplate = + new EffectorTemplate(app, entityId, STOP_EFFECTOR_NAME, getReleaseBody()); + executeEffector(effectorTemplate); + } + private void executeEffector(EffectorTemplate effectorTemplate) { try { restBrooklynClient.executeEffector(effectorTemplate); @@ -87,6 +105,29 @@ private void executeEffector(EffectorTemplate effectorTemplate) { } public String getStopBody() { + try { + return objectMapper.writeValueAsString(MutableMap.of( + STOP_MACHINE_MODE, STOP_PROCESS_MODE_NEVER, + STOP_PROCESS_MODE, STOP_MACHINE_IF_NOT_STOPPED + )); + } catch (Exception e) { + throw new RuntimeException("STOP params can not be generated", e); + } + } + public String getRestartBody() { + try { + return objectMapper.writeValueAsString(MutableMap.of( + + )); + } catch (Exception e) { + throw new RuntimeException("STOP params can not be generated", e); + } + } + + + + + public String getReleaseBody() { try { return objectMapper.writeValueAsString(MutableMap.of(STOP_MACHINE_MODE, STOP_MACHINE_IF_NOT_STOPPED)); } catch (Exception e) { diff --git a/core/src/main/java/org/scenic/orchestrator/core/deployer/dto/BrooklynEntityStatus.java b/core/src/main/java/org/scenic/orchestrator/core/deployer/dto/BrooklynEntityStatus.java index 237b659..f997438 100644 --- a/core/src/main/java/org/scenic/orchestrator/core/deployer/dto/BrooklynEntityStatus.java +++ b/core/src/main/java/org/scenic/orchestrator/core/deployer/dto/BrooklynEntityStatus.java @@ -6,9 +6,10 @@ public enum BrooklynEntityStatus { RUNNING, + STARTING, ON_FIRE, CREATED, - STOPPED - + STOPPED, + STOPPING } diff --git a/core/src/main/java/org/scenic/orchestrator/core/deployer/dto/CustomEntity.java b/core/src/main/java/org/scenic/orchestrator/core/deployer/dto/CustomEntity.java index da04780..75c4417 100644 --- a/core/src/main/java/org/scenic/orchestrator/core/deployer/dto/CustomEntity.java +++ b/core/src/main/java/org/scenic/orchestrator/core/deployer/dto/CustomEntity.java @@ -1,7 +1,12 @@ package org.scenic.orchestrator.core.deployer.dto; +import static java.util.Arrays.stream; + +import java.util.List; import java.util.Map; +import org.apache.brooklyn.rest.domain.LocationSummary; +import org.springframework.core.ParameterizedTypeReference; import org.springframework.web.client.RestTemplate; /** @@ -71,10 +76,55 @@ public Boolean isUp() { return brooklynRestTemplate.getForEntity(sensorlink + IS_UP_SENSOR, Boolean.class).getBody(); } - public BrooklynEntityStatus status() { + public BrooklynEntityStatus getStatus() { return brooklynRestTemplate.getForEntity(sensorlink + STATUS_SENSOR, BrooklynEntityStatus.class).getBody(); } + public String getSensor(String sensorName){ + return brooklynRestTemplate.getForEntity(sensorlink +"/" +sensorName, String.class).getBody(); + } + + public boolean hasSshLiveCloudResources(){ + return stream(brooklynRestTemplate.getForEntity(getLinks().get("locations"), LocationSummary[].class).getBody()) + .anyMatch(this::hasSshResources); + } + + private boolean hasSshResources(LocationSummary l){ + return l.getType().toLowerCase().contains("ssh"); + } + + public boolean isInPaas(){ + return stream(brooklynRestTemplate.getForEntity(getLinks().get("locations"), LocationSummary[].class).getBody()) + .anyMatch(l -> l.getType().toLowerCase().contains("cloudfoundrypaaslocation")); + } + + public static class LocationSummary{ + + String id; + String type; + + public LocationSummary(){ + this.id=null; + this.type=null; + } + + public String getId(){ + return id; + } + + public String getType(){ + return type; + } + + public String setId(String id){ + return this.id=id; + } + + public String getType(String type){ + return this.type=type; + } + } + /*"id": "nDQUMK7J", "name": "SoftcareWS", "type": "org.apache.brooklyn.entity.webapp.tomcat.TomcatServer", @@ -97,6 +147,4 @@ public BrooklynEntityStatus status() { "catalog": "/v1/catalog/entities/org.apache.brooklyn.entity.webapp.tomcat.TomcatServer/0.9.0" } */ - - } diff --git a/core/src/main/java/org/scenic/orchestrator/core/dto/EntityStatus.java b/core/src/main/java/org/scenic/orchestrator/core/dto/EntityStatus.java index 1bfc509..dca5bc3 100644 --- a/core/src/main/java/org/scenic/orchestrator/core/dto/EntityStatus.java +++ b/core/src/main/java/org/scenic/orchestrator/core/dto/EntityStatus.java @@ -11,7 +11,9 @@ public enum EntityStatus { UNAVAILABLE("unavailable"), STARTED("started"), STOPPED("stopped"), - FAILED("failed"); + FAILED("failed"), + RELEASED("failed"), + ; private final String alias; diff --git a/core/src/main/java/org/scenic/orchestrator/core/dto/InitialAppStatusService.java b/core/src/main/java/org/scenic/orchestrator/core/dto/InitialAppStatusService.java index 446a3fc..e50ceff 100644 --- a/core/src/main/java/org/scenic/orchestrator/core/dto/InitialAppStatusService.java +++ b/core/src/main/java/org/scenic/orchestrator/core/dto/InitialAppStatusService.java @@ -27,6 +27,10 @@ public ApplicationStatus build(String appTopology) { return build(getNodeTemplateNames(appTopology)); } + public ApplicationStatus buildSycn(String appTopology) { + return buildSycn(getNodeTemplateNames(appTopology)); + } + public ApplicationStatus build(List entityNames) { Map current = new HashMap<>(); Map target = new HashMap<>(); @@ -38,6 +42,17 @@ public ApplicationStatus build(List entityNames) { return new ApplicationStatus(current, target); } + public ApplicationStatus buildSycn(List entityNames) { + Map current = new HashMap<>(); + Map target = new HashMap<>(); + for (String entityName : entityNames) { + current.put(entityName, EntityStatus.STARTED); + target.put(entityName, EntityStatus.STARTED); + } + + return new ApplicationStatus(current, target); + } + private List getNodeTemplateNames(String app) { final Map obj = yaml.load(app); return new LinkedList<>(((Map) ((Map) obj.get(TOPOLOGY_TEMPLATE)).get(NODE_TEMPLATES)).keySet()); diff --git a/core/src/main/java/org/scenic/orchestrator/core/dto/Plan.java b/core/src/main/java/org/scenic/orchestrator/core/dto/Plan.java index 619c5f3..61dac7a 100644 --- a/core/src/main/java/org/scenic/orchestrator/core/dto/Plan.java +++ b/core/src/main/java/org/scenic/orchestrator/core/dto/Plan.java @@ -4,10 +4,12 @@ import java.util.List; import java.util.stream.Collectors; +import com.fasterxml.jackson.annotation.JsonAlias; import com.fasterxml.jackson.annotation.JsonIgnore; public class Plan { + @JsonAlias({"parallelSteps", "plan"}) private List plan; public Plan() { diff --git a/core/src/main/java/org/scenic/orchestrator/core/dto/PlanOperation.java b/core/src/main/java/org/scenic/orchestrator/core/dto/PlanOperation.java index c4e9070..b5dd62b 100644 --- a/core/src/main/java/org/scenic/orchestrator/core/dto/PlanOperation.java +++ b/core/src/main/java/org/scenic/orchestrator/core/dto/PlanOperation.java @@ -10,7 +10,8 @@ public enum PlanOperation { START("start"), STOP("stop"), - RELEASE("release"); + RELEASE("release"), + RESTART("restart"); private String alias; diff --git a/core/src/main/java/org/scenic/orchestrator/core/dto/RunningAppContext.java b/core/src/main/java/org/scenic/orchestrator/core/dto/RunningAppContext.java index eb0b753..1e2aa16 100644 --- a/core/src/main/java/org/scenic/orchestrator/core/dto/RunningAppContext.java +++ b/core/src/main/java/org/scenic/orchestrator/core/dto/RunningAppContext.java @@ -1,8 +1,14 @@ package org.scenic.orchestrator.core.dto; +import static java.util.Arrays.stream; +import static java.util.stream.Collectors.toList; + +import java.util.List; + import org.scenic.orchestrator.core.deployer.dto.BrooklynEntityStatus; import org.scenic.orchestrator.core.deployer.dto.CustomApplicationEntities; import org.scenic.orchestrator.core.deployer.dto.CustomEntity; +import org.scenic.orchestrator.core.pivotal.PivotalClient; /** * Created by Jose on 23/01/19. @@ -18,13 +24,15 @@ public class RunningAppContext { private String applicationTopology; private String appId; private CustomApplicationEntities entities; + private PivotalClient pivotalClient; - public RunningAppContext(String applicationName, ApplicationStatus status, Plan plan, String applicationTopology) { + public RunningAppContext(String applicationName, ApplicationStatus status, Plan plan, String applicationTopology, PivotalClient pivotalClient) { this.status = status; this.applicationName = applicationName; this.plan = plan; this.applicationTopology = applicationTopology; + this.pivotalClient = pivotalClient; } public ApplicationStatus getStatus() { @@ -76,16 +84,40 @@ public boolean isUp() { } public void updateStatus() { + System.out.println("-- Update the status from brooklyn -- "); for (CustomEntity entity : entities.entities()) { - EntityStatus entityStatus = mapEntityStatus(entity.status()); + EntityStatus entityStatus = mapEntityStatus(entity); status.setCurrentEntityStatus(entity.getName(), entityStatus); + System.out.println(String.format("%s: %s", entity.getName(), entityStatus)); } + System.out.println("[End] -- "); } - private EntityStatus mapEntityStatus(BrooklynEntityStatus status) { + boolean hasCloudResources(CustomEntity entity) { + return entity.hasSshLiveCloudResources() || hasPaasResourcesAssociated(entity); + } + + + private EntityStatus mapEntityStatus(CustomEntity entity) { + + BrooklynEntityStatus status = entity.getStatus(); + + while (status == BrooklynEntityStatus.STOPPING) { + System.out.println("## UNSUPPORTED STOPPING status for entity " + entity.getName()); + try { + Thread.sleep(5000l); + } catch (Exception e) { + throw new RuntimeException(e); + } + status = entity.getStatus(); + } + boolean hasLiveCloudResources = hasCloudResources(entity); switch (status) { case RUNNING: + case STARTING: return EntityStatus.STARTED; + case STOPPED: + return hasLiveCloudResources ? EntityStatus.STOPPED : EntityStatus.UNAVAILABLE; case ON_FIRE: return EntityStatus.FAILED; case CREATED: @@ -93,4 +125,45 @@ private EntityStatus mapEntityStatus(BrooklynEntityStatus status) { return EntityStatus.UNAVAILABLE; } } + + private boolean hasPaasResourcesAssociated(CustomEntity entity) { + System.out.println("checking if pass " + entity.getName()); + if (entity.isInPaas()) { + System.out.println("is pass "); + boolean r = applicationExistsInPivotal(entity); + System.out.println("Application exist?" + r); + System.out.println("-------------------------"); + return r; + } + System.out.println("is NOt pass "); + System.out.println("-------------------------"); + return false; + } + + private boolean applicationExistsInPivotal(CustomEntity entity) { + String webName = webAppDeployedWar(entity).replace("\"", ""); + System.out.println("checking paas resources with name==> " + webName); + Boolean result = null; + int loop = 0; + while (result == null) { + try { + result = pivotalClient.applicationExist(webName); + } catch (Exception e) { + loop++; + if (loop > 11) { + throw e; + } + } + } + return result; + } + + private String webAppDeployedWar(CustomEntity entity) { + return toStringList(entity.getSensor("webapp.deployedWars")).get(0); + } + + private List toStringList(String value) { + return stream(value.replace("[", "").replace("]", "").split(",")).map(String::trim).collect(toList()); + } + } diff --git a/core/src/main/java/org/scenic/orchestrator/core/pivotal/PivotalClient.java b/core/src/main/java/org/scenic/orchestrator/core/pivotal/PivotalClient.java new file mode 100644 index 0000000..3664924 --- /dev/null +++ b/core/src/main/java/org/scenic/orchestrator/core/pivotal/PivotalClient.java @@ -0,0 +1,103 @@ +package org.scenic.orchestrator.core.pivotal; + +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.util.List; + +import org.cloudfoundry.client.lib.CloudCredentials; +import org.cloudfoundry.client.lib.CloudFoundryClient; +import org.cloudfoundry.client.lib.CloudFoundryException; +import org.cloudfoundry.client.lib.domain.CloudApplication; +import org.springframework.http.HttpStatus; + +/** + * Created by Jose on 10/12/19. + */ + +public class PivotalClient { + + private static CloudFoundryClient CLIENT; + + public PivotalClient(String user, String pass) { + setUpClient(user, pass); + } + + private static void setUpClient(String pivotalUser, String pivotalPass) { + if (CLIENT == null) { + CloudCredentials credentials = + new CloudCredentials(pivotalUser, pivotalPass); + CLIENT = new CloudFoundryClient(credentials, getTargetURL("https://api.run.pivotal.io"), + "gsoc", "development", true); + CLIENT.login(); + } + } + + public CloudFoundryClient client(){ + return CLIENT; + } + + public void refresh() { + int i = 0; + while (i < 10) + try { + CLIENT.login().getRefreshToken(); + return; + } catch (Exception e) { + System.out.println("Error in refresh: retrying"); + i++; + if (i == 10) { + throw e; + } + } + } + + private static URL getTargetURL(String target) { + try { + return URI.create(target).toURL(); + } catch (MalformedURLException e) { + throw new RuntimeException("The target URL is not valid: " + e.getMessage()); + } + } + + public List getApplications() { + return CLIENT.getApplications(); + } + + private CloudApplication getApplication(String name) { + return CLIENT.getApplication(name); + + } + + public boolean applicationExist(String appName) { + System.out.println("Checking if application exist"); + //int i=0; + //int limit=20; + //while(i appName.equals(a.getName())); + } catch (CloudFoundryException e) { + if (e.getStatusCode().equals(HttpStatus.NOT_FOUND)) { + System.out.println("NotFoundApplication" + e.getCause()); + return false; + } + System.out.println("Retring checking because" + e.getCause()); + // if(i>limit){ + throw e; + // } + } catch (Exception ee) { + System.out.println("Retring checking because" + ee.getCause()); + //if(i>limit){ + throw ee; + //} + + } + // i++; + //} + //return false; + } +} diff --git a/core/src/main/java/org/scenic/orchestrator/core/pivotal/PivotalHeartbeat.java b/core/src/main/java/org/scenic/orchestrator/core/pivotal/PivotalHeartbeat.java new file mode 100644 index 0000000..5e01cc6 --- /dev/null +++ b/core/src/main/java/org/scenic/orchestrator/core/pivotal/PivotalHeartbeat.java @@ -0,0 +1,44 @@ +package org.scenic.orchestrator.core.pivotal; + +import java.time.Instant; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.security.oauth2.common.OAuth2AccessToken; + +@Configuration +public class PivotalHeartbeat { + + private final PivotalClient pivotalClient; + OAuth2AccessToken login; + public int status=0; + + public PivotalHeartbeat(PivotalClient pivotalClient) { + this.pivotalClient = pivotalClient; + login = pivotalClient.client().login(); + } + + @Scheduled(initialDelay = 3_000, fixedRate = 60_000l) + public void checkApplications() { + try { + System.out.println(Instant.now()+": *Heartbeat: " + login.getExpiresIn()); + + + if(status >= 300){ + System.out.println(Instant.now()+": Status has to been refresed "); + this.pivotalClient.refresh(); + status=0; + } else { + status = status + 60; + } + + + this.pivotalClient.getApplications(); + System.out.println(Instant.now()+":Fin refresh: "+ login.getExpiresIn()); + } catch (Exception e) { + System.out.println("------------------------------------------------------------------------------------------------"); + System.out.println(Instant.now().toString() + ": Error with Pivotal heartbat -----------------------------------> " + e.getCause()); + System.out.println("------------------------------------------------------------------------------------------------"); + } + } +} diff --git a/core/src/main/java/org/scenic/orchestrator/core/service/ApplicationContextManagerService.java b/core/src/main/java/org/scenic/orchestrator/core/service/ApplicationContextManagerService.java index ca03edf..99986e5 100644 --- a/core/src/main/java/org/scenic/orchestrator/core/service/ApplicationContextManagerService.java +++ b/core/src/main/java/org/scenic/orchestrator/core/service/ApplicationContextManagerService.java @@ -2,11 +2,14 @@ import java.util.Map; +import org.scenic.orchestrator.core.deployer.DeployerProxy; import org.scenic.orchestrator.core.dto.ApplicationStatus; import org.scenic.orchestrator.core.dto.InitialAppStatusService; import org.scenic.orchestrator.core.dto.Plan; import org.scenic.orchestrator.core.dto.RunningAppContext; import org.scenic.orchestrator.core.modifier.TopologyModifierService; +import org.scenic.orchestrator.core.pivotal.PivotalClient; +import org.scenic.orchestrator.manager.ManagerAnalyzerClient; import org.springframework.stereotype.Service; import org.yaml.snakeyaml.Yaml; @@ -26,27 +29,63 @@ public class ApplicationContextManagerService { private final TopologyModifierService topologyModifierService; + private final DeployerProxy deployerProxy; + + private final PivotalClient pivotalClient; + public ApplicationContextManagerService(ManagerAnalyzerClient managerAnalyzerClient, Yaml yaml, InitialAppStatusService initialAppStatusService, - TopologyModifierService topologyModifierService) { + TopologyModifierService topologyModifierService, DeployerProxy deployerProxy, + PivotalClient pivotalClient) { this.managerAnalyzerClient = managerAnalyzerClient; this.yaml = yaml; this.initialAppStatusService = initialAppStatusService; this.topologyModifierService = topologyModifierService; + this.deployerProxy = deployerProxy; + this.pivotalClient = pivotalClient; } + //Crea RunningApplication Context public RunningAppContext postApplicationContext(String applicationTopology) { + final String applicationName = getApplicationName(applicationTopology); + + //manda la app a analyzer managerAnalyzerClient.deployApplication(applicationTopology); + + //actualiza el estado (source) unavailable to (target) started managerAnalyzerClient.putStatus(applicationName, initialAppStatusService.build(applicationTopology)); + + //coge el plan final Plan plan = managerAnalyzerClient.getPlan(getApplicationName(applicationTopology)); + + //Application status es el estado actual de la app final ApplicationStatus status = initialAppStatusService.build(plan.getEntities()); - return new RunningAppContext(applicationName, status, plan, topologyModifierService.apply(applicationTopology)); + //Genera un RunningAppContext y lo (guardando la topologia con los midificadores necesarios) + return new RunningAppContext(applicationName, status, plan, topologyModifierService.apply(applicationTopology), pivotalClient); } private String getApplicationName(String applicationTopology) { final Map obj = yaml.load(applicationTopology); return obj.get("template_name").toString(); } + + public RunningAppContext sycnApplication(String applicationTopology, String appId) { + //RunningAppContext runningAppContext = postApplicationContext(applicationTopology); + final String applicationName = getApplicationName(applicationTopology); + managerAnalyzerClient.deployApplication(applicationTopology); + ApplicationStatus status = initialAppStatusService.buildSycn(applicationTopology); + managerAnalyzerClient.putStatus(applicationName, status); + + //Tiene que ser vacio el plan + final Plan plan = managerAnalyzerClient.getPlan(getApplicationName(applicationTopology)); + RunningAppContext runningAppContext = new RunningAppContext(applicationName, status, plan, topologyModifierService.apply(applicationTopology), pivotalClient); + runningAppContext.setAppId(appId); + + System.out.println("Sync the deployed application: " + runningAppContext.getApplicationName() + " with id " + appId); + runningAppContext.setEntities(deployerProxy.getApplicationEntities(appId)); + + return runningAppContext; + } } diff --git a/core/src/main/java/org/scenic/orchestrator/core/service/ApplicationSynchronizerService.java b/core/src/main/java/org/scenic/orchestrator/core/service/ApplicationSynchronizerService.java new file mode 100644 index 0000000..cf55518 --- /dev/null +++ b/core/src/main/java/org/scenic/orchestrator/core/service/ApplicationSynchronizerService.java @@ -0,0 +1,33 @@ +package org.scenic.orchestrator.core.service; + +import org.scenic.orchestrator.core.ManagementContext; +import org.scenic.orchestrator.core.dto.RunningAppContext; +import org.springframework.stereotype.Service; + +/** + * Contains the logic to orchestrate an application deployment. + */ +@Service +public class ApplicationSynchronizerService { + + private final ApplicationContextManagerService applicationContextManagerService; + private final DeploymentOrchestrator deploymentOrchestrator; + private final ManagementContext managementContext; + + public ApplicationSynchronizerService(ApplicationContextManagerService applicationContextManagerService, + DeploymentOrchestrator deploymentOrchestrator, ManagementContext managementContext) { + this.applicationContextManagerService = applicationContextManagerService; + this.deploymentOrchestrator=deploymentOrchestrator; + this.managementContext=managementContext; + } + + public void syncApplication(String applicationTopology, String appId) + throws InterruptedException { + RunningAppContext runningAppContext = applicationContextManagerService.sycnApplication(applicationTopology, appId); + managementContext.addRunningAppContext(runningAppContext); + } + + + + +} diff --git a/core/src/main/java/org/scenic/orchestrator/core/service/AsycnDeploymentOrchestrator.java b/core/src/main/java/org/scenic/orchestrator/core/service/AsycnDeploymentOrchestrator.java index 10aef86..544be3e 100644 --- a/core/src/main/java/org/scenic/orchestrator/core/service/AsycnDeploymentOrchestrator.java +++ b/core/src/main/java/org/scenic/orchestrator/core/service/AsycnDeploymentOrchestrator.java @@ -27,12 +27,18 @@ public AsycnDeploymentOrchestrator(DeployerProxy deployerProxy, PlanManager plan @Override @Async("threadPoolTaskExecutor") public void deploy(RunningAppContext runningAppContext) throws InterruptedException { + + //Esto se hace bajo demanda cuando se hace deploy System.out.println("Start to deploy application: " + runningAppContext.getApplicationName()); String appId = deployerProxy.deployApp(runningAppContext.getApplicationName(), runningAppContext.getApplicationTopology()); + //Crea la app sin iniciar en brooklyn + runningAppContext.setAppId(appId); System.out.println("Add to the deployer application: " + runningAppContext.getApplicationName() + " with id " + appId); + //Pones las entidades en el runnign context runningAppContext.setEntities(deployerProxy.getApplicationEntities(appId)); System.out.println("Start the management"); + // planManager.deploy(runningAppContext); managementContext.addRunningAppContext(runningAppContext); } diff --git a/core/src/main/java/org/scenic/orchestrator/core/service/DeployerService.java b/core/src/main/java/org/scenic/orchestrator/core/service/DeployerService.java index 2092727..b14540c 100644 --- a/core/src/main/java/org/scenic/orchestrator/core/service/DeployerService.java +++ b/core/src/main/java/org/scenic/orchestrator/core/service/DeployerService.java @@ -18,6 +18,12 @@ public DeployerService(ApplicationContextManagerService applicationContextManage this.deploymentOrchestrator=deploymentOrchestrator; } + + //Crea la app sin iniciar en brooklyn +// runningAppContext.setAppId(appId); +// System.out.println("Add to the deployer application: " + runningAppContext.getApplicationName() + " with id " + appId); + // runningAppContext.setEntities(deployerProxy.getApplicationEntities(appId)); + public void deploy(String applicationTopology) throws InterruptedException { RunningAppContext runningAppContext = applicationContextManagerService.postApplicationContext(applicationTopology); @@ -25,4 +31,6 @@ public void deploy(String applicationTopology) } + + } diff --git a/core/src/main/java/org/scenic/orchestrator/core/service/plan/PlanManager.java b/core/src/main/java/org/scenic/orchestrator/core/service/plan/PlanManager.java index 334fca4..bab22db 100644 --- a/core/src/main/java/org/scenic/orchestrator/core/service/plan/PlanManager.java +++ b/core/src/main/java/org/scenic/orchestrator/core/service/plan/PlanManager.java @@ -2,6 +2,7 @@ import org.scenic.orchestrator.core.dto.PlanStep; import org.scenic.orchestrator.core.dto.RunningAppContext; +import org.scenic.orchestrator.core.service.plan.strategy.PlanStepExecutorStrategy; import org.springframework.stereotype.Service; /** @@ -11,17 +12,20 @@ public class PlanManager { - private final PlanExecutor planExecutor; + //private final PlanExecutor planExecutor; private final RunningAppContextSynchronizer runningAppContextSynchronizer; - private final PlanStepExecutor planStepExecutor; + //private final PlanStepExecutor planStepExecutor; + private final PlanStepExecutorStrategy strategy; public PlanManager(PlanExecutor planExecutor, RunningAppContextSynchronizer runningAppContextSynchronizer, - PlanStepExecutor planStepExecutor + //PlanStepExecutor planStepExecutor + PlanStepExecutorStrategy strategy ) { - this.planExecutor = planExecutor; + //this.planExecutor = planExecutor; this.runningAppContextSynchronizer = runningAppContextSynchronizer; - this.planStepExecutor = planStepExecutor; + //this.planStepExecutor = planStepExecutor; + this.strategy = strategy; } @@ -32,19 +36,23 @@ public void update(RunningAppContext appContext) { } public void deploy(RunningAppContext appContext) { - /*try { - this.executePlan(appContext); - } catch (Exception e) { - synchronizeAppContext(appContext); - deploy(appContext); - }*/ + System.out.println("Executing application plan for: " + appContext.getApplicationName() + " " + appContext.getAppId()); + + //Coge el plan y lo ejecuta en paralelo while (!appContext.getPlan().isEmpty()) { - PlanStep firstStep = appContext.getPlan().getPlan().get(0); - executeStep(appContext, firstStep); + + + //Cambiar esta linea para coger todo lo que nos de y ejecutarlo en paralelo (hay que cambir el endpoint) + //PlanStep firstStep = appContext.getPlan().getPlan().get(0); + //executeStep(appContext, firstStep); + strategy.executePlan(appContext); + + synchronizeAppContext(appContext); } } + /* private void executeStep(RunningAppContext appContext, PlanStep step) { try { planStepExecutor.executeStep(step, appContext); @@ -53,15 +61,18 @@ private void executeStep(RunningAppContext appContext, PlanStep step) { } synchronizeAppContext(appContext); } - - private void executePlan(RunningAppContext appContext) { - planExecutor.executePlan(appContext); - } + */ private void synchronizeAppContext(RunningAppContext appContext) { - System.out.println("Synchronizing App Context"); + System.out.println("-------Synchronizing App Context"); appContext.updateStatus(); + + //Actualiza el estado en el manager y carga el plan de nuevo runningAppContextSynchronizer.updateContext(appContext); } + //private void executePlan(RunningAppContext appContext) { + // planExecutor.executePlan(appContext); + //} + } diff --git a/core/src/main/java/org/scenic/orchestrator/core/service/plan/PlanStepExecutor.java b/core/src/main/java/org/scenic/orchestrator/core/service/plan/PlanStepExecutor.java index cd44b0d..c245f3d 100644 --- a/core/src/main/java/org/scenic/orchestrator/core/service/plan/PlanStepExecutor.java +++ b/core/src/main/java/org/scenic/orchestrator/core/service/plan/PlanStepExecutor.java @@ -23,26 +23,41 @@ public PlanStepExecutor(DeployerProxy deployerProxy) { public void executeStep(PlanStep step, RunningAppContext context) { - try{ + try { + System.out.println("PlanStepExecutor.class -- Execute taks: " + step.getOperation()); - if(step.getOperation() == PlanOperation.START) { - String entityId = context.getEntityByDisplayName(step.getNode()).getId(); - System.out.println(String.format(EXECUTION_MESSAGE, step.getNode(), entityId, step.getOperation())); - deployerProxy.startEffector(context, entityId); - context.getStatus().setCurrentEntityStatus(step.getNode(), EntityStatus.STARTED); - } - else if((step.getOperation() == PlanOperation.RELEASE ) || (step.getOperation() == PlanOperation.STOP) ){ - String entityId = context.getEntityByDisplayName(step.getNode()).getId(); - System.out.println(String.format(EXECUTION_MESSAGE, step.getNode(), entityId, step.getOperation())); - deployerProxy.stopEffector(context, entityId); - context.getStatus().setCurrentEntityStatus(step.getNode(), EntityStatus.UNAVAILABLE); - } + if (step.getOperation() == PlanOperation.START) { + String entityId = context.getEntityByDisplayName(step.getNode()).getId(); + System.out.println(String.format(EXECUTION_MESSAGE, step.getNode(), entityId, step.getOperation())); + deployerProxy.startEffector(context, entityId); + context.getStatus().setCurrentEntityStatus(step.getNode(), EntityStatus.STARTED); + } else if (step.getOperation() == PlanOperation.STOP) { + String entityId = context.getEntityByDisplayName(step.getNode()).getId(); + System.out.println(String.format("[STOP]" + EXECUTION_MESSAGE, step.getNode(), entityId, step.getOperation())); + + deployerProxy.stopEffector(context, entityId); + + context.getStatus().setCurrentEntityStatus(step.getNode(), EntityStatus.STOPPED); + } else if (step.getOperation() == PlanOperation.RELEASE) { + String entityId = context.getEntityByDisplayName(step.getNode()).getId(); + System.out.println(String.format("[RELEASING]" + EXECUTION_MESSAGE, step.getNode(), entityId, step.getOperation())); + deployerProxy.releaseEffector(context, entityId); + context.getStatus().setCurrentEntityStatus(step.getNode(), EntityStatus.UNAVAILABLE); + + } else if (step.getOperation() == PlanOperation.RESTART) { + String entityId = context.getEntityByDisplayName(step.getNode()).getId(); + System.out.println(String.format("[RESTART]" + EXECUTION_MESSAGE, step.getNode(), entityId, step.getOperation())); + deployerProxy.restartEffector(context, entityId); + context.getStatus().setCurrentEntityStatus(step.getNode(), EntityStatus.UNAVAILABLE); + + } } catch (Exception e) { + String entityId = context.getEntityByDisplayName(step.getNode()).getId(); + System.out.println(String.format("[ERROR: ]" + EXECUTION_MESSAGE, step.getNode(), entityId, step.getOperation())); context.getStatus().setCurrentEntityStatus(step.getNode(), EntityStatus.FAILED); throw e; } - } diff --git a/core/src/main/java/org/scenic/orchestrator/core/service/plan/RunningAppContextSynchronizer.java b/core/src/main/java/org/scenic/orchestrator/core/service/plan/RunningAppContextSynchronizer.java index b220052..ee1f6f4 100644 --- a/core/src/main/java/org/scenic/orchestrator/core/service/plan/RunningAppContextSynchronizer.java +++ b/core/src/main/java/org/scenic/orchestrator/core/service/plan/RunningAppContextSynchronizer.java @@ -3,7 +3,7 @@ import org.scenic.orchestrator.core.dto.ApplicationStatus; import org.scenic.orchestrator.core.dto.Plan; import org.scenic.orchestrator.core.dto.RunningAppContext; -import org.scenic.orchestrator.core.service.ManagerAnalyzerClient; +import org.scenic.orchestrator.manager.ManagerAnalyzerClient; import org.springframework.stereotype.Service; import com.fasterxml.jackson.databind.ObjectMapper; @@ -32,8 +32,6 @@ public void updateContext(RunningAppContext appContext) { System.out.println("--------**"); } - - //TODO: avoid this... **** ... with lombok public String planToString(Plan plan){ try{ return new ObjectMapper().writeValueAsString(plan); @@ -42,7 +40,6 @@ public String planToString(Plan plan){ } } - //TODO: avoid this... **** ... with lombok public String statusToString(ApplicationStatus status){ try{ return new ObjectMapper().writeValueAsString(status); diff --git a/core/src/main/java/org/scenic/orchestrator/core/service/plan/strategy/ParallelStepExecutorStrategy.java b/core/src/main/java/org/scenic/orchestrator/core/service/plan/strategy/ParallelStepExecutorStrategy.java new file mode 100644 index 0000000..ba58d04 --- /dev/null +++ b/core/src/main/java/org/scenic/orchestrator/core/service/plan/strategy/ParallelStepExecutorStrategy.java @@ -0,0 +1,67 @@ +package org.scenic.orchestrator.core.service.plan.strategy; + +import static java.util.stream.Collectors.toList; + +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; + +import org.scenic.orchestrator.core.dto.PlanStep; +import org.scenic.orchestrator.core.dto.RunningAppContext; +import org.scenic.orchestrator.core.service.plan.PlanStepExecutor; + +/** + * Ejecuta todos los steps que hay en el plan de manera paralela. + */ +public class ParallelStepExecutorStrategy extends PlanStepExecutorStrategy { + + private final ExecutorService executorService; + + public ParallelStepExecutorStrategy(PlanStepExecutor planStepExecutor, + ExecutorService executorService) { + super(planStepExecutor); + this.executorService = executorService; + } + + @Override + public void executePlan(RunningAppContext appContext) { + + + + List stepExecutions = appContext.getPlan().getPlan().stream() + .map(p -> { + System.out.println(String.format("Creating task for Node=%s, Operation=%s, Intf=%s", p.getNode(), p.getOperation(), p.getIntf())); + return new StepExecutionTask(planStepExecutor, p, appContext); + }) + .collect(toList()); + + try { + System.out.println("Executing tasks"); + executorService.invokeAll(stepExecutions); + + } catch (Exception e) { + throw new RuntimeException(e); + } + System.out.println("[END] Executed tasks"); + } + + + public class StepExecutionTask implements Callable { + + private final PlanStepExecutor planStepExecutor; + private final PlanStep planStep; + private final RunningAppContext appContext; + + public StepExecutionTask(PlanStepExecutor planStepExecutor, PlanStep planStep, RunningAppContext appContext) { + this.planStepExecutor = planStepExecutor; + this.planStep = planStep; + this.appContext = appContext; + } + + @Override + public Void call() throws Exception { + planStepExecutor.executeStep(planStep, appContext); + return null; + } + } +} diff --git a/core/src/main/java/org/scenic/orchestrator/core/service/plan/strategy/PlanStepExecutorStrategy.java b/core/src/main/java/org/scenic/orchestrator/core/service/plan/strategy/PlanStepExecutorStrategy.java new file mode 100644 index 0000000..170740d --- /dev/null +++ b/core/src/main/java/org/scenic/orchestrator/core/service/plan/strategy/PlanStepExecutorStrategy.java @@ -0,0 +1,27 @@ +package org.scenic.orchestrator.core.service.plan.strategy; + +import org.scenic.orchestrator.core.dto.PlanStep; +import org.scenic.orchestrator.core.dto.RunningAppContext; +import org.scenic.orchestrator.core.service.plan.PlanStepExecutor; + +public abstract class PlanStepExecutorStrategy { + + final PlanStepExecutor planStepExecutor; + + public PlanStepExecutorStrategy(PlanStepExecutor planStepExecutor) { + this.planStepExecutor = planStepExecutor; + } + + + public abstract void executePlan(RunningAppContext appContext); + + void executeStep(RunningAppContext appContext, PlanStep step) { + try { + planStepExecutor.executeStep(step, appContext); + } catch (Exception e) { + System.out.println("Error managed"); + } + } + + +} diff --git a/core/src/main/java/org/scenic/orchestrator/core/service/plan/strategy/SingleStepExecutorStrategy.java b/core/src/main/java/org/scenic/orchestrator/core/service/plan/strategy/SingleStepExecutorStrategy.java new file mode 100644 index 0000000..ab24127 --- /dev/null +++ b/core/src/main/java/org/scenic/orchestrator/core/service/plan/strategy/SingleStepExecutorStrategy.java @@ -0,0 +1,23 @@ +package org.scenic.orchestrator.core.service.plan.strategy; + +import org.scenic.orchestrator.core.dto.PlanStep; +import org.scenic.orchestrator.core.dto.RunningAppContext; +import org.scenic.orchestrator.core.service.plan.PlanStepExecutor; + +/** + * Ejecuta el primer step del plan + */ +public class SingleStepExecutorStrategy extends PlanStepExecutorStrategy{ + + public SingleStepExecutorStrategy(PlanStepExecutor planStepExecutor) { + super(planStepExecutor); + } + + @Override + public void executePlan(RunningAppContext appContext) { + PlanStep firstStep = appContext.getPlan().getPlan().get(0); + executeStep(appContext, firstStep); + } + + +} diff --git a/core/src/main/java/org/scenic/orchestrator/core/service/ManagerAnalyzerClient.java b/core/src/main/java/org/scenic/orchestrator/manager/ManagerAnalyzerClient.java similarity index 50% rename from core/src/main/java/org/scenic/orchestrator/core/service/ManagerAnalyzerClient.java rename to core/src/main/java/org/scenic/orchestrator/manager/ManagerAnalyzerClient.java index 0efdff8..51ffde2 100644 --- a/core/src/main/java/org/scenic/orchestrator/core/service/ManagerAnalyzerClient.java +++ b/core/src/main/java/org/scenic/orchestrator/manager/ManagerAnalyzerClient.java @@ -1,6 +1,4 @@ -package org.scenic.orchestrator.core.service; - -import java.util.Map; +package org.scenic.orchestrator.manager; import org.scenic.orchestrator.core.dto.ApplicationStatus; import org.scenic.orchestrator.core.dto.Plan; @@ -8,25 +6,19 @@ import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; -import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; -import com.fasterxml.jackson.databind.ObjectMapper; - /** * Created by Jose on 22/01/19. */ -@Service public class ManagerAnalyzerClient { - private static final String BASE = "/mm"; - private static final String APPLICATION_RESOURCE = BASE + "/%s"; - private static final String GET_PLAN_TEMPLATE = APPLICATION_RESOURCE + "/plan"; + protected static final String BASE = "/mm"; + protected static final String APPLICATION_RESOURCE = BASE + "/%s"; + private static final String GET_PARALLEL_PLAN_TEMPLATE = APPLICATION_RESOURCE + "/psteps"; private final RestTemplate restTemplate; - - @Autowired public ManagerAnalyzerClient(RestTemplate restTemplate) { this.restTemplate = restTemplate; @@ -37,7 +29,11 @@ public void deployApplication(String application) { } public Plan getPlan(String applicationName) { - return restTemplate.getForEntity(String.format(GET_PLAN_TEMPLATE, applicationName), Plan.class).getBody(); + return restTemplate.getForEntity(String.format(getPlanResource(), applicationName), Plan.class).getBody(); + } + + protected String getPlanResource() { + return GET_PARALLEL_PLAN_TEMPLATE; } public void putStatus(String applicationName, ApplicationStatus applicationStatus) { @@ -46,9 +42,25 @@ public void putStatus(String applicationName, ApplicationStatus applicationStatu headers.setContentType(MediaType.APPLICATION_JSON); - HttpEntity entity = new HttpEntity<>(applicationStatus,headers); + HttpEntity entity = new HttpEntity<>(applicationStatus, headers); + + putStatusWithRetries(applicationName, entity); + } - restTemplate.put(String.format(APPLICATION_RESOURCE, applicationName), entity); + private void putStatusWithRetries(String applicationName, HttpEntity entity) { + int i = 0; + boolean pushed = false; + while ((i <= 20) && (!pushed)) { + try { + i++; + restTemplate.put(String.format(APPLICATION_RESOURCE, applicationName), entity); + pushed = true; + } catch (Exception e) { + if (i == 20) { + throw e; + } + } + }//while } diff --git a/core/src/main/java/org/scenic/orchestrator/manager/SecuentialManagerAnalyzerClient.java b/core/src/main/java/org/scenic/orchestrator/manager/SecuentialManagerAnalyzerClient.java new file mode 100644 index 0000000..91d1c79 --- /dev/null +++ b/core/src/main/java/org/scenic/orchestrator/manager/SecuentialManagerAnalyzerClient.java @@ -0,0 +1,22 @@ +package org.scenic.orchestrator.manager; + +import org.scenic.orchestrator.core.dto.Plan; +import org.springframework.web.client.RestTemplate; + + +public class SecuentialManagerAnalyzerClient extends ManagerAnalyzerClient { + + private static final String GET_PLAN_TEMPLATE = APPLICATION_RESOURCE + "/plan"; + + public SecuentialManagerAnalyzerClient(RestTemplate restTemplate) { + super(restTemplate); + } + + + @Override + protected String getPlanResource(){ + return GET_PLAN_TEMPLATE; + } + + +} diff --git a/core/src/main/java/org/scenic/orchestrator/webapp/DeployController.java b/core/src/main/java/org/scenic/orchestrator/webapp/DeployController.java index 19d3e15..fd2666e 100644 --- a/core/src/main/java/org/scenic/orchestrator/webapp/DeployController.java +++ b/core/src/main/java/org/scenic/orchestrator/webapp/DeployController.java @@ -1,8 +1,11 @@ package org.scenic.orchestrator.webapp; +import org.scenic.orchestrator.core.service.ApplicationSynchronizerService; import org.scenic.orchestrator.core.service.DeployerService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -15,17 +18,22 @@ public class DeployController { private final DeployerService deployerService; + private final ApplicationSynchronizerService applicationSynchronizerService; @Autowired - public DeployController(DeployerService deployerService) { + public DeployController(DeployerService deployerService, ApplicationSynchronizerService applicationSynchronizerService) { this.deployerService = deployerService; + this.applicationSynchronizerService = applicationSynchronizerService; } - @PostMapping("/deploy") - public void deployApp(@RequestBody String app) throws InterruptedException { - deployerService.deploy(app); + public void deployApp(@RequestBody String topology) throws InterruptedException { + deployerService.deploy(topology); } - + @PutMapping("/sync/{appId}") + public void syncApp(@PathVariable String appId, @RequestBody String topology) throws InterruptedException { + System.out.println("--Sync appId=" + appId); + applicationSynchronizerService.syncApplication(topology, appId); + } } diff --git a/core/src/main/java/org/scenic/orchestrator/webapp/UpdateStatusController.java b/core/src/main/java/org/scenic/orchestrator/webapp/UpdateStatusController.java new file mode 100644 index 0000000..9db0018 --- /dev/null +++ b/core/src/main/java/org/scenic/orchestrator/webapp/UpdateStatusController.java @@ -0,0 +1,43 @@ +package org.scenic.orchestrator.webapp; + +import java.util.concurrent.ExecutorService; + +import org.scenic.orchestrator.core.UpdaterManagement; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping() +public class UpdateStatusController { + + private final UpdaterManagement updaterManagement; + + private final ExecutorService executorService; + + @Autowired + public UpdateStatusController(UpdaterManagement updaterManagement, ExecutorService executorService) { + this.updaterManagement = updaterManagement; + this.executorService = executorService; + } + + @PutMapping("/update") + public void update() throws InterruptedException { + System.out.println("---Updating..."); + executorService.execute(new Runnable() { + @Override + public void run() { + System.out.println("executing in background"); + try{ + updaterManagement.updateApplication(); + } catch(Exception e){ + System.out.println("Error in update " + e.getMessage() + e.getCause()); + throw new RuntimeException(e); + } + } + }); + System.out.println("Executing"); + //updaterManagement.updateApplication(); + } +} diff --git a/core/src/main/resources/application.properties b/core/src/main/resources/application.properties index 475e375..64c49bd 100644 --- a/core/src/main/resources/application.properties +++ b/core/src/main/resources/application.properties @@ -7,6 +7,8 @@ brooklyn.url=http://127.0.0.1:8081 #ManagerAnalyzer manager.analyzer.url=http://127.0.0.1:8080 +#This property is for boxplot testing (false) it should be always true to prod +scheduleUpdating=true instructionSchedularTime=30000 diff --git a/core/src/test/java/org/scenic/orchestrator/it/BaseIntegrationTest.java b/core/src/test/java/org/scenic/orchestrator/it/BaseIntegrationTest.java index 549a1f5..de05040 100644 --- a/core/src/test/java/org/scenic/orchestrator/it/BaseIntegrationTest.java +++ b/core/src/test/java/org/scenic/orchestrator/it/BaseIntegrationTest.java @@ -15,7 +15,7 @@ @RunWith(SpringRunner.class) @TestPropertySource("classpath:application-it.properties") @SpringBootTest(classes = ITConfig.class) -@AutoConfigureWireMock(port = 0) +//@AutoConfigureWireMock(port = 8080) public abstract class BaseIntegrationTest { @MockBean diff --git a/core/src/test/java/org/scenic/orchestrator/it/Parallel.java b/core/src/test/java/org/scenic/orchestrator/it/Parallel.java new file mode 100644 index 0000000..2560465 --- /dev/null +++ b/core/src/test/java/org/scenic/orchestrator/it/Parallel.java @@ -0,0 +1,97 @@ +package org.scenic.orchestrator.it; + +import static java.util.stream.IntStream.range; +import static org.junit.Assert.assertTrue; + +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.junit.Test; + +/** + * Created by Jose on 01/10/19. + */ +public class Parallel { + + + ExecutorService executor + //= Executors.newSingleThreadExecutor(); + = Executors.newFixedThreadPool(20); + + + @Test + public void test() throws Exception { + + + assertTrue(true); + /*SquareCalculator squareCalculator = new SquareCalculator(); + + Future future1 = squareCalculator.calculate(10); + Future future2 = squareCalculator.calculate(100); + + while (!(future1.isDone() && future2.isDone())) { + System.out.println( + String.format( + "future1 is %s and future2 is %s", + future1.isDone() ? "done" : "not done", + future2.isDone() ? "done" : "not done" + ) + ); + Thread.sleep(300); + } + + Integer result1 = future1.get(); + Integer result2 = future2.get(); + + System.out.println(result1 + " and " + result2);*/ + + //List> callables = + List> callables = range(1, 5) + .boxed() + .map(this.c()) + .collect(Collectors.toList()); + + + System.out.println("Start");long init = System.currentTimeMillis(); + List> exists = executor.invokeAll(callables); + System.out.println("Finish " + (System.currentTimeMillis() -init )); + + for(Future f : exists) { + System.out.println(f.isDone()); + } + System.out.println("Bye"); + + + + } + + public Function> c() { + return i -> + () -> { + try { + TimeUnit.MILLISECONDS.sleep(10_000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return "Task's execution"; + + }; + } + + public class SquareCalculator { + + public Future calculate(Integer input) { + return executor.submit(() -> { + Thread.sleep(1000); + return input * input; + }); + } + } + +} diff --git a/core/src/test/java/org/scenic/orchestrator/it/SmokeTest.java b/core/src/test/java/org/scenic/orchestrator/it/SmokeTest.java index 47d4e03..baf926c 100644 --- a/core/src/test/java/org/scenic/orchestrator/it/SmokeTest.java +++ b/core/src/test/java/org/scenic/orchestrator/it/SmokeTest.java @@ -1,22 +1,35 @@ package org.scenic.orchestrator.it; +//import org.apache.commons. + import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; import static com.github.tomakehurst.wiremock.client.WireMock.get; import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static java.time.Instant.now; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + import org.apache.brooklyn.rest.api.VersionApi; +import org.apache.commons.math3.stat.descriptive.moment.StandardDeviation; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; -import org.scenic.orchestrator.it.BaseIntegrationTest; +import org.scenic.orchestrator.core.dto.ApplicationStatus; +import org.scenic.orchestrator.core.dto.EntityStatus; +import org.scenic.orchestrator.manager.ManagerAnalyzerClient; import org.scenic.orchestrator.webapp.CustomVersionsController; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; +import com.google.common.collect.ImmutableMap; + /** * Created by Jose on 21/01/19. */ @@ -33,6 +46,9 @@ public class SmokeTest extends BaseIntegrationTest { @Autowired private CustomVersionsController customVersionsController; + @Autowired + private ManagerAnalyzerClient mmClient; + @Before public void setUp() { when(brooklynApi.getVersionApi()).thenReturn(versionApi); @@ -54,4 +70,57 @@ public void testWM() { ResponseEntity value = restTemplate.getForEntity("/resource", String.class); assertThat(value.getBody()).isEqualTo("Hello World!"); } + + @Test + public void t() { + + //org.apache.commons.math3.stat.descriptive.moment. + StandardDeviation math = new StandardDeviation(); + Map current = ImmutableMap.builder() + .put("SoftcareDB", EntityStatus.UNAVAILABLE) + .put("SoftcareWS", EntityStatus.FAILED) + //.put("Forum", EntityStatus.STARTED) + //.put("ForumDB", EntityStatus.FAILED) + .put("Softcare_dashboard", EntityStatus.FAILED) + .put("Multimedia", EntityStatus.FAILED) + .put("MultimediaDB", EntityStatus.STARTED) + .build(); + + + Map target = ImmutableMap.builder() + .put("SoftcareDB", EntityStatus.STARTED) + .put("SoftcareWS", EntityStatus.STARTED) + //.put("Forum", EntityStatus.STARTED) + //.put("ForumDB", EntityStatus.STARTED) + .put("Softcare_dashboard", EntityStatus.STARTED) + .put("Multimedia", EntityStatus.STARTED) + .put("MultimediaDB", EntityStatus.STARTED) + .build(); + + + String name = "SoftcareApp"; + ApplicationStatus status = new ApplicationStatus(current, target); + mmClient.putStatus(name, status); + List latencies = new ArrayList<>(); + + + for (int i = 0; i < 20; i++) { + Instant before = now(); + mmClient.getPlan(name); + Instant after = now(); + Double latency = (double) (after.getEpochSecond() - before.getEpochSecond()); + latencies.add(latency); + System.out.println(latency); + } + + double[] j = latencies.stream() + .mapToDouble(k -> k) + .toArray(); + + double av = latencies.stream() + .mapToDouble(k -> k) + .average().getAsDouble(); + System.out.println("Std. Desv.: " + math.evaluate(j)); + System.out.println("Av: " + av); + } } diff --git a/core/src/test/java/org/scenic/orchestrator/it/config/TestRestTemplateConfig.java b/core/src/test/java/org/scenic/orchestrator/it/config/TestRestTemplateConfig.java index 0c19584..a1788e6 100644 --- a/core/src/test/java/org/scenic/orchestrator/it/config/TestRestTemplateConfig.java +++ b/core/src/test/java/org/scenic/orchestrator/it/config/TestRestTemplateConfig.java @@ -12,8 +12,8 @@ @Configuration public class TestRestTemplateConfig { - @Value("${wiremock.server.port}") - private int port; + //@Value("${wiremock.server.port}") + private int port=8080; @Bean public RestTemplate restTemplate() { diff --git a/pom.xml b/pom.xml index 2867c74..d774f39 100644 --- a/pom.xml +++ b/pom.xml @@ -58,6 +58,13 @@ 0.9.0 + + org.springframework.boot