aboutsummaryrefslogtreecommitdiffstats
path: root/adapters/mso-openstack-adapters
diff options
context:
space:
mode:
authorEric Multanen <eric.w.multanen@intel.com>2018-09-14 04:42:38 -0700
committerEric Multanen <eric.w.multanen@intel.com>2018-09-20 23:24:04 -0700
commit821851f259e2a11fde31b41ea0740aad81ec7baa (patch)
treedf6364027d60ec5e4fd39b21534c2dd3a7fb8e36 /adapters/mso-openstack-adapters
parent35d4ded98df1d5603c173118fa648bc38967825a (diff)
Add multicloud to VnfPluginAdapter
Adds new mode 'multicloud' to VnfPluginAdapter along with MsoMulticloudUtils and supporting code. Change-Id: I1cfdc9ba09c58315fb0bfc025854cf0122a32759 Issue-ID: SO-752 Signed-off-by: Eric Multanen <eric.w.multanen@intel.com>
Diffstat (limited to 'adapters/mso-openstack-adapters')
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfPluginAdapterImpl.java174
-rw-r--r--adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VnfAdapterRestUtils.java23
-rw-r--r--adapters/mso-openstack-adapters/src/test/java/org/onap/so/adapters/vnf/MsoVnfPluginAdapterImplTest.java111
-rw-r--r--adapters/mso-openstack-adapters/src/test/java/org/onap/so/bpmn/mock/StubOpenStack.java6
-rw-r--r--adapters/mso-openstack-adapters/src/test/resources/__files/OpenstackResponse_AccessMulticloud.json40
5 files changed, 262 insertions, 92 deletions
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfPluginAdapterImpl.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfPluginAdapterImpl.java
index b440f7d521..e9567170dd 100644
--- a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfPluginAdapterImpl.java
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/MsoVnfPluginAdapterImpl.java
@@ -29,7 +29,7 @@
* - base and volume module queries
* - rollback logic
* - logging and error handling
- *
+ *
* Then based on the orchestration mode of the VNF, it will invoke different VDU plug-ins
* to perform the low level instantiations, deletions, and queries. At this time, the
* set of available plug-ins is hard-coded, though in the future a dynamic selection
@@ -81,6 +81,7 @@ import org.onap.so.openstack.exceptions.MsoExceptionCategory;
import org.onap.so.openstack.utils.MsoHeatEnvironmentEntry;
import org.onap.so.openstack.utils.MsoHeatUtils;
import org.onap.so.openstack.utils.MsoKeystoneUtils;
+import org.onap.so.openstack.utils.MsoMulticloudUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
@@ -100,28 +101,31 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
private static MsoAlarmLogger alarmLogger = new MsoAlarmLogger ();
private static final String CHECK_REQD_PARAMS = "org.onap.so.adapters.vnf.checkRequiredParameters";
private static final ObjectMapper JSON_MAPPER = new ObjectMapper();
-
+
@Autowired
protected CloudConfig cloudConfig;
-
+
@Autowired
private VFModuleCustomizationRepository vfModuleCustomRepo;
-
+
@Autowired
private Environment environment;
@Autowired
protected MsoKeystoneUtils keystoneUtils;
-
+
@Autowired
protected MsoCloudifyUtils cloudifyUtils;
-
+
@Autowired
protected MsoHeatUtils heatUtils;
-
+
+ @Autowired
+ protected MsoMulticloudUtils multicloudUtils;
+
@Autowired
protected VfModuleCustomizationToVduMapper vduMapper;
-
+
/**
* Health Check web method. Does nothing but return to show the adapter is deployed.
*/
@@ -192,9 +196,9 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
/**
* This is the "Query VNF" web service implementation.
- *
+ *
* This really should be QueryVfModule, but nobody ever changed it.
- *
+ *
* The method returns an indicator that the VNF exists, along with its status and outputs.
* The input "vnfName" will also be reflected back as its ID.
*
@@ -244,7 +248,7 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
throw new VnfException (e);
}
-
+
if (vduInstance != null && vduInstance.getStatus().getState() != VduStateType.NOTFOUND) {
vnfExists.value = Boolean.TRUE;
status.value = vduStatusToVnfStatus(vduInstance);
@@ -265,7 +269,7 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
return;
}
-
+
/**
* This is the "Delete VNF" web service implementation.
* This function is now unsupported and will return an error.
@@ -278,7 +282,7 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
MsoRequest msoRequest) throws VnfException {
MsoLogger.setLogContext (msoRequest);
MsoLogger.setServiceName ("DeleteVnf");
-
+
// This operation is no longer supported at the VNF level. The adapter is only called to deploy modules.
LOGGER.debug ("DeleteVNF command attempted but not supported");
throw new VnfException ("DeleteVNF: Unsupported command", MsoExceptionCategory.USERDATA);
@@ -289,7 +293,7 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
* A rollback object is returned to the client in a successful creation
* response. The client can pass that object as-is back to the rollbackVnf
* operation to undo the creation.
- *
+ *
* TODO: This should be rollbackVfModule and/or rollbackVolumeGroup,
* but APIs were apparently never updated.
*/
@@ -309,7 +313,7 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Rollback VF Module - nothing to roll back");
return;
}
-
+
// Get the elements of the VnfRollback object for easier access
String cloudSiteId = rollback.getCloudSiteId ();
String tenantId = rollback.getTenantId ();
@@ -330,7 +334,7 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
try {
// TODO: Get a reasonable timeout. Use a global property, or store the creation timeout in rollback object and use that.
vduInstance = vduPlugin.deleteVdu(cloudInfo, vfModuleId, 5);
-
+
LOGGER.debug("Rolled back VDU instantiation: " + vduInstance.getVduInstanceId());
LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from VDU Plugin", "VDU", "DeleteVdu", null);
}
@@ -354,7 +358,7 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
// DeploymentInfo object should be enhanced to report a better status internally.
VduStatus vduStatus = vdu.getStatus();
VduStateType status = vduStatus.getState();
-
+
if (status == null) {
return VnfStatus.UNKNOWN;
}
@@ -379,7 +383,7 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
{
String type = templateParam.getParamType();
LOGGER.debug("Parameter: " + templateParam.getParamName() + " is of type " + type);
-
+
if (type.equalsIgnoreCase("number")) {
try {
return Integer.valueOf(inputValue);
@@ -400,7 +404,7 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
} else if (type.equalsIgnoreCase("boolean")) {
return new Boolean(inputValue);
}
-
+
// Nothing else matched. Return the original string
return inputValue;
}
@@ -464,9 +468,9 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
}
}
LOGGER.debug(sb.toString());
- return;
+ return;
}
-
+
private void sendMapToDebug(Map<String, String> inputs) {
int i = 0;
StringBuilder sb = new StringBuilder("inputs:");
@@ -612,7 +616,7 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
{
// Will capture execution time for metrics
long startTime = System.currentTimeMillis ();
-
+
MsoLogger.setLogContext (msoRequest);
MsoLogger.setServiceName ("CreateVfModule");
@@ -625,14 +629,14 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
throw new VnfException(error, MsoExceptionCategory.USERDATA);
}
-
+
// Clean up some inputs to make comparisons easier
if (requestType == null)
requestType = "";
-
+
if ("".equals(volumeGroupId) || "null".equals(volumeGroupId))
- volumeGroupId = null;
-
+ volumeGroupId = null;
+
if ("".equals(baseVfModuleId) || "null".equals(baseVfModuleId))
baseVfModuleId = null;
@@ -643,7 +647,7 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
} else {
this.sendMapToDebug(inputs);
}
-
+
// Check if this is for a "Volume" module
boolean isVolumeRequest = false;
if (requestType.startsWith("VOLUME")) {
@@ -663,7 +667,7 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
vfRollback.setBaseGroupHeatStackId(baseVfModuleId);
vfRollback.setModelCustomizationUuid(modelCustomizationUuid);
vfRollback.setMode("CFY");
-
+
rollback.value = vfRollback; // Default rollback - no updates performed
// Get the VNF/VF Module definition from the Catalog DB first.
@@ -675,7 +679,7 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
try {
vfModuleCust = vfModuleCustomRepo.findByModelCustomizationUUID(modelCustomizationUuid);
-
+
if (vfModuleCust == null) {
String error = "Create vfModule error: Unable to find vfModuleCust with modelCustomizationUuid=" + modelCustomizationUuid;
LOGGER.debug(error);
@@ -692,7 +696,7 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
vnfResource = vfModuleCust.getVfModule().getVnfResources();
}
catch (Exception e) {
-
+
LOGGER.debug("unhandled exception in create VF - [Query]" + e.getMessage());
throw new VnfException("Exception during create VF " + e.getMessage());
}
@@ -706,10 +710,10 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
CloudSite cloudSite = cloudSiteOp.get();
MavenLikeVersioning aicV = new MavenLikeVersioning();
aicV.setVersion(cloudSite.getCloudVersion());
-
+
String vnfMin = vnfResource.getAicVersionMin();
String vnfMax = vnfResource.getAicVersionMax();
-
+
if ( (vnfMin != null && !(aicV.isMoreRecentThan(vnfMin) || aicV.isTheSameVersion(vnfMin))) ||
(vnfMax != null && aicV.isMoreRecentThan(vnfMax)))
{
@@ -720,11 +724,11 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
throw new VnfException(error, MsoExceptionCategory.USERDATA);
}
// End Version check
-
-
+
+
VduInstance vduInstance = null;
CloudInfo cloudInfo = new CloudInfo (cloudSiteId, tenantId, null);
-
+
// Use the VduPlugin.
VduPlugin vduPlugin = getVduPlugin(cloudSiteId);
@@ -746,12 +750,12 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
me.addContext ("CreateVFModule");
throw new VnfException (me);
}
-
+
// More precise handling/messaging if the Module already exists
if (vduInstance != null && !(vduInstance.getStatus().getState() == VduStateType.NOTFOUND)) {
VduStateType status = vduInstance.getStatus().getState();
LOGGER.debug ("Found Existing VDU, status=" + status);
-
+
if (status == VduStateType.INSTANTIATED) {
if (failIfExists != null && failIfExists) {
// fail - it exists
@@ -799,8 +803,8 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, vduInstance.getVduInstanceId());
}
}
-
-
+
+
// Collect outputs from Base Modules and Volume Modules
Map<String, Object> baseModuleOutputs = null;
Map<String, Object> volumeGroupOutputs = null;
@@ -824,7 +828,7 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
me.addContext ("CreateVFModule(QueryVolume)");
throw new VnfException (me);
}
-
+
if (volumeVdu == null || volumeVdu.getStatus().getState() == VduStateType.NOTFOUND) {
String error = "Create VFModule: Attached Volume Group DOES NOT EXIST " + volumeGroupId + " in " + cloudSiteId + "/" + tenantId + " USER ERROR" ;
LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, volumeGroupId, cloudSiteId, tenantId, error, "VDU", "queryVdu(volume)", MsoLogger.ErrorCode.BusinessProcesssError, "Create VFModule: Attached Volume Group DOES NOT EXIST");
@@ -837,7 +841,7 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
this.sendMapToDebug(volumeGroupOutputs, "volumeGroupOutputs");
}
}
-
+
// If this is an Add-On Module, query the Base Module outputs
// Note: This will be performed whether or not the current request is for an
// Add-On Volume Group or Add-On VF Module
@@ -847,7 +851,7 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
vfRollback.setIsBase(true);
} else {
LOGGER.debug("This is an Add-On Module request");
-
+
// Add-On Modules should always have a Base, but just treat as a warning if not provided.
// Add-on Volume requests may or may not specify a base.
if (!isVolumeRequest && baseVfModuleId == null) {
@@ -867,12 +871,12 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, baseVfModuleId, cloudSiteId, tenantId, "VDU", "queryVdu(Base)", MsoLogger.ErrorCode.DataError, "Exception - queryVdu(Base)", me);
LOGGER.recordMetricEvent (subStartTime2, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "VDU", "QueryVdu(Base)", baseVfModuleId);
LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
-
+
// Convert to a generic VnfException
me.addContext ("CreateVFModule(QueryBase)");
throw new VnfException (me);
}
-
+
if (baseVdu == null || baseVdu.getStatus().getState() == VduStateType.NOTFOUND) {
String error = "Create VFModule: Base Module DOES NOT EXIST " + baseVfModuleId + " in " + cloudSiteId + "/" + tenantId + " USER ERROR" ;
LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, baseVfModuleId, cloudSiteId, tenantId, error, "VDU", "queryVdu(Base)", MsoLogger.ErrorCode.BusinessProcesssError, "Create VFModule: Base Module DOES NOT EXIST");
@@ -886,14 +890,14 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
}
}
}
-
+
// NOTE: For this section, heatTemplate is used for all template artifacts.
// In final implementation (post-POC), the template object would either be generic or there would
// be a separate DB Table/Object for different sub-orchestrators.
// NOTE: The template is fixed for the VF Module. The environment is part of the customization.
-
+
HeatTemplate heatTemplate = null;
HeatEnvironment heatEnvironment = null;
if (isVolumeRequest) {
@@ -903,7 +907,7 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
heatTemplate = vfModule.getModuleHeatTemplate();
heatEnvironment = vfModuleCust.getHeatEnvironment();
}
-
+
if (heatTemplate == null) {
String error = "UpdateVF: No Heat Template ID defined in catalog database for " + vfModuleType + ", reqType=" + requestType;
LOGGER.error(MessageEnum.RA_VNF_UNKNOWN_PARAM, "Heat Template ID", vfModuleType, "VNF", "", MsoLogger.ErrorCode.DataError, error);
@@ -914,7 +918,7 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
} else {
LOGGER.debug ("Got HEAT Template from DB: " + heatTemplate.getHeatTemplate());
}
-
+
if (heatEnvironment == null) {
String error = "Update VNF: undefined Heat Environment. VF=" + vfModuleType;
LOGGER.error (MessageEnum.RA_VNF_UNKNOWN_PARAM, "Heat Environment ID", "OpenStack", "", MsoLogger.ErrorCode.DataError, error);
@@ -927,15 +931,15 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
LOGGER.debug ("Got Heat Environment from DB: " + heatEnvironment.getEnvironment());
}
-
+
// Create the combined set of parameters from the incoming request, base-module outputs,
// volume-module outputs. Also, convert all variables to their native object types.
-
+
HashMap<String, Object> goldenInputs = new HashMap<String,Object>();
List<String> extraInputs = new ArrayList<String>();
Boolean skipInputChecks = false;
-
+
if (skipInputChecks) {
goldenInputs = new HashMap<String,Object>();
for (String key : inputs.keySet()) {
@@ -945,10 +949,10 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
else {
// Build maps for the parameters (including aliases) to simplify checks
HashMap<String, HeatTemplateParam> params = new HashMap<String, HeatTemplateParam>();
-
+
Set<HeatTemplateParam> paramSet = heatTemplate.getParameters();
LOGGER.debug("paramSet has " + paramSet.size() + " entries");
-
+
for (HeatTemplateParam htp : paramSet) {
params.put(htp.getParamName(), htp);
@@ -958,7 +962,7 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
params.put(alias, htp);
}
}
-
+
// First, convert all inputs to their "template" type
for (String key : inputs.keySet()) {
if (params.containsKey(key)) {
@@ -973,11 +977,22 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
extraInputs.add(key);
}
}
-
+
if (!extraInputs.isEmpty()) {
+ // Add directive inputs
+ String[] directives = { "oof_directives", "sdnc_directives" };
+ for (String key : directives) {
+ if (extraInputs.contains(key)) {
+ goldenInputs.put(key, inputs.get(key));
+ extraInputs.remove(key);
+ if (extraInputs.isEmpty()) {
+ break;
+ }
+ }
+ }
LOGGER.debug("Ignoring extra inputs: " + extraInputs);
}
-
+
// Next add in Volume Group Outputs if there are any. Copy directly without conversions.
if (volumeGroupOutputs != null && !volumeGroupOutputs.isEmpty()) {
for (String key : volumeGroupOutputs.keySet()) {
@@ -986,7 +1001,7 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
}
}
}
-
+
// Next add in Base Module Outputs if there are any. Copy directly without conversions.
if (baseModuleOutputs != null && !baseModuleOutputs.isEmpty()) {
for (String key : baseModuleOutputs.keySet()) {
@@ -995,14 +1010,13 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
}
}
}
-
+
// TODO: The model should support a mechanism to pre-assign default parameter values
// per "customization" (i.e. usage) of a given module. In HEAT, this is specified by
// an Environment file. There is not a general mechanism in the model to handle this.
// For the general case, any such parameter/values can be added dynamically to the
// inputs (only if not already specified).
-
-
+
// Check that required parameters have been supplied from any of the sources
String missingParams = null;
boolean checkRequiredParameters = true;
@@ -1017,7 +1031,7 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
// No problem - default is true
LOGGER.debug ("An exception occured trying to get property " + MsoVnfPluginAdapterImpl.CHECK_REQD_PARAMS, e);
}
-
+
// Do the actual parameter checking.
// Include looking at the ENV file as a valid definition of a parameter value.
// TODO: This handling of ENV applies only to Heat. A general mechanism to
@@ -1040,7 +1054,7 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
}
}
}
-
+
if (missingParams != null) {
if (checkRequiredParameters) {
// Problem - missing one or more required parameters
@@ -1056,12 +1070,12 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
}
} // NOTE: END PARAMETER CHECKING
-
-
+
+
// Here we go... ready to deploy the VF Module.
long instantiateVduStartTime = System.currentTimeMillis ();
if (backout == null) backout = true;
-
+
try {
// Construct the VDU Model structure to pass to the targeted VduPlugin
VduModelInfo vduModel = null;
@@ -1070,10 +1084,10 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
} else {
vduModel = vduMapper.mapVfModuleCustVolumeToVdu(vfModuleCust);
}
-
+
// Invoke the VduPlugin to instantiate the VF Module
vduInstance = vduPlugin.instantiateVdu(cloudInfo, vfModuleName, goldenInputs, vduModel, backout);
-
+
LOGGER.recordMetricEvent (instantiateVduStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from VduPlugin", "VDU", "instantiateVdu", vfModuleName);
}
catch (VduException me) {
@@ -1100,7 +1114,7 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.UnknownError, error);
LOGGER.debug("Unhandled exception at vduPlugin.instantiateVdu", e);
throw new VnfException("Exception during instantiateVdu: " + e.getMessage());
- }
+ }
// Reach this point if create is successful.
@@ -1108,7 +1122,7 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
vfRollback.setVnfCreated (true);
vfRollback.setVnfId (vduInstance.getVduInstanceId());
vnfId.value = vduInstance.getVduInstanceId();
- outputs.value = copyStringOutputs (vduInstance.getOutputs ());
+ outputs.value = copyStringOutputs (vduInstance.getOutputs ());
rollback.value = vfRollback;
@@ -1117,7 +1131,7 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
return;
}
-
+
public void deleteVfModule (String cloudSiteId,
String tenantId,
String vfModuleId,
@@ -1126,15 +1140,15 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
{
MsoLogger.setLogContext (msoRequest);
MsoLogger.setServiceName ("DeleteVfModule");
-
+
LOGGER.debug ("Deleting VF Module " + vfModuleId + " in " + cloudSiteId + "/" + tenantId);
// Will capture execution time for metrics
long startTime = System.currentTimeMillis ();
-
+
// Capture the output parameters on a delete, so need to query first
VduInstance vduInstance = null;
CloudInfo cloudInfo = new CloudInfo(cloudSiteId, tenantId, null);
-
+
// Use the VduPlugin.
VduPlugin vduPlugin = getVduPlugin(cloudSiteId);
@@ -1152,7 +1166,7 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
throw new VnfException (e);
}
-
+
// call method which handles the conversion from Map<String,Object> to Map<String,String> for our expected Object types
outputs.value = convertMapStringObjectToStringString(vduInstance.getOutputs());
@@ -1214,16 +1228,18 @@ public class MsoVnfPluginAdapterImpl implements MsoVnfAdapter {
if (cloudSiteOp.isPresent()) {
CloudSite cloudSite = cloudSiteOp.get();
String orchestrator = cloudSite.getOrchestrator();
-
+
if (orchestrator.equalsIgnoreCase("CLOUDIFY")) {
- return cloudifyUtils;
+ return cloudifyUtils;
}
else if (orchestrator.equalsIgnoreCase("HEAT")) {
return heatUtils;
}
+ if (orchestrator.equalsIgnoreCase("MULTICLOUD")) {
+ LOGGER.debug ("Got MulticloudUtils for vduPlugin");
+ return multicloudUtils; }
}
-
- // Default - return HEAT plugin, though will fail later
+ // Default - return HEAT plugin, though will fail later
return heatUtils;
}
-} \ No newline at end of file
+}
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VnfAdapterRestUtils.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VnfAdapterRestUtils.java
index 4da026f454..88f102c2a5 100644
--- a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VnfAdapterRestUtils.java
+++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/vnf/VnfAdapterRestUtils.java
@@ -7,9 +7,9 @@
* 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.
@@ -32,16 +32,19 @@ import org.springframework.stereotype.Component;
public class VnfAdapterRestUtils
{
private static MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA, VnfAdapterRestUtils.class);
-
+
@Autowired
private CloudConfig cloudConfig;
-
+
@Autowired
private MsoVnfCloudifyAdapterImpl cloudifyImpl;
-
+
@Autowired
private MsoVnfAdapterImpl vnfImpl;
-
+
+ @Autowired
+ private MsoVnfPluginAdapterImpl vnfPluginImpl;
+
/*
* Choose which implementation of VNF Adapter to use, based on the orchestration mode.
* Currently, the two supported orchestrators are HEAT and CLOUDIFY.
@@ -72,7 +75,7 @@ public class VnfAdapterRestUtils
LOGGER.debug ("GetVnfAdapterImpl: mode=" + mode);
MsoVnfAdapter vnfAdapter = null;
-
+
// TODO: Make this more dynamic (e.g. Service Loader)
if ("CLOUDIFY".equalsIgnoreCase(mode)) {
LOGGER.debug ("GetVnfAdapterImpl: Return Cloudify Adapter");
@@ -82,12 +85,16 @@ public class VnfAdapterRestUtils
LOGGER.debug ("GetVnfAdapterImpl: Return Heat Adapter");
vnfAdapter = vnfImpl;
}
+ else if ("MULTICLOUD".equalsIgnoreCase(mode)) {
+ LOGGER.debug ("GetVnfAdapterImpl: Return Plugin (multicloud) Adapter");
+ vnfAdapter = vnfPluginImpl;
+ }
else {
// Don't expect this, but default is the HEAT adapter
LOGGER.debug ("GetVnfAdapterImpl: Return Default (Heat) Adapter");
vnfAdapter = vnfImpl;
}
-
+
return vnfAdapter;
}
diff --git a/adapters/mso-openstack-adapters/src/test/java/org/onap/so/adapters/vnf/MsoVnfPluginAdapterImplTest.java b/adapters/mso-openstack-adapters/src/test/java/org/onap/so/adapters/vnf/MsoVnfPluginAdapterImplTest.java
index b21f1f3db2..77ef8d4776 100644
--- a/adapters/mso-openstack-adapters/src/test/java/org/onap/so/adapters/vnf/MsoVnfPluginAdapterImplTest.java
+++ b/adapters/mso-openstack-adapters/src/test/java/org/onap/so/adapters/vnf/MsoVnfPluginAdapterImplTest.java
@@ -7,9 +7,9 @@
* 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.
@@ -20,15 +20,31 @@
package org.onap.so.adapters.vnf;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.github.tomakehurst.wiremock.client.WireMock;
import org.apache.http.HttpStatus;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
+import org.mockito.MockitoAnnotations;
+import org.onap.so.adapters.vdu.CloudInfo;
+import org.onap.so.adapters.vdu.VduInstance;
+import org.onap.so.adapters.vdu.VduStateType;
+import org.onap.so.adapters.vdu.VduStatus;
import org.onap.so.adapters.vnf.exceptions.VnfException;
+import org.onap.so.db.catalog.beans.AuthenticationType;
+import org.onap.so.db.catalog.beans.CloudIdentity;
+import org.onap.so.db.catalog.beans.CloudSite;
+import org.onap.so.db.catalog.beans.ServerType;
import org.onap.so.entity.MsoRequest;
+import org.onap.so.openstack.beans.HeatStatus;
+import org.onap.so.openstack.beans.StackInfo;
import org.onap.so.openstack.beans.VnfRollback;
+import org.onap.so.openstack.utils.MsoMulticloudUtils;
import org.springframework.beans.factory.annotation.Autowired;
+import javax.ws.rs.core.MediaType;
import javax.xml.ws.Holder;
import java.util.HashMap;
import java.util.Map;
@@ -36,11 +52,15 @@ import java.util.Map;
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.delete;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.reset;
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo;
+import static org.mockito.Mockito.when;
import static org.onap.so.bpmn.mock.StubOpenStack.mockOpenStackGetStackVfModule_200;
import static org.onap.so.bpmn.mock.StubOpenStack.mockOpenStackGetStackVfModule_404;
import static org.onap.so.bpmn.mock.StubOpenStack.mockOpenStackResponseAccess;
+import static org.onap.so.bpmn.mock.StubOpenStack.mockOpenStackResponseAccessMulticloud;
+import static org.onap.so.bpmn.mock.StubOpenStack.mockOpenstackGetWithResponse;
public class MsoVnfPluginAdapterImplTest extends BaseRestTestUtils {
@@ -52,6 +72,53 @@ public class MsoVnfPluginAdapterImplTest extends BaseRestTestUtils {
String vnfName = "DEV-VF-1802-it3-pwt3-v6-vSAMP10a-addon2-Replace-1001/stackId";
+ /***
+ * Before each test execution, updating IdentityUrl port value to the ramdom wireMockPort
+ * Since URL will be used as a rest call and required to be mocked in unit tests
+ */
+ @Before
+ public void setUp() throws Exception {
+ reset();
+ mapper = new ObjectMapper();
+
+ CloudIdentity identity = new CloudIdentity();
+ identity.setId("MTN13");
+ identity.setMsoId("m93945");
+ identity.setMsoPass("93937EA01B94A10A49279D4572B48369");
+ identity.setAdminTenant("admin");
+ identity.setMemberRole("admin");
+ identity.setTenantMetadata(new Boolean(true));
+ identity.setIdentityUrl("http://localhost:"+wireMockPort+"/v2.0");
+ identity.setIdentityAuthenticationType(AuthenticationType.USERNAME_PASSWORD);
+
+ CloudSite cloudSite = new CloudSite();
+ cloudSite.setId("MTN13");
+ cloudSite.setCloudVersion("3.0");
+ cloudSite.setClli("MDT13");
+ cloudSite.setRegionId("MTN13");
+ cloudSite.setOrchestrator("multicloud" +
+ "");
+ identity.setIdentityServerType(ServerType.KEYSTONE);
+ cloudSite.setIdentityService(identity);
+
+
+
+ stubFor(get(urlPathEqualTo("/cloudSite/MTN13")).willReturn(aResponse()
+ .withBody(getBody(mapper.writeValueAsString(cloudSite),wireMockPort, ""))
+ .withHeader(org.apache.http.HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
+ .withStatus(HttpStatus.SC_OK)));
+ stubFor(get(urlPathEqualTo("/cloudSite/DEFAULT")).willReturn(aResponse()
+ .withBody(getBody(mapper.writeValueAsString(cloudSite),wireMockPort, ""))
+ .withHeader(org.apache.http.HttpHeaders.CONTENT_TYPE,MediaType.APPLICATION_JSON)
+ .withStatus(HttpStatus.SC_OK)));
+ stubFor(get(urlPathEqualTo("/cloudIdentity/MTN13")).willReturn(aResponse()
+ .withBody(getBody(mapper.writeValueAsString(identity),wireMockPort, ""))
+ .withHeader(org.apache.http.HttpHeaders.CONTENT_TYPE,MediaType.APPLICATION_JSON)
+ .withStatus(HttpStatus.SC_OK)));
+ cloudConfig.getCloudSite("MTN13").get().getIdentityService().setIdentityUrl("http://localhost:" + wireMockPort + "/v2.0");
+
+ }
+
@Test
public void createVfModule_ModelCustUuidIsNull() throws Exception {
expectedException.expect(VnfException.class);
@@ -88,18 +155,52 @@ public class MsoVnfPluginAdapterImplTest extends BaseRestTestUtils {
new Holder<VnfRollback>());
}
- @Test
+ /* @Test
public void createVfModule_INSTANTIATED() throws Exception {
mockOpenStackResponseAccess(wireMockPort);
mockOpenStackGetStackVfModule_200();
+
MsoRequest msoRequest = getMsoRequest();
Map<String, String> map = new HashMap<>();
map.put("key1", "value1");
- msoVnfPluginAdapter.createVfModule("mtn13", "88a6ca3ee0394ade9403f075db23167e", "vnf", "1", vnfName, "VFMOD",
- "volumeGroupHeatStackId|1", "baseVfHeatStackId", "9b339a61-69ca-465f-86b8-1c72c582b8e8", map,
+ msoVnfPluginAdapter.createVfModule("MTN13", "88a6ca3ee0394ade9403f075db23167e", "vnf", "1", vnfName, "VFMOD",
+ null, "baseVfHeatStackId", "9b339a61-69ca-465f-86b8-1c72c582b8e8", map,
+ Boolean.FALSE, Boolean.TRUE, Boolean.FALSE, msoRequest, new Holder<>(), new Holder<Map<String, String>>(),
+ new Holder<VnfRollback>());
+ }*/
+
+ @Test
+ public void createVfModule_INSTANTIATED_Multicloud() throws Exception {
+ mockOpenStackResponseAccessMulticloud(wireMockPort);
+ mockOpenStackGetStackVfModule_200();
+
+ MsoRequest msoRequest = getMsoRequest();
+ Map<String, String> map = new HashMap<>();
+ map.put("key1", "value1");
+ msoVnfPluginAdapter.createVfModule("MTN13", "88a6ca3ee0394ade9403f075db23167e", "vnf", "1", vnfName, "VFMOD",
+ null, "baseVfHeatStackId", "9b339a61-69ca-465f-86b8-1c72c582b8e8", map,
+ Boolean.FALSE, Boolean.TRUE, Boolean.FALSE, msoRequest, new Holder<>(), new Holder<Map<String, String>>(),
+ new Holder<VnfRollback>());
+ }
+
+ /*
+ @Test
+ public void createVfModule_Multicloud() throws Exception {
+ expectedException.expect(VnfException.class);
+ mockOpenStackResponseAccessMulticloud(wireMockPort);
+ mockOpenStackGetStackVfModule_404();
+
+ MsoRequest msoRequest = getMsoRequest();
+ Map<String, String> map = new HashMap<>();
+ map.put("key1", "value1");
+ map.put("oof_directives", "{ abc: 123 }");
+ map.put("sdnc_directives", "{ def: 456 }");
+ msoVnfPluginAdapter.createVfModule("MTN13", "88a6ca3ee0394ade9403f075db23167e", "vnf", "1", vnfName, "VFMOD",
+ null, "baseVfHeatStackId", "9b339a61-69ca-465f-86b8-1c72c582b8e8", map,
Boolean.FALSE, Boolean.TRUE, Boolean.FALSE, msoRequest, new Holder<>(), new Holder<Map<String, String>>(),
new Holder<VnfRollback>());
}
+ */
@Test
public void createVfModule_queryVduNotFoundWithVolumeGroupId() throws Exception {
diff --git a/adapters/mso-openstack-adapters/src/test/java/org/onap/so/bpmn/mock/StubOpenStack.java b/adapters/mso-openstack-adapters/src/test/java/org/onap/so/bpmn/mock/StubOpenStack.java
index 98d5f7eb5f..569a845caa 100644
--- a/adapters/mso-openstack-adapters/src/test/java/org/onap/so/bpmn/mock/StubOpenStack.java
+++ b/adapters/mso-openstack-adapters/src/test/java/org/onap/so/bpmn/mock/StubOpenStack.java
@@ -49,6 +49,12 @@ public class StubOpenStack {
.withStatus(HttpStatus.SC_OK)));
}
+ public static void mockOpenStackResponseAccessMulticloud(int port) throws IOException {
+ stubFor(post(urlPathEqualTo("/v2.0/tokens")).willReturn(aResponse().withHeader("Content-Type", "application/json")
+ .withBody(getBodyFromFile("OpenstackResponse_AccessMulticloud.json", port, "/mockPublicUrl"))
+ .withStatus(HttpStatus.SC_OK)));
+ }
+
public static void mockOpenStackResponseAccessQueryNetwork(int port) throws IOException {
stubFor(post(urlPathEqualTo("/v2.0/tokens"))
.withRequestBody(containing("tenantId"))
diff --git a/adapters/mso-openstack-adapters/src/test/resources/__files/OpenstackResponse_AccessMulticloud.json b/adapters/mso-openstack-adapters/src/test/resources/__files/OpenstackResponse_AccessMulticloud.json
new file mode 100644
index 0000000000..23fbe840e4
--- /dev/null
+++ b/adapters/mso-openstack-adapters/src/test/resources/__files/OpenstackResponse_AccessMulticloud.json
@@ -0,0 +1,40 @@
+{
+ "access": {
+ "token": {
+ "id": "tokenId1234",
+ "issued_at": null,
+ "expires": "1517418429142",
+ "tenant": null
+ },
+ "serviceCatalog": [
+ {
+ "type": "orchestration",
+ "name": null,
+ "endpoints": [
+ {
+ "region": "MTN13",
+ "publicURL": "port",
+ "internalURL": null,
+ "adminURL": null
+ }
+ ],
+ "endpointsLinks": null
+ },
+ {
+ "type": "network",
+ "name": null,
+ "endpoints": [
+ {
+ "region": "MTN13",
+ "publicURL": "port",
+ "internalURL": null,
+ "adminURL": null
+ }
+ ],
+ "endpointsLinks": null
+ }
+ ],
+ "user": null,
+ "metadata": null
+ }
+}