aboutsummaryrefslogtreecommitdiffstats
path: root/adapters/mso-adapter-utils
diff options
context:
space:
mode:
Diffstat (limited to 'adapters/mso-adapter-utils')
-rw-r--r--adapters/mso-adapter-utils/pom.xml5
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/cloud/authentication/KeystoneAuthHolder.java2
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/cloud/authentication/KeystoneV3Authentication.java6
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/cloudify/beans/DeploymentInfoBuilder.java16
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/cloudify/exceptions/MsoCloudifyWorkflowException.java4
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/cloudify/utils/MsoCloudifyUtils.java30
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/CinderClientException.java34
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/CinderClientImpl.java100
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/GlanceClientException.java34
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/GlanceClientImpl.java84
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/HeatClientException.java37
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoCommonUtils.java157
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoHeatEnvironmentEntry.java4
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoHeatUtils.java815
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoHeatUtilsWithUpdate.java45
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoKeystoneUtils.java41
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoMulticloudUtils.java13
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoNeutronUtils.java6
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoYamlEditorWithEnvt.java9
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MulticloudCreateHeatResponse.java2
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MulticloudCreateLinkResponse.java2
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MulticloudCreateResponse.java2
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MulticloudQueryResponse.java2
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MulticloudRequest.java2
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/NeutronClientException.java33
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/NeutronClientImpl.java113
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/NovaClientException.java33
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/NovaClientImpl.java207
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/StackCreationException.java11
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/StackResultWrapper.java62
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/StackRollbackException.java11
-rw-r--r--adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/StackStatusHandler.java49
-rw-r--r--adapters/mso-adapter-utils/src/test/java/org/onap/so/cloud/authentication/KeystoneAuthHolderTest.java2
-rw-r--r--adapters/mso-adapter-utils/src/test/java/org/onap/so/openstack/utils/MsoHeatUtilsITTest.java219
-rw-r--r--adapters/mso-adapter-utils/src/test/java/org/onap/so/openstack/utils/MsoHeatUtilsTest.java605
-rw-r--r--adapters/mso-adapter-utils/src/test/java/org/onap/so/openstack/utils/MsoHeatUtilsWithUpdateTest.java8
-rw-r--r--adapters/mso-adapter-utils/src/test/java/org/onap/so/openstack/utils/StackStatusHandlerTest.java69
-rw-r--r--adapters/mso-adapter-utils/src/test/resources/__files/OpenstackResponse_Stack_Created.json2
38 files changed, 2011 insertions, 865 deletions
diff --git a/adapters/mso-adapter-utils/pom.xml b/adapters/mso-adapter-utils/pom.xml
index 7918072323..aa9a1cea9e 100644
--- a/adapters/mso-adapter-utils/pom.xml
+++ b/adapters/mso-adapter-utils/pom.xml
@@ -147,5 +147,10 @@
<artifactId>cxf-rt-transports-http</artifactId>
<version>${cxf.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.onap.so</groupId>
+ <artifactId>mso-requests-db</artifactId>
+ <version>${project.version}</version>
+ </dependency>
</dependencies>
</project>
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/cloud/authentication/KeystoneAuthHolder.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/cloud/authentication/KeystoneAuthHolder.java
index 4df8a91515..eadbc511d0 100644
--- a/adapters/mso-adapter-utils/src/main/java/org/onap/so/cloud/authentication/KeystoneAuthHolder.java
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/cloud/authentication/KeystoneAuthHolder.java
@@ -51,7 +51,7 @@ public class KeystoneAuthHolder implements Serializable {
return serviceUrl;
}
- public void setHeatUrl(String serviceUrl) {
+ public void setServiceUrl(String serviceUrl) {
this.serviceUrl = serviceUrl;
}
}
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/cloud/authentication/KeystoneV3Authentication.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/cloud/authentication/KeystoneV3Authentication.java
index f717144562..42d200a130 100644
--- a/adapters/mso-adapter-utils/src/main/java/org/onap/so/cloud/authentication/KeystoneV3Authentication.java
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/cloud/authentication/KeystoneV3Authentication.java
@@ -72,9 +72,7 @@ public class KeystoneV3Authentication {
OpenStackRequest<Token> v3Request = keystoneTenantClient.tokens().authenticate(v3Credentials);
- KeystoneAuthHolder holder = makeRequest(v3Request, type, region);
-
- return holder;
+ return makeRequest(v3Request, type, region);
}
protected KeystoneAuthHolder makeRequest(OpenStackRequest<Token> v3Request, String type, String region) {
@@ -87,7 +85,7 @@ public class KeystoneV3Authentication {
KeystoneAuthHolder result = new KeystoneAuthHolder();
result.setId(id);
result.setexpiration(token.getExpiresAt());
- result.setHeatUrl(findEndpointURL(token.getCatalog(), type, region, "public"));
+ result.setServiceUrl(findEndpointURL(token.getCatalog(), type, region, "public"));
return result;
}
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/cloudify/beans/DeploymentInfoBuilder.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/cloudify/beans/DeploymentInfoBuilder.java
index 02ace5665d..072bf404e7 100644
--- a/adapters/mso-adapter-utils/src/main/java/org/onap/so/cloudify/beans/DeploymentInfoBuilder.java
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/cloudify/beans/DeploymentInfoBuilder.java
@@ -72,22 +72,22 @@ public final class DeploymentInfoBuilder {
this.errorMessage = execution.getError();
// Compute the status based on the last workflow
- if (lastAction.equals("install")) {
- if (actionStatus.equals("terminated")) {
+ if (("install").equals(lastAction)) {
+ if (("terminated").equals(actionStatus)) {
this.deploymentStatus = DeploymentStatus.INSTALLED;
- } else if (actionStatus.equals("failed")) {
+ } else if (("failed").equals(actionStatus)) {
this.deploymentStatus = DeploymentStatus.FAILED;
- } else if (actionStatus.equals("started") || actionStatus.equals("pending")) {
+ } else if (("started").equals(actionStatus) || ("pending").equals(actionStatus)) {
this.deploymentStatus = DeploymentStatus.INSTALLING;
} else {
this.deploymentStatus = DeploymentStatus.UNKNOWN;
}
- } else if (lastAction.equals("uninstall")) {
- if (actionStatus.equals("terminated")) {
+ } else if (("uninstall").equals(lastAction)) {
+ if (("terminated").equals(actionStatus)) {
this.deploymentStatus = DeploymentStatus.CREATED;
- } else if (actionStatus.equals("failed")) {
+ } else if (("failed").equals(actionStatus)) {
this.deploymentStatus = DeploymentStatus.FAILED;
- } else if (actionStatus.equals("started") || actionStatus.equals("pending")) {
+ } else if (("started").equals(actionStatus) || ("pending").equals(actionStatus)) {
this.deploymentStatus = DeploymentStatus.UNINSTALLING;
} else {
this.deploymentStatus = DeploymentStatus.UNKNOWN;
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/cloudify/exceptions/MsoCloudifyWorkflowException.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/cloudify/exceptions/MsoCloudifyWorkflowException.java
index 5c2348dffa..2251575671 100644
--- a/adapters/mso-adapter-utils/src/main/java/org/onap/so/cloudify/exceptions/MsoCloudifyWorkflowException.java
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/cloudify/exceptions/MsoCloudifyWorkflowException.java
@@ -38,8 +38,8 @@ public class MsoCloudifyWorkflowException extends MsoCloudifyException {
super(0, "Workflow Exception",
"Workflow " + workflowId + " failed on deployment " + deploymentId + ": " + message);
this.workflowStatus = workflowStatus;
- if (workflowStatus.equals("pending") || workflowStatus.equals("started") || workflowStatus.equals("cancelling")
- || workflowStatus.equals("force_cancelling")) {
+ if (("pending").equals(workflowStatus) || ("started").equals(workflowStatus)
+ || ("cancelling").equals(workflowStatus) || ("force_cancelling").equals(workflowStatus)) {
workflowStillRunning = true;
}
}
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/cloudify/utils/MsoCloudifyUtils.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/cloudify/utils/MsoCloudifyUtils.java
index 0a0f2787da..dd43837c76 100644
--- a/adapters/mso-adapter-utils/src/main/java/org/onap/so/cloudify/utils/MsoCloudifyUtils.java
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/cloudify/utils/MsoCloudifyUtils.java
@@ -109,6 +109,8 @@ public class MsoCloudifyUtils extends MsoCommonUtils implements VduPlugin {
private static final String DELETE_DEPLOYMENT = "DeleteDeployment";
private static final String TERMINATED = "terminated";
private static final String CANCELLED = "cancelled";
+ private static final String UNINSTALL = "uninstall";
+ private static final String UPLOAD_BLUEPRINT = "UPLOAD_BLUEPRINT";
// Fetch cloud configuration each time (may be cached in CloudConfig class)
@Autowired
@@ -181,11 +183,11 @@ public class MsoCloudifyUtils extends MsoCommonUtils implements VduPlugin {
Map<String, Object> expandedInputs = new HashMap<>(inputs);
String platform = cloudSite.get().getPlatform();
- if (platform == null || platform.equals("") || platform.equalsIgnoreCase("OPENSTACK")) {
+ if (platform == null || platform.isEmpty() || ("OPENSTACK").equalsIgnoreCase(platform)) {
// Create the Cloudify OpenstackConfig with the credentials
OpenstackConfig openstackConfig = getOpenstackConfig(cloudSite.get(), tenantId);
expandedInputs.put("openstack_config", openstackConfig);
- } else if (platform.equalsIgnoreCase("AZURE")) {
+ } else if (("AZURE").equalsIgnoreCase(platform)) {
// Create Cloudify AzureConfig with the credentials
AzureConfig azureConfig = getAzureConfig(cloudSite.get(), tenantId);
expandedInputs.put("azure_config", azureConfig);
@@ -265,7 +267,7 @@ public class MsoCloudifyUtils extends MsoCommonUtils implements VduPlugin {
try {
// Run the uninstall to undo the install
- Execution uninstallWorkflow = executeWorkflow(cloudify, deploymentId, "uninstall", null,
+ Execution uninstallWorkflow = executeWorkflow(cloudify, deploymentId, UNINSTALL, null,
pollForCompletion, deletePollTimeout, deletePollInterval);
if (uninstallWorkflow.getStatus().equals(TERMINATED)) {
@@ -306,7 +308,7 @@ public class MsoCloudifyUtils extends MsoCommonUtils implements VduPlugin {
try {
// Run the uninstall to undo the install.
// Always try to run it, as it should be idempotent
- executeWorkflow(cloudify, deploymentId, "uninstall", null, pollForCompletion, deletePollTimeout,
+ executeWorkflow(cloudify, deploymentId, UNINSTALL, null, pollForCompletion, deletePollTimeout,
deletePollInterval);
// Delete the deployment itself
@@ -402,7 +404,7 @@ public class MsoCloudifyUtils extends MsoCommonUtils implements VduPlugin {
GetExecution queryExecution = cloudify.executions().byId(executionId);
command = "query";
- while (!timedOut && !(status.equals(TERMINATED) || status.equals("failed") || status.equals(CANCELLED))) {
+ while (!timedOut && !(status.equals(TERMINATED) || ("failed").equals(status) || status.equals(CANCELLED))) {
// workflow is still running; check for timeout
if (pollTimeout <= 0) {
logger.debug("workflow {} timed out on deployment {}", execution.getWorkflowId(),
@@ -425,7 +427,7 @@ public class MsoCloudifyUtils extends MsoCommonUtils implements VduPlugin {
// Success!
logger.debug("Workflow '{}' completed successfully on deployment '{}'", workflowId, deploymentId);
return execution;
- } else if (status.equals("failed")) {
+ } else if (("failed").equals(status)) {
// Workflow failed. Log it and return the execution object (don't throw exception here)
logger.error("{} Cloudify workflow failure: {} {} Execute Workflow: Failed: {}",
MessageEnum.RA_CREATE_STACK_ERR, execution.getError(),
@@ -665,7 +667,7 @@ public class MsoCloudifyUtils extends MsoCommonUtils implements VduPlugin {
try {
uninstallWorkflow =
- executeWorkflow(cloudify, deploymentId, "uninstall", null, true, pollTimeout, deletePollInterval);
+ executeWorkflow(cloudify, deploymentId, UNINSTALL, null, true, pollTimeout, deletePollInterval);
if (uninstallWorkflow.getStatus().equals(TERMINATED)) {
// Successful uninstall.
@@ -812,7 +814,7 @@ public class MsoCloudifyUtils extends MsoCommonUtils implements VduPlugin {
try {
// Put the root directory
- String rootDir = blueprintId + ((blueprintId.endsWith("/") ? "" : "/"));
+ String rootDir = blueprintId + (blueprintId.endsWith("/") ? "" : "/");
zipOut.putNextEntry(new ZipEntry(rootDir));
zipOut.closeEntry();
@@ -836,13 +838,13 @@ public class MsoCloudifyUtils extends MsoCommonUtils implements VduPlugin {
Blueprint blueprint = uploadRequest.execute();
logger.debug("Successfully uploaded blueprint {}", blueprint.getId());
} catch (CloudifyResponseException | CloudifyConnectException e) {
- throw cloudifyExceptionToMsoException(e, "UPLOAD_BLUEPRINT");
+ throw cloudifyExceptionToMsoException(e, UPLOAD_BLUEPRINT);
} catch (RuntimeException e) {
// Catch-all
- throw runtimeExceptionToMsoException(e, "UPLOAD_BLUEPRINT");
+ throw runtimeExceptionToMsoException(e, UPLOAD_BLUEPRINT);
} catch (IOException e) {
// for try-with-resources
- throw ioExceptionToMsoException(e, "UPLOAD_BLUEPRINT");
+ throw ioExceptionToMsoException(e, UPLOAD_BLUEPRINT);
}
return true;
@@ -960,14 +962,14 @@ public class MsoCloudifyUtils extends MsoCommonUtils implements VduPlugin {
String type = templateParam.getParamType();
logger.debug("Parameter: {} is of type {}", templateParam.getParamName(), type);
- if (type.equalsIgnoreCase("number")) {
+ if (("number").equalsIgnoreCase(type)) {
try {
return Integer.valueOf(inputValue.toString());
} catch (Exception e) {
logger.debug("Unable to convert {} to an integer!", inputValue);
return null;
}
- } else if (type.equalsIgnoreCase("json")) {
+ } else if (("json").equalsIgnoreCase(type)) {
try {
if (inputValue instanceof String) {
return JSON_MAPPER.readTree(inputValue.toString());
@@ -978,7 +980,7 @@ public class MsoCloudifyUtils extends MsoCommonUtils implements VduPlugin {
logger.debug("Unable to convert {} to a JsonNode!", inputValue);
return null;
}
- } else if (type.equalsIgnoreCase("boolean")) {
+ } else if (("boolean").equalsIgnoreCase(type)) {
return new Boolean(inputValue.toString());
}
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/CinderClientException.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/CinderClientException.java
new file mode 100644
index 0000000000..f7f521e6f7
--- /dev/null
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/CinderClientException.java
@@ -0,0 +1,34 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.openstack.utils;
+
+public class CinderClientException extends Exception {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -6865047344405492982L;
+
+ public CinderClientException(String errorMessage, Exception e) {
+ super(errorMessage, e);
+ }
+
+}
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/CinderClientImpl.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/CinderClientImpl.java
new file mode 100644
index 0000000000..567f849b36
--- /dev/null
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/CinderClientImpl.java
@@ -0,0 +1,100 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+
+package org.onap.so.openstack.utils;
+
+import org.onap.so.cloud.authentication.KeystoneAuthHolder;
+import org.onap.so.openstack.exceptions.MsoCloudSiteNotFound;
+import org.onap.so.openstack.exceptions.MsoException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import com.woorea.openstack.base.client.OpenStackRequest;
+import com.woorea.openstack.cinder.Cinder;
+import com.woorea.openstack.cinder.model.Volume;
+import com.woorea.openstack.cinder.model.Volumes;
+
+
+
+@Component
+public class CinderClientImpl extends MsoCommonUtils {
+
+ private static final Logger logger = LoggerFactory.getLogger(CinderClientImpl.class);
+
+ /**
+ * Gets the Cinder client.
+ *
+ * @param cloudSite the cloud site
+ * @param tenantId the tenant id
+ * @return the glance client
+ * @throws MsoException the mso exception
+ */
+ private Cinder getCinderClient(String cloudSiteId, String tenantId) throws MsoException {
+ KeystoneAuthHolder keystone = getKeystoneAuthHolder(cloudSiteId, tenantId, "volumev2");
+ Cinder cinderClient = new Cinder(keystone.getServiceUrl());
+ cinderClient.token(keystone.getId());
+ return cinderClient;
+ }
+
+
+ /**
+ * Query images
+ *
+ *
+ * @param cloudSiteId the cloud site id
+ * @param tenantId the tenant id
+ * @param limit limits the number of records returned
+ * @param visibility visibility in the image in openstack
+ * @param marker the last viewed record
+ * @param name the image names
+ * @return the list of images in openstack
+ * @throws MsoCloudSiteNotFound the mso cloud site not found
+ * @throws CinderClientException the glance client exception
+ */
+ public Volumes queryVolumes(String cloudSiteId, String tenantId, int limit, String marker)
+ throws MsoCloudSiteNotFound, CinderClientException {
+ try {
+ Cinder cinderClient = getCinderClient(cloudSiteId, tenantId);
+ // list is set to false, otherwise an invalid URL is appended
+ OpenStackRequest<Volumes> request =
+ cinderClient.volumes().list(false).queryParam("limit", limit).queryParam("marker", marker);
+ return executeAndRecordOpenstackRequest(request);
+ } catch (MsoException e) {
+ logger.error("Error building Cinder Client", e);
+ throw new CinderClientException("Error building Cinder Client", e);
+ }
+ }
+
+
+ public Volume queryVolume(String cloudSiteId, String tenantId, String volumeId)
+ throws MsoCloudSiteNotFound, CinderClientException {
+ try {
+ Cinder cinderClient = getCinderClient(cloudSiteId, tenantId);
+ // list is set to false, otherwise an invalid URL is appended
+ OpenStackRequest<Volume> request = cinderClient.volumes().show(volumeId);
+ return executeAndRecordOpenstackRequest(request);
+ } catch (MsoException e) {
+ logger.error("Error building Cinder Client", e);
+ throw new CinderClientException("Error building Cinder Client", e);
+ }
+ }
+
+}
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/GlanceClientException.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/GlanceClientException.java
new file mode 100644
index 0000000000..065fb83844
--- /dev/null
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/GlanceClientException.java
@@ -0,0 +1,34 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.openstack.utils;
+
+public class GlanceClientException extends Exception {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -5202512087480589226L;
+
+ public GlanceClientException(String errorMessage, Exception e) {
+ super(errorMessage, e);
+ }
+
+}
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/GlanceClientImpl.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/GlanceClientImpl.java
new file mode 100644
index 0000000000..57faaac717
--- /dev/null
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/GlanceClientImpl.java
@@ -0,0 +1,84 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.openstack.utils;
+
+import org.onap.so.cloud.authentication.KeystoneAuthHolder;
+import org.onap.so.openstack.exceptions.MsoCloudSiteNotFound;
+import org.onap.so.openstack.exceptions.MsoException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import com.woorea.openstack.base.client.OpenStackRequest;
+import com.woorea.openstack.glance.Glance;
+import com.woorea.openstack.glance.model.Images;
+
+
+@Component
+public class GlanceClientImpl extends MsoCommonUtils {
+
+ /** The Constant logger. */
+ private static final Logger logger = LoggerFactory.getLogger(GlanceClientImpl.class);
+
+ /**
+ * Gets the glance client.
+ *
+ * @param cloudSite the cloud site
+ * @param tenantId the tenant id
+ * @return the glance client
+ * @throws MsoException the mso exception
+ */
+ private Glance getGlanceClient(String cloudSiteId, String tenantId) throws MsoException {
+ KeystoneAuthHolder keystone = getKeystoneAuthHolder(cloudSiteId, tenantId, "image");
+ Glance glanceClient = new Glance(keystone.getServiceUrl() + "/v2.0/");
+ glanceClient.token(keystone.getId());
+ return glanceClient;
+ }
+
+
+ /**
+ * Query images
+ *
+ *
+ * @param cloudSiteId the cloud site id
+ * @param tenantId the tenant id
+ * @param limit limits the number of records returned
+ * @param visibility visibility in the image in openstack
+ * @param marker the last viewed record
+ * @param name the image names
+ * @return the list of images in openstack
+ * @throws MsoCloudSiteNotFound the mso cloud site not found
+ * @throws GlanceClientException the glance client exception
+ */
+ public Images queryImages(String cloudSiteId, String tenantId, int limit, String visibility, String marker,
+ String name) throws MsoCloudSiteNotFound, GlanceClientException {
+ try {
+ Glance glanceClient = getGlanceClient(cloudSiteId, tenantId);
+ // list is set to false, otherwise an invalid URL is appended
+ OpenStackRequest<Images> request = glanceClient.images().list(false).queryParam("visibility", visibility)
+ .queryParam("limit", limit).queryParam("marker", marker).queryParam("name", name);
+ return executeAndRecordOpenstackRequest(request);
+ } catch (MsoException e) {
+ logger.error("Error building Glance Client", e);
+ throw new GlanceClientException("Error building Glance Client", e);
+ }
+ }
+
+}
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/HeatClientException.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/HeatClientException.java
new file mode 100644
index 0000000000..b49d632fdb
--- /dev/null
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/HeatClientException.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.openstack.utils;
+
+public class HeatClientException extends Exception {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -3143699004848022343L;
+
+ public HeatClientException(String errorMessage, Exception e) {
+ super(errorMessage, e);
+ }
+
+ public HeatClientException(String error) {
+ super(error);
+ }
+
+}
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoCommonUtils.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoCommonUtils.java
index c9a548d5f1..4ea205a8e1 100644
--- a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoCommonUtils.java
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoCommonUtils.java
@@ -24,24 +24,23 @@
package org.onap.so.openstack.utils;
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.woorea.openstack.base.client.OpenStackBaseException;
-import com.woorea.openstack.base.client.OpenStackConnectException;
-import com.woorea.openstack.base.client.OpenStackRequest;
-import com.woorea.openstack.base.client.OpenStackResponseException;
-import com.woorea.openstack.heat.model.CreateStackParam;
-import com.woorea.openstack.heat.model.Explanation;
-import com.woorea.openstack.keystone.model.Error;
-import com.woorea.openstack.quantum.model.NeutronError;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
+import org.onap.so.cloud.CloudConfig;
+import org.onap.so.cloud.authentication.AuthenticationMethodFactory;
+import org.onap.so.cloud.authentication.KeystoneAuthHolder;
+import org.onap.so.cloud.authentication.KeystoneV3Authentication;
+import org.onap.so.cloud.authentication.ServiceEndpointNotFoundException;
import org.onap.so.config.beans.PoConfig;
+import org.onap.so.db.catalog.beans.CloudIdentity;
+import org.onap.so.db.catalog.beans.CloudSite;
+import org.onap.so.db.catalog.beans.ServerType;
import org.onap.so.logger.ErrorCode;
import org.onap.so.logger.MessageEnum;
import org.onap.so.openstack.exceptions.MsoAdapterException;
+import org.onap.so.openstack.exceptions.MsoCloudSiteNotFound;
import org.onap.so.openstack.exceptions.MsoException;
import org.onap.so.openstack.exceptions.MsoExceptionCategory;
import org.onap.so.openstack.exceptions.MsoIOException;
@@ -50,15 +49,48 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.woorea.openstack.base.client.OpenStackBaseException;
+import com.woorea.openstack.base.client.OpenStackConnectException;
+import com.woorea.openstack.base.client.OpenStackRequest;
+import com.woorea.openstack.base.client.OpenStackResponseException;
+import com.woorea.openstack.heat.model.CreateStackParam;
+import com.woorea.openstack.heat.model.Explanation;
+import com.woorea.openstack.keystone.Keystone;
+import com.woorea.openstack.keystone.model.Access;
+import com.woorea.openstack.keystone.model.Authentication;
+import com.woorea.openstack.keystone.model.Error;
+import com.woorea.openstack.keystone.utils.KeystoneUtils;
+import com.woorea.openstack.quantum.model.NeutronError;
@Component("CommonUtils")
public class MsoCommonUtils {
private static Logger logger = LoggerFactory.getLogger(MsoCommonUtils.class);
+ /** The Constant TOKEN_AUTH. */
+ protected static final String TOKEN_AUTH = "TokenAuth";
+
+ /** The cloud config. */
+ @Autowired
+ protected CloudConfig cloudConfig;
+
+ /** The authentication method factory. */
+ @Autowired
+ protected AuthenticationMethodFactory authenticationMethodFactory;
+
+ /** The tenant utils factory. */
+ @Autowired
+ protected MsoTenantUtilsFactory tenantUtilsFactory;
+ /** The keystone V 3 authentication. */
@Autowired
- private PoConfig poConfig;
+ protected KeystoneV3Authentication keystoneV3Authentication;
+
+ @Autowired
+ protected PoConfig poConfig;
+
/*
* Method to execute an Openstack command and track its execution time. For the metrics log, a category of
* "Openstack" is used along with a sub-category that identifies the specific call (using the real
@@ -67,9 +99,6 @@ public class MsoCommonUtils {
protected <T> T executeAndRecordOpenstackRequest(OpenStackRequest<T> request) {
- int limit;
-
- long start = System.currentTimeMillis();
String requestType;
if (request.getClass().getEnclosingClass() != null) {
requestType =
@@ -98,8 +127,8 @@ public class MsoCommonUtils {
retryCount--;
retry = true;
logger.debug(
- "OpenStackResponseException ResponseCode: {} request:{} Retry indicated. Attempts remaining:{}",
- code, requestType, retryCount);
+ "OpenStackResponseException ResponseCode: {} Retry indicated. Attempts remaining:{}",
+ code, retryCount);
break;
}
} catch (NumberFormatException e1) {
@@ -123,7 +152,7 @@ public class MsoCommonUtils {
// Connection to Openstack failed
if (retryCount > 0) {
retryCount--;
- logger.debug(" request: {} Retry indicated. Attempts remaining:{}", requestType, retryCount);
+ logger.debug("Retry indicated. Attempts remaining:{}", retryCount);
try {
Thread.sleep(retryDelay * 1000L);
} catch (InterruptedException e1) {
@@ -194,40 +223,29 @@ public class MsoCommonUtils {
try {
// Failed Heat calls return an Explanation entity body.
Explanation explanation = re.getResponse().getErrorEntity(Explanation.class);
- logger.error("{} {} Exception - Openstack Error on {} : {}", MessageEnum.RA_CONNECTION_EXCEPTION,
- ErrorCode.DataError.getValue(), context, explanation.toString());
+ logger.error("Exception - Openstack Error on {} : {}", context, explanation);
String fullError = explanation.getExplanation() + ", error.type=" + explanation.getError().getType()
+ ", error.message=" + explanation.getError().getMessage();
- logger.debug(fullError);
- me = new MsoOpenstackException(explanation.getCode(), explanation.getTitle(),
- // explanation.getExplanation ());
- fullError);
+ logger.error(fullError);
+ me = new MsoOpenstackException(explanation.getCode(), explanation.getTitle(), fullError);
} catch (Exception e2) {
// Couldn't parse the body as an "Explanation". Report the original HTTP error.
logger.error("{} {} Exception - HTTP Error on {}: {}, ", MessageEnum.RA_CONNECTION_EXCEPTION,
ErrorCode.DataError.getValue(), context, re.getStatus(), e.getMessage(), e2);
- me = new MsoOpenstackException(re.getStatus(), re.getMessage(), "");
+ me = new MsoOpenstackException(re.getStatus(), re.getMessage(), re.getMessage());
}
// Add the context of the error
me.addContext(context);
- // Generate an alarm for 5XX and higher errors.
- if (re.getStatus() >= 500) {
-
- }
} else if (e instanceof OpenStackConnectException) {
OpenStackConnectException ce = (OpenStackConnectException) e;
-
me = new MsoIOException(ce.getMessage());
me.addContext(context);
-
// Generate an alarm for all connection errors.
-
logger.error("{} {} Openstack Heat connection error on {}: ", MessageEnum.RA_CONNECTION_EXCEPTION,
ErrorCode.DataError.getValue(), context, e);
}
-
return me;
}
@@ -404,4 +422,79 @@ public class MsoCommonUtils {
return stack;
}
+
+ /**
+ * Gets the Keystone Authorization
+ *
+ * @param cloudSite the cloud site
+ * @param tenantId the tenant id
+ * @return the Neutron client
+ * @throws MsoException the mso exception
+ */
+ protected KeystoneAuthHolder getKeystoneAuthHolder(String cloudSiteId, String tenantId, String serviceName)
+ throws MsoException {
+ CloudSite cloudSite =
+ cloudConfig.getCloudSite(cloudSiteId).orElseThrow(() -> new MsoCloudSiteNotFound(cloudSiteId));
+ String cloudId = cloudSite.getId();
+ String region = cloudSite.getRegionId();
+ CloudIdentity cloudIdentity = cloudSite.getIdentityService();
+ MsoTenantUtils tenantUtils =
+ tenantUtilsFactory.getTenantUtilsByServerType(cloudIdentity.getIdentityServerType());
+ String keystoneUrl = tenantUtils.getKeystoneUrl(cloudId, cloudIdentity);
+ try {
+ if (ServerType.KEYSTONE.equals(cloudIdentity.getIdentityServerType())) {
+ Access access = getKeystone(tenantId, cloudIdentity, keystoneUrl);
+ try {
+ KeystoneAuthHolder keystoneAuthV2 = new KeystoneAuthHolder();
+ keystoneAuthV2.setServiceUrl(
+ KeystoneUtils.findEndpointURL(access.getServiceCatalog(), serviceName, region, "public"));
+ keystoneAuthV2.setId(access.getToken().getId());
+ return keystoneAuthV2;
+ } catch (RuntimeException e) {
+ String error = "Openstack did not match an orchestration service for: region=" + region + ",cloud="
+ + cloudIdentity.getIdentityUrl();
+ throw new MsoAdapterException(error, e);
+ }
+ } else if (ServerType.KEYSTONE_V3.equals(cloudIdentity.getIdentityServerType())) {
+ try {
+ return keystoneV3Authentication.getToken(cloudSite, tenantId, serviceName);
+ } catch (ServiceEndpointNotFoundException e) {
+ String error = "cloud did not match an orchestration service for: region=" + region + ",cloud="
+ + cloudIdentity.getIdentityUrl();
+ throw new MsoAdapterException(error, e);
+ }
+ } else {
+ throw new MsoAdapterException("Unknown Keystone Server Type");
+ }
+ } catch (OpenStackResponseException e) {
+ if (e.getStatus() == 401) {
+ String error = "Authentication Failure: tenant=" + tenantId + ",cloud=" + cloudIdentity.getId();
+ throw new MsoAdapterException(error);
+ } else {
+ throw keystoneErrorToMsoException(e, TOKEN_AUTH);
+ }
+ } catch (OpenStackConnectException e) {
+ MsoIOException me = new MsoIOException(e.getMessage(), e);
+ me.addContext(TOKEN_AUTH);
+ throw me;
+ } catch (RuntimeException e) {
+ throw runtimeExceptionToMsoException(e, TOKEN_AUTH);
+ }
+ }
+
+ /**
+ * @param tenantId
+ * @param cloudIdentity
+ * @param keystoneUrl
+ * @return
+ */
+ protected Access getKeystone(String tenantId, CloudIdentity cloudIdentity, String keystoneUrl) {
+ Keystone keystoneTenantClient = new Keystone(keystoneUrl);
+ Access access = null;
+ Authentication credentials = authenticationMethodFactory.getAuthenticationFor(cloudIdentity);
+ OpenStackRequest<Access> request =
+ keystoneTenantClient.tokens().authenticate(credentials).withTenantId(tenantId);
+ access = executeAndRecordOpenstackRequest(request);
+ return access;
+ }
}
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoHeatEnvironmentEntry.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoHeatEnvironmentEntry.java
index a21db78cee..723bed17f7 100644
--- a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoHeatEnvironmentEntry.java
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoHeatEnvironmentEntry.java
@@ -70,7 +70,7 @@ public class MsoHeatEnvironmentEntry {
logger.debug("Exception:", e);
this.valid = false;
this.errorString = e.getMessage();
- // e.printStackTrace();
+
}
}
@@ -173,7 +173,7 @@ public class MsoHeatEnvironmentEntry {
// Basically give back the envt - but exclude the params that aren't in the HeatTemplate
StringBuilder sb = new StringBuilder();
- ArrayList<String> paramNameList = new ArrayList<String>(params.size());
+ ArrayList<String> paramNameList = new ArrayList<>(params.size());
for (HeatTemplateParam htp : params) {
paramNameList.add(htp.getParamName());
}
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoHeatUtils.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoHeatUtils.java
index b54301509f..bf6374bc2f 100644
--- a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoHeatUtils.java
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoHeatUtils.java
@@ -23,30 +23,17 @@
package org.onap.so.openstack.utils;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.woorea.openstack.base.client.OpenStackConnectException;
-import com.woorea.openstack.base.client.OpenStackRequest;
-import com.woorea.openstack.base.client.OpenStackResponseException;
-import com.woorea.openstack.heat.Heat;
-import com.woorea.openstack.heat.model.CreateStackParam;
-import com.woorea.openstack.heat.model.Resources;
-import com.woorea.openstack.heat.model.Stack;
-import com.woorea.openstack.heat.model.Stack.Output;
-import com.woorea.openstack.heat.model.Stacks;
-import com.woorea.openstack.keystone.Keystone;
-import com.woorea.openstack.keystone.model.Access;
-import com.woorea.openstack.keystone.model.Authentication;
-import com.woorea.openstack.keystone.utils.KeystoneUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import org.onap.logging.ref.slf4j.ONAPLogConstants;
import org.onap.so.adapters.vdu.CloudInfo;
import org.onap.so.adapters.vdu.PluginAction;
import org.onap.so.adapters.vdu.VduArtifact;
@@ -58,48 +45,68 @@ import org.onap.so.adapters.vdu.VduPlugin;
import org.onap.so.adapters.vdu.VduStateType;
import org.onap.so.adapters.vdu.VduStatus;
import org.onap.so.cloud.CloudConfig;
-import org.onap.so.cloud.authentication.AuthenticationMethodFactory;
import org.onap.so.cloud.authentication.KeystoneAuthHolder;
-import org.onap.so.cloud.authentication.KeystoneV3Authentication;
-import org.onap.so.cloud.authentication.ServiceEndpointNotFoundException;
import org.onap.so.db.catalog.beans.CloudIdentity;
import org.onap.so.db.catalog.beans.CloudSite;
import org.onap.so.db.catalog.beans.HeatTemplate;
import org.onap.so.db.catalog.beans.HeatTemplateParam;
-import org.onap.so.db.catalog.beans.ServerType;
+import org.onap.so.db.request.beans.CloudApiRequests;
+import org.onap.so.db.request.beans.InfraActiveRequests;
+import org.onap.so.db.request.client.RequestsDbClient;
import org.onap.so.logger.ErrorCode;
import org.onap.so.logger.MessageEnum;
import org.onap.so.openstack.beans.HeatStatus;
import org.onap.so.openstack.beans.StackInfo;
-import org.onap.so.openstack.exceptions.MsoAdapterException;
import org.onap.so.openstack.exceptions.MsoCloudSiteNotFound;
import org.onap.so.openstack.exceptions.MsoException;
-import org.onap.so.openstack.exceptions.MsoIOException;
import org.onap.so.openstack.exceptions.MsoOpenstackException;
import org.onap.so.openstack.exceptions.MsoStackAlreadyExists;
import org.onap.so.openstack.exceptions.MsoTenantNotFound;
import org.onap.so.openstack.mappers.StackInfoMapper;
-import org.onap.so.utils.CryptoUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.base.Strings;
+import com.woorea.openstack.base.client.OpenStackConnectException;
+import com.woorea.openstack.base.client.OpenStackRequest;
+import com.woorea.openstack.base.client.OpenStackResponseException;
+import com.woorea.openstack.heat.Heat;
+import com.woorea.openstack.heat.model.CreateStackParam;
+import com.woorea.openstack.heat.model.Events;
+import com.woorea.openstack.heat.model.Resource;
+import com.woorea.openstack.heat.model.Resources;
+import com.woorea.openstack.heat.model.Stack;
+import com.woorea.openstack.heat.model.Stack.Output;
+import com.woorea.openstack.heat.model.Stacks;
+
@Primary
@Component
public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin {
- private static final String TOKEN_AUTH = "TokenAuth";
+ private static final String CREATE_COMPLETE = "CREATE_COMPLETE";
+
+ private static final String DELETE_COMPLETE = "DELETE_COMPLETE";
- private static final String QUERY_ALL_STACKS = "QueryAllStacks";
+ private static final String DELETE_IN_PROGRESS = "DELETE_IN_PROGRESS";
+
+ private static final String CREATE_IN_PROGRESS = "CREATE_IN_PROGRESS";
private static final String DELETE_STACK = "DeleteStack";
protected static final String HEAT_ERROR = "HeatError";
protected static final String CREATE_STACK = "CreateStack";
+ public static final String FOUND = "Found: {}";
+ public static final String EXCEPTION_ROLLING_BACK_STACK =
+ "{} Create Stack: Nested exception rolling back stack: {} ";
+ public static final String IN_PROGRESS = "in_progress";
// Fetch cloud configuration each time (may be cached in CloudConfig class)
@Autowired
@@ -109,13 +116,13 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin {
private Environment environment;
@Autowired
- private AuthenticationMethodFactory authenticationMethodFactory;
+ RequestsDbClient requestDBClient;
@Autowired
- private MsoTenantUtilsFactory tenantUtilsFactory;
+ StackStatusHandler statusHandler;
@Autowired
- private KeystoneV3Authentication keystoneV3Authentication;
+ NovaClientImpl novaClient;
private static final Logger logger = LoggerFactory.getLogger(MsoHeatUtils.class);
@@ -123,9 +130,11 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin {
protected String createPollIntervalProp = "org.onap.so.adapters.po.pollInterval";
private String deletePollIntervalProp = "org.onap.so.adapters.po.pollInterval";
private String deletePollTimeoutProp = "org.onap.so.adapters.po.pollTimeout";
+ private String pollingMultiplierProp = "org.onap.so.adapters.po.pollMultiplier";
- protected static final String createPollIntervalDefault = "15";
- private static final String deletePollIntervalDefault = "15";
+ protected static final String CREATE_POLL_INTERVAL_DEFAULT = "15";
+ private static final String DELETE_POLL_INTERVAL_DEFAULT = "15";
+ private static final String pollingMultiplierDefault = "60";
private static final ObjectMapper JSON_MAPPER = new ObjectMapper();
@@ -210,6 +219,26 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin {
int timeoutMinutes, String environment, Map<String, Object> files, Map<String, Object> heatFiles,
boolean backout) throws MsoException {
+ stripMultiCloudInputs(stackInputs);
+
+ CreateStackParam createStack =
+ createStackParam(stackName, heatTemplate, stackInputs, timeoutMinutes, environment, files, heatFiles);
+ Stack currentStack = createStack(createStack, cloudSiteId, tenantId);
+ currentStack.setStackName(stackName);
+ if (pollForCompletion) {
+ currentStack =
+ processCreateStack(cloudSiteId, tenantId, timeoutMinutes, backout, currentStack, createStack, true);
+ } else {
+ currentStack =
+ queryHeatStack(currentStack.getStackName() + "/" + currentStack.getId(), cloudSiteId, tenantId);
+ }
+ return new StackInfoMapper(currentStack).map();
+ }
+
+ /**
+ * @param stackInputs
+ */
+ protected void stripMultiCloudInputs(Map<String, ?> stackInputs) {
// Take out the multicloud inputs, if present.
for (String key : MsoMulticloudUtils.MULTICLOUD_INPUTS) {
if (stackInputs.containsKey(key)) {
@@ -219,35 +248,20 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin {
}
}
}
+ }
- CreateStackParam stack =
- createStackParam(stackName, heatTemplate, stackInputs, timeoutMinutes, environment, files, heatFiles);
-
- // Obtain the cloud site information where we will create the stack
- CloudSite cloudSite =
- cloudConfig.getCloudSite(cloudSiteId).orElseThrow(() -> new MsoCloudSiteNotFound(cloudSiteId));
- logger.debug("Found: {}", cloudSite);
- // Get a Heat client. They are cached between calls (keyed by tenantId:cloudId)
- // This could throw MsoTenantNotFound or MsoOpenstackException (both propagated)
- Heat heatClient = getHeatClient(cloudSite, tenantId);
- logger.debug("Found: {}", heatClient);
-
- logger.debug("Ready to Create Stack ({}) with input params: {}", heatTemplate, stackInputs);
-
- Stack heatStack = null;
+ protected Stack createStack(CreateStackParam stack, String cloudSiteId, String tenantId) throws MsoException {
try {
- OpenStackRequest<Stack> request = heatClient.getStacks().create(stack);
- CloudIdentity cloudIdentity = cloudSite.getIdentityService();
- request.header("X-Auth-User", cloudIdentity.getMsoId());
- request.header("X-Auth-Key", CryptoUtils.decryptCloudConfigPassword(cloudIdentity.getMsoPass()));
- heatStack = executeAndRecordOpenstackRequest(request);
+ OpenStackRequest<Stack> request = getHeatClient(cloudSiteId, tenantId).getStacks().create(stack);
+ saveStackRequest(request, MDC.get(ONAPLogConstants.MDCs.REQUEST_ID), stack.getStackName());
+ return executeAndRecordOpenstackRequest(request);
} catch (OpenStackResponseException e) {
if (e.getStatus() == 409) {
- MsoStackAlreadyExists me = new MsoStackAlreadyExists(stackName, tenantId, cloudSiteId);
+ MsoStackAlreadyExists me = new MsoStackAlreadyExists(stack.getStackName(), tenantId, cloudSiteId);
me.addContext(CREATE_STACK);
throw me;
} else {
- logger.debug("ERROR STATUS = {},\n{}\n{}", e.getStatus(), e.getMessage(), e.getLocalizedMessage());
+ logger.error("ERROR STATUS = {},\n{}\n{}", e.getStatus(), e.getMessage(), e.getLocalizedMessage());
throw heatExceptionToMsoException(e, CREATE_STACK);
}
} catch (OpenStackConnectException e) {
@@ -255,225 +269,147 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin {
} catch (RuntimeException e) {
throw runtimeExceptionToMsoException(e, CREATE_STACK);
}
+ }
- // Subsequent access by the canonical name "<stack name>/<stack-id>".
- // Otherwise, simple query by name returns a 302 redirect.
- // NOTE: This is specific to the v1 Orchestration API.
- String canonicalName = stackName + "/" + heatStack.getId();
+ protected Stack processCreateStack(String cloudSiteId, String tenantId, int timeoutMinutes, boolean backout,
+ Stack heatStack, CreateStackParam stackCreate, boolean keyPairCleanUp) throws MsoException {
+ Stack latestStack;
+ try {
+ latestStack = pollStackForStatus(timeoutMinutes, heatStack, CREATE_IN_PROGRESS, cloudSiteId, tenantId);
+ } catch (MsoException me) {
+ if (!backout) {
+ logger.info("Exception in Create Stack, stack deletion suppressed", me);
+ } else {
+ logger.info("Exception in Create Stack, stack deletion will be executed", me);
+ handleUnknownCreateStackFailure(heatStack, timeoutMinutes, cloudSiteId, tenantId);
+ }
+ me.addContext(CREATE_STACK);
+ throw me;
+ }
+ return postProcessStackCreate(latestStack, backout, timeoutMinutes, keyPairCleanUp, cloudSiteId, tenantId,
+ stackCreate);
+ }
- if (pollForCompletion) {
- heatStack = pollStackForCompletion(cloudSiteId, tenantId, stackName, timeoutMinutes, backout, heatClient,
- heatStack, canonicalName);
+ protected Stack postProcessStackCreate(Stack stack, boolean backout, int timeoutMinutes, boolean cleanUpKeyPair,
+ String cloudSiteId, String tenantId, CreateStackParam stackCreate) throws MsoException {
+ logger.info("Performing post processing backout: {} cleanUpKeyPair: {}, stack {}", backout, cleanUpKeyPair,
+ stack);
+ if (!CREATE_COMPLETE.equals(stack.getStackStatus())) {
+ if (cleanUpKeyPair && !Strings.isNullOrEmpty(stack.getStackStatusReason())
+ && isKeyPairFailure(stack.getStackStatusReason())) {
+ return handleKeyPairConflict(cloudSiteId, tenantId, stackCreate, timeoutMinutes, backout, stack);
+ }
+ if (!backout) {
+ logger.info("Status is not CREATE_COMPLETE, stack deletion suppressed");
+ throw new StackCreationException("Stack rollback suppressed, stack not deleted");
+ } else {
+ logger.info("Status is not CREATE_COMPLETE, stack deletion will be executed");
+ Stack deletedStack = handleUnknownCreateStackFailure(stack, timeoutMinutes, cloudSiteId, tenantId);
+ throw new StackCreationException("Stack Creation Failed Openstack Status: " + stack.getStackStatus()
+ + " Status Reason: " + stack.getStackStatusReason()
+ + " , Rollback of Stack Creation completed with status: " + deletedStack.getStackStatus()
+ + " Status Reason: " + deletedStack.getStackStatusReason());
+ }
} else {
- // Get initial status, since it will have been null after the create.
- heatStack = queryHeatStack(heatClient, canonicalName);
- logger.debug(heatStack.getStackStatus());
+ return stack;
}
- return new StackInfoMapper(heatStack).map();
}
- private Stack pollStackForCompletion(String cloudSiteId, String tenantId, String stackName, int timeoutMinutes,
- boolean backout, Heat heatClient, Stack heatStack, String canonicalName)
- throws MsoException, MsoOpenstackException {
- int createPollInterval =
- Integer.parseInt(this.environment.getProperty(createPollIntervalProp, createPollIntervalDefault));
- int pollTimeout = (timeoutMinutes * 60) + createPollInterval;
- int deletePollInterval = createPollInterval;
- int deletePollTimeout = pollTimeout;
- boolean createTimedOut = false;
- StringBuilder stackErrorStatusReason = new StringBuilder("");
- logger.debug("createPollInterval={}, pollTimeout={}", createPollInterval, pollTimeout);
-
+ protected Stack pollStackForStatus(int timeoutMinutes, Stack stack, String stackStatus, String cloudSiteId,
+ String tenantId) throws MsoException {
+ int pollingFrequency =
+ Integer.parseInt(this.environment.getProperty(createPollIntervalProp, CREATE_POLL_INTERVAL_DEFAULT));
+ int pollingMultiplier =
+ Integer.parseInt(this.environment.getProperty(pollingMultiplierProp, pollingMultiplierDefault));
+ int numberOfPollingAttempts = Math.floorDiv((timeoutMinutes * pollingMultiplier), pollingFrequency);
+ Heat heatClient = getHeatClient(cloudSiteId, tenantId);
+ Stack latestStack = null;
while (true) {
- try {
- heatStack = queryHeatStack(heatClient, canonicalName);
- logger.debug("{} ({})", heatStack.getStackStatus(), canonicalName);
- try {
- logger.debug("Current stack {}", this.getOutputsAsStringBuilder(heatStack).toString());
- } catch (Exception e) {
- logger.debug("an error occurred trying to print out the current outputs of the stack", e);
- }
-
- if ("CREATE_IN_PROGRESS".equals(heatStack.getStackStatus())) {
- if (pollTimeout <= 0) {
- logger.error("{} Cloud site: {} Tenant: {} Stack: {} Stack status: {} {} Create stack timeout",
- MessageEnum.RA_CREATE_STACK_TIMEOUT, cloudSiteId, tenantId, stackName,
- heatStack.getStackStatus(), ErrorCode.AvailabilityError.getValue());
- createTimedOut = true;
- break;
- }
- sleep(createPollInterval * 1000L);
- pollTimeout -= createPollInterval;
- logger.debug("pollTimeout remaining: {}", pollTimeout);
- } else {
- stackErrorStatusReason.append(
- "Stack error (" + heatStack.getStackStatus() + "): " + heatStack.getStackStatusReason());
- break;
+ latestStack = queryHeatStack(heatClient, stack.getStackName() + "/" + stack.getId());
+ statusHandler.updateStackStatus(stack);
+ logger.debug("Polling: {} ({})", latestStack.getStackStatus(), latestStack.getStackName());
+ if (stackStatus.equals(latestStack.getStackStatus())) {
+ if (numberOfPollingAttempts <= 0) {
+ logger.error("Polling of stack timed out with Status: {}", latestStack.getStackStatus());
+ return latestStack;
}
- } catch (MsoException me) {
- // Cannot query the stack status. Something is wrong.
- // Try to roll back the stack
- if (!backout) {
- logger.warn("{} Exception in Create Stack, stack deletion suppressed {}",
- MessageEnum.RA_CREATE_STACK_ERR, ErrorCode.BusinessProcesssError.getValue());
- } else {
- try {
- logger.debug(
- "Create Stack error - unable to query for stack status - attempting to delete stack: {}"
- + " - This will likely fail and/or we won't be able to query to see if delete worked",
- canonicalName);
- OpenStackRequest<Void> request = heatClient.getStacks().deleteByName(canonicalName);
- executeAndRecordOpenstackRequest(request);
- boolean deleted = false;
- while (!deleted) {
- try {
- heatStack = queryHeatStack(heatClient, canonicalName);
- if (heatStack != null) {
- logger.debug(heatStack.getStackStatus());
- if ("DELETE_IN_PROGRESS".equals(heatStack.getStackStatus())) {
- if (deletePollTimeout <= 0) {
- logger.error(
- "{} Cloud site: {} Tenant: {} Stack: {} Stack status: {} {} Rollback: DELETE stack timeout",
- MessageEnum.RA_CREATE_STACK_TIMEOUT, cloudSiteId, tenantId,
- stackName, heatStack.getStackStatus(),
- ErrorCode.AvailabilityError.getValue());
- break;
- } else {
- sleep(deletePollInterval * 1000L);
- deletePollTimeout -= deletePollInterval;
- }
- } else if ("DELETE_COMPLETE".equals(heatStack.getStackStatus())) {
- logger.debug("DELETE_COMPLETE for {}", canonicalName);
- deleted = true;
- continue;
- } else {
- // got a status other than DELETE_IN_PROGRESS or DELETE_COMPLETE - so break and
- // evaluate
- break;
- }
- } else {
- // assume if we can't find it - it's deleted
- logger.debug("heatStack returned null - assume the stack {} has been deleted",
- canonicalName);
- deleted = true;
- continue;
- }
-
- } catch (Exception e3) {
- // Just log this one. We will report the original exception.
- logger.error("{} Create Stack: Nested exception rolling back stack: {} ",
- MessageEnum.RA_CREATE_STACK_ERR, ErrorCode.BusinessProcesssError.getValue(),
- e3);
- }
- }
- } catch (Exception e2) {
- // Just log this one. We will report the original exception.
- logger.error("{} Create Stack: Nested exception rolling back stack: {} ",
- MessageEnum.RA_CREATE_STACK_ERR, ErrorCode.BusinessProcesssError.getValue(), e2);
- }
- }
-
- // Propagate the original exception from Stack Query.
- me.addContext(CREATE_STACK);
- throw me;
+ sleep(pollingFrequency * 1000L);
+ numberOfPollingAttempts -= 1;
+ } else {
+ return latestStack;
}
}
+ }
- if (!"CREATE_COMPLETE".equals(heatStack.getStackStatus())) {
- logger.error("{} Create Stack error: Polling complete with non-success status: {}, {} {} ",
- MessageEnum.RA_CREATE_STACK_ERR, heatStack.getStackStatus(), heatStack.getStackStatusReason(),
- ErrorCode.BusinessProcesssError.getValue());
-
- // Rollback the stack creation, since it is in an indeterminate state.
- if (!backout) {
- logger.warn(
- "{} Create Stack errored, stack deletion suppressed {} Create Stack error, stack deletion suppressed",
- MessageEnum.RA_CREATE_STACK_ERR, ErrorCode.BusinessProcesssError.getValue());
+ protected void saveStackRequest(OpenStackRequest<Stack> request, String requestId, String stackName) {
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ InfraActiveRequests foundRequest = requestDBClient.getInfraActiveRequestbyRequestId(requestId);
+ String stackRequest = mapper.writeValueAsString(request.entity());
+ CloudApiRequests cloudReq = new CloudApiRequests();
+ cloudReq.setCloudIdentifier(stackName);
+ cloudReq.setRequestBody(stackRequest);
+ cloudReq.setRequestId(requestId);
+ CloudApiRequests foundCloudReq = foundRequest.getCloudApiRequests().stream()
+ .filter(cloudReqToFind -> stackName.equals(cloudReq.getCloudIdentifier())).findAny().orElse(null);
+ if (foundCloudReq != null) {
+ foundCloudReq.setRequestBody(stackRequest);
} else {
- try {
- logger.debug("Create Stack errored - attempting to DELETE stack: {}", canonicalName);
- logger.debug("deletePollInterval={}, deletePollTimeout={}", deletePollInterval, deletePollTimeout);
- OpenStackRequest<Void> request = heatClient.getStacks().deleteByName(canonicalName);
- executeAndRecordOpenstackRequest(request);
- boolean deleted = false;
- while (!deleted) {
- try {
- heatStack = queryHeatStack(heatClient, canonicalName);
- if (heatStack != null) {
- logger.debug("{} ({})", heatStack.getStackStatus(), canonicalName);
- if ("DELETE_IN_PROGRESS".equals(heatStack.getStackStatus())) {
- if (deletePollTimeout <= 0) {
- logger.error(
- "{} Cloud site: {} Tenant: {} Stack: {} Stack status: {} {} Rollback: DELETE stack timeout",
- MessageEnum.RA_CREATE_STACK_TIMEOUT, cloudSiteId, tenantId, stackName,
- heatStack.getStackStatus(), ErrorCode.AvailabilityError.getValue());
- break;
- } else {
- sleep(deletePollInterval * 1000L);
- deletePollTimeout -= deletePollInterval;
- logger.debug("deletePollTimeout remaining: {}", deletePollTimeout);
- }
- } else if ("DELETE_COMPLETE".equals(heatStack.getStackStatus())) {
- logger.debug("DELETE_COMPLETE for {}", canonicalName);
- deleted = true;
- continue;
- } else if ("DELETE_FAILED".equals(heatStack.getStackStatus())) {
- // Warn about this (?) - but still throw the original exception
- logger.warn(
- "{} Create Stack errored, stack deletion FAILED {} Create Stack error, stack deletion FAILED",
- MessageEnum.RA_CREATE_STACK_ERR,
- ErrorCode.BusinessProcesssError.getValue());
- logger.debug(
- "Stack deletion FAILED on a rollback of a create - {}, status={}, reason={}",
- canonicalName, heatStack.getStackStatus(),
- heatStack.getStackStatusReason());
- break;
- } else {
- // got a status other than DELETE_IN_PROGRESS or DELETE_COMPLETE - so break and
- // evaluate
- break;
- }
- } else {
- // assume if we can't find it - it's deleted
- logger.debug("heatStack returned null - assume the stack {} has been deleted",
- canonicalName);
- deleted = true;
- continue;
- }
-
- } catch (MsoException me2) {
- // We got an exception on the delete - don't throw this exception - throw the original -
- // just log.
- logger.debug("Exception thrown trying to delete {} on a create->rollback: {} ",
- canonicalName, me2.getContextMessage(), me2);
- logger.warn("{} Create Stack errored, then stack deletion FAILED - exception thrown {} {}",
- MessageEnum.RA_CREATE_STACK_ERR, ErrorCode.BusinessProcesssError.getValue(),
- me2.getContextMessage());
- }
-
- } // end while !deleted
- StringBuilder errorContextMessage;
- if (createTimedOut) {
- errorContextMessage = new StringBuilder("Stack Creation Timeout");
- } else {
- errorContextMessage = stackErrorStatusReason;
- }
- if (deleted) {
- errorContextMessage.append(" - stack successfully deleted");
- } else {
- errorContextMessage.append(" - encountered an error trying to delete the stack");
- }
- } catch (Exception e2) {
- // shouldn't happen - but handle
- logger.error("{} Create Stack: Nested exception rolling back stack: {} ",
- MessageEnum.RA_CREATE_STACK_ERR, ErrorCode.BusinessProcesssError.getValue(), e2);
- }
+ foundRequest.getCloudApiRequests().add(cloudReq);
}
- MsoOpenstackException me = new MsoOpenstackException(0, "", stackErrorStatusReason.toString());
- me.addContext(CREATE_STACK);
- throw me;
+ requestDBClient.updateInfraActiveRequests(foundRequest);
+ } catch (Exception e) {
+ logger.error("Error updating in flight request with Openstack Create Request", e);
+ }
+ }
+
+ protected boolean isKeyPairFailure(String errorMessage) {
+ return Pattern.compile(".*Key pair.*already exists.*").matcher(errorMessage).matches();
+ }
+
+ protected Stack handleUnknownCreateStackFailure(Stack stack, int timeoutMinutes, String cloudSiteId,
+ String tenantId) throws MsoException {
+ if (stack != null && !Strings.isNullOrEmpty(stack.getStackName()) && !Strings.isNullOrEmpty(stack.getId())) {
+ OpenStackRequest<Void> request = getHeatClient(cloudSiteId, tenantId).getStacks()
+ .deleteByName(stack.getStackName() + "/" + stack.getId());
+ executeAndRecordOpenstackRequest(request);
+ Stack currentStack = pollStackForStatus(timeoutMinutes, stack, DELETE_IN_PROGRESS, cloudSiteId, tenantId);
+ postProcessStackDelete(currentStack);
+ return currentStack;
+ } else {
+ throw new StackCreationException("Cannot Find Stack Name or Id");
}
- return heatStack;
+ }
+
+ protected void postProcessStackDelete(Stack stack) throws MsoException {
+ logger.info("Performing post processing on delete stack {}", stack);
+ if (stack != null && !Strings.isNullOrEmpty(stack.getStackStatus())) {
+ if (!DELETE_COMPLETE.equals(stack.getStackStatus()))
+ throw new StackRollbackException("Stack Deletion completed with status: " + stack.getStackStatus()
+ + " Status Reason: " + stack.getStackStatusReason());
+ } else {
+ throw new StackRollbackException("Cannot Find Stack Name or Id");
+ }
+ }
+
+ protected Stack handleKeyPairConflict(String cloudSiteId, String tenantId, CreateStackParam stackCreate,
+ int timeoutMinutes, boolean backout, Stack stack) throws MsoException {
+ logger.info("Keypair conflict found on stack, attempting to clean up");
+
+ Resources resources = queryStackResources(cloudSiteId, tenantId, stackCreate.getStackName(), 2);
+ List<Resource> keyPairs = resources.getList().stream()
+ .filter(p -> "OS::Nova::KeyPair".equalsIgnoreCase(p.getType())).collect(Collectors.toList());
+ keyPairs.stream().forEach(keyPair -> {
+ try {
+ novaClient.deleteKeyPair(cloudSiteId, tenantId, keyPair.getPhysicalResourceId());
+ } catch (MsoCloudSiteNotFound | NovaClientException e) {
+ logger.warn("Could not delete keypair", e);
+ }
+ });
+ handleUnknownCreateStackFailure(stack, timeoutMinutes, cloudSiteId, tenantId);
+ Stack newStack = createStack(stackCreate, cloudSiteId, tenantId);
+ newStack.setStackName(stackCreate.getStackName());
+ return processCreateStack(cloudSiteId, tenantId, timeoutMinutes, backout, newStack, stackCreate, false);
}
/**
@@ -490,19 +426,9 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin {
public StackInfo queryStack(String cloudSiteId, String cloudOwner, String tenantId, String stackName)
throws MsoException {
logger.debug("Query HEAT stack: {} in tenant {}", stackName, tenantId);
-
- // Obtain the cloud site information where we will create the stack
- CloudSite cloudSite =
- cloudConfig.getCloudSite(cloudSiteId).orElseThrow(() -> new MsoCloudSiteNotFound(cloudSiteId));
- logger.debug("Found: {}", cloudSite.toString());
-
- // Get a Heat client. They are cached between calls (keyed by tenantId:cloudId)
Heat heatClient = null;
try {
- heatClient = getHeatClient(cloudSite, tenantId);
- if (heatClient != null) {
- logger.debug("Found: {}", heatClient.toString());
- }
+ heatClient = getHeatClient(cloudSiteId, tenantId);
} catch (MsoTenantNotFound e) {
// Tenant doesn't exist, so stack doesn't either
logger.debug("Tenant with id " + tenantId + "not found.", e);
@@ -550,24 +476,13 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin {
*/
public StackInfo deleteStack(String tenantId, String cloudOwner, String cloudSiteId, String stackName,
boolean pollForCompletion) throws MsoException {
- // Obtain the cloud site information where we will create the stack
- CloudSite cloudSite =
- cloudConfig.getCloudSite(cloudSiteId).orElseThrow(() -> new MsoCloudSiteNotFound(cloudSiteId));
- logger.debug("Found: {}", cloudSite.toString());
-
- // Get a Heat client. They are cached between calls (keyed by tenantId:cloudId)
Heat heatClient = null;
try {
- heatClient = getHeatClient(cloudSite, tenantId);
- if (heatClient != null) {
- logger.debug("Found: {}", heatClient.toString());
- }
+ heatClient = getHeatClient(cloudSiteId, tenantId);
} catch (MsoTenantNotFound e) {
- // Tenant doesn't exist, so stack doesn't either
logger.debug("Tenant with id " + tenantId + "not found.", e);
return new StackInfo(stackName, HeatStatus.NOTFOUND);
} catch (MsoException me) {
- // Got an Openstack error. Propagate it
logger.error("{} {} Openstack Exception on Token request: ", MessageEnum.RA_CONNECTION_EXCEPTION,
ErrorCode.AvailabilityError.getValue(), me);
me.addContext(DELETE_STACK);
@@ -576,13 +491,11 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin {
// OK if stack not found, perform a query first
Stack heatStack = queryHeatStack(heatClient, stackName);
- if (heatStack == null || "DELETE_COMPLETE".equals(heatStack.getStackStatus())) {
+ if (heatStack == null || DELETE_COMPLETE.equals(heatStack.getStackStatus())) {
// Not found. Return a StackInfo with status NOTFOUND
return new StackInfo(stackName, HeatStatus.NOTFOUND);
}
- // Delete the stack.
-
// Use canonical name "<stack name>/<stack-id>" to delete.
// Otherwise, deletion by name returns a 302 redirect.
// NOTE: This is specific to the v1 Orchestration API.
@@ -595,7 +508,6 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin {
} else {
logger.debug("Heat Client is NULL");
}
-
executeAndRecordOpenstackRequest(request);
} catch (OpenStackResponseException e) {
if (e.getStatus() == 404) {
@@ -616,18 +528,16 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin {
// Requery the stack for current status.
// It will probably still exist with "DELETE_IN_PROGRESS" status.
heatStack = queryHeatStack(heatClient, canonicalName);
-
+ statusHandler.updateStackStatus(heatStack);
if (pollForCompletion) {
- // Set a timeout on polling
-
int pollInterval = Integer
- .parseInt(this.environment.getProperty(deletePollIntervalProp, "" + deletePollIntervalDefault));
+ .parseInt(this.environment.getProperty(deletePollIntervalProp, "" + DELETE_POLL_INTERVAL_DEFAULT));
int pollTimeout = Integer
- .parseInt(this.environment.getProperty(deletePollTimeoutProp, "" + deletePollIntervalDefault));
-
+ .parseInt(this.environment.getProperty(deletePollTimeoutProp, "" + DELETE_POLL_INTERVAL_DEFAULT));
+ statusHandler.updateStackStatus(heatStack);
// When querying by canonical name, Openstack returns DELETE_COMPLETE status
// instead of "404" (which would result from query by stack name).
- while (heatStack != null && !"DELETE_COMPLETE".equals(heatStack.getStackStatus())) {
+ while (heatStack != null && !DELETE_COMPLETE.equals(heatStack.getStackStatus())) {
logger.debug("Stack status: {}", heatStack.getStackStatus());
if ("DELETE_FAILED".equals(heatStack.getStackStatus())) {
@@ -669,67 +579,13 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin {
// The stack is gone when this point is reached
return new StackInfo(stackName, HeatStatus.NOTFOUND);
}
-
// Return the current status (if not polling, the delete may still be in progress)
StackInfo stackInfo = new StackInfoMapper(heatStack).map();
stackInfo.setName(stackName);
-
return stackInfo;
}
/**
- * Query for all stacks in a tenant site. This call will return a List of StackInfo objects, one for each deployed
- * stack.
- *
- * Note that this is limited to a single site. To ensure that a tenant is truly empty would require looping across
- * all tenant endpoints.
- *
- * @param tenantId The Openstack ID of the tenant to query
- * @param cloudSiteId The cloud identifier (may be a region) in which to query.
- * @return A List of StackInfo objects
- * @throws MsoOpenstackException Thrown if the Openstack API call returns an exception.
- * @throws MsoCloudSiteNotFound
- */
- public List<StackInfo> queryAllStacks(String tenantId, String cloudSiteId) throws MsoException {
- // Obtain the cloud site information where we will create the stack
- CloudSite cloudSite =
- cloudConfig.getCloudSite(cloudSiteId).orElseThrow(() -> new MsoCloudSiteNotFound(cloudSiteId));
- // Get a Heat client. They are cached between calls (keyed by tenantId:cloudId)
- Heat heatClient = getHeatClient(cloudSite, tenantId);
-
- try {
- OpenStackRequest<Stacks> request = heatClient.getStacks().list();
- Stacks stacks = executeAndRecordOpenstackRequest(request);
-
- List<StackInfo> stackList = new ArrayList<>();
-
- // Not sure if returns an empty list or null if no stacks exist
- if (stacks != null) {
- for (Stack stack : stacks) {
- stackList.add(new StackInfoMapper(stack).map());
- }
- }
-
- return stackList;
- } catch (OpenStackResponseException e) {
- if (e.getStatus() == 404) {
- // Not sure if this can happen, but return an empty list
- logger.debug("queryAllStacks - stack not found: ");
- return new ArrayList<>();
- } else {
- // Convert the OpenStackResponseException to an MsoOpenstackException
- throw heatExceptionToMsoException(e, QUERY_ALL_STACKS);
- }
- } catch (OpenStackConnectException e) {
- // Error connecting to Openstack instance. Convert to an MsoException
- throw heatExceptionToMsoException(e, QUERY_ALL_STACKS);
- } catch (RuntimeException e) {
- // Catch-all
- throw runtimeExceptionToMsoException(e, QUERY_ALL_STACKS);
- }
- }
-
- /**
* Validate parameters to be passed to Heat template. This method performs three functions: 1. Apply default values
* to parameters which have them defined 2. Report any required parameters that are missing. This will generate an
* exception in the caller, since stack create/update operations would fail. 3. Report and remove any extraneous
@@ -785,8 +641,6 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin {
return updatedParams;
}
- // ---------------------------------------------------------------
- // PRIVATE FUNCTIONS FOR USE WITHIN THIS CLASS
/**
* Get a Heat client for the Openstack Identity service. This requires a 'member'-level userId + password, which
@@ -798,91 +652,10 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin {
*
* @return an authenticated Heat object
*/
- public Heat getHeatClient(CloudSite cloudSite, String tenantId) throws MsoException {
- String cloudId = cloudSite.getId();
- // For DCP/LCP, the region should be the cloudId.
- String region = cloudSite.getRegionId();
-
- // Obtain an MSO token for the tenant
- CloudIdentity cloudIdentity = cloudSite.getIdentityService();
- logger.debug("Found: {}", cloudIdentity.toString());
- MsoTenantUtils tenantUtils =
- tenantUtilsFactory.getTenantUtilsByServerType(cloudIdentity.getIdentityServerType());
- String keystoneUrl = tenantUtils.getKeystoneUrl(cloudId, cloudIdentity);
- logger.debug("keystoneUrl={}", keystoneUrl);
- String heatUrl = null;
- String tokenId = null;
- Calendar expiration = null;
- try {
- if (ServerType.KEYSTONE.equals(cloudIdentity.getIdentityServerType())) {
- Keystone keystoneTenantClient = new Keystone(keystoneUrl);
- Access access = null;
-
- Authentication credentials = authenticationMethodFactory.getAuthenticationFor(cloudIdentity);
-
- OpenStackRequest<Access> request =
- keystoneTenantClient.tokens().authenticate(credentials).withTenantId(tenantId);
-
- access = executeAndRecordOpenstackRequest(request);
-
- try {
- // Isolate trying to printout the region IDs
- try {
- logger.debug("access={}", access.toString());
- for (Access.Service service : access.getServiceCatalog()) {
- List<Access.Service.Endpoint> endpoints = service.getEndpoints();
- for (Access.Service.Endpoint endpoint : endpoints) {
- logger.debug("AIC returned region={}", endpoint.getRegion());
- }
- }
- } catch (Exception e) {
- logger.debug("Encountered an error trying to printout Access object returned from AIC. {}",
- e.getMessage(), e);
- }
- heatUrl = KeystoneUtils.findEndpointURL(access.getServiceCatalog(), "orchestration", region,
- "public");
- logger.debug("heatUrl={}, region={}", heatUrl, region);
- } catch (RuntimeException e) {
- // This comes back for not found (probably an incorrect region ID)
- String error = "AIC did not match an orchestration service for: region=" + region + ",cloud="
- + cloudIdentity.getIdentityUrl();
- throw new MsoAdapterException(error, e);
- }
- tokenId = access.getToken().getId();
- expiration = access.getToken().getExpires();
- } else if (ServerType.KEYSTONE_V3.equals(cloudIdentity.getIdentityServerType())) {
- try {
- KeystoneAuthHolder holder = keystoneV3Authentication.getToken(cloudSite, tenantId, "orchestration");
- tokenId = holder.getId();
- expiration = holder.getexpiration();
- heatUrl = holder.getServiceUrl();
- } catch (ServiceEndpointNotFoundException e) {
- // This comes back for not found (probably an incorrect region ID)
- String error = "cloud did not match an orchestration service for: region=" + region + ",cloud="
- + cloudIdentity.getIdentityUrl();
- throw new MsoAdapterException(error, e);
- }
- }
- } catch (OpenStackResponseException e) {
- if (e.getStatus() == 401) {
- // Authentication error.
- String error = "Authentication Failure: tenant=" + tenantId + ",cloud=" + cloudIdentity.getId();
-
- throw new MsoAdapterException(error);
- } else {
- throw keystoneErrorToMsoException(e, TOKEN_AUTH);
- }
- } catch (OpenStackConnectException e) {
- // Connection to Openstack failed
- MsoIOException me = new MsoIOException(e.getMessage(), e);
- me.addContext(TOKEN_AUTH);
- throw me;
- } catch (RuntimeException e) {
- // Catch-all
- throw runtimeExceptionToMsoException(e, TOKEN_AUTH);
- }
- Heat heatClient = new Heat(heatUrl);
- heatClient.token(tokenId);
+ public Heat getHeatClient(String cloudSiteId, String tenantId) throws MsoException {
+ KeystoneAuthHolder keystone = getKeystoneAuthHolder(cloudSiteId, tenantId, "orchestration");
+ Heat heatClient = new Heat(keystone.getServiceUrl());
+ heatClient.token(keystone.getId());
return heatClient;
}
@@ -904,7 +677,7 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin {
*
* @throws MsoOpenstackException Thrown if the Openstack API call returns an exception
*/
- protected Stack queryHeatStack(Heat heatClient, String stackName) throws MsoException {
+ public Stack queryHeatStack(Heat heatClient, String stackName) throws MsoException {
if (stackName == null) {
return null;
}
@@ -926,6 +699,13 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin {
}
}
+ public Stack queryHeatStack(String stackName, String cloudSiteId, String tenantId) throws MsoException {
+ if (stackName == null) {
+ return null;
+ }
+ return queryHeatStack(getHeatClient(cloudSiteId, tenantId), stackName);
+ }
+
public Map<String, Object> queryStackForOutputs(String cloudSiteId, String cloudOwner, String tenantId,
String stackName) throws MsoException {
@@ -988,47 +768,10 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin {
return;
}
- public StringBuilder requestToStringBuilder(CreateStackParam stack) {
- StringBuilder sb = new StringBuilder();
- sb.append("Stack:\n");
- sb.append("\tStackName: " + stack.getStackName());
- sb.append("\tTemplateUrl: " + stack.getTemplateUrl());
- sb.append("\tTemplate: " + stack.getTemplate());
- sb.append("\tEnvironment: " + stack.getEnvironment());
- sb.append("\tTimeout: " + stack.getTimeoutMinutes());
- sb.append("\tParameters:\n");
- Map<String, Object> params = stack.getParameters();
- if (params == null || params.size() < 1) {
- sb.append("\nNONE");
- } else {
- for (String key : params.keySet()) {
- if (params.get(key) instanceof String) {
- sb.append("\n").append(key).append("=").append((String) params.get(key));
- } else if (params.get(key) instanceof JsonNode) {
- String jsonStringOut = this.convertNode((JsonNode) params.get(key));
- sb.append("\n").append(key).append("=").append(jsonStringOut);
- } else if (params.get(key) instanceof Integer) {
- String integerOut = "" + params.get(key);
- sb.append("\n").append(key).append("=").append(integerOut);
-
- } else {
- try {
- String str = params.get(key).toString();
- sb.append("\n").append(key).append("=").append(str);
- } catch (Exception e) {
- logger.debug("Exception :", e);
- }
- }
- }
- }
- return sb;
- }
-
private String convertNode(final JsonNode node) {
try {
final Object obj = JSON_MAPPER.treeToValue(node, Object.class);
- final String json = JSON_MAPPER.writeValueAsString(obj);
- return json;
+ return JSON_MAPPER.writeValueAsString(obj);
} catch (Exception e) {
logger.debug("Error converting json to string {} ", e.getMessage(), e);
}
@@ -1192,44 +935,32 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin {
HashMap<String, HeatTemplateParam> paramAliases = new HashMap<>();
if (inputs == null) {
- logger.debug("convertInputMap - inputs is null - nothing to do here");
return new HashMap<>();
}
-
- logger.debug("convertInputMap in MsoHeatUtils called, with {} inputs, and template {}", inputs.size(),
- template.getArtifactUuid());
try {
- logger.debug(template.toString());
Set<HeatTemplateParam> paramSet = template.getParameters();
- logger.debug("paramSet has {} entries", paramSet.size());
} catch (Exception e) {
logger.debug("Exception occurred in convertInputMap {} :", e.getMessage(), e);
}
for (HeatTemplateParam htp : template.getParameters()) {
- logger.debug("Adding {}", htp.getParamName());
params.put(htp.getParamName(), htp);
if (htp.getParamAlias() != null && !"".equals(htp.getParamAlias())) {
logger.debug("\tFound ALIAS {} -> {}", htp.getParamName(), htp.getParamAlias());
paramAliases.put(htp.getParamAlias(), htp);
}
}
- logger.debug("Now iterate through the inputs...");
+
for (String key : inputs.keySet()) {
- logger.debug("key={}", key);
boolean alias = false;
String realName = null;
if (!params.containsKey(key)) {
- logger.debug("{} is not a parameter in the template! - check for an alias", key);
// add check here for an alias
if (!paramAliases.containsKey(key)) {
- logger.debug("The parameter {} is in the inputs, but it's not a parameter for this template - omit",
- key);
continue;
} else {
alias = true;
realName = paramAliases.get(key).getParamName();
- logger.debug("FOUND AN ALIAS! Will use {} in lieu of give key/alias {}", realName, key);
}
}
String type = params.get(key).getParamType();
@@ -1237,7 +968,6 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin {
logger.debug("**PARAM_TYPE is null/empty for {}, will default to string", key);
type = "string";
}
- logger.debug("Parameter: {} is of type {}", key, type);
if ("string".equalsIgnoreCase(type)) {
// Easiest!
String str = inputs.get(key) != null ? inputs.get(key).toString() : null;
@@ -1321,92 +1051,21 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin {
* This helpful method added for Valet
*/
public String getCloudSiteKeystoneUrl(String cloudSiteId) throws MsoCloudSiteNotFound {
- String keystone_url = null;
+ String keystoneUrl = null;
try {
CloudSite cloudSite =
cloudConfig.getCloudSite(cloudSiteId).orElseThrow(() -> new MsoCloudSiteNotFound(cloudSiteId));
CloudIdentity cloudIdentity = cloudSite.getIdentityService();
- keystone_url = cloudIdentity.getIdentityUrl();
+ keystoneUrl = cloudIdentity.getIdentityUrl();
} catch (Exception e) {
throw new MsoCloudSiteNotFound(cloudSiteId);
}
- if (keystone_url == null || keystone_url.isEmpty()) {
+ if (keystoneUrl == null || keystoneUrl.isEmpty()) {
throw new MsoCloudSiteNotFound(cloudSiteId);
}
- return keystone_url;
+ return keystoneUrl;
}
- /*
- * Create a string suitable for being dumped to a debug log that creates a pseudo-JSON request dumping what's being
- * sent to Openstack API in the create or update request
- */
-
- private String printStackRequest(String tenantId, Map<String, Object> heatFiles,
- Map<String, Object> nestedTemplates, String environment, Map<String, Object> inputs, String vfModuleName,
- String template, int timeoutMinutes, boolean backout, String cloudSiteId) {
- StringBuilder sb = new StringBuilder();
- sb.append("CREATE STACK REQUEST (formatted for readability)\n");
- sb.append("tenant=" + tenantId + ", cloud=" + cloudSiteId);
- sb.append("{\n");
- sb.append(" \"stack_name\": \"" + vfModuleName + "\",\n");
- sb.append(" \"disable_rollback\": " + backout + ",\n");
- sb.append(" \"timeout_mins\": " + timeoutMinutes + ",\n");
- sb.append(" \"template\": {\n");
- sb.append(template);
- sb.append(" },\n");
- sb.append(" \"environment\": {\n");
- if (environment == null)
- sb.append("<none>");
- else
- sb.append(environment);
- sb.append(" },\n");
- sb.append(" \"files\": {\n");
- int filesCounter = 0;
- if (heatFiles != null) {
- for (String key : heatFiles.keySet()) {
- filesCounter++;
- if (filesCounter > 1) {
- sb.append(",\n");
- }
- sb.append(" \"" + key + "\": {\n");
- sb.append(heatFiles.get(key).toString() + "\n }");
- }
- }
- if (nestedTemplates != null) {
- for (String key : nestedTemplates.keySet()) {
- filesCounter++;
- if (filesCounter > 1) {
- sb.append(",\n");
- }
- sb.append(" \"" + key + "\": {\n");
- sb.append(nestedTemplates.get(key).toString() + "\n }");
- }
- }
- sb.append("\n },\n");
- sb.append(" \"parameters\": {\n");
- int paramCounter = 0;
- for (String name : inputs.keySet()) {
- paramCounter++;
- if (paramCounter > 1) {
- sb.append(",\n");
- }
- Object o = inputs.get(name);
- if (o instanceof java.lang.String) {
- sb.append(" \"" + name + "\": \"" + inputs.get(name).toString() + "\"");
- } else if (o instanceof Integer) {
- sb.append(" \"" + name + "\": " + inputs.get(name).toString());
- } else if (o instanceof ArrayList) {
- sb.append(" \"" + name + "\": " + inputs.get(name).toString());
- } else if (o instanceof Boolean) {
- sb.append(" \"" + name + "\": " + inputs.get(name).toString());
- } else {
- sb.append(" \"" + name + "\": " + "\"(there was an issue trying to dump this value...)\"");
- }
- }
- sb.append("\n }\n}\n");
-
- return sb.toString();
- }
/*******************************************************************************
*
@@ -1550,7 +1209,7 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin {
if (heatStatus == HeatStatus.INIT || heatStatus == HeatStatus.BUILDING) {
vduStatus.setState(VduStateType.INSTANTIATING);
- vduStatus.setLastAction((new PluginAction("create", "in_progress", statusMessage)));
+ vduStatus.setLastAction((new PluginAction("create", IN_PROGRESS, statusMessage)));
} else if (heatStatus == HeatStatus.NOTFOUND) {
vduStatus.setState(VduStateType.NOTFOUND);
} else if (heatStatus == HeatStatus.CREATED) {
@@ -1561,10 +1220,10 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin {
vduStatus.setLastAction((new PluginAction("update", "complete", statusMessage)));
} else if (heatStatus == HeatStatus.UPDATING) {
vduStatus.setState(VduStateType.UPDATING);
- vduStatus.setLastAction((new PluginAction("update", "in_progress", statusMessage)));
+ vduStatus.setLastAction((new PluginAction("update", IN_PROGRESS, statusMessage)));
} else if (heatStatus == HeatStatus.DELETING) {
vduStatus.setState(VduStateType.DELETING);
- vduStatus.setLastAction((new PluginAction("delete", "in_progress", statusMessage)));
+ vduStatus.setLastAction((new PluginAction("delete", IN_PROGRESS, statusMessage)));
} else if (heatStatus == HeatStatus.FAILED) {
vduStatus.setState(VduStateType.FAILED);
vduStatus.setErrorMessage(stackInfo.getStatusMessage());
@@ -1577,19 +1236,37 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin {
public Resources queryStackResources(String cloudSiteId, String tenantId, String stackName, int nestedDepth)
throws MsoException {
- CloudSite cloudSite =
- cloudConfig.getCloudSite(cloudSiteId).orElseThrow(() -> new MsoCloudSiteNotFound(cloudSiteId));
- Heat heatClient = getHeatClient(cloudSite, tenantId);
+ Heat heatClient = getHeatClient(cloudSiteId, tenantId);
OpenStackRequest<Resources> request =
heatClient.getResources().listResources(stackName).queryParam("nested_depth", nestedDepth);
return executeAndRecordOpenstackRequest(request);
}
+ public Events queryStackEvents(String cloudSiteId, String tenantId, String stackName, String stackId,
+ int nestedDepth) throws MsoException {
+ Heat heatClient = getHeatClient(cloudSiteId, tenantId);
+ OpenStackRequest<Events> request =
+ heatClient.getEvents().listEvents(stackName, stackId).queryParam("nested_depth", nestedDepth);
+ return executeAndRecordOpenstackRequest(request);
+ }
+
+ public Stacks queryStacks(String cloudSiteId, String tenantId, int limit, String marker)
+ throws MsoCloudSiteNotFound, HeatClientException {
+ Heat heatClient;
+ try {
+ heatClient = getHeatClient(cloudSiteId, tenantId);
+ } catch (MsoException e) {
+ logger.error("Error Creating Heat Client", e);
+ throw new HeatClientException("Error Creating Heat Client", e);
+ }
+ OpenStackRequest<Stacks> request =
+ heatClient.getStacks().list().queryParam("limit", limit).queryParam("marker", marker);
+ return executeAndRecordOpenstackRequest(request);
+ }
+
public <R> R executeHeatClientRequest(String url, String cloudSiteId, String tenantId, Class<R> returnType)
throws MsoException {
- CloudSite cloudSite =
- cloudConfig.getCloudSite(cloudSiteId).orElseThrow(() -> new MsoCloudSiteNotFound(cloudSiteId));
- Heat heatClient = getHeatClient(cloudSite, tenantId);
+ Heat heatClient = getHeatClient(cloudSiteId, tenantId);
OpenStackRequest<R> request = heatClient.get(url, returnType);
return executeAndRecordOpenstackRequest(request);
}
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoHeatUtilsWithUpdate.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoHeatUtilsWithUpdate.java
index 1bf780f6d3..684fe98bf3 100644
--- a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoHeatUtilsWithUpdate.java
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoHeatUtilsWithUpdate.java
@@ -24,25 +24,14 @@
package org.onap.so.openstack.utils;
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.woorea.openstack.base.client.OpenStackBaseException;
-import com.woorea.openstack.base.client.OpenStackRequest;
-import com.woorea.openstack.heat.Heat;
-import com.woorea.openstack.heat.model.Stack;
-import com.woorea.openstack.heat.model.Stack.Output;
-import com.woorea.openstack.heat.model.UpdateStackParam;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import org.onap.so.db.catalog.beans.CloudSite;
import org.onap.so.logger.ErrorCode;
import org.onap.so.logger.MessageEnum;
import org.onap.so.openstack.beans.StackInfo;
-import org.onap.so.openstack.exceptions.MsoCloudSiteNotFound;
import org.onap.so.openstack.exceptions.MsoException;
import org.onap.so.openstack.exceptions.MsoOpenstackException;
import org.onap.so.openstack.exceptions.MsoStackNotFound;
@@ -52,6 +41,15 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.woorea.openstack.base.client.OpenStackBaseException;
+import com.woorea.openstack.base.client.OpenStackRequest;
+import com.woorea.openstack.heat.Heat;
+import com.woorea.openstack.heat.model.Stack;
+import com.woorea.openstack.heat.model.Stack.Output;
+import com.woorea.openstack.heat.model.UpdateStackParam;
@Component
public class MsoHeatUtilsWithUpdate extends MsoHeatUtils {
@@ -60,6 +58,7 @@ public class MsoHeatUtilsWithUpdate extends MsoHeatUtils {
private static final Logger logger = LoggerFactory.getLogger(MsoHeatUtilsWithUpdate.class);
private static final ObjectMapper JSON_MAPPER = new ObjectMapper();
+ public static final String EXCEPTION = "Exception :";
@Autowired
private Environment environment;
@@ -137,12 +136,7 @@ public class MsoHeatUtilsWithUpdate extends MsoHeatUtils {
haveHeatFiles = false;
}
- // Obtain the cloud site information where we will create the stack
- CloudSite cloudSite =
- cloudConfig.getCloudSite(cloudSiteId).orElseThrow(() -> new MsoCloudSiteNotFound(cloudSiteId));
- // Get a Heat client. They are cached between calls (keyed by tenantId:cloudId)
- // This could throw MsoTenantNotFound or MsoOpenstackException (both propagated)
- Heat heatClient = getHeatClient(cloudSite, tenantId);
+ Heat heatClient = getHeatClient(cloudSiteId, tenantId);
// Perform a query first to get the current status
Stack heatStack = queryHeatStack(heatClient, stackName);
@@ -221,8 +215,8 @@ public class MsoHeatUtilsWithUpdate extends MsoHeatUtils {
// Set a time limit on overall polling.
// Use the resource (template) timeout for Openstack (expressed in minutes)
// and add one poll interval to give Openstack a chance to fail on its own.
- int createPollInterval =
- Integer.parseInt(this.environment.getProperty(createPollIntervalProp, createPollIntervalDefault));
+ int createPollInterval = Integer
+ .parseInt(this.environment.getProperty(createPollIntervalProp, CREATE_POLL_INTERVAL_DEFAULT));
int pollTimeout = (timeoutMinutes * 60) + createPollInterval;
boolean loopAgain = true;
@@ -335,7 +329,7 @@ public class MsoHeatUtilsWithUpdate extends MsoHeatUtils {
String str = JSON_MAPPER.writeValueAsString(obj);
sb.append(str).append(" (a java.util.LinkedHashMap)");
} catch (Exception e) {
- logger.debug("Exception :", e);
+ logger.debug(EXCEPTION, e);
sb.append("(a LinkedHashMap value that would not convert nicely)");
}
} else if (obj instanceof Integer) {
@@ -343,7 +337,7 @@ public class MsoHeatUtilsWithUpdate extends MsoHeatUtils {
try {
str = obj.toString() + " (an Integer)\n";
} catch (Exception e) {
- logger.debug("Exception :", e);
+ logger.debug(EXCEPTION, e);
str = "(an Integer unable to call .toString() on)";
}
sb.append(str);
@@ -352,7 +346,7 @@ public class MsoHeatUtilsWithUpdate extends MsoHeatUtils {
try {
str = obj.toString() + " (an ArrayList)";
} catch (Exception e) {
- logger.debug("Exception :", e);
+ logger.debug(EXCEPTION, e);
str = "(an ArrayList unable to call .toString() on?)";
}
sb.append(str);
@@ -361,7 +355,7 @@ public class MsoHeatUtilsWithUpdate extends MsoHeatUtils {
try {
str = obj.toString() + " (a Boolean)";
} catch (Exception e) {
- logger.debug("Exception :", e);
+ logger.debug(EXCEPTION, e);
str = "(an Boolean unable to call .toString() on?)";
}
sb.append(str);
@@ -370,7 +364,7 @@ public class MsoHeatUtilsWithUpdate extends MsoHeatUtils {
try {
str = obj.toString() + " (unknown Object type)";
} catch (Exception e) {
- logger.debug("Exception :", e);
+ logger.debug(EXCEPTION, e);
str = "(a value unable to call .toString() on?)";
}
sb.append(str);
@@ -384,8 +378,7 @@ public class MsoHeatUtilsWithUpdate extends MsoHeatUtils {
private String convertNodeWithUpdate(final JsonNode node) {
try {
final Object obj = JSON_MAPPER.treeToValue(node, Object.class);
- final String json = JSON_MAPPER.writeValueAsString(obj);
- return json;
+ return JSON_MAPPER.writeValueAsString(obj);
} catch (Exception e) {
logger.debug("Error converting json to string {} ", e.getMessage(), e);
}
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoKeystoneUtils.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoKeystoneUtils.java
index cfc8c23c5f..f74a3f5f53 100644
--- a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoKeystoneUtils.java
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoKeystoneUtils.java
@@ -23,19 +23,6 @@
package org.onap.so.openstack.utils;
-import com.woorea.openstack.base.client.OpenStackBaseException;
-import com.woorea.openstack.base.client.OpenStackConnectException;
-import com.woorea.openstack.base.client.OpenStackRequest;
-import com.woorea.openstack.base.client.OpenStackResponseException;
-import com.woorea.openstack.keystone.Keystone;
-import com.woorea.openstack.keystone.model.Access;
-import com.woorea.openstack.keystone.model.Authentication;
-import com.woorea.openstack.keystone.model.Metadata;
-import com.woorea.openstack.keystone.model.Role;
-import com.woorea.openstack.keystone.model.Roles;
-import com.woorea.openstack.keystone.model.Tenant;
-import com.woorea.openstack.keystone.model.User;
-import com.woorea.openstack.keystone.utils.KeystoneUtils;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
@@ -54,10 +41,24 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
+import com.woorea.openstack.base.client.OpenStackBaseException;
+import com.woorea.openstack.base.client.OpenStackConnectException;
+import com.woorea.openstack.base.client.OpenStackRequest;
+import com.woorea.openstack.base.client.OpenStackResponseException;
+import com.woorea.openstack.keystone.Keystone;
+import com.woorea.openstack.keystone.model.Access;
+import com.woorea.openstack.keystone.model.Authentication;
+import com.woorea.openstack.keystone.model.Metadata;
+import com.woorea.openstack.keystone.model.Role;
+import com.woorea.openstack.keystone.model.Roles;
+import com.woorea.openstack.keystone.model.Tenant;
+import com.woorea.openstack.keystone.model.User;
+import com.woorea.openstack.keystone.utils.KeystoneUtils;
@Component
public class MsoKeystoneUtils extends MsoTenantUtils {
+ public static final String DELETE_TENANT = "Delete Tenant";
private static Logger logger = LoggerFactory.getLogger(MsoKeystoneUtils.class);
@Autowired
@@ -207,7 +208,7 @@ public class MsoKeystoneUtils extends MsoTenantUtils {
return null;
}
- Map<String, String> metadata = new HashMap<String, String>();
+ Map<String, String> metadata = new HashMap<>();
if (cloudSite.getIdentityService().getTenantMetadata()) {
OpenStackRequest<Metadata> request = keystoneAdminClient.tenants().showMetadata(tenant.getId());
Metadata tenantMetadata = executeAndRecordOpenstackRequest(request);
@@ -252,7 +253,7 @@ public class MsoKeystoneUtils extends MsoTenantUtils {
return null;
}
- Map<String, String> metadata = new HashMap<String, String>();
+ Map<String, String> metadata = new HashMap<>();
if (cloudSite.getIdentityService().getTenantMetadata()) {
OpenStackRequest<Metadata> request = keystoneAdminClient.tenants().showMetadata(tenant.getId());
Metadata tenantMetadata = executeAndRecordOpenstackRequest(request);
@@ -304,10 +305,10 @@ public class MsoKeystoneUtils extends MsoTenantUtils {
logger.debug("Deleted Tenant {} ({})", tenant.getId(), tenant.getName());
} catch (OpenStackBaseException e) {
// Convert Keystone OpenStackResponseException to MsoOpenstackException
- throw keystoneErrorToMsoException(e, "Delete Tenant");
+ throw keystoneErrorToMsoException(e, DELETE_TENANT);
} catch (RuntimeException e) {
// Catch-all
- throw runtimeExceptionToMsoException(e, "DeleteTenant");
+ throw runtimeExceptionToMsoException(e, DELETE_TENANT);
}
return true;
@@ -354,10 +355,10 @@ public class MsoKeystoneUtils extends MsoTenantUtils {
} catch (OpenStackBaseException e) {
// Note: It doesn't seem to matter if tenant doesn't exist, no exception is thrown.
// Convert Keystone OpenStackResponseException to MsoOpenstackException
- throw keystoneErrorToMsoException(e, "DeleteTenant");
+ throw keystoneErrorToMsoException(e, DELETE_TENANT);
} catch (RuntimeException e) {
// Catch-all
- throw runtimeExceptionToMsoException(e, "DeleteTenant");
+ throw runtimeExceptionToMsoException(e, DELETE_TENANT);
}
return true;
@@ -379,7 +380,6 @@ public class MsoKeystoneUtils extends MsoTenantUtils {
public Keystone getKeystoneAdminClient(CloudSite cloudSite) throws MsoException {
CloudIdentity cloudIdentity = cloudSite.getIdentityService();
- String cloudId = cloudIdentity.getId();
String adminTenantName = cloudIdentity.getAdminTenant();
String region = cloudSite.getRegionId();
@@ -414,7 +414,6 @@ public class MsoKeystoneUtils extends MsoTenantUtils {
// Get the Identity service URL. Throws runtime exception if not found per region.
String adminUrl = null;
try {
- // TODO: FOR TESTING!!!!
adminUrl = KeystoneUtils.findEndpointURL(access.getServiceCatalog(), "identity", region, "public");
adminUrl = adminUrl.replaceFirst("5000", "35357");
} catch (RuntimeException e) {
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoMulticloudUtils.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoMulticloudUtils.java
index 8c570e25d7..49ba336e3f 100644
--- a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoMulticloudUtils.java
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoMulticloudUtils.java
@@ -28,9 +28,7 @@ import com.woorea.openstack.heat.model.CreateStackParam;
import com.woorea.openstack.heat.model.Stack;
import java.net.MalformedURLException;
import java.net.URL;
-import java.util.Arrays;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import java.util.Scanner;
import javax.ws.rs.core.Response;
@@ -64,6 +62,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
+import com.google.common.collect.ImmutableSet;
@Component
public class MsoMulticloudUtils extends MsoHeatUtils implements VduPlugin {
@@ -75,8 +74,8 @@ public class MsoMulticloudUtils extends MsoHeatUtils implements VduPlugin {
public static final String VF_MODULE_ID = "vf_module_id";
public static final String TEMPLATE_TYPE = "template_type";
public static final String MULTICLOUD_QUERY_BODY_NULL = "multicloudQueryBody is null";
- public static final List<String> MULTICLOUD_INPUTS =
- Arrays.asList(OOF_DIRECTIVES, SDNC_DIRECTIVES, USER_DIRECTIVES, TEMPLATE_TYPE);
+ public static final ImmutableSet<String> MULTICLOUD_INPUTS =
+ ImmutableSet.of(OOF_DIRECTIVES, SDNC_DIRECTIVES, USER_DIRECTIVES, TEMPLATE_TYPE);
private static final Logger logger = LoggerFactory.getLogger(MsoMulticloudUtils.class);
@@ -468,7 +467,7 @@ public class MsoMulticloudUtils extends MsoHeatUtils implements VduPlugin {
}
int updatePollInterval =
- Integer.parseInt(this.environment.getProperty(createPollIntervalProp, createPollIntervalDefault));
+ Integer.parseInt(this.environment.getProperty(createPollIntervalProp, CREATE_POLL_INTERVAL_DEFAULT));
int pollTimeout = (timeoutMinutes * 60) + updatePollInterval;
boolean updateTimedOut = false;
logger.debug("updatePollInterval=" + updatePollInterval + ", pollTimeout=" + pollTimeout);
@@ -536,8 +535,8 @@ public class MsoMulticloudUtils extends MsoHeatUtils implements VduPlugin {
// Use the resource (template) timeout for Openstack (expressed in minutes)
// and add one poll interval to give Openstack a chance to fail on its own.s
- int createPollInterval =
- Integer.parseInt(this.environment.getProperty(createPollIntervalProp, createPollIntervalDefault));
+ int createPollInterval = Integer
+ .parseInt(this.environment.getProperty(createPollIntervalProp, CREATE_POLL_INTERVAL_DEFAULT));
int pollTimeout = (timeoutMinutes * 60) + createPollInterval;
// New 1610 - poll on delete if we rollback - use same values for now
int deletePollInterval = createPollInterval;
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoNeutronUtils.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoNeutronUtils.java
index 78db27f65e..6f08afc55f 100644
--- a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoNeutronUtils.java
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoNeutronUtils.java
@@ -373,7 +373,7 @@ public class MsoNeutronUtils extends MsoCommonUtils {
final String keystoneUrl = tenantUtils.getKeystoneUrl(cloudId, cloudIdentity);
String neutronUrl = null;
String tokenId = null;
- Calendar expiration = null;
+
try {
if (ServerType.KEYSTONE.equals(cloudIdentity.getIdentityServerType())) {
Keystone keystoneTenantClient = new Keystone(keystoneUrl);
@@ -396,12 +396,12 @@ public class MsoNeutronUtils extends MsoCommonUtils {
throw new MsoAdapterException(error, e);
}
tokenId = access.getToken().getId();
- expiration = access.getToken().getExpires();
+
} else if (ServerType.KEYSTONE_V3.equals(cloudIdentity.getIdentityServerType())) {
try {
KeystoneAuthHolder holder = keystoneV3Authentication.getToken(cloudSite, tenantId, "network");
tokenId = holder.getId();
- expiration = holder.getexpiration();
+
neutronUrl = holder.getServiceUrl();
if (!neutronUrl.endsWith("/")) {
neutronUrl += "/v2.0/";
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoYamlEditorWithEnvt.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoYamlEditorWithEnvt.java
index 0541a8f51b..9ee8a09ea6 100644
--- a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoYamlEditorWithEnvt.java
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MsoYamlEditorWithEnvt.java
@@ -40,6 +40,7 @@ import org.yaml.snakeyaml.Yaml;
public class MsoYamlEditorWithEnvt {
private static final Logger logger = LoggerFactory.getLogger(MsoYamlEditorWithEnvt.class);
+ public static final String EXCEPTION = "Exception:";
private Map<String, Object> yml;
private Yaml yaml = new Yaml();
@@ -68,7 +69,7 @@ public class MsoYamlEditorWithEnvt {
try {
resourceMap = (Map<String, Object>) yml.get("parameters");
} catch (Exception e) {
- logger.debug("Exception:", e);
+ logger.debug(EXCEPTION, e);
return paramSet;
}
if (resourceMap == null) {
@@ -89,7 +90,7 @@ public class MsoYamlEditorWithEnvt {
try {
value = JSON_MAPPER.writeValueAsString(obj);
} catch (Exception e) {
- logger.debug("Exception:", e);
+ logger.debug(EXCEPTION, e);
value = "_BAD_JSON_MAPPING";
}
} else {
@@ -118,7 +119,7 @@ public class MsoYamlEditorWithEnvt {
}
return resourceList;
} catch (Exception e) {
- logger.debug("Exception:", e);
+ logger.debug(EXCEPTION, e);
}
return null;
}
@@ -137,7 +138,7 @@ public class MsoYamlEditorWithEnvt {
try {
value = resourceEntry.get("default");
} catch (ClassCastException cce) {
- logger.debug("Exception:", cce);
+ logger.debug(EXCEPTION, cce);
// This exception only - the value is an integer. For what we're doing
// here - we don't care - so set value to something - and it will
// get marked as not being required - which is correct.
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MulticloudCreateHeatResponse.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MulticloudCreateHeatResponse.java
index a4cdba22a1..16671bbe50 100644
--- a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MulticloudCreateHeatResponse.java
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MulticloudCreateHeatResponse.java
@@ -31,7 +31,7 @@ import org.apache.commons.lang.builder.ToStringBuilder;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({"id", "links"})
public class MulticloudCreateHeatResponse implements Serializable {
- private final static long serialVersionUID = -5215028275577848311L;
+ private static final long serialVersionUID = -5215028275577848311L;
@JsonProperty("id")
private String id;
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MulticloudCreateLinkResponse.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MulticloudCreateLinkResponse.java
index e8a5b1480e..1f55aa92a2 100644
--- a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MulticloudCreateLinkResponse.java
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MulticloudCreateLinkResponse.java
@@ -31,7 +31,7 @@ import org.apache.commons.lang.builder.ToStringBuilder;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({"href", "rel"})
public class MulticloudCreateLinkResponse implements Serializable {
- private final static long serialVersionUID = -5215028275577848311L;
+ private static final long serialVersionUID = -5215028275577848311L;
@JsonProperty("href")
private String href;
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MulticloudCreateResponse.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MulticloudCreateResponse.java
index 732f9b5196..9fa4557a45 100644
--- a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MulticloudCreateResponse.java
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MulticloudCreateResponse.java
@@ -33,7 +33,7 @@ import org.apache.commons.lang.builder.ToStringBuilder;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonPropertyOrder({"template_type", "workload_id", "template_response", "workload_status_reason", "workload_status"})
public class MulticloudCreateResponse implements Serializable {
- private final static long serialVersionUID = -5215028275577848311L;
+ private static final long serialVersionUID = -5215028275577848311L;
@JsonProperty("template_type")
private String templateType;
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MulticloudQueryResponse.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MulticloudQueryResponse.java
index a22937aea3..ad37b39f30 100644
--- a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MulticloudQueryResponse.java
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MulticloudQueryResponse.java
@@ -31,7 +31,7 @@ import org.apache.commons.lang.builder.ToStringBuilder;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({"template_type", "workload_id", "workload_status", "workload_status_reason"})
public class MulticloudQueryResponse implements Serializable {
- private final static long serialVersionUID = -5215028275577848311L;
+ private static final long serialVersionUID = -5215028275577848311L;
@JsonProperty("template_type")
private String templateType;
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MulticloudRequest.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MulticloudRequest.java
index b733552a2b..95dd48caa6 100644
--- a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MulticloudRequest.java
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/MulticloudRequest.java
@@ -33,7 +33,7 @@ import org.apache.commons.lang.builder.ToStringBuilder;
"vf-module-model-customization-id", "oof_directives", "sdnc_directives", "user_directives", "template_type",
"template_data"})
public class MulticloudRequest implements Serializable {
- private final static long serialVersionUID = -5215028275577848311L;
+ private static final long serialVersionUID = -5215028275577848311L;
@JsonProperty("generic-vnf-id")
private String genericVnfId;
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/NeutronClientException.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/NeutronClientException.java
new file mode 100644
index 0000000000..e2c917c6eb
--- /dev/null
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/NeutronClientException.java
@@ -0,0 +1,33 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.openstack.utils;
+
+public class NeutronClientException extends Exception {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -9047340957886416022L;
+
+ public NeutronClientException(String error, Exception e) {
+ super(error, e);
+ }
+
+}
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/NeutronClientImpl.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/NeutronClientImpl.java
new file mode 100644
index 0000000000..93745de54a
--- /dev/null
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/NeutronClientImpl.java
@@ -0,0 +1,113 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.openstack.utils;
+
+import org.onap.so.cloud.authentication.KeystoneAuthHolder;
+import org.onap.so.openstack.exceptions.MsoCloudSiteNotFound;
+import org.onap.so.openstack.exceptions.MsoException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import com.woorea.openstack.base.client.OpenStackRequest;
+import com.woorea.openstack.quantum.Quantum;
+import com.woorea.openstack.quantum.model.Networks;
+import com.woorea.openstack.quantum.model.Subnets;
+
+
+
+@Component
+public class NeutronClientImpl extends MsoCommonUtils {
+
+ /** The Constant logger. */
+ private static final Logger logger = LoggerFactory.getLogger(NeutronClientImpl.class);
+
+ /**
+ * Gets the Neutron client, using old object named Quantum, now renamed Neutron
+ *
+ * @param cloudSite the cloud site
+ * @param tenantId the tenant id
+ * @return the Neutron client
+ * @throws MsoException the mso exception
+ */
+ private Quantum getNeutronClient(String cloudSiteId, String tenantId) throws MsoException {
+ KeystoneAuthHolder keystone = getKeystoneAuthHolder(cloudSiteId, tenantId, "network");
+ Quantum neutronClient = new Quantum(keystone.getServiceUrl() + "/v2.0/");
+ neutronClient.token(keystone.getId());
+ return neutronClient;
+ }
+
+
+ /**
+ * Query Networks
+ *
+ *
+ * @param cloudSiteId the cloud site id
+ * @param tenantId the tenant id
+ * @param limit limits the number of records returned
+ * @param marker the last viewed record
+ * @param name of the newtork
+ * @param id of the network
+ * @return the list of networks in openstack
+ * @throws MsoCloudSiteNotFound the mso cloud site not found
+ * @throws NeutronClientException if the client cannot be built this is thrown
+ */
+ public Networks queryNetworks(String cloudSiteId, String tenantId, int limit, String marker, String name, String id)
+ throws MsoCloudSiteNotFound, NeutronClientException {
+ try {
+ Quantum neutronClient = getNeutronClient(cloudSiteId, tenantId);
+ OpenStackRequest<Networks> request = neutronClient.networks().list().queryParam("id", id)
+ .queryParam("limit", limit).queryParam("marker", marker).queryParam("name", name);
+ return executeAndRecordOpenstackRequest(request);
+ } catch (MsoException e) {
+ logger.error("Error building Neutron Client", e);
+ throw new NeutronClientException("Error building Neutron Client", e);
+ }
+ }
+
+
+ /**
+ * Query Networks
+ *
+ *
+ * @param cloudSiteId the cloud site id
+ * @param tenantId the tenant id
+ * @param limit limits the number of records returned
+ * @param marker the last viewed record
+ * @param name of the subnet
+ * @param id of the subnet
+ * @return the list of subnets in openstack
+ * @throws MsoCloudSiteNotFound the mso cloud site not found
+ * @throws NeutronClientException if the client cannot be built this is thrown
+ */
+ public Subnets querySubnets(String cloudSiteId, String tenantId, int limit, String marker, String name, String id)
+ throws MsoCloudSiteNotFound, NeutronClientException {
+ try {
+ Quantum neutronClient = getNeutronClient(cloudSiteId, tenantId);
+ OpenStackRequest<Subnets> request = neutronClient.subnets().list().queryParam("id", id)
+ .queryParam("limit", limit).queryParam("marker", marker).queryParam("name", name);
+ return executeAndRecordOpenstackRequest(request);
+ } catch (MsoException e) {
+ logger.error("Error building Neutron Client", e);
+ throw new NeutronClientException("Error building Neutron Client", e);
+ }
+ }
+
+}
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/NovaClientException.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/NovaClientException.java
new file mode 100644
index 0000000000..c5b6563dff
--- /dev/null
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/NovaClientException.java
@@ -0,0 +1,33 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.openstack.utils;
+
+public class NovaClientException extends Exception {
+
+ public NovaClientException(String error, Exception e) {
+ super(error, e);
+ }
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -1920095376579954885L;
+
+}
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/NovaClientImpl.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/NovaClientImpl.java
new file mode 100644
index 0000000000..6cd79de476
--- /dev/null
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/NovaClientImpl.java
@@ -0,0 +1,207 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.openstack.utils;
+
+import org.onap.so.cloud.authentication.KeystoneAuthHolder;
+import org.onap.so.openstack.exceptions.MsoCloudSiteNotFound;
+import org.onap.so.openstack.exceptions.MsoException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import com.woorea.openstack.base.client.OpenStackRequest;
+import com.woorea.openstack.nova.Nova;
+import com.woorea.openstack.nova.model.Flavor;
+import com.woorea.openstack.nova.model.Flavors;
+import com.woorea.openstack.nova.model.HostAggregate;
+import com.woorea.openstack.nova.model.HostAggregates;
+import com.woorea.openstack.nova.model.QuotaSet;
+
+
+@Component
+public class NovaClientImpl extends MsoCommonUtils {
+
+
+ /** The logger. */
+ private static final Logger logger = LoggerFactory.getLogger(NovaClientImpl.class);
+
+ /**
+ * Gets the Nova client
+ *
+ * @param cloudSiteId id of the cloud site
+ * @param tenantId the tenant id
+ * @return the Nova client
+ * @throws MsoException the mso exception
+ */
+ private Nova getNovaClient(String cloudSiteId, String tenantId) throws MsoException {
+ KeystoneAuthHolder keystone = getKeystoneAuthHolder(cloudSiteId, tenantId, "compute");
+ Nova novaClient = new Nova(keystone.getServiceUrl());
+ novaClient.token(keystone.getId());
+ return novaClient;
+ }
+
+
+ /**
+ * Query Networks
+ *
+ *
+ * @param cloudSiteId the cloud site id
+ * @param tenantId the tenant id
+ * @param limit limits the number of records returned
+ * @param marker the last viewed record
+ * @param name of the newtork
+ * @param id of the network
+ * @return the list of networks in openstack
+ * @throws MsoCloudSiteNotFound the mso cloud site not found
+ * @throws NeutronClientException if the client cannot be built this is thrown
+ */
+ public Flavors queryFlavors(String cloudSiteId, String tenantId, int limit, String marker)
+ throws MsoCloudSiteNotFound, NovaClientException {
+ try {
+ Nova novaClient = getNovaClient(cloudSiteId, tenantId);
+ OpenStackRequest<Flavors> request =
+ novaClient.flavors().list(false).queryParam("limit", limit).queryParam("marker", marker);
+ return executeAndRecordOpenstackRequest(request);
+ } catch (MsoException e) {
+ logger.error("Error building Nova Client", e);
+ throw new NovaClientException("Error building Nova Client", e);
+ }
+
+ }
+
+ /**
+ * Query Networks
+ *
+ *
+ * @param cloudSiteId the cloud site id
+ * @param tenantId the tenant id
+ * @param id of the network
+ * @return the the flavor from openstack
+ * @throws MsoCloudSiteNotFound the mso cloud site not found
+ * @throws NeutronClientException if the client cannot be built this is thrown
+ */
+ public Flavor queryFlavorById(String cloudSiteId, String tenantId, String id)
+ throws MsoCloudSiteNotFound, NovaClientException {
+ try {
+ Nova novaClient = getNovaClient(cloudSiteId, tenantId);
+ novaClient = getNovaClient(cloudSiteId, tenantId);
+ OpenStackRequest<Flavor> request = novaClient.flavors().show(id);
+ return executeAndRecordOpenstackRequest(request);
+ } catch (MsoException e) {
+ logger.error("Error building Nova Client", e);
+ throw new NovaClientException("Error building Nova Client", e);
+ }
+ }
+
+ /**
+ * Query Host Aggregates
+ *
+ *
+ * @param cloudSiteId the cloud site id
+ * @param tenantId the tenant id
+ * @param limit limits the number of records returned
+ * @param marker the last viewed record
+ * @return the list of host aggregates found in openstack
+ * @throws MsoCloudSiteNotFound the mso cloud site not found
+ * @throws NeutronClientException if the client cannot be built this is thrown
+ */
+ public HostAggregates queryHostAggregates(String cloudSiteId, String tenantId, int limit, String marker)
+ throws MsoCloudSiteNotFound, NovaClientException {
+ try {
+ Nova novaClient = getNovaClient(cloudSiteId, tenantId);
+ OpenStackRequest<HostAggregates> request =
+ novaClient.aggregates().list().queryParam("limit", limit).queryParam("marker", marker);
+ return executeAndRecordOpenstackRequest(request);
+ } catch (MsoException e) {
+ logger.error("Error building Nova Client", e);
+ throw new NovaClientException("Error building Nova Client", e);
+ }
+ }
+
+ /**
+ * Query Host Aggregate
+ *
+ *
+ * @param cloudSiteId the cloud site id
+ * @param tenantId the tenant id
+ * @param limit limits the number of records returned
+ * @param marker the last viewed record
+ * @return a host aggregate
+ * @throws MsoCloudSiteNotFound the mso cloud site not found
+ * @throws NeutronClientException if the client cannot be built this is thrown
+ */
+ public HostAggregate queryHostAggregateById(String cloudSiteId, String tenantId, String id)
+ throws MsoCloudSiteNotFound, NovaClientException {
+ try {
+ Nova novaClient = getNovaClient(cloudSiteId, tenantId);
+ OpenStackRequest<HostAggregate> request = novaClient.aggregates().showAggregate(id);
+ return executeAndRecordOpenstackRequest(request);
+ } catch (MsoException e) {
+ logger.error("Error building Nova Client", e);
+ throw new NovaClientException("Error building Nova Client", e);
+ }
+ }
+
+ /**
+ * Query OS Quota Set
+ *
+ *
+ * @param cloudSiteId the cloud site id
+ * @param tenantId the tenant id
+ * @param limit limits the number of records returned
+ * @param marker the last viewed record
+ * @return a host aggregate
+ * @throws MsoCloudSiteNotFound the mso cloud site not found
+ * @throws NeutronClientException if the client cannot be built this is thrown
+ */
+ public QuotaSet queryOSQuotaSet(String cloudSiteId, String tenantId)
+ throws MsoCloudSiteNotFound, NovaClientException {
+ try {
+ Nova novaClient = getNovaClient(cloudSiteId, tenantId);
+ OpenStackRequest<QuotaSet> request = novaClient.quotaSets().showQuota(tenantId);
+ return executeAndRecordOpenstackRequest(request);
+ } catch (MsoException e) {
+ logger.error("Error building Nova Client", e);
+ throw new NovaClientException("Error building Nova Client", e);
+ }
+ }
+
+ /**
+ * Deletes a keypair inside openstack
+ *
+ *
+ * @param cloudSiteId the cloud site id
+ * @param tenantId the tenant id
+ * @param keyPairName name of the keypair to be deleted
+ * @throws MsoCloudSiteNotFound the mso cloud site not found
+ * @throws NeutronClientException if the client cannot be built this is thrown
+ */
+ public void deleteKeyPair(String cloudSiteId, String tenantId, String keyPairName)
+ throws MsoCloudSiteNotFound, NovaClientException {
+ try {
+ Nova novaClient = getNovaClient(cloudSiteId, tenantId);
+ OpenStackRequest<Void> request = novaClient.keyPairs().delete(keyPairName);
+ executeAndRecordOpenstackRequest(request);
+ } catch (MsoException e) {
+ logger.error("Error building Nova Client", e);
+ throw new NovaClientException("Error building Nova Client", e);
+ }
+ }
+}
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/StackCreationException.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/StackCreationException.java
new file mode 100644
index 0000000000..3a377efce6
--- /dev/null
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/StackCreationException.java
@@ -0,0 +1,11 @@
+package org.onap.so.openstack.utils;
+
+import org.onap.so.openstack.exceptions.MsoException;
+
+public class StackCreationException extends MsoException {
+
+ public StackCreationException(String error) {
+ super(error);
+ }
+
+}
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/StackResultWrapper.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/StackResultWrapper.java
new file mode 100644
index 0000000000..c3b3c1de2a
--- /dev/null
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/StackResultWrapper.java
@@ -0,0 +1,62 @@
+package org.onap.so.openstack.utils;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import com.woorea.openstack.heat.model.Stack;
+
+public class StackResultWrapper {
+
+ private Stack stack;
+ private boolean stackTimedOutPolling;
+ private boolean stackNotFound;
+ private String errorMessage;
+ private String errorCode;
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this).append("stack", stack).append("stackTimedOutPolling", stackTimedOutPolling)
+ .append("stackNotFound", stackNotFound).append("errorMessage", errorMessage)
+ .append("errorCode", errorCode).toString();
+ }
+
+ public Stack getStack() {
+ return stack;
+ }
+
+ public void setStack(Stack stack) {
+ this.stack = stack;
+ }
+
+ public boolean isStackTimedOutPolling() {
+ return stackTimedOutPolling;
+ }
+
+ public void setStackTimedOutPolling(boolean stackTimedOutPolling) {
+ this.stackTimedOutPolling = stackTimedOutPolling;
+ }
+
+ public boolean isStackNotFound() {
+ return stackNotFound;
+ }
+
+ public void setStackNotFound(boolean stackNotFound) {
+ this.stackNotFound = stackNotFound;
+ }
+
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ public void setErrorMessage(String errorMessage) {
+ this.errorMessage = errorMessage;
+ }
+
+ public String getErrorCode() {
+ return errorCode;
+ }
+
+ public void setErrorCode(String errorCode) {
+ this.errorCode = errorCode;
+ }
+
+
+}
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/StackRollbackException.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/StackRollbackException.java
new file mode 100644
index 0000000000..1bad7ef51c
--- /dev/null
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/StackRollbackException.java
@@ -0,0 +1,11 @@
+package org.onap.so.openstack.utils;
+
+import org.onap.so.openstack.exceptions.MsoException;
+
+public class StackRollbackException extends MsoException {
+
+ public StackRollbackException(String error) {
+ super(error);
+ }
+
+}
diff --git a/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/StackStatusHandler.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/StackStatusHandler.java
new file mode 100644
index 0000000000..df173c002d
--- /dev/null
+++ b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/StackStatusHandler.java
@@ -0,0 +1,49 @@
+package org.onap.so.openstack.utils;
+
+
+import org.onap.logging.ref.slf4j.ONAPLogConstants;
+import org.onap.so.db.request.beans.RequestProcessingData;
+import org.onap.so.db.request.client.RequestsDbClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Component;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.woorea.openstack.heat.model.Stack;
+
+@Component
+public class StackStatusHandler {
+
+ private static final Logger logger = LoggerFactory.getLogger(StackStatusHandler.class);
+ private static final ObjectMapper mapper = new ObjectMapper();
+
+ @Autowired
+ private RequestsDbClient requestDBClient;
+
+ @Async
+ public void updateStackStatus(Stack stack) {
+ try {
+ String requestId = MDC.get(ONAPLogConstants.MDCs.REQUEST_ID);
+ String stackStatus = mapper.writeValueAsString(stack);
+ RequestProcessingData requestProcessingData =
+ requestDBClient.getRequestProcessingDataBySoRequestIdAndNameAndGrouping(requestId, stack.getId(),
+ stack.getStackName());
+ if (requestProcessingData == null) {
+ requestProcessingData = new RequestProcessingData();
+ requestProcessingData.setGroupingId(stack.getId());
+ requestProcessingData.setName(stack.getStackName());
+ requestProcessingData.setTag("StackInformation");
+ requestProcessingData.setSoRequestId(requestId);
+ requestProcessingData.setValue(stackStatus);
+ requestDBClient.saveRequestProcessingData(requestProcessingData);
+ } else {
+ requestProcessingData.setValue(stackStatus);
+ requestDBClient.updateRequestProcessingData(requestProcessingData);
+ }
+ } catch (Exception e) {
+ logger.warn("Error adding stack status to request database", e);
+ }
+ }
+}
diff --git a/adapters/mso-adapter-utils/src/test/java/org/onap/so/cloud/authentication/KeystoneAuthHolderTest.java b/adapters/mso-adapter-utils/src/test/java/org/onap/so/cloud/authentication/KeystoneAuthHolderTest.java
index 5bd77d8e10..0137148835 100644
--- a/adapters/mso-adapter-utils/src/test/java/org/onap/so/cloud/authentication/KeystoneAuthHolderTest.java
+++ b/adapters/mso-adapter-utils/src/test/java/org/onap/so/cloud/authentication/KeystoneAuthHolderTest.java
@@ -65,7 +65,7 @@ public class KeystoneAuthHolderTest {
@Test
public void testGetServiceUrl() {
- keystoneAuthHolder.setHeatUrl("testURL");
+ keystoneAuthHolder.setServiceUrl("testURL");
assertEquals("testURL", keystoneAuthHolder.getServiceUrl());
}
diff --git a/adapters/mso-adapter-utils/src/test/java/org/onap/so/openstack/utils/MsoHeatUtilsITTest.java b/adapters/mso-adapter-utils/src/test/java/org/onap/so/openstack/utils/MsoHeatUtilsITTest.java
new file mode 100644
index 0000000000..7e783aa7a4
--- /dev/null
+++ b/adapters/mso-adapter-utils/src/test/java/org/onap/so/openstack/utils/MsoHeatUtilsITTest.java
@@ -0,0 +1,219 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - SO
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Modifications Copyright (c) 2019 Samsung
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.so.openstack.utils;
+
+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.urlPathEqualTo;
+import static com.shazam.shazamcrest.MatcherAssert.assertThat;
+import static com.shazam.shazamcrest.matcher.Matchers.sameBeanAs;
+import static org.junit.Assert.assertNotNull;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.http.HttpStatus;
+import org.junit.Assert;
+import org.junit.Test;
+import org.onap.so.BaseTest;
+import org.onap.so.StubOpenStack;
+import org.onap.so.adapters.vdu.CloudInfo;
+import org.onap.so.adapters.vdu.PluginAction;
+import org.onap.so.adapters.vdu.VduArtifact;
+import org.onap.so.adapters.vdu.VduArtifact.ArtifactType;
+import org.onap.so.adapters.vdu.VduInstance;
+import org.onap.so.adapters.vdu.VduModelInfo;
+import org.onap.so.adapters.vdu.VduStateType;
+import org.onap.so.adapters.vdu.VduStatus;
+import org.onap.so.db.catalog.beans.CloudIdentity;
+import org.onap.so.db.catalog.beans.CloudSite;
+import org.onap.so.openstack.beans.StackInfo;
+import org.onap.so.openstack.exceptions.MsoAdapterException;
+import org.onap.so.openstack.exceptions.MsoException;
+import org.onap.so.openstack.exceptions.MsoOpenstackException;
+import org.springframework.beans.factory.annotation.Autowired;
+import com.woorea.openstack.heat.Heat;
+
+public class MsoHeatUtilsITTest extends BaseTest {
+
+ @Autowired
+ private MsoHeatUtils heatUtils;
+
+ @Test
+ public void instantiateVduTest() throws MsoException, IOException {
+ VduInstance expected = new VduInstance();
+ expected.setVduInstanceId("name/da886914-efb2-4917-b335-c8381528d90b");
+ expected.setVduInstanceName("name");
+ VduStatus status = new VduStatus();
+ status.setState(VduStateType.INSTANTIATED);
+ status.setLastAction((new PluginAction("create", "complete", null)));
+ expected.setStatus(status);
+
+ CloudInfo cloudInfo = new CloudInfo();
+ cloudInfo.setCloudSiteId("MTN13");
+ cloudInfo.setTenantId("tenantId");
+ VduModelInfo vduModel = new VduModelInfo();
+ vduModel.setModelCustomizationUUID("blueprintId");
+ vduModel.setTimeoutMinutes(1);
+ VduArtifact artifact = new VduArtifact();
+ artifact.setName("name");
+ artifact.setType(ArtifactType.MAIN_TEMPLATE);
+ byte[] content = new byte[1];
+ artifact.setContent(content);
+ List<VduArtifact> artifacts = new ArrayList<>();
+ artifacts.add(artifact);
+ vduModel.setArtifacts(artifacts);
+ Map<String, byte[]> blueprintFiles = new HashMap<>();
+ blueprintFiles.put(artifact.getName(), artifact.getContent());
+ String instanceName = "stackname";
+ Map<String, Object> inputs = new HashMap<>();
+ boolean rollbackOnFailure = true;
+
+ StubOpenStack.mockOpenStackResponseAccess(wireMockServer, wireMockPort);
+ StubOpenStack.mockOpenStackPostStack_200(wireMockServer, "OpenstackResponse_Stack_Created.json");
+
+ wireMockServer.stubFor(get(urlPathEqualTo("/mockPublicUrl/stacks/stackname/stackId"))
+ .willReturn(aResponse().withHeader("Content-Type", "application/json")
+ .withBodyFile("OpenstackResponse_StackId.json").withStatus(HttpStatus.SC_OK)));
+
+ VduInstance actual = heatUtils.instantiateVdu(cloudInfo, instanceName, inputs, vduModel, rollbackOnFailure);
+
+ assertThat(actual, sameBeanAs(expected));
+ }
+
+
+ @Test
+ public void queryVduTest() throws Exception {
+ VduInstance expected = new VduInstance();
+ expected.setVduInstanceId("name/da886914-efb2-4917-b335-c8381528d90b");
+ expected.setVduInstanceName("name");
+ VduStatus status = new VduStatus();
+ status.setState(VduStateType.INSTANTIATED);
+ status.setLastAction((new PluginAction("create", "complete", null)));
+ expected.setStatus(status);
+
+ CloudInfo cloudInfo = new CloudInfo();
+ cloudInfo.setCloudSiteId("mtn13");
+ cloudInfo.setTenantId("tenantId");
+ String instanceId = "instanceId";
+
+ StubOpenStack.mockOpenStackResponseAccess(wireMockServer, wireMockPort);
+ StubOpenStack.mockOpenStackPostStack_200(wireMockServer, "OpenstackResponse_Stack_Created.json");
+
+ wireMockServer.stubFor(get(urlPathEqualTo("/mockPublicUrl/stacks/instanceId"))
+ .willReturn(aResponse().withHeader("Content-Type", "application/json")
+ .withBodyFile("OpenstackResponse_StackId.json").withStatus(HttpStatus.SC_OK)));
+
+ VduInstance actual = heatUtils.queryVdu(cloudInfo, instanceId);
+
+ assertThat(actual, sameBeanAs(expected));
+ }
+
+ @Test
+ public void deleteVduTest() throws Exception {
+ VduInstance expected = new VduInstance();
+ expected.setVduInstanceId("instanceId");
+ expected.setVduInstanceName("instanceId");
+ VduStatus status = new VduStatus();
+ status.setState(VduStateType.DELETED);
+ expected.setStatus(status);
+
+ CloudInfo cloudInfo = new CloudInfo();
+ cloudInfo.setCloudSiteId("mtn13");
+ cloudInfo.setTenantId("tenantId");
+ String instanceId = "instanceId";
+
+ int timeoutInMinutes = 1;
+
+ StubOpenStack.mockOpenStackResponseAccess(wireMockServer, wireMockPort);
+ wireMockServer.stubFor(get(urlPathEqualTo("/mockPublicUrl/stacks/instanceId"))
+ .willReturn(aResponse().withBodyFile("OpenstackResponse_StackId.json").withStatus(HttpStatus.SC_OK)));
+ StubOpenStack.mockOpenStackDelete(wireMockServer, "name/da886914-efb2-4917-b335-c8381528d90b");
+ wireMockServer.stubFor(get(urlPathEqualTo("/mockPublicUrl/stacks/name/da886914-efb2-4917-b335-c8381528d90b"))
+ .willReturn(aResponse().withBodyFile("OpenstackResponse_Stack_DeleteComplete.json")
+ .withStatus(HttpStatus.SC_OK)));
+
+ VduInstance actual = heatUtils.deleteVdu(cloudInfo, instanceId, timeoutInMinutes);
+
+ assertThat(actual, sameBeanAs(expected));
+ }
+
+ @Test
+ public final void copyBaseOutputsToInputsTest() {
+ Map<String, Object> inputs = new HashMap<>();
+ inputs.put("str1", "str");
+ Map<String, Object> otherStackOutputs = new HashMap<>();
+ otherStackOutputs.put("str", "str");
+ List<String> paramNames = new ArrayList<>();
+ Map<String, String> aliases = new HashMap<>();
+ aliases.put("str", "str");
+ heatUtils.copyBaseOutputsToInputs(inputs, otherStackOutputs, null, aliases);
+ Assert.assertEquals("str", otherStackOutputs.get("str"));
+ }
+
+ @Test
+ public final void getHeatClientSuccessTest() throws MsoException, IOException {
+ CloudSite cloudSite = getCloudSite(getCloudIdentity());
+ StubOpenStack.mockOpenStackResponseAccess(wireMockServer, wireMockPort);
+ Heat heatClient = heatUtils.getHeatClient("MTN13", "TEST-tenant");
+ assertNotNull(heatClient);
+ }
+
+ @Test(expected = MsoOpenstackException.class)
+ public final void getHeatClientOpenStackResponseException404Test() throws MsoException, IOException {
+ CloudSite cloudSite = getCloudSite(getCloudIdentity());
+ // mo mocks setup will cause 404 response from wiremock
+ heatUtils.getHeatClient("MTN13", "TEST-tenant");
+ }
+
+ @Test(expected = MsoAdapterException.class)
+ public final void getHeatClientOpenStackResponseException401Test() throws MsoException, IOException {
+ CloudSite cloudSite = getCloudSite(getCloudIdentity());
+ StubOpenStack.mockOpenStackResponseUnauthorized(wireMockServer, wireMockPort);
+ heatUtils.getHeatClient("MTN13", "TEST-tenant");
+ }
+
+ @Test(expected = MsoOpenstackException.class)
+ public final void getHeatClientOpenStackConnectExceptionTest() throws MsoException, IOException {
+ CloudIdentity identity = getCloudIdentity();
+ identity.setIdentityUrl("http://unreachable");
+ CloudSite cloudSite = getCloudSite(identity);
+ // mo mocks setup will cause 404 response from wiremock
+ heatUtils.getHeatClient("MTN13", "TEST-tenant");
+ }
+
+ @Test
+ public final void createStackSuccessTest() throws MsoException, IOException {
+ CloudSite cloudSite = getCloudSite(getCloudIdentity());
+ StubOpenStack.mockOpenStackResponseAccess(wireMockServer, wireMockPort);
+ StubOpenStack.mockOpenStackPostStack_200(wireMockServer, "OpenstackResponse_Stack_Created.json");
+ StubOpenStack.mockOpenStackGet(wireMockServer, "TEST-stack/stackId");
+ StackInfo stackInfo = heatUtils.createStack(cloudSite.getId(), "CloudOwner", "tenantId", "TEST-stack",
+ "TEST-heat", new HashMap<>(), false, 1, "TEST-env", new HashMap<>(), new HashMap<>());
+ assertNotNull(stackInfo);
+ }
+
+
+
+}
diff --git a/adapters/mso-adapter-utils/src/test/java/org/onap/so/openstack/utils/MsoHeatUtilsTest.java b/adapters/mso-adapter-utils/src/test/java/org/onap/so/openstack/utils/MsoHeatUtilsTest.java
index 3f5402cc99..5a2515a81e 100644
--- a/adapters/mso-adapter-utils/src/test/java/org/onap/so/openstack/utils/MsoHeatUtilsTest.java
+++ b/adapters/mso-adapter-utils/src/test/java/org/onap/so/openstack/utils/MsoHeatUtilsTest.java
@@ -2,16 +2,14 @@
* ============LICENSE_START=======================================================
* ONAP - SO
* ================================================================================
- * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * Modifications Copyright (c) 2019 Samsung
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -22,214 +20,501 @@
package org.onap.so.openstack.utils;
-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.urlPathEqualTo;
-import static com.shazam.shazamcrest.MatcherAssert.assertThat;
-import static com.shazam.shazamcrest.matcher.Matchers.sameBeanAs;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isA;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.times;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
-import org.apache.http.HttpStatus;
-import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
-import org.onap.so.BaseTest;
-import org.onap.so.StubOpenStack;
-import org.onap.so.adapters.vdu.CloudInfo;
-import org.onap.so.adapters.vdu.PluginAction;
-import org.onap.so.adapters.vdu.VduArtifact;
-import org.onap.so.adapters.vdu.VduArtifact.ArtifactType;
-import org.onap.so.adapters.vdu.VduInstance;
-import org.onap.so.adapters.vdu.VduModelInfo;
-import org.onap.so.adapters.vdu.VduStateType;
-import org.onap.so.adapters.vdu.VduStatus;
-import org.onap.so.db.catalog.beans.CloudIdentity;
-import org.onap.so.db.catalog.beans.CloudSite;
-import org.onap.so.openstack.beans.StackInfo;
-import org.onap.so.openstack.exceptions.MsoAdapterException;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.onap.so.db.request.beans.CloudApiRequests;
+import org.onap.so.db.request.beans.InfraActiveRequests;
+import org.onap.so.db.request.client.RequestsDbClient;
import org.onap.so.openstack.exceptions.MsoException;
-import org.onap.so.openstack.exceptions.MsoIOException;
import org.onap.so.openstack.exceptions.MsoOpenstackException;
-import org.springframework.beans.factory.annotation.Autowired;
+import org.onap.so.openstack.exceptions.MsoStackAlreadyExists;
+import org.springframework.core.env.Environment;
+import com.woorea.openstack.base.client.Entity;
+import com.woorea.openstack.base.client.OpenStackResponseException;
import com.woorea.openstack.heat.Heat;
+import com.woorea.openstack.heat.StackResource;
+import com.woorea.openstack.heat.StackResource.CreateStack;
+import com.woorea.openstack.heat.StackResource.DeleteStack;
import com.woorea.openstack.heat.model.CreateStackParam;
+import com.woorea.openstack.heat.model.Resource;
+import com.woorea.openstack.heat.model.Resources;
+import com.woorea.openstack.heat.model.Stack;
-public class MsoHeatUtilsTest extends BaseTest {
+@RunWith(MockitoJUnitRunner.class)
+public class MsoHeatUtilsTest extends MsoHeatUtils {
- @Autowired
+ @Rule
+ public ExpectedException exceptionRule = ExpectedException.none();
+
+ @Spy
+ @InjectMocks
private MsoHeatUtils heatUtils;
- @Test
- public void instantiateVduTest() throws MsoException, IOException {
- VduInstance expected = new VduInstance();
- expected.setVduInstanceId("name/da886914-efb2-4917-b335-c8381528d90b");
- expected.setVduInstanceName("name");
- VduStatus status = new VduStatus();
- status.setState(VduStateType.INSTANTIATED);
- status.setLastAction((new PluginAction("create", "complete", null)));
- expected.setStatus(status);
+ @Mock
+ private RequestsDbClient requestDbClient;
- CloudInfo cloudInfo = new CloudInfo();
- cloudInfo.setCloudSiteId("MTN13");
- cloudInfo.setTenantId("tenantId");
- VduModelInfo vduModel = new VduModelInfo();
- vduModel.setModelCustomizationUUID("blueprintId");
- vduModel.setTimeoutMinutes(1);
- VduArtifact artifact = new VduArtifact();
- artifact.setName("name");
- artifact.setType(ArtifactType.MAIN_TEMPLATE);
- byte[] content = new byte[1];
- artifact.setContent(content);
- List<VduArtifact> artifacts = new ArrayList<>();
- artifacts.add(artifact);
- vduModel.setArtifacts(artifacts);
- Map<String, byte[]> blueprintFiles = new HashMap<>();
- blueprintFiles.put(artifact.getName(), artifact.getContent());
- String instanceName = "instanceName";
- Map<String, Object> inputs = new HashMap<>();
- boolean rollbackOnFailure = true;
+ @Mock
+ private Heat heatClient;
- StubOpenStack.mockOpenStackResponseAccess(wireMockServer, wireMockPort);
- StubOpenStack.mockOpenStackPostStack_200(wireMockServer, "OpenstackResponse_Stack_Created.json");
+ @Mock
+ private StackStatusHandler stackStatusHandler;
- wireMockServer.stubFor(get(urlPathEqualTo("/mockPublicUrl/stacks/instanceName/stackId"))
- .willReturn(aResponse().withHeader("Content-Type", "application/json")
- .withBodyFile("OpenstackResponse_StackId.json").withStatus(HttpStatus.SC_OK)));
+ @Mock
+ private Environment env;
- VduInstance actual = heatUtils.instantiateVdu(cloudInfo, instanceName, inputs, vduModel, rollbackOnFailure);
+ @Mock
+ private StackResource stackResource;
- assertThat(actual, sameBeanAs(expected));
- }
+ @Mock
+ private NovaClientImpl novaClient;
+
+ @Mock
+ private DeleteStack mockDeleteStack;
+
+ @Mock
+ private Resources mockResources;
+
+ @Mock
+ private CreateStack mockCreateStack;
+
+ private String cloudSiteId = "cloudSiteId";
+ private String tenantId = "tenantId";
+ @Before
+ public void setup() {
+ doReturn("15").when(env).getProperty("org.onap.so.adapters.po.pollInterval", "15");
+ doReturn("1").when(env).getProperty("org.onap.so.adapters.po.pollMultiplier", "60");
+ }
@Test
- public void queryVduTest() throws Exception {
- VduInstance expected = new VduInstance();
- expected.setVduInstanceId("name/da886914-efb2-4917-b335-c8381528d90b");
- expected.setVduInstanceName("name");
- VduStatus status = new VduStatus();
- status.setState(VduStateType.INSTANTIATED);
- status.setLastAction((new PluginAction("create", "complete", null)));
- expected.setStatus(status);
+ public final void pollStackForStatus_Create_Complete_Test() throws MsoException, IOException {
+ Stack stack = new Stack();
+ stack.setId("id");
+ stack.setStackName("stackName");
+ stack.setStackStatus("CREATE_IN_PROGRESS");
+ stack.setStackStatusReason("Stack Finished");
+
+ Stack latestStack = new Stack();
+ latestStack.setId("id");
+ latestStack.setStackName("stackName");
+ latestStack.setStackStatus("CREATE_COMPLETE");
+ latestStack.setStackStatusReason("Stack Finished");
+ doNothing().when(stackStatusHandler).updateStackStatus(stack);
+ doReturn(latestStack).when(heatUtils).queryHeatStack(isA(Heat.class), eq("stackName/id"));
+ doReturn(heatClient).when(heatUtils).getHeatClient(cloudSiteId, tenantId);
+ Stack actual = heatUtils.pollStackForStatus(1, stack, "CREATE_IN_PROGRESS", cloudSiteId, tenantId);
+ Mockito.verify(stackStatusHandler, times(1)).updateStackStatus(stack);
+ Mockito.verify(heatUtils, times(1)).queryHeatStack(isA(Heat.class), eq("stackName/id"));
+ assertEquals(true, actual != null);
+ }
- CloudInfo cloudInfo = new CloudInfo();
- cloudInfo.setCloudSiteId("mtn13");
- cloudInfo.setTenantId("tenantId");
- String instanceId = "instanceId";
- StubOpenStack.mockOpenStackResponseAccess(wireMockServer, wireMockPort);
- StubOpenStack.mockOpenStackPostStack_200(wireMockServer, "OpenstackResponse_Stack_Created.json");
+ @Test
+ public final void pollStackForStatus_Polling_Exhausted_Test() throws MsoException, IOException {
+ Stack stack = new Stack();
+ stack.setId("id");
+ stack.setStackName("stackName");
+ stack.setStackStatus("CREATE_IN_PROGRESS");
+ stack.setStackStatusReason("Stack Finished");
+ doNothing().when(stackStatusHandler).updateStackStatus(stack);
+ doReturn(stack).when(heatUtils).queryHeatStack(isA(Heat.class), eq("stackName/id"));
+ doReturn(heatClient).when(heatUtils).getHeatClient(cloudSiteId, tenantId);
+ Stack actual = heatUtils.pollStackForStatus(1, stack, "CREATE_IN_PROGRESS", cloudSiteId, tenantId);
+ Mockito.verify(stackStatusHandler, times(1)).updateStackStatus(stack);
+ Mockito.verify(heatUtils, times(1)).queryHeatStack(isA(Heat.class), eq("stackName/id"));
+ assertEquals(true, actual != null);
+ }
- wireMockServer.stubFor(get(urlPathEqualTo("/mockPublicUrl/stacks/instanceId"))
- .willReturn(aResponse().withHeader("Content-Type", "application/json")
- .withBodyFile("OpenstackResponse_StackId.json").withStatus(HttpStatus.SC_OK)));
+ @Test
+ public final void postProcessStackCreate_CREATE_IN_PROGRESS_Test() throws MsoException, IOException {
+ Stack stack = new Stack();
+ stack.setId("id");
+ stack.setStackName("stackName");
+ stack.setStackStatus("CREATE_IN_PROGRESS");
+ stack.setStackStatusReason("Stack Finished");
+ CreateStackParam createStackParam = new CreateStackParam();
+ createStackParam.setStackName("stackName");
+
+ exceptionRule.expect(StackCreationException.class);
+ exceptionRule.expectMessage("Stack rollback suppressed, stack not deleted");
+ heatUtils.postProcessStackCreate(stack, false, 120, false, cloudSiteId, tenantId, createStackParam);
+ }
- VduInstance actual = heatUtils.queryVdu(cloudInfo, instanceId);
+ @Test
+ public final void postProcessStackCreate_Backout_True_Test() throws MsoException, IOException {
+ Stack stack = new Stack();
+ stack.setId("id");
+ stack.setStackName("stackName");
+ stack.setStackStatus("CREATE_IN_PROGRESS");
+ stack.setStackStatusReason("Stack Finished");
+
+ Stack deletedStack = new Stack();
+ deletedStack.setId("id");
+ deletedStack.setStackName("stackName");
+ deletedStack.setStackStatus("DELETE_COMPLETE");
+ deletedStack.setStackStatusReason("Stack Deleted");
+
+ CreateStackParam createStackParam = new CreateStackParam();
+ createStackParam.setStackName("stackName");
+ doReturn(deletedStack).when(heatUtils).handleUnknownCreateStackFailure(stack, 120, cloudSiteId, tenantId);
+ exceptionRule.expect(StackCreationException.class);
+ exceptionRule.expectMessage(
+ "Stack Creation Failed Openstack Status: CREATE_IN_PROGRESS Status Reason: Stack Finished , Rollback of Stack Creation completed with status: DELETE_COMPLETE Status Reason: Stack Deleted");
+ heatUtils.postProcessStackCreate(stack, true, 120, false, cloudSiteId, tenantId, createStackParam);
+ Mockito.verify(heatUtils, times(1)).handleUnknownCreateStackFailure(stack, 120, cloudSiteId, tenantId);
+ }
- assertThat(actual, sameBeanAs(expected));
+ @Test
+ public final void postProcessStackCreate_Keypair_True_Test() throws MsoException, IOException {
+ Stack stack = new Stack();
+ stack.setId("id");
+ stack.setStackName("stackName");
+ stack.setStackStatus("CREATE_IN_PROGRESS");
+ stack.setStackStatusReason(
+ "Resource CREATE failed: Conflict: resources.my_keypair: Key pair 'hst3bbfnm0011vm001' already exists. (HTTP 409) (Request-ID: req-941b0af6-63ae-4d6a-afbc-90b728bacf82");
+
+ Stack createdStack = new Stack();
+ createdStack.setId("id");
+ createdStack.setStackName("stackName");
+ createdStack.setStackStatus("CREATE_COMPLETE");
+ createdStack.setStackStatusReason("Stack Created");
+
+ CreateStackParam createStackParam = new CreateStackParam();
+ createStackParam.setStackName("stackName");
+ doReturn(createdStack).when(heatUtils).handleKeyPairConflict(cloudSiteId, tenantId, createStackParam, 120, true,
+ stack);
+ heatUtils.postProcessStackCreate(stack, true, 120, true, cloudSiteId, tenantId, createStackParam);
+ Mockito.verify(heatUtils, times(1)).handleKeyPairConflict(cloudSiteId, tenantId, createStackParam, 120, true,
+ stack);
}
@Test
- public void deleteVduTest() throws Exception {
- VduInstance expected = new VduInstance();
- expected.setVduInstanceId("instanceId");
- expected.setVduInstanceName("instanceId");
- VduStatus status = new VduStatus();
- status.setState(VduStateType.DELETED);
- expected.setStatus(status);
+ public final void handleUnknownCreateStackFailure_Test() throws MsoException, IOException {
+
+ Stack stack = new Stack();
+ stack.setId("id");
+ stack.setStackName("stackName");
+ stack.setStackStatus("CREATE_FAILED");
+ stack.setStackStatusReason(
+ "Resource CREATE failed: Conflict: resources.my_keypair: Key pair 'hst3bbfnm0011vm001' already exists. (HTTP 409) (Request-ID: req-941b0af6-63ae-4d6a-afbc-90b728bacf82");
+
+ Stack deletedStack = new Stack();
+ deletedStack.setId("id");
+ deletedStack.setStackName("stackName");
+ deletedStack.setStackStatus("DELETE_COMPLETE");
+ deletedStack.setStackStatusReason("Stack Deleted");
+
+ CreateStackParam createStackParam = new CreateStackParam();
+ createStackParam.setStackName("stackName");
+ doReturn(heatClient).when(heatUtils).getHeatClient(cloudSiteId, tenantId);
+ doNothing().when(heatUtils).postProcessStackDelete(deletedStack);
+ doReturn(null).when(heatUtils).executeAndRecordOpenstackRequest(mockDeleteStack);
+ doReturn(stackResource).when(heatClient).getStacks();
+ doReturn(mockDeleteStack).when(stackResource).deleteByName("stackName/id");
+ doReturn(deletedStack).when(heatUtils).pollStackForStatus(120, stack, "DELETE_IN_PROGRESS", cloudSiteId,
+ tenantId);
+
+ heatUtils.handleUnknownCreateStackFailure(stack, 120, cloudSiteId, tenantId);
+ Mockito.verify(heatUtils, times(1)).executeAndRecordOpenstackRequest(mockDeleteStack);
+ Mockito.verify(heatUtils, times(1)).pollStackForStatus(120, stack, "DELETE_IN_PROGRESS", cloudSiteId, tenantId);
+ Mockito.verify(heatUtils, times(1)).postProcessStackDelete(deletedStack);
+ }
- CloudInfo cloudInfo = new CloudInfo();
- cloudInfo.setCloudSiteId("mtn13");
- cloudInfo.setTenantId("tenantId");
- String instanceId = "instanceId";
- int timeoutInMinutes = 1;
+ @Test
+ public final void handleUnknownCreateStackFailure_Null_Stack_Test() throws MsoException, IOException {
+ Stack stack = null;
+ exceptionRule.expect(StackCreationException.class);
+ exceptionRule.expectMessage("Cannot Find Stack Name or Id");
+ heatUtils.handleUnknownCreateStackFailure(stack, 120, cloudSiteId, tenantId);
+ }
- StubOpenStack.mockOpenStackResponseAccess(wireMockServer, wireMockPort);
- wireMockServer.stubFor(get(urlPathEqualTo("/mockPublicUrl/stacks/instanceId"))
- .willReturn(aResponse().withBodyFile("OpenstackResponse_StackId.json").withStatus(HttpStatus.SC_OK)));
- StubOpenStack.mockOpenStackDelete(wireMockServer, "name/da886914-efb2-4917-b335-c8381528d90b");
- wireMockServer.stubFor(get(urlPathEqualTo("/mockPublicUrl/stacks/name/da886914-efb2-4917-b335-c8381528d90b"))
- .willReturn(aResponse().withBodyFile("OpenstackResponse_Stack_DeleteComplete.json")
- .withStatus(HttpStatus.SC_OK)));
+ @Test
+ public final void postProcessStackDelete_Stack_Test() throws MsoException, IOException {
+ Stack deletedStack = new Stack();
+ deletedStack.setId("id");
+ deletedStack.setStackName("stackName");
+ deletedStack.setStackStatus("DELETE_FAILED");
+ deletedStack.setStackStatusReason("Stack DID NOT DELETE");
+ exceptionRule.expect(StackRollbackException.class);
+ exceptionRule.expectMessage(
+ "Stack Deletion completed with status: DELETE_FAILED Status Reason: Stack DID NOT DELETE");
+ heatUtils.postProcessStackDelete(deletedStack);
+ }
- VduInstance actual = heatUtils.deleteVdu(cloudInfo, instanceId, timeoutInMinutes);
+ @Test
+ public final void postProcessStackDelete__Null_Stack_Test() throws MsoException, IOException {
+ Stack stack = null;
+ exceptionRule.expect(StackRollbackException.class);
+ exceptionRule.expectMessage("Cannot Find Stack Name or Id");
+ heatUtils.postProcessStackDelete(stack);
+ }
- assertThat(actual, sameBeanAs(expected));
+ @Test
+ public final void isKeyPairFailure_Test() throws MsoException, IOException {
+ boolean actual = heatUtils.isKeyPairFailure(
+ "Exception during create VF 0 : Stack error (CREATE_FAILED): Resource CREATE failed: Conflict: resources.bfnm_my_keypair: Key pair 'hst3bbfnm0011vm001' already exists. (HTTP 409) (Request-ID:req-941b0af6-63ae-4d6a-afbc-90b728bacf82) - stack successfully deleted'rolledBack='true'");
+ assertEquals(true, actual);
}
@Test
- public final void requestToStringBuilderTest() {
- CreateStackParam param = new CreateStackParam();
- param.setDisableRollback(false);
- param.setEnvironment("environment");
- param.setFiles(new HashMap<String, Object>());
- param.setParameters(new HashMap<>());
- param.setStackName("stackName");
- param.setTemplate("template");
- param.setTemplateUrl("http://templateUrl");
- param.setTimeoutMinutes(1);
+ public final void handleKeyPairConflict_Test() throws MsoException, IOException, NovaClientException {
+ Stack stack = new Stack();
+ stack.setId("id");
+ stack.setStackName("stackName");
+ stack.setStackStatus("CREATE_FAILED");
+ stack.setStackStatusReason(
+ "Resource CREATE failed: Conflict: resources.my_keypair: Key pair 'hst3bbfnm0011vm001' already exists. (HTTP 409) (Request-ID: req-941b0af6-63ae-4d6a-afbc-90b728bacf82");
+
+ Stack createdStack = new Stack();
+ createdStack.setId("id");
+ createdStack.setStackName("stackName");
+ createdStack.setStackStatus("CREATE_COMPLETE");
+ createdStack.setStackStatusReason("Stack Created");
+
+
+
+ List<Resource> resources = new ArrayList<>();
+ Resource resource = new Resource();
+ resource.setName("KeypairName");
+ resource.setPhysicalResourceId("KeypairName");
+ resource.setType("OS::Nova::KeyPair");
+ resources.add(resource);
+
+ CreateStackParam createStackParam = new CreateStackParam();
+ createStackParam.setStackName("stackName");
+
+ doReturn(resources).when(mockResources).getList();
+ doReturn(mockResources).when(heatUtils).queryStackResources(cloudSiteId, tenantId, "stackName", 2);
+ doNothing().when(novaClient).deleteKeyPair(cloudSiteId, tenantId, "KeypairName");
+ doReturn(null).when(heatUtils).handleUnknownCreateStackFailure(stack, 120, cloudSiteId, tenantId);
+ doReturn(createdStack).when(heatUtils).createStack(createStackParam, cloudSiteId, tenantId);
+ doReturn(createdStack).when(heatUtils).processCreateStack(cloudSiteId, tenantId, 120, true, createdStack,
+ createStackParam, false);
+
+ heatUtils.handleKeyPairConflict(cloudSiteId, tenantId, createStackParam, 120, true, stack);
+ Mockito.verify(heatUtils, times(1)).queryStackResources(cloudSiteId, tenantId, "stackName", 2);
+ Mockito.verify(novaClient, times(1)).deleteKeyPair(cloudSiteId, tenantId, "KeypairName");
+ Mockito.verify(heatUtils, times(1)).handleUnknownCreateStackFailure(stack, 120, cloudSiteId, tenantId);
+ Mockito.verify(heatUtils, times(1)).createStack(createStackParam, cloudSiteId, tenantId);
+ Mockito.verify(heatUtils, times(1)).processCreateStack(cloudSiteId, tenantId, 120, true, createdStack,
+ createStackParam, false);
+ }
- StringBuilder stringBuilder = heatUtils.requestToStringBuilder(param);
+ @Test
+ public final void processCreateStack_Test() throws MsoException, IOException, NovaClientException {
+ Stack stack = new Stack();
+ stack.setId("id");
+ stack.setStackName("stackName");
+ stack.setStackStatus("CREATE_FAILED");
+ stack.setStackStatusReason(
+ "Resource CREATE failed: Conflict: resources.my_keypair: Key pair 'hst3bbfnm0011vm001' already exists. (HTTP 409) (Request-ID: req-941b0af6-63ae-4d6a-afbc-90b728bacf82");
+
+ Stack createdStack = new Stack();
+ createdStack.setId("id");
+ createdStack.setStackName("stackName");
+ createdStack.setStackStatus("CREATE_COMPLETE");
+ createdStack.setStackStatusReason("Stack Created");
+
+
+ CreateStackParam createStackParam = new CreateStackParam();
+ createStackParam.setStackName("stackName");
+
+ doReturn(createdStack).when(heatUtils).pollStackForStatus(120, stack, "CREATE_IN_PROGRESS", cloudSiteId,
+ tenantId);
+ doReturn(createdStack).when(heatUtils).postProcessStackCreate(createdStack, true, 120, true, cloudSiteId,
+ tenantId, createStackParam);
+
+ heatUtils.processCreateStack(cloudSiteId, tenantId, 120, true, stack, createStackParam, true);
+ Mockito.verify(heatUtils, times(1)).pollStackForStatus(120, stack, "CREATE_IN_PROGRESS", cloudSiteId, tenantId);
+ Mockito.verify(heatUtils, times(1)).postProcessStackCreate(createdStack, true, 120, true, cloudSiteId, tenantId,
+ createStackParam);
+ }
- Assert.assertTrue(stringBuilder.toString().contains("StackName:"));
+ @Test
+ public final void processCreateStack_Exception_Backout_Test()
+ throws MsoException, IOException, NovaClientException {
+ Stack stack = new Stack();
+ stack.setId("id");
+ stack.setStackName("stackName");
+ stack.setStackStatus("CREATE_FAILED");
+ stack.setStackStatusReason(
+ "Resource CREATE failed: Conflict: resources.my_keypair: Key pair 'hst3bbfnm0011vm001' already exists. (HTTP 409) (Request-ID: req-941b0af6-63ae-4d6a-afbc-90b728bacf82");
+
+ Stack deletedStack = new Stack();
+ deletedStack.setId("id");
+ deletedStack.setStackName("stackName");
+ deletedStack.setStackStatus("DELETE_COMPLETE");
+ deletedStack.setStackStatusReason("Stack Deleted");
+
+ CreateStackParam createStackParam = new CreateStackParam();
+ createStackParam.setStackName("stackName");
+
+ doThrow(new StackCreationException("Error")).when(heatUtils).pollStackForStatus(120, stack,
+ "CREATE_IN_PROGRESS", cloudSiteId, tenantId);
+ doReturn(deletedStack).when(heatUtils).handleUnknownCreateStackFailure(stack, 120, cloudSiteId, tenantId);
+ exceptionRule.expect(MsoException.class);
+ exceptionRule.expectMessage("Error");
+ heatUtils.processCreateStack(cloudSiteId, tenantId, 120, true, stack, createStackParam, true);
+ Mockito.verify(heatUtils, times(1)).pollStackForStatus(120, stack, "CREATE_IN_PROGRESS", cloudSiteId, tenantId);
+ Mockito.verify(heatUtils, times(1)).handleUnknownCreateStackFailure(stack, 120, cloudSiteId, tenantId);
}
+
@Test
- public final void copyBaseOutputsToInputsTest() {
- Map<String, Object> inputs = new HashMap<>();
- inputs.put("str1", "str");
- Map<String, Object> otherStackOutputs = new HashMap<>();
- otherStackOutputs.put("str", "str");
- List<String> paramNames = new ArrayList<>();
- Map<String, String> aliases = new HashMap<>();
- aliases.put("str", "str");
- heatUtils.copyBaseOutputsToInputs(inputs, otherStackOutputs, null, aliases);
- Assert.assertEquals("str", otherStackOutputs.get("str"));
+ public final void createStack_Test() throws MsoException, IOException, NovaClientException {
+ CreateStackParam createStackParam = new CreateStackParam();
+ createStackParam.setStackName("stackName");
+
+ doReturn(heatClient).when(heatUtils).getHeatClient(cloudSiteId, tenantId);
+ doReturn(stackResource).when(heatClient).getStacks();
+ doReturn(mockCreateStack).when(stackResource).create(createStackParam);
+
+ doReturn(null).when(heatUtils).executeAndRecordOpenstackRequest(mockCreateStack);
+
+ heatUtils.createStack(createStackParam, cloudSiteId, tenantId);
+ Mockito.verify(stackResource, times(1)).create(createStackParam);
+ Mockito.verify(heatUtils, times(1)).saveStackRequest(eq(mockCreateStack), isNull(), eq("stackName"));
+ Mockito.verify(heatClient, times(1)).getStacks();
+ Mockito.verify(stackResource, times(1)).create(createStackParam);
}
@Test
- public final void getHeatClientSuccessTest() throws MsoException, IOException {
- CloudSite cloudSite = getCloudSite(getCloudIdentity());
- StubOpenStack.mockOpenStackResponseAccess(wireMockServer, wireMockPort);
- Heat heatClient = heatUtils.getHeatClient(cloudSite, "TEST-tenant");
- assertNotNull(heatClient);
+ public final void saveStack_Test() throws MsoException, IOException, NovaClientException {
+ Stack stack = new Stack();
+ stack.setId("id");
+ stack.setStackName("stackName");
+ stack.setStackStatus("CREATE_FAILED");
+ stack.setStackStatusReason(
+ "Resource CREATE failed: Conflict: resources.my_keypair: Key pair 'hst3bbfnm0011vm001' already exists. (HTTP 409) (Request-ID: req-941b0af6-63ae-4d6a-afbc-90b728bacf82");
+ Entity<Stack> entity = new Entity(stack, "application/json");
+ doReturn(entity).when(mockCreateStack).entity();
+ InfraActiveRequests request = new InfraActiveRequests();
+ request.setRequestId("requestId");
+ doReturn(request).when(requestDbClient).getInfraActiveRequestbyRequestId("requestId");
+ doNothing().when(requestDbClient).updateInfraActiveRequests(request);
+ heatUtils.saveStackRequest(mockCreateStack, "requestId", "stackName");
+ Mockito.verify(requestDbClient, times(1)).updateInfraActiveRequests(request);
+ assertNotNull(request.getCloudApiRequests().get(0));
+ assertEquals(request.getCloudApiRequests().get(0).getRequestId(), "requestId");
}
- @Test(expected = MsoOpenstackException.class)
- public final void getHeatClientOpenStackResponseException404Test() throws MsoException, IOException {
- CloudSite cloudSite = getCloudSite(getCloudIdentity());
- // mo mocks setup will cause 404 response from wiremock
- heatUtils.getHeatClient(cloudSite, "TEST-tenant");
+ @Test
+ public final void saveStack__Exists_Test() throws MsoException, IOException, NovaClientException {
+ Stack stack = new Stack();
+ stack.setId("id");
+ stack.setStackName("stackName");
+ stack.setStackStatus("CREATE_FAILED");
+ stack.setStackStatusReason(
+ "Resource CREATE failed: Conflict: resources.my_keypair: Key pair 'hst3bbfnm0011vm001' already exists. (HTTP 409) (Request-ID: req-941b0af6-63ae-4d6a-afbc-90b728bacf82");
+ Entity<Stack> entity = new Entity(stack, "application/json");
+ doReturn(entity).when(mockCreateStack).entity();
+ InfraActiveRequests request = new InfraActiveRequests();
+ request.setRequestId("requestId");
+ CloudApiRequests cloudRequest = new CloudApiRequests();
+ cloudRequest.setCloudIdentifier("stackName");
+ cloudRequest.setRequestBody("testMe");
+ cloudRequest.setRequestId("requestId");
+ request.getCloudApiRequests().add(cloudRequest);
+ doReturn(request).when(requestDbClient).getInfraActiveRequestbyRequestId("requestId");
+ doNothing().when(requestDbClient).updateInfraActiveRequests(request);
+ heatUtils.saveStackRequest(mockCreateStack, "requestId", "stackName");
+ Mockito.verify(requestDbClient, times(1)).updateInfraActiveRequests(request);
+ assertNotNull(request.getCloudApiRequests().get(0));
+ assertEquals("requestId", request.getCloudApiRequests().get(0).getRequestId());
+ assertNotEquals("testMe", request.getCloudApiRequests().get(0).getRequestBody());
}
- @Test(expected = MsoAdapterException.class)
- public final void getHeatClientOpenStackResponseException401Test() throws MsoException, IOException {
- CloudSite cloudSite = getCloudSite(getCloudIdentity());
- StubOpenStack.mockOpenStackResponseUnauthorized(wireMockServer, wireMockPort);
- heatUtils.getHeatClient(cloudSite, "TEST-tenant");
+ @Test
+ public final void createStack_Error_Test() throws MsoException, IOException, NovaClientException {
+ CreateStackParam createStackParam = new CreateStackParam();
+ createStackParam.setStackName("stackName");
+
+ doReturn(heatClient).when(heatUtils).getHeatClient(cloudSiteId, tenantId);
+ doReturn(stackResource).when(heatClient).getStacks();
+ doReturn(mockCreateStack).when(stackResource).create(createStackParam);
+
+ doThrow(new OpenStackResponseException("Unknown Error", 500)).when(heatUtils)
+ .executeAndRecordOpenstackRequest(mockCreateStack);
+ exceptionRule.expect(MsoOpenstackException.class);
+ exceptionRule.expectMessage("Unknown Error");
+ heatUtils.createStack(createStackParam, cloudSiteId, tenantId);
+ Mockito.verify(stackResource, times(1)).create(createStackParam);
+ Mockito.verify(heatUtils, times(1)).saveStackRequest(eq(mockCreateStack), isNull(), eq("stackName"));
+ Mockito.verify(heatClient, times(1)).getStacks();
+ Mockito.verify(stackResource, times(1)).create(createStackParam);
}
- @Test(expected = MsoIOException.class)
- public final void getHeatClientOpenStackConnectExceptionTest() throws MsoException, IOException {
- CloudIdentity identity = getCloudIdentity();
- identity.setIdentityUrl("http://unreachable");
- CloudSite cloudSite = getCloudSite(identity);
- // mo mocks setup will cause 404 response from wiremock
- heatUtils.getHeatClient(cloudSite, "TEST-tenant");
+ @Test
+ public final void createStack_Error_404_Test() throws MsoException, IOException, NovaClientException {
+ CreateStackParam createStackParam = new CreateStackParam();
+ createStackParam.setStackName("stackName");
+
+ doReturn(heatClient).when(heatUtils).getHeatClient(cloudSiteId, tenantId);
+ doReturn(stackResource).when(heatClient).getStacks();
+ doReturn(mockCreateStack).when(stackResource).create(createStackParam);
+
+ doThrow(new OpenStackResponseException("Not Found", 409)).when(heatUtils)
+ .executeAndRecordOpenstackRequest(mockCreateStack);
+ exceptionRule.expect(MsoStackAlreadyExists.class);
+ exceptionRule.expectMessage("Stack stackName already exists in Tenant tenantId in Cloud cloudSiteId");
+ heatUtils.createStack(createStackParam, cloudSiteId, tenantId);
+ Mockito.verify(stackResource, times(1)).create(createStackParam);
+ Mockito.verify(heatUtils, times(1)).saveStackRequest(eq(mockCreateStack), isNull(), eq("stackName"));
+ Mockito.verify(heatClient, times(1)).getStacks();
+ Mockito.verify(stackResource, times(1)).create(createStackParam);
}
@Test
- public final void createStackSuccessTest() throws MsoException, IOException {
- CloudSite cloudSite = getCloudSite(getCloudIdentity());
- StubOpenStack.mockOpenStackResponseAccess(wireMockServer, wireMockPort);
- StubOpenStack.mockOpenStackPostStack_200(wireMockServer, "OpenstackResponse_Stack_Created.json");
- StubOpenStack.mockOpenStackGet(wireMockServer, "TEST-stack/stackId");
- StackInfo stackInfo = heatUtils.createStack(cloudSite.getId(), "CloudOwner", "tenantId", "TEST-stack", null,
- "TEST-heat", new HashMap<>(), false, 1, "TEST-env", new HashMap<>(), new HashMap<>(), false);
- assertNotNull(stackInfo);
+ public final void processCreateStack_Exception_No_Backout_Test()
+ throws MsoException, IOException, NovaClientException {
+ Stack stack = new Stack();
+ stack.setId("id");
+ stack.setStackName("stackName");
+ stack.setStackStatus("CREATE_FAILED");
+ stack.setStackStatusReason(
+ "Resource CREATE failed: Conflict: resources.my_keypair: Key pair 'hst3bbfnm0011vm001' already exists. (HTTP 409) (Request-ID: req-941b0af6-63ae-4d6a-afbc-90b728bacf82");
+
+ Stack deletedStack = new Stack();
+ deletedStack.setId("id");
+ deletedStack.setStackName("stackName");
+ deletedStack.setStackStatus("DELETE_COMPLETE");
+ deletedStack.setStackStatusReason("Stack Deleted");
+
+ CreateStackParam createStackParam = new CreateStackParam();
+ createStackParam.setStackName("stackName");
+
+ doThrow(new StackCreationException("Error")).when(heatUtils).pollStackForStatus(120, stack,
+ "CREATE_IN_PROGRESS", cloudSiteId, tenantId);
+
+ exceptionRule.expect(MsoException.class);
+ exceptionRule.expectMessage("Error");
+ heatUtils.processCreateStack(cloudSiteId, tenantId, 120, false, stack, createStackParam, true);
+ Mockito.verify(heatUtils, times(1)).pollStackForStatus(120, stack, "CREATE_IN_PROGRESS", cloudSiteId, tenantId);
+ Mockito.verify(heatUtils, times(0)).handleUnknownCreateStackFailure(stack, 120, cloudSiteId, tenantId);
}
+
}
diff --git a/adapters/mso-adapter-utils/src/test/java/org/onap/so/openstack/utils/MsoHeatUtilsWithUpdateTest.java b/adapters/mso-adapter-utils/src/test/java/org/onap/so/openstack/utils/MsoHeatUtilsWithUpdateTest.java
index 8951f8a304..acd42dd8da 100644
--- a/adapters/mso-adapter-utils/src/test/java/org/onap/so/openstack/utils/MsoHeatUtilsWithUpdateTest.java
+++ b/adapters/mso-adapter-utils/src/test/java/org/onap/so/openstack/utils/MsoHeatUtilsWithUpdateTest.java
@@ -22,10 +22,8 @@ package org.onap.so.openstack.utils;
import static com.shazam.shazamcrest.matcher.Matchers.sameBeanAs;
import static org.junit.Assert.assertThat;
-import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.verify;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
@@ -98,7 +96,7 @@ public class MsoHeatUtilsWithUpdateTest extends TestDataSetup {
expectedStackInfo.setCanonicalName("stackName/id");
doReturn(Optional.of(cloudSite)).when(cloudConfig).getCloudSite(isA(String.class));
- doReturn(heatClient).when(heatUtils).getHeatClient(isA(CloudSite.class), isA(String.class));
+ doReturn(heatClient).when(heatUtils).getHeatClient(isA(String.class), isA(String.class));
doReturn(null).when(heatUtils).executeAndRecordOpenstackRequest(isA(OpenStackRequest.class));
doReturn("0").when(environment).getProperty(isA(String.class), isA(String.class));
doReturn(updateStack).when(heatUtils).queryHeatStack(isA(Heat.class), isA(String.class));
@@ -123,7 +121,7 @@ public class MsoHeatUtilsWithUpdateTest extends TestDataSetup {
expectedStackInfo.setCanonicalName("stackName/id");
doReturn(Optional.of(cloudSite)).when(cloudConfig).getCloudSite(isA(String.class));
- doReturn(heatClient).when(heatUtils).getHeatClient(isA(CloudSite.class), isA(String.class));
+ doReturn(heatClient).when(heatUtils).getHeatClient(isA(String.class), isA(String.class));
doReturn(null).when(heatUtils).executeAndRecordOpenstackRequest(isA(OpenStackRequest.class));
doReturn("0").when(environment).getProperty(isA(String.class), isA(String.class));
@@ -150,7 +148,7 @@ public class MsoHeatUtilsWithUpdateTest extends TestDataSetup {
expectedStackInfo.setCanonicalName("stackName/id");
doReturn(Optional.of(cloudSite)).when(cloudConfig).getCloudSite(isA(String.class));
- doReturn(heatClient).when(heatUtils).getHeatClient(isA(CloudSite.class), isA(String.class));
+ doReturn(heatClient).when(heatUtils).getHeatClient(isA(String.class), isA(String.class));
doReturn(null).when(heatUtils).executeAndRecordOpenstackRequest(isA(OpenStackRequest.class));
doReturn("0").when(environment).getProperty(isA(String.class), isA(String.class));
doReturn(updateStack).when(heatUtils).queryHeatStack(isA(Heat.class), isA(String.class));
diff --git a/adapters/mso-adapter-utils/src/test/java/org/onap/so/openstack/utils/StackStatusHandlerTest.java b/adapters/mso-adapter-utils/src/test/java/org/onap/so/openstack/utils/StackStatusHandlerTest.java
new file mode 100644
index 0000000000..54e2bbf06d
--- /dev/null
+++ b/adapters/mso-adapter-utils/src/test/java/org/onap/so/openstack/utils/StackStatusHandlerTest.java
@@ -0,0 +1,69 @@
+package org.onap.so.openstack.utils;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import java.io.IOException;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.onap.so.db.request.beans.RequestProcessingData;
+import org.onap.so.db.request.client.RequestsDbClient;
+import org.onap.so.openstack.exceptions.MsoException;
+import com.woorea.openstack.heat.model.Stack;
+
+@RunWith(MockitoJUnitRunner.class)
+public class StackStatusHandlerTest {
+
+ @InjectMocks
+ StackStatusHandler statusHandler;
+
+ @Mock
+ RequestsDbClient requestDBClient;
+
+ @Test
+ public final void recordExists_Test() throws MsoException, IOException {
+ RequestProcessingData requestProcessingData = new RequestProcessingData();
+ requestProcessingData.setValue("testMe");
+
+ doReturn(requestProcessingData).when(requestDBClient)
+ .getRequestProcessingDataBySoRequestIdAndNameAndGrouping(null, "id", "stackName");
+ Stack latestStack = new Stack();
+ latestStack.setId("id");
+ latestStack.setStackName("stackName");
+ latestStack.setStackStatus("CREATE_COMPLETE");
+ latestStack.setStackStatusReason("Stack Finished");
+
+ statusHandler.updateStackStatus(latestStack);
+ Mockito.verify(requestDBClient, times(1)).updateRequestProcessingData(requestProcessingData);
+ assertNotEquals("testMe", requestProcessingData.getValue());
+ }
+
+ @Test
+ public final void record_Not_Exists_Test() throws MsoException, IOException {
+ ArgumentCaptor<RequestProcessingData> requestCaptor = ArgumentCaptor.forClass(RequestProcessingData.class);
+ doReturn(null).when(requestDBClient).getRequestProcessingDataBySoRequestIdAndNameAndGrouping(null, "id",
+ "stackName");
+ Stack latestStack = new Stack();
+ latestStack.setId("id");
+ latestStack.setStackName("stackName");
+ latestStack.setStackStatus("CREATE_COMPLETE");
+ latestStack.setStackStatusReason("Stack Finished");
+ statusHandler.updateStackStatus(latestStack);
+ Mockito.verify(requestDBClient, times(1)).saveRequestProcessingData(requestCaptor.capture());
+ RequestProcessingData actualRequest = requestCaptor.getValue();
+ assertEquals("id", actualRequest.getGroupingId());
+ assertEquals("StackInformation", actualRequest.getTag());
+ assertEquals("stackName", actualRequest.getName());
+ assertNotNull(actualRequest.getValue());
+
+ }
+
+
+}
diff --git a/adapters/mso-adapter-utils/src/test/resources/__files/OpenstackResponse_Stack_Created.json b/adapters/mso-adapter-utils/src/test/resources/__files/OpenstackResponse_Stack_Created.json
index 477acadf81..7eae6d14a4 100644
--- a/adapters/mso-adapter-utils/src/test/resources/__files/OpenstackResponse_Stack_Created.json
+++ b/adapters/mso-adapter-utils/src/test/resources/__files/OpenstackResponse_Stack_Created.json
@@ -2,7 +2,7 @@
"stack": {
"description": null,
"links": null,
- "stack_status_reason": null,
+ "stack_status_reason": "Stack Created",
"stack_name": "stackname",
"updated_time": null,
"creation_time": null,