diff options
24 files changed, 1150 insertions, 951 deletions
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 a6a2f8402f..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 @@ -127,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) { @@ -152,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) { @@ -223,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; } @@ -435,7 +424,7 @@ public class MsoCommonUtils { /** - * Gets the Nova client + * Gets the Keystone Authorization * * @param cloudSite the cloud site * @param tenantId the tenant id 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 376ed20ed0..683bb28726 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 @@ -31,6 +31,8 @@ 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; @@ -43,15 +45,11 @@ 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; @@ -59,15 +57,12 @@ 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; @@ -77,28 +72,31 @@ 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; -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; + @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 DELETE_IN_PROGRESS = "DELETE_IN_PROGRESS"; - private static final String QUERY_ALL_STACKS = "QueryAllStacks"; + private static final String CREATE_IN_PROGRESS = "CREATE_IN_PROGRESS"; private static final String DELETE_STACK = "DeleteStack"; @@ -118,29 +116,25 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin { private Environment environment; @Autowired - private AuthenticationMethodFactory authenticationMethodFactory; - - @Autowired - private MsoTenantUtilsFactory tenantUtilsFactory; - - @Autowired - private KeystoneV3Authentication keystoneV3Authentication; - - @Autowired RequestsDbClient requestDBClient; @Autowired StackStatusHandler statusHandler; + @Autowired + NovaClientImpl novaClient; + private static final Logger logger = LoggerFactory.getLogger(MsoHeatUtils.class); // Properties names and variables (with default values) 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 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(); @@ -225,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)) { @@ -234,36 +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); - saveStackRequest(request, MDC.get(ONAPLogConstants.MDCs.REQUEST_ID), stackName); - 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) { @@ -271,24 +269,79 @@ 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; + } + } + + 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) { + 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; + } + sleep(pollingFrequency * 1000L); + numberOfPollingAttempts -= 1; + } else { + return latestStack; + } } - return new StackInfoMapper(heatStack).map(); } - private void saveStackRequest(OpenStackRequest<Stack> request, String requestId, String stackName) { + protected void saveStackRequest(OpenStackRequest<Stack> request, String requestId, String stackName) { try { ObjectMapper mapper = new ObjectMapper(); InfraActiveRequests foundRequest = requestDBClient.getInfraActiveRequestbyRequestId(requestId); @@ -304,209 +357,53 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin { } } - 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, CREATE_POLL_INTERVAL_DEFAULT)); - int pollTimeout = (timeoutMinutes * 60) + createPollInterval; - int deletePollInterval = createPollInterval; - int deletePollTimeout = pollTimeout; - boolean createTimedOut = false; - StringBuilder stackErrorStatusReason = new StringBuilder(""); - logger.debug("createPollInterval={}, pollTimeout={}", createPollInterval, pollTimeout); - - while (true) { - try { - heatStack = queryHeatStack(heatClient, canonicalName); - statusHandler.updateStackStatus(heatStack, MDC.get(ONAPLogConstants.MDCs.REQUEST_ID)); - 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); - } + protected boolean isKeyPairFailure(String errorMessage) { + return Pattern.compile(".*Key pair.*already exists.*").matcher(errorMessage).matches(); + } - 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; - } - } 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); - statusHandler.updateStackStatus(heatStack, MDC.get(ONAPLogConstants.MDCs.REQUEST_ID)); - 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(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(EXCEPTION_ROLLING_BACK_STACK, MessageEnum.RA_CREATE_STACK_ERR, - ErrorCode.BusinessProcesssError.getValue(), e2); - } - } + 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"); + } + } - // Propagate the original exception from Stack Query. - me.addContext(CREATE_STACK); - throw me; - } + 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"); } + } - 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()); + 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"); - // 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()); - } 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(EXCEPTION_ROLLING_BACK_STACK, MessageEnum.RA_CREATE_STACK_ERR, - ErrorCode.BusinessProcesssError.getValue(), e2); - } + 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); } - MsoOpenstackException me = new MsoOpenstackException(0, "", stackErrorStatusReason.toString()); - me.addContext(CREATE_STACK); - throw me; - } - return heatStack; + }); + handleUnknownCreateStackFailure(stack, timeoutMinutes, cloudSiteId, tenantId); + Stack newStack = createStack(stackCreate, cloudSiteId, tenantId); + newStack.setStackName(stackCreate.getStackName()); + return processCreateStack(cloudSiteId, tenantId, timeoutMinutes, backout, newStack, stackCreate, false); } /** @@ -523,19 +420,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); @@ -583,11 +470,9 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin { */ public StackInfo deleteStack(String tenantId, String cloudOwner, String cloudSiteId, String stackName, boolean pollForCompletion) throws MsoException { - CloudSite cloudSite = - cloudConfig.getCloudSite(cloudSiteId).orElseThrow(() -> new MsoCloudSiteNotFound(cloudSiteId)); Heat heatClient = null; try { - heatClient = getHeatClient(cloudSite, tenantId); + heatClient = getHeatClient(cloudSiteId, tenantId); } catch (MsoTenantNotFound e) { logger.debug("Tenant with id " + tenantId + "not found.", e); return new StackInfo(stackName, HeatStatus.NOTFOUND); @@ -600,7 +485,7 @@ 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); } @@ -637,16 +522,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, MDC.get(ONAPLogConstants.MDCs.REQUEST_ID)); + statusHandler.updateStackStatus(heatStack); if (pollForCompletion) { int pollInterval = Integer .parseInt(this.environment.getProperty(deletePollIntervalProp, "" + DELETE_POLL_INTERVAL_DEFAULT)); int pollTimeout = Integer .parseInt(this.environment.getProperty(deletePollTimeoutProp, "" + DELETE_POLL_INTERVAL_DEFAULT)); - statusHandler.updateStackStatus(heatStack, MDC.get(ONAPLogConstants.MDCs.REQUEST_ID)); + 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())) { @@ -695,58 +580,6 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin { } /** - * 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 @@ -802,8 +635,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 @@ -815,76 +646,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; - 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 { - logger.debug("access={}", access.toString()); - 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(); - } else if (ServerType.KEYSTONE_V3.equals(cloudIdentity.getIdentityServerType())) { - try { - KeystoneAuthHolder holder = keystoneV3Authentication.getToken(cloudSite, tenantId, "orchestration"); - tokenId = holder.getId(); - 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; } @@ -928,6 +693,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 { @@ -990,42 +762,6 @@ 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); @@ -1193,44 +929,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(); @@ -1238,7 +962,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; @@ -1507,9 +1230,7 @@ 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); @@ -1517,9 +1238,7 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin { public Events queryStackEvents(String cloudSiteId, String tenantId, String stackName, String stackId, int nestedDepth) throws MsoException { - CloudSite cloudSite = - cloudConfig.getCloudSite(cloudSiteId).orElseThrow(() -> new MsoCloudSiteNotFound(cloudSiteId)); - Heat heatClient = getHeatClient(cloudSite, tenantId); + Heat heatClient = getHeatClient(cloudSiteId, tenantId); OpenStackRequest<Events> request = heatClient.getEvents().listEvents(stackName, stackId).queryParam("nested_depth", nestedDepth); return executeAndRecordOpenstackRequest(request); @@ -1527,11 +1246,9 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin { public Stacks queryStacks(String cloudSiteId, String tenantId, int limit, String marker) throws MsoCloudSiteNotFound, HeatClientException { - CloudSite cloudSite = - cloudConfig.getCloudSite(cloudSiteId).orElseThrow(() -> new MsoCloudSiteNotFound(cloudSiteId)); Heat heatClient; try { - heatClient = getHeatClient(cloudSite, tenantId); + heatClient = getHeatClient(cloudSiteId, tenantId); } catch (MsoException e) { logger.error("Error Creating Heat Client", e); throw new HeatClientException("Error Creating Heat Client", e); @@ -1543,9 +1260,7 @@ public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin { 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 a2e386adea..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 { @@ -138,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); 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 ab93a6c4c6..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,6 +41,19 @@ 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 { @@ -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/NovaClientImpl.java b/adapters/mso-adapter-utils/src/main/java/org/onap/so/openstack/utils/NovaClientImpl.java index a342f770ef..6cd79de476 100644 --- 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 @@ -183,4 +183,25 @@ public class NovaClientImpl extends MsoCommonUtils { } } + /** + * 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 index 990e9a4543..53337b33f8 100644 --- 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 @@ -1,10 +1,12 @@ 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; @@ -21,8 +23,9 @@ public class StackStatusHandler { private RequestsDbClient requestDBClient; @Async - public void updateStackStatus(Stack stack, String requestId) { + 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(), 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..1d38bc2431 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,446 @@ 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 static org.junit.Assert.assertEquals; +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.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.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 Heat heatClient; - 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 StackStatusHandler stackStatusHandler; - StubOpenStack.mockOpenStackResponseAccess(wireMockServer, wireMockPort); - StubOpenStack.mockOpenStackPostStack_200(wireMockServer, "OpenstackResponse_Stack_Created.json"); + @Mock + private Environment env; - 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 StackResource stackResource; - VduInstance actual = heatUtils.instantiateVdu(cloudInfo, instanceName, inputs, vduModel, rollbackOnFailure); + @Mock + private NovaClientImpl novaClient; - assertThat(actual, sameBeanAs(expected)); - } + @Mock + private DeleteStack mockDeleteStack; + @Mock + private Resources mockResources; - @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); + @Mock + private CreateStack mockCreateStack; - CloudInfo cloudInfo = new CloudInfo(); - cloudInfo.setCloudSiteId("mtn13"); - cloudInfo.setTenantId("tenantId"); - String instanceId = "instanceId"; + private String cloudSiteId = "cloudSiteId"; + private String tenantId = "tenantId"; - StubOpenStack.mockOpenStackResponseAccess(wireMockServer, wireMockPort); - StubOpenStack.mockOpenStackPostStack_200(wireMockServer, "OpenstackResponse_Stack_Created.json"); + @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 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); + } - 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); + @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); + } - assertThat(actual, sameBeanAs(expected)); + @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); } @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 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); + } - CloudInfo cloudInfo = new CloudInfo(); - cloudInfo.setCloudSiteId("mtn13"); - cloudInfo.setTenantId("tenantId"); - String instanceId = "instanceId"; + @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); + } - int timeoutInMinutes = 1; + @Test + 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); + } - 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); + @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); + } - assertThat(actual, sameBeanAs(expected)); + @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); } @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 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); + } - StringBuilder stringBuilder = heatUtils.requestToStringBuilder(param); + @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); + } - Assert.assertTrue(stringBuilder.toString().contains("StackName:")); + @Test + 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); } @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 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); } @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 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(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 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(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/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, diff --git a/adapters/mso-adapters-rest-interface/src/main/java/org/onap/so/openstack/beans/HostRoute.java b/adapters/mso-adapters-rest-interface/src/main/java/org/onap/so/openstack/beans/HostRoute.java index 431870ba9e..afe9d71e92 100644 --- a/adapters/mso-adapters-rest-interface/src/main/java/org/onap/so/openstack/beans/HostRoute.java +++ b/adapters/mso-adapters-rest-interface/src/main/java/org/onap/so/openstack/beans/HostRoute.java @@ -20,16 +20,16 @@ package org.onap.so.openstack.beans; - - +import java.io.Serializable; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlType; @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "", propOrder = {"prefix", "nextHop"}) -public class HostRoute { +public class HostRoute implements Serializable { + private static final long serialVersionUID = 2468793257174064133L; private String prefix; private String nextHop; diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/audit/AuditStackService.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/audit/AuditStackService.java index 57d31bf308..f354e6c532 100644 --- a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/audit/AuditStackService.java +++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/audit/AuditStackService.java @@ -71,7 +71,7 @@ public class AuditStackService { ClientRequestInterceptor interceptor = createClientRequestInterceptor(); ExternalTaskClient client = ExternalTaskClient.create() .baseUrl(env.getRequiredProperty("mso.workflow.endpoint")).maxTasks(1).addInterceptor(interceptor) - .asyncResponseTimeout(120000).backoffStrategy(new ExponentialBackoffStrategy(10000, 2, 120000)).build(); + .asyncResponseTimeout(120000).backoffStrategy(new ExponentialBackoffStrategy(0, 0, 0)).build(); return client; } diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfAdapterImpl.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfAdapterImpl.java index bac41a1f8b..352cd7b554 100644 --- a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfAdapterImpl.java +++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfAdapterImpl.java @@ -64,9 +64,9 @@ import org.onap.so.db.catalog.data.repository.VFModuleCustomizationRepository; import org.onap.so.db.catalog.data.repository.VnfResourceRepository; import org.onap.so.db.catalog.utils.MavenLikeVersioning; import org.onap.so.entity.MsoRequest; -import org.onap.so.logger.ErrorCode; import org.onap.so.heatbridge.HeatBridgeApi; import org.onap.so.heatbridge.HeatBridgeImpl; +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; @@ -79,10 +79,6 @@ import org.onap.so.openstack.exceptions.MsoHeatNotFoundException; import org.onap.so.openstack.utils.MsoHeatEnvironmentEntry; import org.onap.so.openstack.utils.MsoHeatUtils; import org.onap.so.openstack.utils.MsoHeatUtilsWithUpdate; -import org.openstack4j.model.compute.Flavor; -import org.openstack4j.model.compute.Image; -import org.openstack4j.model.compute.Server; -import org.openstack4j.model.heat.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -92,6 +88,10 @@ import org.springframework.transaction.annotation.Transactional; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import org.openstack4j.model.compute.Flavor; +import org.openstack4j.model.compute.Image; +import org.openstack4j.model.compute.Server; +import org.openstack4j.model.heat.Resource; @WebService(serviceName = "VnfAdapter", endpointInterface = "org.onap.so.adapters.vnf.MsoVnfAdapter", targetNamespace = "http://org.onap.so/vnf") @@ -107,6 +107,7 @@ public class MsoVnfAdapterImpl implements MsoVnfAdapter { private static final Logger logger = LoggerFactory.getLogger(MsoVnfAdapterImpl.class); + private static final String VNF_ADAPTER_SERVICE_NAME = "MSO-BPMN:MSO-VnfAdapter."; private static final String CHECK_REQD_PARAMS = "org.onap.so.adapters.vnf.checkRequiredParameters"; private static final String ADD_GET_FILES_ON_VOLUME_REQ = "org.onap.so.adapters.vnf.addGetFilesOnVolumeReq"; @@ -116,6 +117,8 @@ public class MsoVnfAdapterImpl implements MsoVnfAdapter { "org.onap.so.adapters.vnf.fail_requests_on_valet_failure"; private static final String OPENSTACK = "OpenStack"; + + @Autowired private VFModuleCustomizationRepository vfModuleCustomRepo; @@ -606,7 +609,7 @@ public class MsoVnfAdapterImpl implements MsoVnfAdapter { requestTypeString = requestTypeString.substring(1); } - // 1607 - let's parse out the request type we're being sent + // let's parse out the request type we're being sent boolean isBaseRequest = false; boolean isVolumeRequest = false; if (requestTypeString.startsWith("VOLUME")) { @@ -615,8 +618,6 @@ public class MsoVnfAdapterImpl implements MsoVnfAdapter { logger.debug("requestTypeString = " + requestTypeString + ", nestedStackId = " + nestedStackId + ", nestedBaseStackId = " + nestedBaseStackId); - // Will capture execution time for metrics - long startTime = System.currentTimeMillis(); // Build a default rollback object (no actions performed) VnfRollback vfRollback = new VnfRollback(); @@ -636,7 +637,6 @@ public class MsoVnfAdapterImpl implements MsoVnfAdapter { } StackInfo heatStack = null; - long subStartTime1 = System.currentTimeMillis(); try { heatStack = heat.queryStack(cloudSiteId, cloudOwner, tenantId, vfModuleName); } catch (MsoException me) { @@ -651,7 +651,7 @@ public class MsoVnfAdapterImpl implements MsoVnfAdapter { me.addContext("CreateVFModule"); throw new VnfException(me); } - // New with 1607 - more precise handling/messaging if the stack already exists + // more precise handling/messaging if the stack already exists if (heatStack != null && heatStack.getStatus() != HeatStatus.NOTFOUND) { // INIT, CREATED, NOTFOUND, FAILED, BUILDING, DELETING, UNKNOWN, UPDATING, UPDATED HeatStatus status = heatStack.getStatus(); @@ -716,7 +716,7 @@ public class MsoVnfAdapterImpl implements MsoVnfAdapter { // handle a nestedStackId if sent- this one would be for the volume - so applies to both Vf and Vnf StackInfo nestedHeatStack = null; - long subStartTime2 = System.currentTimeMillis(); + Map<String, Object> nestedVolumeOutputs = null; if (nestedStackId != null) { try { @@ -751,7 +751,6 @@ public class MsoVnfAdapterImpl implements MsoVnfAdapter { // handle a nestedBaseStackId if sent- this is the stack ID of the base. Should be null for VNF requests StackInfo nestedBaseHeatStack = null; - long subStartTime3 = System.currentTimeMillis(); Map<String, Object> baseStackOutputs = null; if (nestedBaseStackId != null) { try { @@ -785,25 +784,19 @@ public class MsoVnfAdapterImpl implements MsoVnfAdapter { } } - // Ready to deploy the new VNF - - - try { // Retrieve the VF VfModule vf = null; VnfResource vnfResource = null; VfModuleCustomization vfmc = null; - logger.debug("version: {}", vfVersion); if (useMCUuid) { - // 1707 - db refactoring vfmc = vfModuleCustomRepo.findFirstByModelCustomizationUUIDOrderByCreatedDesc(mcu); if (vfmc != null) vf = vfmc.getVfModule(); else vf = null; - // 1702 - this will be the new way going forward. We find the vf by mcu - otherwise, code is the same. + // this will be the new way going forward. We find the vf by mcu - otherwise, code is the same. if (vf == null) { logger.debug("Unable to find vfModuleCust with modelCustomizationUuid={}", mcu); String error = @@ -846,7 +839,7 @@ public class MsoVnfAdapterImpl implements MsoVnfAdapter { } // By here - we have either a vf or vnfResource - // 1607 - Add version check + // Add version check // First - see if it's in the VnfResource record // if we have a vf Module - then we have to query to get the VnfResource record. if (!oldWay && vf.getVnfResources() != null) { @@ -894,7 +887,7 @@ public class MsoVnfAdapterImpl implements MsoVnfAdapter { equalToMax = aicV.isTheSameVersion(maxVersionVnf); } catch (Exception e) { logger.debug( - "An exception occurred while trying to test AIC Version {} - will default to not check", + "An exception occurred while trying to test Cloud Version {} - will default to not check", e.getMessage(), e); doNotTest = true; } @@ -917,20 +910,13 @@ public class MsoVnfAdapterImpl implements MsoVnfAdapter { throw new VnfException(error, MsoExceptionCategory.USERDATA); } } else { - logger.debug("bypassing testing AIC version..."); + logger.debug("bypassing testing Cloud version..."); } } // let this error out downstream to avoid introducing uncertainty at this stage } else { logger.debug("cloudConfig is NULL - cannot check cloud site version"); } - } else { - logger.debug( - "AIC Version not set in VNF_Resource - this is expected thru 1607 - do not error here - not checked" - + "."); } - // End Version check 1607 - - // By the time we get here - heatTemplateId and heatEnvtId should be populated (or null) HeatTemplate heatTemplate = null; @@ -994,7 +980,7 @@ public class MsoVnfAdapterImpl implements MsoVnfAdapter { nestedTemplatesChecked = null; } - // 1510 - Also add the files: for any get_files associated with this vnf_resource_id + // Also add the files: for any get_files associated with this vnf_resource_id // *if* there are any List<HeatFiles> heatFiles = null; @@ -1015,11 +1001,9 @@ public class MsoVnfAdapterImpl implements MsoVnfAdapter { if (!isVolumeRequest || addGetFilesOnVolumeReq) { if (oldWay) { - logger.debug( - "In MsoVnfAdapterImpl createVfModule, this should not happen - old way is gamma only - no heat " - + "files!"); + logger.debug("In MsoVnfAdapterImpl createVfModule, this should not happen, no heat files!"); } else { - // 1607 - now use VF_MODULE_TO_HEAT_FILES table + // now use VF_MODULE_TO_HEAT_FILES table logger.debug( "In MsoVnfAdapterImpl createVfModule, about to call db.getHeatFilesForVfModule avec vfModuleId=" + vf.getModelUUID()); @@ -1046,9 +1030,9 @@ public class MsoVnfAdapterImpl implements MsoVnfAdapter { String missingParams = null; List<String> paramList = new ArrayList<>(); - // New for 1510 - consult the PARAM_ALIAS field to see if we've been + // consult the PARAM_ALIAS field to see if we've been // supplied an alias. Only check if we don't find it initially. - // Also new in 1510 - don't flag missing parameters if there's an environment - because they might be there. + // don't flag missing parameters if there's an environment - because they might be there. // And also new - add parameter to turn off checking all together if we find we're blocking orders we // shouldn't boolean checkRequiredParameters = true; @@ -1063,7 +1047,6 @@ public class MsoVnfAdapterImpl implements MsoVnfAdapter { // No problem - default is true logger.debug("An exception occured trying to get property {}", MsoVnfAdapterImpl.CHECK_REQD_PARAMS, e); } - // 1604 - Add enhanced environment & parameter checking // Part 1: parse envt entries to see if reqd parameter is there (before used a simple grep // Part 2: only submit to openstack the parameters in the envt that are in the heat template // Note this also removes any comments @@ -1071,7 +1054,6 @@ public class MsoVnfAdapterImpl implements MsoVnfAdapter { if (heatEnvironment != null && heatEnvironment.getEnvironment() != null && heatEnvironment.getEnvironment().contains("parameters:")) { - logger.debug("Enhanced environment checking enabled - 1604"); StringBuilder sb = new StringBuilder(heatEnvironment.getEnvironment()); mhee = new MsoHeatEnvironmentEntry(sb); @@ -1089,10 +1071,9 @@ public class MsoVnfAdapterImpl implements MsoVnfAdapter { } else { logger.debug("NO ENVIRONMENT for this entry"); } - // New with 1707 - all variables converted to their native object types + // all variables converted to their native object types Map<String, Object> goldenInputs = null; - logger.debug("Now handle the inputs....first convert"); ArrayList<String> parameterNames = new ArrayList<>(); HashMap<String, String> aliasToParam = new HashMap<>(); StringBuilder sb = new StringBuilder("\nTemplate Parameters:\n"); @@ -1193,31 +1174,21 @@ public class MsoVnfAdapterImpl implements MsoVnfAdapter { // Have the tenant. Now deploy the stack itself // Ignore MsoTenantNotFound and MsoStackAlreadyExists exceptions // because we already checked for those. - long createStackStarttime = System.currentTimeMillis(); try { - // heatStack = heat.createStack(cloudSiteId, tenantId, vnfName, template, inputs, true, - // heatTemplate.getTimeoutMinutes()); if (backout == null) { backout = true; } if (heat != null) { - logger.debug("heat is not null!!"); heatStack = heat.createStack(cloudSiteId, cloudOwner, tenantId, vfModuleName, null, template, goldenInputs, true, heatTemplate.getTimeoutMinutes(), newEnvironmentString, nestedTemplatesChecked, heatFilesObjects, backout.booleanValue()); } else { - logger.debug("heat is null!"); throw new MsoHeatNotFoundException(); } } catch (MsoException me) { me.addContext("CreateVFModule"); - String error = "Create VF Module " + vfModuleType + " in " + cloudOwner + "/" + cloudSiteId + "/" - + tenantId + ": " + me; - logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_CREATE_VNF_ERR.toString(), vfModuleType, - cloudOwner, cloudSiteId, tenantId, OPENSTACK, ErrorCode.DataError.getValue(), - "MsoException - createStack", me); - logger.debug(error); + logger.error("Error creating Stack", me); if (isValetEnabled && sendResponseToValet) { logger.debug("valet is enabled, the orchestration failed - now sending rollback to valet"); try { @@ -1231,17 +1202,10 @@ public class MsoVnfAdapterImpl implements MsoVnfAdapter { } throw new VnfException(me); } catch (NullPointerException npe) { - String error = "Create VFModule " + vfModuleType + " in " + cloudOwner + "/" + cloudSiteId + "/" - + tenantId + ": " + npe; - logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_CREATE_VNF_ERR.toString(), vfModuleType, - cloudOwner, cloudSiteId, tenantId, OPENSTACK, ErrorCode.DataError.getValue(), - "NullPointerException - createStack", npe); - logger.debug(error); - logger.debug("NULL POINTER EXCEPTION at heat.createStack"); - // npe.addContext ("CreateVNF"); + logger.error("Error creating Stack", npe); throw new VnfException("NullPointerException during heat.createStack"); } catch (Exception e) { - logger.debug("unhandled exception at heat.createStack", e); + logger.error("Error creating Stack", e); throw new VnfException("Exception during heat.createStack! " + e.getMessage()); } // Reach this point if createStack is successful. @@ -1899,8 +1863,6 @@ public class MsoVnfAdapterImpl implements MsoVnfAdapter { } else { logger.debug("found missing parameters - but checkRequiredParameters is false - will not block"); } - } else { - logger.debug("No missing parameters found - ok to proceed"); } // Just submit the envt entry as received from the database diff --git a/adapters/mso-openstack-adapters/src/test/java/org/onap/so/adapters/network/MSONetworkAdapterImplTest.java b/adapters/mso-openstack-adapters/src/test/java/org/onap/so/adapters/network/MSONetworkAdapterImplTest.java index 4dcb7c8710..add1918748 100644 --- a/adapters/mso-openstack-adapters/src/test/java/org/onap/so/adapters/network/MSONetworkAdapterImplTest.java +++ b/adapters/mso-openstack-adapters/src/test/java/org/onap/so/adapters/network/MSONetworkAdapterImplTest.java @@ -20,18 +20,6 @@ package org.onap.so.adapters.network; -import org.apache.http.HttpStatus; -import org.junit.Test; -import org.onap.so.adapters.vnf.BaseRestTestUtils; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpMethod; -import org.springframework.http.ResponseEntity; -import org.springframework.web.util.UriComponentsBuilder; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; import static org.junit.Assert.assertEquals; import static org.onap.so.bpmn.mock.StubOpenStack.mockOpenStackDeleteNeutronNetwork; import static org.onap.so.bpmn.mock.StubOpenStack.mockOpenStackDeleteStack_200; @@ -52,6 +40,18 @@ import static org.onap.so.bpmn.mock.StubOpenStack.mockOpenStackPutStack; import static org.onap.so.bpmn.mock.StubOpenStack.mockOpenStackResponseAccess; import static org.onap.so.bpmn.mock.StubOpenStack.mockOpenstackGet; import static org.onap.so.bpmn.mock.StubOpenStack.mockOpenstackPost; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.apache.http.HttpStatus; +import org.junit.Test; +import org.onap.so.adapters.vnf.BaseRestTestUtils; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.web.util.UriComponentsBuilder; public class MSONetworkAdapterImplTest extends BaseRestTestUtils { @@ -142,12 +142,12 @@ public class MSONetworkAdapterImplTest extends BaseRestTestUtils { mockOpenStackResponseAccess(wireMockServer, wireMockPort); - mockOpenStackGetStack_404(wireMockServer, "dvspg-VCE_VPE-mtjnj40avbc"); + mockOpenStackGetStack_404(wireMockServer, "DEV-VF-1802-it3-pwt3-v6-vSAMP10a-addon2-Replace-1001/stackId"); mockOpenStackPostStack_200(wireMockServer, "OpenstackResponse_Stack.json"); mockOpenStackGetStackCreated_200(wireMockServer, "OpenstackResponse_Stack_Created.json", - "dvspg-VCE_VPE-mtjnj40avbc/stackId"); + "DEV-VF-1802-it3-pwt3-v6-vSAMP10a-addon2-Replace-1001/stackId"); String uri = "/services/NetworkAdapter"; headers.set("X-ECOMP-RequestID", "123456789456127"); @@ -163,7 +163,7 @@ public class MSONetworkAdapterImplTest extends BaseRestTestUtils { mockOpenStackPostStack_200(wireMockServer, "OpenstackResponse_Stack.json"); mockOpenStackGetStackCreated_200(wireMockServer, "OpenstackResponse_Stack_Created.json", - "dvspg-VCE_VPE-mtjnj40avbc"); + "DEV-VF-1802-it3-pwt3-v6-vSAMP10a-addon2-Replace-1001/stackId"); String uri = "/services/NetworkAdapter"; headers.set("X-ECOMP-RequestID", "123456789456127"); diff --git a/adapters/mso-openstack-adapters/src/test/resources/CreateNetwork.xml b/adapters/mso-openstack-adapters/src/test/resources/CreateNetwork.xml index b9fc419a65..5ee33ab3dc 100644 --- a/adapters/mso-openstack-adapters/src/test/resources/CreateNetwork.xml +++ b/adapters/mso-openstack-adapters/src/test/resources/CreateNetwork.xml @@ -4,7 +4,7 @@ <cloudSiteId>mtn13</cloudSiteId> <tenantId>bef254252c5d44e6bcec65c180180ab5</tenantId> <networkType>CONTRAIL30_GNDIRECT</networkType> - <networkName>dvspg-VCE_VPE-mtjnj40avbc</networkName> + <networkName>DEV-VF-1802-it3-pwt3-v6-vSAMP10a-addon2-Replace-1001</networkName> <physicalNetworkName>dvs-mtjnj-01</physicalNetworkName> <vlans>3014</vlans> <failIfExists>false</failIfExists> diff --git a/adapters/mso-openstack-adapters/src/test/resources/__files/OpenstackResponse_Stack.json b/adapters/mso-openstack-adapters/src/test/resources/__files/OpenstackResponse_Stack.json index af63ca7de4..be50d09ef6 100644 --- a/adapters/mso-openstack-adapters/src/test/resources/__files/OpenstackResponse_Stack.json +++ b/adapters/mso-openstack-adapters/src/test/resources/__files/OpenstackResponse_Stack.json @@ -1,17 +1,15 @@ { - "stack": { - "description": null, - "links": null, - "stackStatusReason": null, - "stackName": null, - "updatedTime": null, - "creationTime": null, - "stackStatus": "NOT_FOUND", - "id": "stackId", - "files": null, - "outputs": null, - "parameters": { - - } - } -}
\ No newline at end of file + "stack": { + "creationTime": null, + "description": null, + "files": null, + "id": "stackId", + "links": null, + "outputs": null, + "parameters": {}, + "stack_name": "DEV-VF-1802-it3-pwt3-v6-vSAMP10a-addon2-Replace-1001", + "stack_status": "CREATE_IN_PROGRESS", + "stack_status_reason": null, + "updatedTime": null + } +} diff --git a/adapters/mso-openstack-adapters/src/test/resources/__files/OpenstackResponse_Stack_Created_VfModule.json b/adapters/mso-openstack-adapters/src/test/resources/__files/OpenstackResponse_Stack_Created_VfModule.json index 29893ccb7b..e49d407766 100644 --- a/adapters/mso-openstack-adapters/src/test/resources/__files/OpenstackResponse_Stack_Created_VfModule.json +++ b/adapters/mso-openstack-adapters/src/test/resources/__files/OpenstackResponse_Stack_Created_VfModule.json @@ -1,17 +1,15 @@ { - "stack": { - "description": null, - "links": null, - "stack_status_reason": null, - "stack_name": "DEV-VF-1802-it3-pwt3-v6-vSAMP10a-addon2-Replace-1001", - "updated_time": null, - "creation_time": null, - "stack_status": "CREATE_COMPLETE", - "id": "stackId", - "files": null, - "outputs": null, - "parameters": { - - } - } -}
\ No newline at end of file + "stack": { + "creationTime": null, + "description": null, + "files": null, + "id": "stackId", + "links": null, + "outputs": null, + "parameters": {}, + "stack_name": "DEV-VF-1802-it3-pwt3-v6-vSAMP10a-addon2-Replace-1001", + "stack_status": "CREATE_COMPLETE", + "stack_status_reason": "Create Completed", + "updatedTime": null + } +} diff --git a/adapters/mso-openstack-adapters/src/test/resources/__files/OpenstackResponse_Stack_DeleteComplete.json b/adapters/mso-openstack-adapters/src/test/resources/__files/OpenstackResponse_Stack_DeleteComplete.json index 8612258eee..bad85f37c8 100644 --- a/adapters/mso-openstack-adapters/src/test/resources/__files/OpenstackResponse_Stack_DeleteComplete.json +++ b/adapters/mso-openstack-adapters/src/test/resources/__files/OpenstackResponse_Stack_DeleteComplete.json @@ -3,7 +3,7 @@ "description": null, "links": null, "stackStatusReason": null, - "stackName": null, + "stackName": "stackName", "updatedTime": null, "creationTime": null, "stack_status": "DELETE_COMPLETE", diff --git a/adapters/mso-openstack-adapters/src/test/resources/__files/OpenstackResponse_VnfBaseStackId.json b/adapters/mso-openstack-adapters/src/test/resources/__files/OpenstackResponse_VnfBaseStackId.json index f4a3c520ba..70c78a6047 100644 --- a/adapters/mso-openstack-adapters/src/test/resources/__files/OpenstackResponse_VnfBaseStackId.json +++ b/adapters/mso-openstack-adapters/src/test/resources/__files/OpenstackResponse_VnfBaseStackId.json @@ -7,6 +7,7 @@ "rel" : "self" } ], - "stack_name": "vnfBaseStack" + "stack_name": "vnfBaseStack", + "stack_status": "CREATE_COMPLETE" } }
\ No newline at end of file diff --git a/adapters/mso-openstack-adapters/src/test/resources/logback-test.xml b/adapters/mso-openstack-adapters/src/test/resources/logback-test.xml index 5d6eee746f..8bfa6d83c3 100644 --- a/adapters/mso-openstack-adapters/src/test/resources/logback-test.xml +++ b/adapters/mso-openstack-adapters/src/test/resources/logback-test.xml @@ -29,25 +29,15 @@ </appender> - <logger name="com.att.eelf.audit" level="INFO" additivity="false"> - <appender-ref ref="STDOUT" /> - </logger> - - <logger name="com.att.eelf.metrics" level="INFO" additivity="false"> - <appender-ref ref="STDOUT" /> - </logger> - <logger name="com.att.eelf.error" level="WARN" additivity="false"> + <logger name="com.woorea.openstack" level="${so.log.level:-DEBUG}" additivity="false"> <appender-ref ref="STDOUT" /> </logger> <logger name="org.onap" level="${so.log.level:-DEBUG}" additivity="false"> <appender-ref ref="STDOUT" /> </logger> - - <logger name="org.onap" level="${so.log.level:-DEBUG}" additivity="false"> - <appender-ref ref="STDOUT" /> - </logger> + <root level="WARN"> <appender-ref ref="STDOUT" /> diff --git a/vnfm-simulator/vnfm-service/pom.xml b/vnfm-simulator/vnfm-service/pom.xml index 380381f53b..c09c5f070a 100644 --- a/vnfm-simulator/vnfm-service/pom.xml +++ b/vnfm-simulator/vnfm-service/pom.xml @@ -1,149 +1,148 @@ -<project xmlns="http://maven.apache.org/POM/4.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - <modelVersion>4.0.0</modelVersion> - <parent> - <groupId>org.onap.so.vnfm</groupId> - <artifactId>vnfm-simulator</artifactId> - <version>1.4.0-SNAPSHOT</version> - </parent> - <artifactId>vnfm-service</artifactId> - <name>${project.artifactId}</name> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.onap.so.vnfm</groupId> + <artifactId>vnfm-simulator</artifactId> + <version>1.4.0-SNAPSHOT</version> + </parent> + <artifactId>vnfm-service</artifactId> + <name>${project.artifactId}</name> - <properties> - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <java.version>1.8</java.version> - <okhttp-version>2.7.5</okhttp-version> - <gson-version>2.8.1</gson-version> - </properties> - <dependencies> - <dependency> - <groupId>org.onap.so.adapters</groupId> - <artifactId>mso-vnfm-adapter-ext-clients</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-web</artifactId> - </dependency> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-data-jpa</artifactId> - </dependency> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-actuator</artifactId> - </dependency> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-test</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-devtools</artifactId> - <scope>runtime</scope> - </dependency> - <dependency> - <groupId>junit</groupId> - <artifactId>junit</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>io.swagger</groupId> - <artifactId>swagger-jaxrs</artifactId> - <version>1.5.0</version> - </dependency> - <dependency> - <groupId>org.apache.directory.studio</groupId> - <artifactId>org.apache.commons.io</artifactId> - <version>2.4</version> - </dependency> - <dependency> - <groupId>com.googlecode.json-simple</groupId> - <artifactId>json-simple</artifactId> - <version>1.1.1</version> - </dependency> + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <java.version>1.8</java.version> + <okhttp-version>2.7.5</okhttp-version> + <gson-version>2.8.1</gson-version> + </properties> + <dependencies> + <dependency> + <groupId>org.onap.so.adapters</groupId> + <artifactId>mso-vnfm-adapter-ext-clients</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-data-jpa</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-actuator</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-test</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-devtools</artifactId> + <scope>runtime</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>io.swagger</groupId> + <artifactId>swagger-jaxrs</artifactId> + <version>1.5.0</version> + </dependency> + <dependency> + <groupId>org.apache.directory.studio</groupId> + <artifactId>org.apache.commons.io</artifactId> + <version>2.4</version> + </dependency> + <dependency> + <groupId>com.googlecode.json-simple</groupId> + <artifactId>json-simple</artifactId> + <version>1.1.1</version> + </dependency> - <dependency> - <groupId>io.springfox</groupId> - <artifactId>springfox-swagger-ui</artifactId> - <version>2.6.1</version> - <scope>compile</scope> - </dependency> - <dependency> - <groupId>io.springfox</groupId> - <artifactId>springfox-swagger2</artifactId> - <version>2.6.1</version> - <scope>compile</scope> - </dependency> - <dependency> - <groupId>com.fasterxml.jackson.core</groupId> - <artifactId>jackson-databind</artifactId> - <version>2.9.8</version> - </dependency> - <dependency> - <groupId>com.h2database</groupId> - <artifactId>h2</artifactId> - </dependency> - <!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils --> - <dependency> - <groupId>commons-beanutils</groupId> - <artifactId>commons-beanutils</artifactId> - <version>1.9.3</version> - </dependency> - <dependency> - <groupId>org.modelmapper</groupId> - <artifactId>modelmapper</artifactId> - <version>2.3.0</version> - </dependency> - <dependency> - <groupId>com.squareup.okio</groupId> - <artifactId>okio</artifactId> - <version>1.13.0</version> - </dependency> - <dependency> - <groupId>com.squareup.okhttp</groupId> - <artifactId>okhttp</artifactId> - <version>${okhttp-version}</version> - </dependency> - <dependency> - <groupId>com.squareup.okhttp</groupId> - <artifactId>logging-interceptor</artifactId> - <version>${okhttp-version}</version> - </dependency> - <dependency> - <groupId>com.google.code.gson</groupId> - <artifactId>gson</artifactId> - <version>${gson-version}</version> - </dependency> - <dependency> - <groupId>org.onap.so</groupId> - <artifactId>common</artifactId> - <version>${project.version}</version> - </dependency> - </dependencies> - <build> - <plugins> - <plugin> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-maven-plugin</artifactId> - <version>${springboot.version}</version> - <configuration> - <mainClass>org.onap.svnfm.simulator.config.SvnfmApplication</mainClass> - </configuration> - <executions> - <execution> - <goals> - <goal>repackage</goal> - </goals> - </execution> - </executions> - </plugin> - <plugin> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-maven-plugin</artifactId> - </plugin> - </plugins> - </build> + <dependency> + <groupId>io.springfox</groupId> + <artifactId>springfox-swagger-ui</artifactId> + <version>2.6.1</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>io.springfox</groupId> + <artifactId>springfox-swagger2</artifactId> + <version>2.6.1</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + <version>2.9.8</version> + </dependency> + <dependency> + <groupId>com.h2database</groupId> + <artifactId>h2</artifactId> + </dependency> + <!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils --> + <dependency> + <groupId>commons-beanutils</groupId> + <artifactId>commons-beanutils</artifactId> + <version>1.9.3</version> + </dependency> + <dependency> + <groupId>org.modelmapper</groupId> + <artifactId>modelmapper</artifactId> + <version>2.3.0</version> + </dependency> + <dependency> + <groupId>com.squareup.okio</groupId> + <artifactId>okio</artifactId> + <version>1.13.0</version> + </dependency> + <dependency> + <groupId>com.squareup.okhttp</groupId> + <artifactId>okhttp</artifactId> + <version>${okhttp-version}</version> + </dependency> + <dependency> + <groupId>com.squareup.okhttp</groupId> + <artifactId>logging-interceptor</artifactId> + <version>${okhttp-version}</version> + </dependency> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>${gson-version}</version> + </dependency> + <dependency> + <groupId>org.onap.so</groupId> + <artifactId>common</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-maven-plugin</artifactId> + <version>${springboot.version}</version> + <configuration> + <mainClass>org.onap.svnfm.simulator.config.SvnfmApplication</mainClass> + </configuration> + <executions> + <execution> + <goals> + <goal>repackage</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-maven-plugin</artifactId> + </plugin> + </plugins> + </build> </project> |