diff --git a/pom.xml b/pom.xml index 00291121f5..41b99b535f 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ 2.6.4 4.3.11.Final - 0.3.4 + 0.4.2 1.10.19 diff --git a/restdocs/index.html b/restdocs/index.html index 70d3c07e51..aa2962eb6e 100644 --- a/restdocs/index.html +++ b/restdocs/index.html @@ -886,7 +886,7 @@

Example res
HTTP/1.1 200 OK
 Content-Type: application/json
-Content-Length: 943
+Content-Length: 1597
 
 {
   "links" : [ {
@@ -902,7 +902,7 @@ 

Example res "server_ip" : "10.0.0.1" }, "task" : "NONE", - "callback" : "http://test.test", + "callback" : "http://test-server.com", "links" : [ { "rel" : "self", "href" : "http://localhost:8080/deployments/mmd34483-d937-4578-bfdb-ebe196bf82dd" @@ -913,10 +913,27 @@

Example res "rel" : "template", "href" : "http://localhost:8080/deployments/mmd34483-d937-4578-bfdb-ebe196bf82dd/template" } ] + }, { + "uuid" : "mmd34483-d937-4578-bfdb-ebe196bf82de", + "creationTime" : "2015-12-11T16:14+0000", + "updateTime" : "2015-12-11T10:11+0000", + "status" : "DELETE_IN_PROGRESS", + "outputs" : { }, + "task" : "NONE", + "links" : [ { + "rel" : "self", + "href" : "http://localhost:8080/deployments/mmd34483-d937-4578-bfdb-ebe196bf82de" + }, { + "rel" : "resources", + "href" : "http://localhost:8080/deployments/mmd34483-d937-4578-bfdb-ebe196bf82de/resources" + }, { + "rel" : "template", + "href" : "http://localhost:8080/deployments/mmd34483-d937-4578-bfdb-ebe196bf82de/template" + } ] } ], "page" : { "size" : 10, - "totalElements" : 1, + "totalElements" : 2, "totalPages" : 1, "number" : 0 } @@ -1047,21 +1064,21 @@

Example Content-Length: 619 { - "uuid" : "53557dd2-55fd-4d44-88d0-d348a673a325", - "creationTime" : "2016-04-01T10:54+0000", + "uuid" : "cbba86fa-dcaa-43db-8063-2bee4c765d92", + "creationTime" : "2016-04-27T13:04+0000", "status" : "CREATE_IN_PROGRESS", "outputs" : { }, "task" : "NONE", "callback" : "http://localhost:8080/callback", "links" : [ { "rel" : "self", - "href" : "http://localhost:8080/deployments/53557dd2-55fd-4d44-88d0-d348a673a325" + "href" : "http://localhost:8080/deployments/cbba86fa-dcaa-43db-8063-2bee4c765d92" }, { "rel" : "resources", - "href" : "http://localhost:8080/deployments/53557dd2-55fd-4d44-88d0-d348a673a325/resources" + "href" : "http://localhost:8080/deployments/cbba86fa-dcaa-43db-8063-2bee4c765d92/resources" }, { "rel" : "template", - "href" : "http://localhost:8080/deployments/53557dd2-55fd-4d44-88d0-d348a673a325/template" + "href" : "http://localhost:8080/deployments/cbba86fa-dcaa-43db-8063-2bee4c765d92/template" } ] }

@@ -1147,7 +1164,7 @@

Example
HTTP/1.1 200 OK
 Content-Type: application/json
