import java.util.Map;
import java.util.Set;
+import org.openecomp.mso.adapters.vdu.CloudInfo;
+import org.openecomp.mso.adapters.vdu.PluginAction;
+import org.openecomp.mso.adapters.vdu.VduArtifact;
+import org.openecomp.mso.adapters.vdu.VduArtifact.ArtifactType;
+import org.openecomp.mso.adapters.vdu.VduException;
+import org.openecomp.mso.adapters.vdu.VduInstance;
+import org.openecomp.mso.adapters.vdu.VduModelInfo;
+import org.openecomp.mso.adapters.vdu.VduPlugin;
+import org.openecomp.mso.adapters.vdu.VduStateType;
+import org.openecomp.mso.adapters.vdu.VduStatus;
import org.openecomp.mso.cloud.CloudConfig;
import org.openecomp.mso.cloud.CloudConfigFactory;
import org.openecomp.mso.cloud.CloudIdentity;
import org.openecomp.mso.properties.MsoPropertiesException;
import org.openecomp.mso.properties.MsoPropertiesFactory;
-import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.woorea.openstack.base.client.OpenStackConnectException;
import com.woorea.openstack.keystone.model.Authentication;
import com.woorea.openstack.keystone.utils.KeystoneUtils;
-public class MsoHeatUtils extends MsoCommonUtils {
+public class MsoHeatUtils extends MsoCommonUtils implements VduPlugin{
private MsoPropertiesFactory msoPropertiesFactory;
// The cache key is "tenantId:cloudId"
private static Map <String, HeatCacheEntry> heatClientCache = new HashMap <> ();
- // Fetch cloud configuration each time (may be cached in CloudConfig class)
- protected CloudConfig cloudConfig;
-
private static final MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA);
protected MsoJavaProperties msoProps = null;
private static final ObjectMapper JSON_MAPPER = new ObjectMapper();
+ /**
+ * This constructor MUST be used ONLY in the JUNIT tests, not for real code.
+ */
+ public MsoHeatUtils() {
+
+ }
+
/**
* This constructor MUST be used ONLY in the JUNIT tests, not for real code.
* The MsoPropertiesFactory will be added by EJB injection.
} catch (MsoPropertiesException e) {
LOGGER.error (MessageEnum.LOAD_PROPERTIES_FAIL, "Unknown. Mso Properties ID not found in cache: " + msoPropID, "", "", MsoLogger.ErrorCode.DataError, "Exception - Mso Properties ID not found in cache", e);
}
- cloudConfig = cloudConfigFactory.getCloudConfig ();
LOGGER.debug("MsoHeatUtils:" + msoPropID);
-
}
+ protected CloudConfigFactory getCloudConfigFactory() {
+ return cloudConfigFactory;
+ }
/**
* keep this old method signature here to maintain backwards compatibility. keep others as well.
}
// Obtain the cloud site information where we will create the stack
- CloudSite cloudSite = cloudConfig.getCloudSite(cloudSiteId).orElseThrow(
+ CloudSite cloudSite = getCloudConfigFactory().getCloudConfig().getCloudSite(cloudSiteId).orElseThrow(
() -> new MsoCloudSiteNotFound(cloudSiteId));
LOGGER.debug("Found: " + cloudSite.toString());
// Get a Heat client. They are cached between calls (keyed by tenantId:cloudId)
LOGGER.debug ("Query HEAT stack: " + stackName + " in tenant " + tenantId);
// Obtain the cloud site information where we will create the stack
- CloudSite cloudSite = cloudConfig.getCloudSite(cloudSiteId).orElseThrow(
+ CloudSite cloudSite = getCloudConfigFactory().getCloudConfig().getCloudSite(cloudSiteId).orElseThrow(
() -> new MsoCloudSiteNotFound(cloudSiteId));
LOGGER.debug("Found: " + cloudSite.toString());
String stackName,
boolean pollForCompletion) throws MsoException {
// Obtain the cloud site information where we will create the stack
- CloudSite cloudSite = cloudConfig.getCloudSite(cloudSiteId).orElseThrow(
+ CloudSite cloudSite = getCloudConfigFactory().getCloudConfig().getCloudSite(cloudSiteId).orElseThrow(
() -> new MsoCloudSiteNotFound(cloudSiteId));
LOGGER.debug("Found: " + cloudSite.toString());
*/
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(
+ CloudSite cloudSite = getCloudConfigFactory().getCloudConfig().getCloudSite(cloudSiteId).orElseThrow(
() -> new MsoCloudSiteNotFound(cloudSiteId));
// Get a Heat client. They are cached between calls (keyed by tenantId:cloudId)
Heat heatClient = getHeatClient (cloudSite, tenantId);
return sb.toString();
}
+ /*******************************************************************************
+ *
+ * Methods (and associated utilities) to implement the VduPlugin interface
+ *
+ *******************************************************************************/
+
+ /**
+ * VduPlugin interface for instantiate function.
+ *
+ * Translate the VduPlugin parameters to the corresponding 'createStack' parameters,
+ * and then invoke the existing function.
+ */
+ public VduInstance instantiateVdu (
+ CloudInfo cloudInfo,
+ String instanceName,
+ Map<String,Object> inputs,
+ VduModelInfo vduModel,
+ boolean rollbackOnFailure)
+ throws VduException
+ {
+ String cloudSiteId = cloudInfo.getCloudSiteId();
+ String tenantId = cloudInfo.getTenantId();
+
+ // Translate the VDU ModelInformation structure to that which is needed for
+ // creating the Heat stack. Loop through the artifacts, looking specifically
+ // for MAIN_TEMPLATE and ENVIRONMENT. Any other artifact will
+ // be attached as a FILE.
+ String heatTemplate = null;
+ Map<String,Object> nestedTemplates = new HashMap<>();
+ Map<String,Object> files = new HashMap<>();
+ String heatEnvironment = null;
+
+ for (VduArtifact vduArtifact: vduModel.getArtifacts()) {
+ if (vduArtifact.getType() == ArtifactType.MAIN_TEMPLATE) {
+ heatTemplate = new String(vduArtifact.getContent());
+ }
+ else if (vduArtifact.getType() == ArtifactType.NESTED_TEMPLATE) {
+ nestedTemplates.put(vduArtifact.getName(), new String(vduArtifact.getContent()));
+ }
+ else if (vduArtifact.getType() == ArtifactType.ENVIRONMENT) {
+ heatEnvironment = new String(vduArtifact.getContent());
+ }
+ }
+
+ try {
+ StackInfo stackInfo = createStack (cloudSiteId,
+ tenantId,
+ instanceName,
+ heatTemplate,
+ inputs,
+ true, // poll for completion
+ vduModel.getTimeoutMinutes(),
+ heatEnvironment,
+ nestedTemplates,
+ files,
+ rollbackOnFailure);
+
+ // Populate a vduInstance from the StackInfo
+ VduInstance vduInstance = stackInfoToVduInstance(stackInfo);
+
+ return vduInstance;
+ }
+ catch (Exception e) {
+ throw new VduException ("MsoHeatUtils (instantiateVDU): createStack Exception", e);
+ }
+ }
+
+
+ /**
+ * VduPlugin interface for query function.
+ */
+ public VduInstance queryVdu (CloudInfo cloudInfo, String instanceId)
+ throws VduException
+ {
+ String cloudSiteId = cloudInfo.getCloudSiteId();
+ String tenantId = cloudInfo.getTenantId();
+
+ try {
+ // Query the Cloudify Deployment object and populate a VduInstance
+ StackInfo stackInfo = queryStack (cloudSiteId, tenantId, instanceId);
+
+ VduInstance vduInstance = stackInfoToVduInstance(stackInfo);
+
+ return vduInstance;
+ }
+ catch (Exception e) {
+ throw new VduException ("MsoHeatUtile (queryVdu): queryStack Exception ", e);
+ }
+ }
+
+
+ /**
+ * VduPlugin interface for delete function.
+ */
+ public VduInstance deleteVdu (CloudInfo cloudInfo, String instanceId, int timeoutMinutes)
+ throws VduException
+ {
+ String cloudSiteId = cloudInfo.getCloudSiteId();
+ String tenantId = cloudInfo.getTenantId();
+
+ try {
+ // Delete the Heat stack
+ StackInfo stackInfo = deleteStack (tenantId, cloudSiteId, instanceId, true);
+
+ // Populate a VduInstance based on the deleted Cloudify Deployment object
+ VduInstance vduInstance = stackInfoToVduInstance(stackInfo);
+
+ // Override return state to DELETED (HeatUtils sets to NOTFOUND)
+ vduInstance.getStatus().setState(VduStateType.DELETED);
+
+ return vduInstance;
+ }
+ catch (Exception e) {
+ throw new VduException ("Delete VDU Exception", e);
+ }
+ }
+
+
+ /**
+ * VduPlugin interface for update function.
+ *
+ * Update is currently not supported in the MsoHeatUtils implementation of VduPlugin.
+ * Just return a VduException.
+ *
+ */
+ public VduInstance updateVdu (
+ CloudInfo cloudInfo,
+ String instanceId,
+ Map<String,Object> inputs,
+ VduModelInfo vduModel,
+ boolean rollbackOnFailure)
+ throws VduException
+ {
+ throw new VduException ("MsoHeatUtils: updateVdu interface not supported");
+ }
+
+
+ /*
+ * Convert the local DeploymentInfo object (Cloudify-specific) to a generic VduInstance object
+ */
+ private VduInstance stackInfoToVduInstance (StackInfo stackInfo)
+ {
+ VduInstance vduInstance = new VduInstance();
+
+ // The full canonical name as the instance UUID
+ vduInstance.setVduInstanceId(stackInfo.getCanonicalName());
+ vduInstance.setVduInstanceName(stackInfo.getName());
+
+ // Copy inputs and outputs
+ vduInstance.setInputs(stackInfo.getParameters());
+ vduInstance.setOutputs(stackInfo.getOutputs());
+
+ // Translate the status elements
+ vduInstance.setStatus(stackStatusToVduStatus (stackInfo));
+
+ return vduInstance;
+ }
+
+ private VduStatus stackStatusToVduStatus (StackInfo stackInfo)
+ {
+ VduStatus vduStatus = new VduStatus();
+
+ // Map the status fields to more generic VduStatus.
+ // There are lots of HeatStatus values, so this is a bit long...
+ HeatStatus heatStatus = stackInfo.getStatus();
+ String statusMessage = stackInfo.getStatusMessage();
+
+ if (heatStatus == HeatStatus.INIT || heatStatus == HeatStatus.BUILDING) {
+ vduStatus.setState(VduStateType.INSTANTIATING);
+ vduStatus.setLastAction((new PluginAction ("create", "in_progress", statusMessage)));
+ }
+ else if (heatStatus == HeatStatus.NOTFOUND) {
+ vduStatus.setState(VduStateType.NOTFOUND);
+ }
+ else if (heatStatus == HeatStatus.CREATED) {
+ vduStatus.setState(VduStateType.INSTANTIATED);
+ vduStatus.setLastAction((new PluginAction ("create", "complete", statusMessage)));
+ }
+ else if (heatStatus == HeatStatus.UPDATED) {
+ vduStatus.setState(VduStateType.INSTANTIATED);
+ vduStatus.setLastAction((new PluginAction ("update", "complete", statusMessage)));
+ }
+ else if (heatStatus == HeatStatus.UPDATING) {
+ vduStatus.setState(VduStateType.UPDATING);
+ vduStatus.setLastAction((new PluginAction ("update", "in_progress", statusMessage)));
+ }
+ else if (heatStatus == HeatStatus.DELETING) {
+ vduStatus.setState(VduStateType.DELETING);
+ vduStatus.setLastAction((new PluginAction ("delete", "in_progress", statusMessage)));
+ }
+ else if (heatStatus == HeatStatus.FAILED) {
+ vduStatus.setState(VduStateType.FAILED);
+ vduStatus.setErrorMessage(stackInfo.getStatusMessage());
+ } else {
+ vduStatus.setState(VduStateType.UNKNOWN);
+ }
+
+ return vduStatus;
+ }
+
}