-Content-Length: 678
+Content-Length: 684
 
 {
   "uuid" : "mmd34483-d937-4578-bfdb-ebe196bf82dd",
@@ -1158,7 +1175,7 @@ 

Example "server_ip" : "10.0.0.1" }, "task" : "NONE", - "callback" : "http://test.test", + "callback" : "http://test-server.com", "links" : [ { "rel" : "self", "href" : "http://localhost:8080/deployments/mmd34483-d937-4578-bfdb-ebe196bf82dd" @@ -1387,14 +1404,9 @@

Res

Creation date-time (http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14)

-

content[].status

-

String

-

The status of the deployment. (http://indigo-dc.github.io/orchestrator/apidocs/it/reply/orchestrator/enums/Status.html)

- - -

content[].statusReason

+

content[].state

String

-

The description of the state

+

The status of the resource. (http://indigo-dc.github.io/orchestrator/apidocs/it/reply/orchestrator/enums/NodeStates.html)

content[].toscaNodeType

@@ -1415,7 +1427,7 @@

Example
HTTP/1.1 200 OK
 Content-Type: application/json
-Content-Length: 1401
+Content-Length: 1313
 
 {
   "links" : [ {
@@ -1425,8 +1437,7 @@ 

Example "content" : [ { "uuid" : "mmd34483-d937-4578-bfdb-ebe196bf82dd", "creationTime" : "2015-12-11T16:14+0000", - "status" : "CREATE_COMPLETE", - "statusReason" : "Deployed", + "state" : "STARTED", "toscaNodeType" : "tosca.nodes.Compute", "requiredBy" : [ ], "links" : [ { @@ -1439,8 +1450,7 @@

Example }, { "uuid" : "bbd34483-d937-4578-bfdb-ebe196bf82dd", "creationTime" : "2015-12-11T16:14+0000", - "status" : "CREATE_IN_PROGRESS", - "statusReason" : "Deployed", + "state" : "CREATING", "toscaNodeType" : "tosca.nodes.Compute", "requiredBy" : [ ], "links" : [ { @@ -1508,14 +1518,9 @@

Res

Creation date-time (http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14)

-

status

-

String

-

The status of the deployment. (http://indigo-dc.github.io/orchestrator/apidocs/it/reply/orchestrator/enums/Status.html)

- - -

statusReason

+

state

String

-

The description of the state

+

The status of the resource. (http://indigo-dc.github.io/orchestrator/apidocs/it/reply/orchestrator/enums/NodeStates.html)

toscaNodeType

@@ -1536,13 +1541,12 @@

Example diff --git a/src/main/java/it/reply/orchestrator/dal/entity/AbstractResourceEntity.java b/src/main/java/it/reply/orchestrator/dal/entity/AbstractResourceEntity.java index 0d51b643d7..7393cc1d82 100644 --- a/src/main/java/it/reply/orchestrator/dal/entity/AbstractResourceEntity.java +++ b/src/main/java/it/reply/orchestrator/dal/entity/AbstractResourceEntity.java @@ -29,13 +29,6 @@ public abstract class AbstractResourceEntity implements Identifiable, Se @Column(name = "uuid", unique = true) private String id; - @Enumerated(EnumType.STRING) - @Column(name = "status", length = 500) - private Status status; - - @Column(name = "statusReason", columnDefinition = "LONGTEXT") - private String statusReason; - private Date created; private Date updated; @@ -55,22 +48,6 @@ public void setId(String id) { this.id = id; } - public Status getStatus() { - return status; - } - - public void setStatus(Status status) { - this.status = status; - } - - public String getStatusReason() { - return statusReason; - } - - public void setStatusReason(String statusReason) { - this.statusReason = statusReason; - } - public void setCreated(Date created) { this.created = created; } @@ -107,8 +84,8 @@ protected void onUpdate() { @Override public String toString() { - return "AbstractResourceEntity [id=" + id + ", status=" + status + ", created=" + created - + ", updated=" + updated + "]"; + return "AbstractResourceEntity [id=" + id + ", created=" + created + ", updated=" + updated + + "]"; } } \ No newline at end of file diff --git a/src/main/java/it/reply/orchestrator/dal/entity/Deployment.java b/src/main/java/it/reply/orchestrator/dal/entity/Deployment.java index b3e1a2df6e..3bbf6d362b 100644 --- a/src/main/java/it/reply/orchestrator/dal/entity/Deployment.java +++ b/src/main/java/it/reply/orchestrator/dal/entity/Deployment.java @@ -1,6 +1,7 @@ package it.reply.orchestrator.dal.entity; import it.reply.orchestrator.enums.DeploymentProvider; +import it.reply.orchestrator.enums.Status; import it.reply.orchestrator.enums.Task; import java.util.ArrayList; @@ -25,6 +26,13 @@ public class Deployment extends AbstractResourceEntity { private static final long serialVersionUID = 3866893436735377053L; + @Enumerated(EnumType.STRING) + @Column(name = "status", length = 500) + private Status status; + + @Column(name = "statusReason", columnDefinition = "LONGTEXT") + private String statusReason; + @Enumerated(EnumType.STRING) @Column(name = "task") private Task task; @@ -52,7 +60,7 @@ public class Deployment extends AbstractResourceEntity { @Column(name = "value") Map outputs = new HashMap(); - @OneToMany(cascade = CascadeType.ALL, mappedBy = "deployment") + @OneToMany(cascade = CascadeType.ALL, mappedBy = "deployment", orphanRemoval = true) List resources = new ArrayList<>(); @OneToMany(cascade = CascadeType.ALL, mappedBy = "deployment", orphanRemoval = true) @@ -62,6 +70,22 @@ public Deployment() { super(); } + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + public String getStatusReason() { + return statusReason; + } + + public void setStatusReason(String statusReason) { + this.statusReason = statusReason; + } + public Task getTask() { return task; } diff --git a/src/main/java/it/reply/orchestrator/dal/entity/Resource.java b/src/main/java/it/reply/orchestrator/dal/entity/Resource.java index fe20bcac7d..d97ef87b71 100644 --- a/src/main/java/it/reply/orchestrator/dal/entity/Resource.java +++ b/src/main/java/it/reply/orchestrator/dal/entity/Resource.java @@ -1,11 +1,15 @@ package it.reply.orchestrator.dal.entity; +import it.reply.orchestrator.enums.NodeStates; + import java.util.ArrayList; import java.util.List; import javax.persistence.Column; import javax.persistence.ElementCollection; import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; @@ -14,6 +18,10 @@ public class Resource extends AbstractResourceEntity { private static final long serialVersionUID = -4916577635363604624L; + @Enumerated(EnumType.STRING) + @Column(name = "state", length = 500) + private NodeStates state; + @Column(name = "iaasId", length = 500) private String iaasId; @@ -36,6 +44,14 @@ public Resource() { super(); } + public NodeStates getState() { + return state; + } + + public void setState(NodeStates state) { + this.state = state; + } + public String getIaasId() { return iaasId; } diff --git a/src/main/java/it/reply/orchestrator/dto/im/InfrastructureStatus.java b/src/main/java/it/reply/orchestrator/dto/im/InfrastructureStatus.java deleted file mode 100644 index 97e8832823..0000000000 --- a/src/main/java/it/reply/orchestrator/dto/im/InfrastructureStatus.java +++ /dev/null @@ -1,34 +0,0 @@ -package it.reply.orchestrator.dto.im; - -import com.fasterxml.jackson.annotation.JsonProperty; - -import java.util.Map; - -public class InfrastructureStatus { - - @JsonProperty("vm_states") - private Map vmStates; - @JsonProperty("state") - private String state; - - @JsonProperty("vm_states") - public Map getVmStates() { - return vmStates; - } - - @JsonProperty("vm_states") - public void setVmStates(Map vmStates) { - this.vmStates = vmStates; - } - - @JsonProperty("state") - public String getState() { - return state; - } - - @JsonProperty("state") - public void setState(String state) { - this.state = state; - } - -} \ No newline at end of file diff --git a/src/main/java/it/reply/orchestrator/enums/NodeStates.java b/src/main/java/it/reply/orchestrator/enums/NodeStates.java new file mode 100644 index 0000000000..64b5158a67 --- /dev/null +++ b/src/main/java/it/reply/orchestrator/enums/NodeStates.java @@ -0,0 +1,45 @@ +package it.reply.orchestrator.enums; + +/** + * Normative nodes states. For more details see @see + * Tosca Simple Profile + * + */ +public enum NodeStates { + + // @formatter:off + + // Node is not yet created. Node only exists as a template definition. + INITIAL, + + // Node is transitioning from initial state to created state. + CREATING, + + // Node software has been installed. + CREATED, + + // Node is transitioning from created state to configured state. + CONFIGURING, + + // Node has been configured prior to being started. + CONFIGURED, + + // Node is transitioning from configured state to started state. + STARTING, + + // Node is started. + STARTED, + + // Node is transitioning from its current state to a configured state. + STOPPING, + + // Node is transitioning from its current state to one where it is deleted and its state is no + // longer tracked by the instance model. + DELETING, + + // Node is in an error state. + ERROR; + // @formatter:on + +} diff --git a/src/main/java/it/reply/orchestrator/exception/service/DeploymentException.java b/src/main/java/it/reply/orchestrator/exception/service/DeploymentException.java index 059e3d112e..9e18c9ba92 100644 --- a/src/main/java/it/reply/orchestrator/exception/service/DeploymentException.java +++ b/src/main/java/it/reply/orchestrator/exception/service/DeploymentException.java @@ -16,4 +16,8 @@ public DeploymentException(String message) { super(message); } + public DeploymentException(String message, Exception ex) { + super(message, ex); + } + } diff --git a/src/main/java/it/reply/orchestrator/resource/BaseResource.java b/src/main/java/it/reply/orchestrator/resource/BaseResource.java index 91c81744ff..1072809ebc 100644 --- a/src/main/java/it/reply/orchestrator/resource/BaseResource.java +++ b/src/main/java/it/reply/orchestrator/resource/BaseResource.java @@ -1,9 +1,9 @@ package it.reply.orchestrator.resource; +import it.reply.orchestrator.enums.NodeStates; +import it.reply.orchestrator.enums.Status; import it.reply.orchestrator.resource.common.AbstractResource; -import org.apache.commons.lang3.builder.EqualsBuilder; -import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.ToStringBuilder; import java.util.ArrayList; @@ -11,10 +11,19 @@ public class BaseResource extends AbstractResource { + private NodeStates state; private String toscaNodeType; private String toscaNodeName; private List requiredBy = new ArrayList(); + public NodeStates getState() { + return state; + } + + public void setState(NodeStates state) { + this.state = state; + } + public String getToscaNodeType() { return this.toscaNodeType; } diff --git a/src/main/java/it/reply/orchestrator/resource/BaseResourceAssembler.java b/src/main/java/it/reply/orchestrator/resource/BaseResourceAssembler.java index 626a940576..0932fd13f6 100644 --- a/src/main/java/it/reply/orchestrator/resource/BaseResourceAssembler.java +++ b/src/main/java/it/reply/orchestrator/resource/BaseResourceAssembler.java @@ -24,8 +24,7 @@ private BaseResource getBaseResource(Resource entity) { BaseResource resource = new BaseResource(); resource.setUuid(entity.getId()); resource.setCreationTime(entity.getCreated()); - resource.setStatus(entity.getStatus()); - resource.setStatusReason(entity.getStatusReason()); + resource.setState(entity.getState()); resource.setToscaNodeType(entity.getToscaNodeType()); resource.setToscaNodeName(entity.getToscaNodeName()); resource.add(ControllerLinkBuilder.linkTo(DeploymentController.class).slash("deployments") diff --git a/src/main/java/it/reply/orchestrator/resource/DeploymentResource.java b/src/main/java/it/reply/orchestrator/resource/DeploymentResource.java index a26ef73e40..623992b028 100644 --- a/src/main/java/it/reply/orchestrator/resource/DeploymentResource.java +++ b/src/main/java/it/reply/orchestrator/resource/DeploymentResource.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import it.reply.orchestrator.enums.Status; import it.reply.orchestrator.enums.Task; import it.reply.orchestrator.resource.common.AbstractResource; import it.reply.orchestrator.resource.common.CustomSerializer; @@ -11,6 +12,9 @@ public class DeploymentResource extends AbstractResource { + private Status status; + private String statusReason; + @JsonSerialize(using = CustomSerializer.class) private Map outputs; private Task task; @@ -21,6 +25,22 @@ public DeploymentResource() { super(); } + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + public String getStatusReason() { + return statusReason; + } + + public void setStatusReason(String statusReason) { + this.statusReason = statusReason; + } + public Map getOutputs() { return outputs; } diff --git a/src/main/java/it/reply/orchestrator/resource/common/AbstractResource.java b/src/main/java/it/reply/orchestrator/resource/common/AbstractResource.java index dedfc036a5..37e9b2c32c 100644 --- a/src/main/java/it/reply/orchestrator/resource/common/AbstractResource.java +++ b/src/main/java/it/reply/orchestrator/resource/common/AbstractResource.java @@ -3,8 +3,6 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; -import it.reply.orchestrator.enums.Status; - import org.springframework.hateoas.ResourceSupport; import java.text.DateFormat; @@ -19,9 +17,6 @@ public class AbstractResource extends ResourceSupport { private String creationTime; private String updateTime; - private Status status; - private String statusReason; - public AbstractResource() { } @@ -73,22 +68,6 @@ public void setUpdateTime(Date updateTime) { this.updateTime = convertDate(updateTime); } - public Status getStatus() { - return status; - } - - public void setStatus(Status status) { - this.status = status; - } - - public String getStatusReason() { - return statusReason; - } - - public void setStatusReason(String statusReason) { - this.statusReason = statusReason; - } - private String convertDate(Date date) { TimeZone tz = TimeZone.getTimeZone("UTC"); DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mmZ"); diff --git a/src/main/java/it/reply/orchestrator/service/DeploymentServiceImpl.java b/src/main/java/it/reply/orchestrator/service/DeploymentServiceImpl.java index d16d808341..5f1f8fab0b 100644 --- a/src/main/java/it/reply/orchestrator/service/DeploymentServiceImpl.java +++ b/src/main/java/it/reply/orchestrator/service/DeploymentServiceImpl.java @@ -6,6 +6,7 @@ import alien4cloud.tosca.model.ArchiveRoot; import alien4cloud.tosca.parser.ParsingException; import alien4cloud.tosca.parser.ParsingResult; + import it.reply.orchestrator.config.WorkflowConfigProducerBean; import it.reply.orchestrator.dal.entity.Deployment; import it.reply.orchestrator.dal.entity.Resource; @@ -13,6 +14,7 @@ import it.reply.orchestrator.dal.repository.DeploymentRepository; import it.reply.orchestrator.dal.repository.ResourceRepository; import it.reply.orchestrator.dto.request.DeploymentRequest; +import it.reply.orchestrator.enums.NodeStates; import it.reply.orchestrator.enums.Status; import it.reply.orchestrator.enums.Task; import it.reply.orchestrator.exception.OrchestratorException; @@ -84,9 +86,8 @@ public Deployment createDeployment(DeploymentRequest request) { String template = toscaService.customizeTemplate(request.getTemplate(), deployment.getId()); deployment.setTemplate(template); - Map nodes = - toscaService.getArchiveRootFromTemplate(template).getResult().getTopology() - .getNodeTemplates(); + Map nodes = toscaService.getArchiveRootFromTemplate(template) + .getResult().getTopology().getNodeTemplates(); createResources(deployment, nodes); } catch (IOException | ParsingException ex) { @@ -97,9 +98,8 @@ public Deployment createDeployment(DeploymentRequest request) { params.put("DEPLOYMENT_ID", deployment.getId()); ProcessInstance pi = null; try { - pi = - wfService.startProcess(WorkflowConfigProducerBean.DEPLOY.getProcessId(), params, - RUNTIME_STRATEGY.PER_PROCESS_INSTANCE); + pi = wfService.startProcess(WorkflowConfigProducerBean.DEPLOY.getProcessId(), params, + RUNTIME_STRATEGY.PER_PROCESS_INSTANCE); } catch (WorkflowException ex) { throw new OrchestratorException(ex); } @@ -121,6 +121,7 @@ public void deleteDeployment(String uuid) { String.format("Deployment already in %s state.", deployment.getStatus().toString())); } else { deployment.setStatus(Status.DELETE_IN_PROGRESS); + deployment.setStatusReason(""); deployment.setTask(Task.NONE); Iterator wrIt = deployment.getWorkflowReferences().iterator(); while (wrIt.hasNext()) { @@ -134,9 +135,8 @@ public void deleteDeployment(String uuid) { params.put("DEPLOYMENT_ID", deployment.getId()); ProcessInstance pi = null; try { - pi = - wfService.startProcess(WorkflowConfigProducerBean.UNDEPLOY.getProcessId(), params, - RUNTIME_STRATEGY.PER_PROCESS_INSTANCE); + pi = wfService.startProcess(WorkflowConfigProducerBean.UNDEPLOY.getProcessId(), params, + RUNTIME_STRATEGY.PER_PROCESS_INSTANCE); } catch (WorkflowException ex) { throw new OrchestratorException(ex); } @@ -177,9 +177,8 @@ public void updateDeployment(String id, DeploymentRequest request) { params.put("TOSCA_TEMPLATE", request.getTemplate()); ProcessInstance pi = null; try { - pi = - wfService.startProcess(WorkflowConfigProducerBean.UPDATE.getProcessId(), params, - RUNTIME_STRATEGY.PER_PROCESS_INSTANCE); + pi = wfService.startProcess(WorkflowConfigProducerBean.UPDATE.getProcessId(), params, + RUNTIME_STRATEGY.PER_PROCESS_INSTANCE); } catch (WorkflowException ex) { throw new OrchestratorException(ex); } @@ -211,7 +210,7 @@ private void createResources(Deployment deployment, Map no for (int i = 0; i < count; i++) { resource = new Resource(); resource.setDeployment(deployment); - resource.setStatus(Status.CREATE_IN_PROGRESS); + resource.setState(NodeStates.CREATING); resource.setToscaNodeName(entry.getKey()); resource.setToscaNodeType(entry.getValue().getType()); resourceRepository.save(resource); diff --git a/src/main/java/it/reply/orchestrator/service/ToscaServiceImpl.java b/src/main/java/it/reply/orchestrator/service/ToscaServiceImpl.java index 82cc02409e..b6dae3eaa7 100644 --- a/src/main/java/it/reply/orchestrator/service/ToscaServiceImpl.java +++ b/src/main/java/it/reply/orchestrator/service/ToscaServiceImpl.java @@ -245,9 +245,12 @@ private static void setAutentication() { @Override public Capability getNodeCapabilityByName(NodeTemplate node, String propertyName) { - for (Entry entry : node.getCapabilities().entrySet()) { - if (entry.getKey().equals(propertyName)) { - return entry.getValue(); + if (node != null && node.getCapabilities() != null) { + for (Entry entry : node.getCapabilities() + .entrySet()) { + if (entry.getKey().equals(propertyName)) { + return entry.getValue(); + } } } return null; diff --git a/src/main/java/it/reply/orchestrator/service/commands/Update.java b/src/main/java/it/reply/orchestrator/service/commands/Update.java index 91dfa464d4..eeb196c650 100644 --- a/src/main/java/it/reply/orchestrator/service/commands/Update.java +++ b/src/main/java/it/reply/orchestrator/service/commands/Update.java @@ -18,8 +18,8 @@ public class Update extends BaseCommand { protected ExecutionResults customExecute(CommandContext ctx) throws Exception { String deploymentId = (String) getWorkItem(ctx).getParameter("DEPLOYMENT_ID"); String template = (String) getWorkItem(ctx).getParameter("TOSCA_TEMPLATE"); - imService.doUpdate(deploymentId, template); - return new ExecutionResults(); + boolean result = imService.doUpdate(deploymentId, template); + return resultOccurred(result); } } diff --git a/src/main/java/it/reply/orchestrator/service/deployment/providers/AbstractDeploymentProviderService.java b/src/main/java/it/reply/orchestrator/service/deployment/providers/AbstractDeploymentProviderService.java index 4f44494a7b..08a0e06f26 100644 --- a/src/main/java/it/reply/orchestrator/service/deployment/providers/AbstractDeploymentProviderService.java +++ b/src/main/java/it/reply/orchestrator/service/deployment/providers/AbstractDeploymentProviderService.java @@ -2,7 +2,10 @@ import it.reply.orchestrator.dal.entity.Deployment; import it.reply.orchestrator.dal.entity.Resource; +import it.reply.orchestrator.dal.entity.WorkflowReference; import it.reply.orchestrator.dal.repository.DeploymentRepository; +import it.reply.orchestrator.dal.repository.ResourceRepository; +import it.reply.orchestrator.enums.NodeStates; import it.reply.orchestrator.enums.Status; import it.reply.orchestrator.enums.Task; @@ -10,6 +13,9 @@ import org.apache.logging.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; import java.util.function.Function; public abstract class AbstractDeploymentProviderService implements DeploymentProviderService { @@ -137,8 +143,44 @@ public void updateOnSuccess(String deploymentUuid) { } private void updateResources(Deployment deployment, Status status) { - for (Resource r : deployment.getResources()) { - r.setStatus(status); + + for (Resource resource : deployment.getResources()) { + if (status.equals(Status.CREATE_COMPLETE) || status.equals(Status.UPDATE_COMPLETE)) { + switch (resource.getState()) { + case INITIAL: + case CREATING: + case CREATED: + case CONFIGURING: + case CONFIGURED: + case STARTING: + resource.setState(NodeStates.STARTED); + break; + case STARTED: + break; + case DELETING: + // Resource should be deleted into bindresource function + resource.setState(NodeStates.ERROR); + break; + default: + resource.setState(NodeStates.ERROR); + break; + } + } else { + switch (resource.getState()) { + case INITIAL: + case CREATING: + case CREATED: + case CONFIGURING: + case CONFIGURED: + case STARTING: + case STOPPING: + case DELETING: + resource.setState(NodeStates.ERROR); + break; + default: + break; + } + } } } } diff --git a/src/main/java/it/reply/orchestrator/service/deployment/providers/DeploymentProviderService.java b/src/main/java/it/reply/orchestrator/service/deployment/providers/DeploymentProviderService.java index 21337281aa..1354a4163c 100644 --- a/src/main/java/it/reply/orchestrator/service/deployment/providers/DeploymentProviderService.java +++ b/src/main/java/it/reply/orchestrator/service/deployment/providers/DeploymentProviderService.java @@ -22,9 +22,9 @@ public interface DeploymentProviderService { public void finalizeDeploy(Deployment deployment, boolean deployed); - public void doUpdate(String deploymentId, String template); + public boolean doUpdate(String deploymentId, String template); - public void doUpdate(Deployment deployment, String template); + public boolean doUpdate(Deployment deployment, String template); public boolean doUndeploy(String deploymentUuid); diff --git a/src/main/java/it/reply/orchestrator/service/deployment/providers/ImServiceImpl.java b/src/main/java/it/reply/orchestrator/service/deployment/providers/ImServiceImpl.java index d47a46f283..b343be9d89 100644 --- a/src/main/java/it/reply/orchestrator/service/deployment/providers/ImServiceImpl.java +++ b/src/main/java/it/reply/orchestrator/service/deployment/providers/ImServiceImpl.java @@ -5,22 +5,25 @@ import alien4cloud.tosca.parser.ParsingException; import alien4cloud.tosca.parser.ParsingResult; -import com.fasterxml.jackson.databind.ObjectMapper; - -import es.upv.i3m.grycap.im.api.InfrastructureManagerApiClient; -import es.upv.i3m.grycap.im.api.RestApiBodyContentType; -import es.upv.i3m.grycap.im.api.VmStates; -import es.upv.i3m.grycap.im.client.ServiceResponse; +import es.upv.i3m.grycap.im.InfrastructureManager; +import es.upv.i3m.grycap.im.States; +import es.upv.i3m.grycap.im.exceptions.ImClientErrorException; import es.upv.i3m.grycap.im.exceptions.ImClientException; -import es.upv.i3m.grycap.im.exceptions.NoEnumFoundException; +import es.upv.i3m.grycap.im.pojo.InfOutputValues; +import es.upv.i3m.grycap.im.pojo.InfrastructureState; +import es.upv.i3m.grycap.im.pojo.InfrastructureUri; +import es.upv.i3m.grycap.im.pojo.InfrastructureUris; +import es.upv.i3m.grycap.im.pojo.Property; +import es.upv.i3m.grycap.im.pojo.ResponseError; +import es.upv.i3m.grycap.im.pojo.VirtualMachineInfo; +import es.upv.i3m.grycap.im.rest.client.BodyContentType; import it.reply.orchestrator.dal.entity.Deployment; import it.reply.orchestrator.dal.entity.Resource; import it.reply.orchestrator.dal.repository.DeploymentRepository; import it.reply.orchestrator.dal.repository.ResourceRepository; -import it.reply.orchestrator.dto.im.InfrastructureStatus; import it.reply.orchestrator.enums.DeploymentProvider; -import it.reply.orchestrator.enums.Status; +import it.reply.orchestrator.enums.NodeStates; import it.reply.orchestrator.enums.Task; import it.reply.orchestrator.exception.OrchestratorException; import it.reply.orchestrator.exception.service.DeploymentException; @@ -43,6 +46,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -80,6 +84,7 @@ public class ImServiceImpl extends AbstractDeploymentProviderService { private String onedockAuthFilePath; private static final Pattern UUID_PATTERN = Pattern.compile(".*\\/([^\"\\/]+)\\/?\"?"); + private static final Pattern VM_ID_PATTERN = Pattern.compile("(\\w+)$"); @Autowired private ToscaService toscaService; @@ -96,7 +101,7 @@ public enum IaaSSite { // @formatter:on } - private InfrastructureManagerApiClient getClient(IaaSSite iaaSSite) { + private InfrastructureManager getClient(IaaSSite iaaSSite) { InputStream inputStream = null; try { switch (iaaSSite) { @@ -139,9 +144,8 @@ private InfrastructureManagerApiClient getClient(IaaSSite iaaSSite) { try (OutputStream outStream = new FileOutputStream(tmp)) { IOUtils.copy(inputStream, outStream); } - InfrastructureManagerApiClient imClient = - new InfrastructureManagerApiClient(imUrl, tmp.getAbsolutePath()); - return imClient; + InfrastructureManager im = new InfrastructureManager(imUrl, tmp.toPath()); + return im; } catch (IOException | ImClientException ex) { throw new OrchestratorException("Cannot load IM auth file", ex); } finally { @@ -182,33 +186,32 @@ public boolean doDeploy(Deployment deployment) { deployment = deploymentRepository.save(deployment); // FIXME this is a trick used only for demo purpose - InfrastructureManagerApiClient imClient = - getClient(getIaaSSiteFromTosca(deployment.getTemplate())); + InfrastructureManager im = getClient(getIaaSSiteFromTosca(deployment.getTemplate())); // TODO improve with template inputs - ServiceResponse response = imClient.createInfrastructure(deployment.getTemplate(), - RestApiBodyContentType.TOSCA, true); - if (!response.isReponseSuccessful()) { - String responseError = getAndLogImErrorResponse(response); - updateOnError(deploymentUuid, responseError); - return false; + InfrastructureUri infrastructureUri = + im.createInfrastructure(deployment.getTemplate(), BodyContentType.TOSCA); + + String infrastructureId = infrastructureUri.getInfrastructureId(); + if (infrastructureId != null) { + deployment.setEndpoint(infrastructureId); + deployment = deploymentRepository.save(deployment); + return true; } else { - String infrastructureId = null; - Matcher matcher = UUID_PATTERN.matcher(response.getResult()); - if (matcher.matches()) { - infrastructureId = matcher.group(1); - deployment.setEndpoint(infrastructureId); - deployment = deploymentRepository.save(deployment); - return true; - } else { - updateOnError(deploymentUuid, - String.format( - "Creation of deployment <%s>: Couldn't extract infrastructureId from IM endpoint." - + "\nIM endpoint was %s.", - deploymentUuid, response.getResult())); - return false; - } + updateOnError(deploymentUuid, + String.format( + "Creation of deployment <%s>: Couldn't extract infrastructureId from IM endpoint." + + "\nIM endpoint was %s.", + deploymentUuid, infrastructureUri.getUri())); + return false; } + // Exception generated when the im produces an error message + } catch (ImClientErrorException exception) { + logImErrorResponse(exception); + ResponseError responseError = getImResponseError(exception); + updateOnError(deploymentUuid, responseError.getFormattedErrorMessage()); + return false; + } catch (Exception ex) { LOG.error(ex); updateOnError(deploymentUuid, ex); @@ -224,38 +227,55 @@ public boolean isDeployed(String deploymentUuid) throws DeploymentException { @Override public boolean isDeployed(Deployment deployment) throws DeploymentException { + InfrastructureManager im = null; try { // FIXME this is a trick used only for demo purpose - InfrastructureManagerApiClient imClient = - getClient(getIaaSSiteFromTosca(deployment.getTemplate())); - ServiceResponse response = imClient.getInfrastructureState(deployment.getEndpoint()); - InfrastructureStatus status = - new ObjectMapper().readValue(response.getResult(), InfrastructureStatus.class); - - // FIXME Are the infrastructure states equals to the VmStates? - if (status.getState().equals(VmStates.CONFIGURED.toString())) { - return true; - } else if (status.getState().equals(VmStates.FAILED.toString()) - || status.getState().equals(VmStates.UNCONFIGURED.toString())) { - String errorMsg = String.format( - "Fail to deploy deployment <%s>." + "\nIM id is: <%s>" + "\nIM response is: <%s>", - deployment.getId(), deployment.getEndpoint(), response.getResult()); - try { - // Try to get the logs of the virtual infrastructure for debug purpose. - ServiceResponse responseContMsg = - imClient.getInfrastructureContMsg(deployment.getEndpoint(), true); - errorMsg = errorMsg.concat("\nIM contMsg is: " + responseContMsg.getResult()); - } catch (Exception ex) { - // Do nothing - } - throw new DeploymentException(errorMsg); - } else { - return false; + im = getClient(getIaaSSiteFromTosca(deployment.getTemplate())); + + InfrastructureState infrastructureState = im.getInfrastructureState(deployment.getEndpoint()); + LOG.debug(infrastructureState.toString()); + + States enumState = infrastructureState.getEnumState(); + switch (enumState) { + case CONFIGURED: + return true; + case FAILED: + case UNCONFIGURED: + String errorMsg = String.format( + "Fail to deploy deployment <%s>." + "\nIM id is: <%s>" + "\nIM response is: <%s>", + deployment.getId(), deployment.getEndpoint(), + infrastructureState.getFormattedInfrastructureStateString()); + try { + // Try to get the logs of the virtual infrastructure for debug + // purpose. + Property contMsg = im.getInfrastructureContMsg(deployment.getEndpoint()); + errorMsg = errorMsg.concat("\nIM contMsg is: " + contMsg.getValue()); + } catch (Exception ex) { + // Do nothing + } + throw new DeploymentException(errorMsg); + default: + return false; } - } catch (ImClientException | IOException ex) { - // TODO improve exception handling - LOG.error(ex); - return false; + } catch (ImClientException exception) { + String errorResponse = exception.getMessage(); + if (exception instanceof ImClientErrorException) { + ImClientErrorException ex = (ImClientErrorException) exception; + errorResponse = ex.getResponseError().getFormattedErrorMessage(); + } + + String errorMsg = String.format( + "Fail to deploy deployment <%s>." + "\nIM id is: <%s>" + "\nIM error is: <%s>", + deployment.getId(), deployment.getEndpoint(), errorResponse); + try { + // Try to get the logs of the virtual infrastructure for debug + // purpose. + Property contMsg = im.getInfrastructureContMsg(deployment.getEndpoint()); + errorMsg = errorMsg.concat("\nIM contMsg is: " + contMsg.getValue()); + } catch (Exception ex) { + // Do nothing + } + throw new DeploymentException(errorMsg); } } @@ -270,26 +290,27 @@ public void finalizeDeploy(Deployment deployment, boolean deployed) { if (deployed) { try { // FIXME this is a trick used only for demo purpose - InfrastructureManagerApiClient imClient = - getClient(getIaaSSiteFromTosca(deployment.getTemplate())); - // Save outputs - es.upv.i3m.grycap.im.api.InfrastructureStatus statusResponse = - imClient.getInfrastructureOutputs(deployment.getEndpoint()); - - Map outputs = new HashMap(); - for (Entry entry : statusResponse.getProperties().entrySet()) { - if (entry.getValue() != null) { - outputs.put(entry.getKey(), JsonUtility.serializeJson(entry.getValue())); - } else { - outputs.put(entry.getKey(), ""); + InfrastructureManager im = getClient(getIaaSSiteFromTosca(deployment.getTemplate())); + if (deployment.getOutputs().isEmpty()) { + InfOutputValues outputValues = im.getInfrastructureOutputs(deployment.getEndpoint()); + Map outputs = new HashMap(); + for (Entry entry : outputValues.getOutputs().entrySet()) { + if (entry.getValue() != null) { + outputs.put(entry.getKey(), JsonUtility.serializeJson(entry.getValue())); + } else { + outputs.put(entry.getKey(), ""); + } } + deployment.setOutputs(outputs); } - deployment.setOutputs(outputs); - bindResources(deployment, deployment.getEndpoint()); updateOnSuccess(deployment.getId()); + } catch (ImClientErrorException exception) { + logImErrorResponse(exception); + updateOnError(deployment.getId(), exception); + } catch (Exception ex) { LOG.error(ex); updateOnError(deployment.getId(), ex); @@ -300,13 +321,13 @@ public void finalizeDeploy(Deployment deployment, boolean deployed) { } @Override - public void doUpdate(String deploymentId, String template) { + public boolean doUpdate(String deploymentId, String template) { Deployment deployment = deploymentRepository.findOne(deploymentId); - doUpdate(deployment, template); + return doUpdate(deployment, template); } @Override - public void doUpdate(Deployment deployment, String template) { + public boolean doUpdate(Deployment deployment, String template) { // Check if count is increased or if there is a removal list, other kinds of update are // discarded @@ -326,115 +347,78 @@ public void doUpdate(Deployment deployment, String template) { Map newNodes = toscaService.getCountNodes(newParsingResult.getResult()); try { + // Create the new template with the nodes to be added + ArchiveRoot root = newParsingResult.getResult(); + Map nodes = new HashMap<>(); + + // List of vmIds to be removed + List vmIds = new ArrayList(); + for (Map.Entry entry : oldNodes.entrySet()) { if (newNodes.containsKey(entry.getKey())) { int oldCount = toscaService.getCount(entry.getValue()); int newCount = toscaService.getCount(newNodes.get(entry.getKey())); - if (newCount > oldCount) { + List removalList = toscaService.getRemovalList(newNodes.get(entry.getKey())); + if (newCount > oldCount && removalList.size() == 0) { Resource resource; for (int i = 0; i < (newCount - oldCount); i++) { resource = new Resource(); resource.setDeployment(deployment); - resource.setStatus(Status.CREATE_IN_PROGRESS); + resource.setState(NodeStates.CREATING); resource.setToscaNodeName(entry.getKey()); resource.setToscaNodeType(entry.getValue().getType()); resourceRepository.save(resource); } - - ArchiveRoot root = newParsingResult.getResult(); - Map nodes = new HashMap<>(); nodes.put(entry.getKey(), newNodes.get(entry.getKey())); - root.getTopology().setNodeTemplates(nodes); - // FIXME this is a trick used only for demo purpose - InfrastructureManagerApiClient imClient = - getClient(getIaaSSiteFromTosca(deployment.getTemplate())); - ServiceResponse response = imClient.addResource(deployment.getEndpoint(), - toscaService.getTemplateFromTopology(root), RestApiBodyContentType.TOSCA, true, - true); - - if (!response.isReponseSuccessful()) { - String responseError = getAndLogImErrorResponse(response); - // updateOnError(deploymentId, response.getReasonPhrase() + ": " + responseError); - throw new DeploymentException(response.getReasonPhrase() + ": " + responseError); - } else { - boolean result = doPoller(this::isDeployed, deployment); - if (!result) { - throw new DeploymentException("An error occur during the update: polling failed"); - } - } - } else if (newCount < oldCount) { + } else if (newCount < oldCount && removalList.size() == (oldCount - newCount)) { // delete a WN. - List removalList = toscaService.getRemovalList(newNodes.get(entry.getKey())); - if (removalList.size() != (oldCount - newCount)) { - throw new DeploymentException("An error occur during the update. Count is <" - + newCount + "> but removal_list contains <" + removalList.size() - + "> elements in the node: " + entry.getKey()); - } // Find the nodes to be removed. for (String resourceId : removalList) { Resource resource = resourceRepository.findOne(resourceId); - resource.setStatus(Status.DELETE_IN_PROGRESS); + resource.setState(NodeStates.DELETING); resource = resourceRepository.save(resource); - // FIXME this is a trick used only for demo purpose - InfrastructureManagerApiClient imClient = - getClient(getIaaSSiteFromTosca(deployment.getTemplate())); - ServiceResponse response = - imClient.removeResource(deployment.getEndpoint(), resource.getIaasId(), true); - if (!response.isReponseSuccessful()) { - if (response.getServiceStatusCode() != 404) { - LOG.error(response.getResult()); - throw new DeploymentException("An error occur during the update: fail to delete: " - + resource.getToscaNodeName() + " with id: " + resourceId); - } - } else { - boolean result = doPoller(this::isResourceDeleted, resource); - if (result) { - List resurces = deployment.getResources(); - resurces.remove(resource); - resourceRepository.delete(resourceId); - } else { - throw new DeploymentException( - "An error occur during the update: polling failed " + resource.getId()); - } - - } + vmIds.add(resource.getIaasId()); } + } else { + throw new DeploymentException("An error occur during the update. Count is <" + newCount + + "> but removal_list contains <" + removalList.size() + "> elements in the node: " + + entry.getKey()); } } } - bindResources(deployment, deployment.getEndpoint()); + + // Pulisco gli output e aggiungo i nodi da creare + root.getTopology().setOutputs(null); + root.getTopology().setNodeTemplates(nodes); + if (!root.getTopology().isEmpty()) { + try { + InfrastructureManager im = getClient(getIaaSSiteFromTosca(deployment.getTemplate())); + + im.addResource(deployment.getEndpoint(), toscaService.getTemplateFromTopology(root), + BodyContentType.TOSCA); + } catch (ImClientErrorException exception) { + throw new DeploymentException( + "An error occur during the update: fail to add new resources.", exception); + } + } + // DELETE + if (vmIds.size() > 0) { + try { + // FIXME this is a trick used only for demo purpose + InfrastructureManager im = getClient(getIaaSSiteFromTosca(deployment.getTemplate())); + im.removeResource(deployment.getEndpoint(), vmIds); + } catch (ImClientErrorException exception) { + throw new DeploymentException( + "An error occur during the update: fail to delete resources.", exception); + } + } deployment.setTemplate(toscaService.updateTemplate(template)); - updateOnSuccess(deployment.getId()); + return true; } catch (ImClientException | IOException | DeploymentException ex) { updateOnError(deployment.getId(), ex); - } - - } - - private Status getOrchestratorStatusFromImStatus(String value) throws NoEnumFoundException { - VmStates vmState = VmStates.getEnumFromValue(value); - switch (vmState) { - case PENDING: - case RUNNING: - return Status.CREATE_IN_PROGRESS; - - case FAILED: - case UNCONFIGURED: - return Status.CREATE_FAILED; - - case CONFIGURED: - return Status.CREATE_COMPLETE; - - // TODO Understand if we need other Status - case OFF: - case STOPPED: - case UNKNOWN: - return Status.UNKNOWN; - - default: - return Status.UNKNOWN; + return false; } } @@ -453,25 +437,26 @@ public boolean doUndeploy(Deployment deployment) { deployment = deploymentRepository.save(deployment); // FIXME this is a trick used only for demo purpose - InfrastructureManagerApiClient imClient = - getClient(getIaaSSiteFromTosca(deployment.getTemplate())); + InfrastructureManager im = getClient(getIaaSSiteFromTosca(deployment.getTemplate())); if (deployment.getEndpoint() == null) { updateOnSuccess(deploymentUuid); return true; } - ServiceResponse response = imClient.destroyInfrastructure(deployment.getEndpoint(), true); - if (!response.isReponseSuccessful()) { - if (response.getServiceStatusCode() == 404) { - updateOnSuccess(deploymentUuid); - return true; - } else { - String responseError = getAndLogImErrorResponse(response); - updateOnError(deploymentUuid, responseError); - return false; - } - } else { + im.destroyInfrastructure(deployment.getEndpoint()); + return true; + + } catch (ImClientErrorException exception) { + logImErrorResponse(exception); + ResponseError error = getImResponseError(exception); + if (error.is404Error()) { + updateOnSuccess(deploymentUuid); return true; + + } else { + updateOnError(deploymentUuid, error.getFormattedErrorMessage()); + return false; } + } catch (Exception ex) { LOG.error(ex); updateOnError(deploymentUuid, ex); @@ -488,23 +473,20 @@ public boolean isUndeployed(String deploymentUuid) throws DeploymentException { @Override public boolean isUndeployed(Deployment deployment) throws DeploymentException { try { - // FIXME this is a trick used only for demo purpose - InfrastructureManagerApiClient imClient = - getClient(getIaaSSiteFromTosca(deployment.getTemplate())); + InfrastructureManager im = getClient(getIaaSSiteFromTosca(deployment.getTemplate())); + + // TODO verificare if (deployment.getEndpoint() == null) { return true; } - ServiceResponse response = imClient.getInfrastructureState(deployment.getEndpoint()); - if (!response.isReponseSuccessful()) { - if (response.getServiceStatusCode() == 404) { - return true; - } else { - return false; - } - } else { - return false; - } + im.getInfrastructureState(deployment.getEndpoint()); + return false; + + } catch (ImClientErrorException exception) { + ResponseError error = getImResponseError(exception); + return error.is404Error(); + } catch (ImClientException ex) { // TODO improve exception handling LOG.error(ex); @@ -528,20 +510,15 @@ private boolean isResourceDeleted(Resource resource) { try { Deployment deployment = resource.getDeployment(); // FIXME this is a trick used only for demo purpose - InfrastructureManagerApiClient imClient = - getClient(getIaaSSiteFromTosca(deployment.getTemplate())); + InfrastructureManager im = getClient(getIaaSSiteFromTosca(deployment.getTemplate())); + + im.getVmInfo(deployment.getEndpoint(), resource.getIaasId()); + return false; + + } catch (ImClientErrorException exception) { + ResponseError error = getImResponseError(exception); + return error.is404Error(); - ServiceResponse response = - imClient.getVmInfo(deployment.getEndpoint(), resource.getIaasId(), true); - if (!response.isReponseSuccessful()) { - if (response.getServiceStatusCode() == 404) { - return true; - } else { - return false; - } - } else { - return false; - } } catch (ImClientException ex) { // TODO improve exception handling LOG.error(ex); @@ -557,23 +534,17 @@ private void bindResources(Deployment deployment, String infrastructureId) throws ImClientException { // FIXME this is a trick used only for demo purpose - InfrastructureManagerApiClient imClient = - getClient(getIaaSSiteFromTosca(deployment.getTemplate())); + InfrastructureManager im = getClient(getIaaSSiteFromTosca(deployment.getTemplate())); // Get the URLs of the VMs composing the virtual infrastructure // TODO test in case of errors - String[] vmUrls = - imClient.getInfrastructureInfo(infrastructureId, true).getResult().split("\\r?\\n"); + InfrastructureUris vmUrls = im.getInfrastructureInfo(infrastructureId); // for each URL get the information about the VM - Map vmMap = new HashMap(); - for (String vm : vmUrls) { - String vmId = null; - int index = vm.lastIndexOf("/"); - if (index != -1) { - vmId = vm.substring(index + 1); - } - String vmInfo = imClient.getVmInfo(infrastructureId, vmId, true).getResult(); + Map vmMap = new HashMap(); + for (InfrastructureUri vmUri : vmUrls.getUris()) { + String vmId = extractVmId(vmUri); + VirtualMachineInfo vmInfo = im.getVmInfo(infrastructureId, vmId); vmMap.put(vmId, vmInfo); } @@ -589,29 +560,35 @@ private void bindResources(Deployment deployment, String infrastructureId) Set insered = new HashSet(); for (Resource r : resources) { - if (r.getStatus() == Status.CREATE_IN_PROGRESS - || r.getStatus() == Status.UPDATE_IN_PROGRESS) { - for (Map.Entry entry : vmMap.entrySet()) { - if (entry.getValue().contains(r.getToscaNodeName()) + if (r.getState() == NodeStates.CREATING || r.getState() == NodeStates.CONFIGURING + || r.getState() == NodeStates.ERROR) { + for (Map.Entry entry : vmMap.entrySet()) { + if (entry.getValue().toString().contains(r.getToscaNodeName()) && !insered.contains(entry.getKey())) { r.setIaasId(entry.getKey()); insered.add(entry.getKey()); break; } } + } else if (r.getState() == NodeStates.DELETING) { + deployment.getResources().remove(r); } } } - private String getAndLogImErrorResponse(ServiceResponse response) { - try { - es.upv.i3m.grycap.im.pojo.Error error = - new ObjectMapper().readValue(response.getResult(), es.upv.i3m.grycap.im.pojo.Error.class); - LOG.error(error.toString()); - return error.getMessage(); - } catch (IOException ex) { - LOG.error(ex); + private String extractVmId(InfrastructureUri vmUri) { + Matcher matcher = VM_ID_PATTERN.matcher(vmUri.getUri()); + if (matcher.find()) { + return matcher.group(0); } - return response.getResult(); + return ""; + } + + private ResponseError getImResponseError(ImClientErrorException exception) { + return exception.getResponseError(); + } + + private void logImErrorResponse(ImClientErrorException exception) { + LOG.error(exception.getResponseError().getFormattedErrorMessage()); } } diff --git a/src/main/resources/workflows/Update.bpmn2 b/src/main/resources/workflows/Update.bpmn2 index 766f198fe5..e75f9bb940 100644 --- a/src/main/resources/workflows/Update.bpmn2 +++ b/src/main/resources/workflows/Update.bpmn2 @@ -2,11 +2,14 @@ - + + - + + + SequenceFlow_1 @@ -17,7 +20,7 @@ - SequenceFlow_8 + SequenceFlow_14 SequenceFlow_2 @@ -25,13 +28,16 @@ - + + DataInput_2 DataInput_3 - DataInput_1 + DataInput_10 - + + DataOutput_4 + DataInput_2 @@ -44,10 +50,14 @@ DEPLOYMENT_ID DataInput_3 - + TOSCA_TEMPLATE - DataInput_1 + DataInput_10 + + DataOutput_4 + Result + @@ -95,7 +105,7 @@ SequenceFlow_7 - SequenceFlow_8 + SequenceFlow_3 DEPLOYMENT_ID @@ -107,7 +117,106 @@ - + + SequenceFlow_6 + SequenceFlow_11 + + + + + + + + + DataInput_1 + DataInput_4 + DataInput_11 + DataInput_12 + + + DataOutput_2 + DataOutput_3 + + + + DataInput_1 + + it.reply.orchestrator.service.commands.PollDeploy + DataInput_2 + + + + DEPLOYMENT_ID + DataInput_4 + + + pollingStatus + DataInput_11 + + + Result + DataInput_12 + + + DataOutput_2 + pollingStatus + + + DataOutput_3 + Result + + + + SequenceFlow_16 + SequenceFlow_6 + + 30s + + + + + SequenceFlow_11 + SequenceFlow_13 + SequenceFlow_15 + + + + SequenceFlow_13 + SequenceFlow_14 + + + DEPLOYMENT_ID + DataInput_8 + + + DataInput_8 + + + + + return Result != null && Result; + + + + SequenceFlow_15 + SequenceFlow_4 + SequenceFlow_16 + + + + + SequenceFlow_3 + SequenceFlow_4 + SequenceFlow_5 + + + SequenceFlow_5 + + + + return Result != null && Result; + + @@ -132,9 +241,9 @@ - + - + @@ -148,7 +257,7 @@ - + @@ -175,6 +284,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -195,12 +346,6 @@ - - - - - - @@ -213,6 +358,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/java/it/reply/orchestrator/controller/DeploymentControllerTest.java b/src/test/java/it/reply/orchestrator/controller/DeploymentControllerTest.java index 63ffd285ec..21aebff217 100644 --- a/src/test/java/it/reply/orchestrator/controller/DeploymentControllerTest.java +++ b/src/test/java/it/reply/orchestrator/controller/DeploymentControllerTest.java @@ -23,7 +23,9 @@ import com.github.springtestdbunit.annotation.DatabaseSetup; import com.github.springtestdbunit.annotation.DatabaseTearDown; +import es.upv.i3m.grycap.file.NoNullOrEmptyFile; import es.upv.i3m.grycap.file.Utf8File; +import es.upv.i3m.grycap.im.exceptions.FileException; import it.reply.orchestrator.config.WebAppConfigurationAware; import it.reply.orchestrator.dto.request.DeploymentRequest; @@ -43,6 +45,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.context.WebApplicationContext; +import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; @@ -228,7 +231,7 @@ public void createDeploymentUnsupportedMediaType() throws Exception { Map parameters = new HashMap<>(); parameters.put("cpus", 1); request.setParameters(parameters); - request.setTemplate(new Utf8File("./src/test/resources/tosca/compute_tosca.yaml").read()); + request.setTemplate(getFileContentAsString("./src/test/resources/tosca/compute_tosca.yaml")); request.setCallback("http://localhost:8080/callback"); mockMvc .perform(post("/deployments").contentType(MediaType.TEXT_PLAIN) @@ -245,7 +248,7 @@ public void createDeploymentSuccessfully() throws Exception { Map parameters = new HashMap<>(); parameters.put("cpus", 1); request.setParameters(parameters); - request.setTemplate(new Utf8File("./src/test/resources/tosca/compute_tosca.yaml").read()); + request.setTemplate(getFileContentAsString("./src/test/resources/tosca/compute_tosca.yaml")); request.setCallback("http://localhost:8080/callback"); mockMvc.perform(post("/deployments").contentType(MediaType.APPLICATION_JSON) .content(TestUtil.convertObjectToJsonBytes(request))) @@ -279,7 +282,7 @@ public void updateDeploymentNotExists() throws Exception { Map parameters = new HashMap<>(); parameters.put("cpus", 1); request.setParameters(parameters); - request.setTemplate(new Utf8File("./src/test/resources/tosca/galaxy_tosca.yaml").read()); + request.setTemplate(getFileContentAsString("./src/test/resources/tosca/galaxy_tosca.yaml")); request.setCallback("http://localhost:8080/callback"); mockMvc .perform(put("/deployments/not-found").contentType(MediaType.APPLICATION_JSON) @@ -293,7 +296,7 @@ public void updateDeploymentNotExists() throws Exception { @DatabaseSetup("/data/database-init.xml") public void updateDeploymentDeleteInProgress() throws Exception { DeploymentRequest request = new DeploymentRequest(); - request.setTemplate(new Utf8File("./src/test/resources/tosca/galaxy_tosca.yaml").read()); + request.setTemplate(getFileContentAsString("./src/test/resources/tosca/galaxy_tosca.yaml")); mockMvc .perform(put("/deployments/mmd34483-d937-4578-bfdb-ebe196bf82de") .contentType(MediaType.APPLICATION_JSON) @@ -312,7 +315,7 @@ public void updateDeploymentSuccessfully() throws Exception { Map parameters = new HashMap<>(); parameters.put("cpus", 1); request.setParameters(parameters); - request.setTemplate(new Utf8File("./src/test/resources/tosca/galaxy_tosca.yaml").read()); + request.setTemplate(getFileContentAsString("./src/test/resources/tosca/galaxy_tosca.yaml")); request.setCallback("http://localhost:8080/callback"); mockMvc.perform(put("/deployments/mmd34483-d937-4578-bfdb-ebe196bf82dd") .contentType(MediaType.APPLICATION_JSON) @@ -334,7 +337,7 @@ public void updateDeploymentSuccessfully() throws Exception { public void createDeploymentWithoutCallbackSuccessfully() throws Exception { DeploymentRequest request = new DeploymentRequest(); - request.setTemplate(new Utf8File("./src/test/resources/tosca/galaxy_tosca.yaml").read()); + request.setTemplate(getFileContentAsString("./src/test/resources/tosca/galaxy_tosca.yaml")); mockMvc .perform(post("/deployments").contentType(MediaType.APPLICATION_JSON) .content(TestUtil.convertObjectToJsonBytes(request))) @@ -349,7 +352,7 @@ public void createDeploymentWithCallbackUnsuccessfully() throws Exception { DeploymentRequest request = new DeploymentRequest(); String callback = "httptest.com"; request.setCallback(callback); - request.setTemplate(new Utf8File("./src/test/resources/tosca/galaxy_tosca.yaml").read()); + request.setTemplate(getFileContentAsString("./src/test/resources/tosca/galaxy_tosca.yaml")); mockMvc .perform(post("/deployments").contentType(MediaType.APPLICATION_JSON) .content(TestUtil.convertObjectToJsonBytes(request))) @@ -389,4 +392,8 @@ public void deleteDeploymentNotFound() throws Exception { .andExpect(jsonPath("$.code", is(404))).andExpect(jsonPath("$.title", is("Not Found"))) .andExpect(jsonPath("$.message", is("The deployment doesn't exist"))); } + + private String getFileContentAsString(String fileUri) throws FileException{ + return new NoNullOrEmptyFile(new Utf8File(Paths.get(fileUri))).read(); + } } diff --git a/src/test/java/it/reply/orchestrator/controller/ResourceControllerTest.java b/src/test/java/it/reply/orchestrator/controller/ResourceControllerTest.java index 1657a99fa7..09f53169b6 100644 --- a/src/test/java/it/reply/orchestrator/controller/ResourceControllerTest.java +++ b/src/test/java/it/reply/orchestrator/controller/ResourceControllerTest.java @@ -54,10 +54,8 @@ public class ResourceControllerTest extends WebAppConfigurationAware { @Before public void setup() { MockitoAnnotations.initMocks(this); - mockMvc = - MockMvcBuilders.webAppContextSetup(wac) - .apply(documentationConfiguration(this.restDocumentation)).dispatchOptions(true) - .build(); + mockMvc = MockMvcBuilders.webAppContextSetup(wac) + .apply(documentationConfiguration(this.restDocumentation)).dispatchOptions(true).build(); } @Test @@ -79,15 +77,13 @@ public void getResources() throws Exception { fieldWithPath("content[].uuid").description("The unique identifier of a resource"), fieldWithPath("content[].creationTime").description( "Creation date-time (http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14)"), - fieldWithPath("content[].status").description( - "The status of the deployment. (http://indigo-dc.github.io/orchestrator/apidocs/it/reply/orchestrator/enums/Status.html)"), - fieldWithPath("content[].statusReason").optional() - .description("The description of the state"), - fieldWithPath("content[].toscaNodeType").optional() - .description("The type of the represented TOSCA node"), - fieldWithPath("content[].requiredBy") - .description("A list of nodes that require this resource"), - fieldWithPath("content[].links[]").ignored(), fieldWithPath("page").ignored()))); + fieldWithPath("content[].state").description( + "The status of the resource. (http://indigo-dc.github.io/orchestrator/apidocs/it/reply/orchestrator/enums/NodeStates.html)"), + fieldWithPath("content[].toscaNodeType").optional() + .description("The type of the represented TOSCA node"), + fieldWithPath("content[].requiredBy") + .description("A list of nodes that require this resource"), + fieldWithPath("content[].links[]").ignored(), fieldWithPath("page").ignored()))); } @@ -110,13 +106,12 @@ public void getResourceByIdAndDeploymentIdSuccesfully() throws Exception { .andExpect(jsonPath("$.links[1].rel", equalTo("self"))) .andExpect(jsonPath("$.links[1].href", endsWith("/deployments/" + deploymentId + "/resources/" + resourceId))) - .andDo(document("get-resource", preprocessResponse(prettyPrint()), - responseFields(fieldWithPath("uuid").description("The unique identifier of a resource"), - fieldWithPath("creationTime").description( - "Creation date-time (http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14)"), - fieldWithPath("status").description( - "The status of the deployment. (http://indigo-dc.github.io/orchestrator/apidocs/it/reply/orchestrator/enums/Status.html)"), - fieldWithPath("statusReason").optional().description("The description of the state"), + .andDo(document("get-resource", preprocessResponse(prettyPrint()), responseFields( + fieldWithPath("uuid").description("The unique identifier of a resource"), + fieldWithPath("creationTime").description( + "Creation date-time (http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14)"), + fieldWithPath("state").description( + "The status of the resource. (http://indigo-dc.github.io/orchestrator/apidocs/it/reply/orchestrator/enums/NodeStates.html)"), fieldWithPath("toscaNodeType").optional() .description("The type of the represented TOSCA node"), fieldWithPath("requiredBy").description("A list of nodes that require this resource"), diff --git a/src/test/java/it/reply/orchestrator/controller/TemplateControllerTest.java b/src/test/java/it/reply/orchestrator/controller/TemplateControllerTest.java index 1d5208448d..1e3f36bff3 100644 --- a/src/test/java/it/reply/orchestrator/controller/TemplateControllerTest.java +++ b/src/test/java/it/reply/orchestrator/controller/TemplateControllerTest.java @@ -12,6 +12,7 @@ import com.github.springtestdbunit.annotation.DatabaseSetup; import com.github.springtestdbunit.annotation.DatabaseTearDown; +import es.upv.i3m.grycap.file.NoNullOrEmptyFile; import es.upv.i3m.grycap.file.Utf8File; import it.reply.orchestrator.config.WebAppConfigurationAware; @@ -29,6 +30,7 @@ import org.springframework.web.context.WebApplicationContext; import java.nio.charset.Charset; +import java.nio.file.Paths; @DatabaseTearDown("/data/database-empty.xml") public class TemplateControllerTest extends WebAppConfigurationAware { @@ -61,7 +63,7 @@ public void setup() { @DatabaseSetup("/data/database-resource-init.xml") public void getTemplate() throws Exception { - String template = new Utf8File(templatePath).read(); + String template = new NoNullOrEmptyFile(new Utf8File(Paths.get(templatePath))).read(); MvcResult result = mockMvc.perform(get("/deployments/" + deploymentId + "/template")) .andExpect(status().isOk()).andExpect(content().contentType(MediaType.TEXT_PLAIN)) .andDo(document("get-template")).andReturn(); diff --git a/src/test/java/it/reply/orchestrator/service/ToscaServiceTest.java b/src/test/java/it/reply/orchestrator/service/ToscaServiceTest.java index ba2526b3aa..03198291dd 100644 --- a/src/test/java/it/reply/orchestrator/service/ToscaServiceTest.java +++ b/src/test/java/it/reply/orchestrator/service/ToscaServiceTest.java @@ -6,6 +6,7 @@ import alien4cloud.model.topology.NodeTemplate; import alien4cloud.tosca.parser.ParsingException; +import es.upv.i3m.grycap.file.NoNullOrEmptyFile; import es.upv.i3m.grycap.file.Utf8File; import es.upv.i3m.grycap.im.exceptions.FileException; @@ -16,7 +17,9 @@ import org.springframework.beans.factory.annotation.Autowired; import java.io.IOException; +import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; @@ -30,16 +33,16 @@ public class ToscaServiceTest extends WebAppConfigurationAware { @Test(expected = ToscaException.class) public void customizeTemplateWithError() throws Exception { - String template = new Utf8File("./src/test/resources/tosca/galaxy_tosca_clues_error.yaml") - .read(); + String template = getFileContentAsString( + "./src/test/resources/tosca/galaxy_tosca_clues_error.yaml"); toscaService.customizeTemplate(template, deploymentId); - } @Test public void customizeTemplateWithDeplymentIdSuccessfully() throws Exception { - String template = new Utf8File("./src/test/resources/tosca/galaxy_tosca_clues.yaml").read(); + String template = getFileContentAsString( + "./src/test/resources/tosca/galaxy_tosca_clues.yaml"); String customizedTemplate = toscaService.customizeTemplate(template, deploymentId); String templateDeploymentId = ""; Map nodes = toscaService.getArchiveRootFromTemplate(customizedTemplate) @@ -56,14 +59,16 @@ public void customizeTemplateWithDeplymentIdSuccessfully() throws Exception { @Test public void getRemovalList() throws IOException, ParsingException, FileException { - List expectedRemovalList = new ArrayList<>(); - expectedRemovalList.add("to-be-deleted-1"); - expectedRemovalList.add("to-be-deleted-2"); - String template = new Utf8File( - "./src/test/resources/tosca/galaxy_tosca_clues_removal_list.yaml").read(); + List expectedRemovalList = Arrays.asList("to-be-deleted-1", "to-be-deleted-2"); + String template = getFileContentAsString( + "./src/test/resources/tosca/galaxy_tosca_clues_removal_list.yaml"); NodeTemplate node = toscaService.getArchiveRootFromTemplate(template).getResult().getTopology() .getNodeTemplates().get("torque_wn"); List removalList = toscaService.getRemovalList(node); assertEquals(expectedRemovalList, removalList); } + + private String getFileContentAsString(String fileUri) throws FileException{ + return new NoNullOrEmptyFile(new Utf8File(Paths.get(fileUri))).read(); + } } diff --git a/src/test/resources/data/database-resource-init.xml b/src/test/resources/data/database-resource-init.xml index 6b9518553f..66fe25e4b4 100644 --- a/src/test/resources/data/database-resource-init.xml +++ b/src/test/resources/data/database-resource-init.xml @@ -1,6 +1,6 @@ - - + + \ No newline at end of file