2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Modifications Copyright (C) 2018 IBM.
8 * Modifications Copyright (c) 2019 Samsung
9 * ================================================================================
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 * ============LICENSE_END=========================================================
24 package org.onap.so.adapters.vnf;
27 import java.util.ArrayList;
28 import java.util.HashMap;
29 import java.util.List;
31 import java.util.Optional;
34 import javax.jws.WebService;
35 import javax.xml.ws.Holder;
37 import org.onap.so.adapters.vnf.exceptions.VnfAlreadyExists;
38 import org.onap.so.adapters.vnf.exceptions.VnfException;
39 import org.onap.so.cloud.CloudConfig;
40 import org.onap.so.db.catalog.beans.CloudSite;
41 import org.onap.so.cloudify.beans.DeploymentInfo;
42 import org.onap.so.cloudify.beans.DeploymentStatus;
43 import org.onap.so.cloudify.exceptions.MsoCloudifyManagerNotFound;
44 import org.onap.so.cloudify.utils.MsoCloudifyUtils;
45 import org.onap.so.db.catalog.beans.HeatEnvironment;
46 import org.onap.so.db.catalog.beans.HeatFiles;
47 import org.onap.so.db.catalog.beans.HeatTemplate;
48 import org.onap.so.db.catalog.beans.HeatTemplateParam;
49 import org.onap.so.db.catalog.beans.VfModule;
50 import org.onap.so.db.catalog.beans.VfModuleCustomization;
51 import org.onap.so.db.catalog.beans.VnfResource;
52 import org.onap.so.db.catalog.data.repository.VFModuleCustomizationRepository;
53 import org.onap.so.db.catalog.utils.MavenLikeVersioning;
54 import org.onap.so.entity.MsoRequest;
55 import org.onap.so.logger.MessageEnum;
57 import org.onap.so.logger.MsoLogger;
58 import org.onap.so.openstack.beans.MsoTenant;
59 import org.onap.so.openstack.beans.VnfRollback;
60 import org.onap.so.openstack.beans.VnfStatus;
61 import org.onap.so.openstack.exceptions.MsoCloudSiteNotFound;
62 import org.onap.so.openstack.exceptions.MsoException;
63 import org.onap.so.openstack.exceptions.MsoExceptionCategory;
64 import org.onap.so.openstack.utils.MsoHeatEnvironmentEntry;
65 import org.onap.so.openstack.utils.MsoHeatEnvironmentParameter;
66 import org.onap.so.openstack.utils.MsoKeystoneUtils;
67 import org.slf4j.Logger;
68 import org.slf4j.LoggerFactory;
69 import org.springframework.beans.factory.annotation.Autowired;
70 import org.springframework.core.env.Environment;
71 import org.springframework.stereotype.Component;
73 import com.fasterxml.jackson.core.JsonParseException;
74 import com.fasterxml.jackson.databind.JsonNode;
75 import com.fasterxml.jackson.databind.ObjectMapper;
76 import org.springframework.transaction.annotation.Transactional;
80 @WebService(serviceName = "VnfAdapter", endpointInterface = "org.onap.so.adapters.vnf.MsoVnfAdapter", targetNamespace = "http://org.onap.so/vnf")
81 public class MsoVnfCloudifyAdapterImpl implements MsoVnfAdapter {
83 private static Logger logger = LoggerFactory.getLogger(MsoVnfCloudifyAdapterImpl.class);
85 private static final String MSO_CONFIGURATION_ERROR = "MsoConfigurationError";
86 private static final String VNF_ADAPTER_SERVICE_NAME = "MSO-BPMN:MSO-VnfAdapter.";
87 private static final String LOG_REPLY_NAME = "MSO-VnfAdapter:MSO-BPMN.";
88 private static final String CHECK_REQD_PARAMS = "org.onap.so.adapters.vnf.checkRequiredParameters";
89 private static final String ADD_GET_FILES_ON_VOLUME_REQ = "org.onap.so.adapters.vnf.addGetFilesOnVolumeReq";
90 private static final String CLOUDIFY_RESPONSE_SUCCESS="Successfully received response from Cloudify";
91 private static final String CLOUDIFY="Cloudify";
93 private static final ObjectMapper JSON_MAPPER = new ObjectMapper();
96 protected CloudConfig cloudConfig;
99 private VFModuleCustomizationRepository vfModuleCustomRepo;
102 private Environment environment;
105 protected MsoKeystoneUtils keystoneUtils;
108 protected MsoCloudifyUtils cloudifyUtils;
110 * Health Check web method. Does nothing but return to show the adapter is deployed.
113 public void healthCheck () {
114 logger.debug("Health check call in VNF Cloudify Adapter");
118 * DO NOT use that constructor to instantiate this class, the msoPropertiesfactory will be NULL.
119 * @see MsoVnfCloudifyAdapterImpl#MsoVnfAdapterImpl(MsoPropertiesFactory, CloudConfigFactory)
121 public MsoVnfCloudifyAdapterImpl() {
126 * This is the "Create VNF" web service implementation.
127 * This function is now unsupported and will return an error.
131 public void createVnf (String cloudSiteId,
137 String volumeGroupHeatStackId,
138 Map <String, Object> inputs,
139 Boolean failIfExists,
141 Boolean enableBridge,
142 MsoRequest msoRequest,
143 Holder <String> vnfId,
144 Holder <Map <String, String>> outputs,
145 Holder <VnfRollback> rollback)
148 // This operation is no longer supported at the VNF level. The adapter is only called to deploy modules.
149 logger.debug("CreateVNF command attempted but not supported");
150 throw new VnfException("CreateVNF: Unsupported command", MsoExceptionCategory.USERDATA);
154 * This is the "Update VNF" web service implementation.
155 * This function is now unsupported and will return an error.
159 public void updateVnf (String cloudSiteId,
165 String volumeGroupHeatStackId,
166 Map <String, Object> inputs,
167 MsoRequest msoRequest,
168 Holder <Map <String, String>> outputs,
169 Holder <VnfRollback> rollback)
172 // This operation is no longer supported at the VNF level. The adapter is only called to deploy modules.
173 logger.debug("UpdateVNF command attempted but not supported");
174 throw new VnfException ("UpdateVNF: Unsupported command", MsoExceptionCategory.USERDATA);
178 * This is the "Query VNF" web service implementation.
180 * This really should be QueryVfModule, but nobody ever changed it.
182 * For Cloudify, this will look up a deployment by its deployment ID, which is really the same
183 * as deployment name, since it assigned by the client when a deployment is created.
184 * Also, the input cloudSiteId is used only to identify which Cloudify instance to query,
185 * and the tenantId is ignored (since that really only applies for Openstack/Heat).
187 * The method returns an indicator that the VNF exists, along with its status and outputs.
188 * The input "vnfName" will also be reflected back as its ID.
190 * @param cloudSiteId CLLI code of the cloud site in which to query
191 * @param tenantId Openstack tenant identifier - ignored for Cloudify
192 * @param vnfName VNF Name (should match a deployment ID)
193 * @param msoRequest Request tracking information for logs
194 * @param vnfExists Flag reporting the result of the query
195 * @param vnfId Holder for output VNF ID
196 * @param outputs Holder for Map of VNF outputs from Cloudify deployment (assigned IPs, etc)
199 public void queryVnf (String cloudSiteId,
202 MsoRequest msoRequest,
203 Holder <Boolean> vnfExists,
204 Holder <String> vnfId,
205 Holder <VnfStatus> status,
206 Holder <Map <String, String>> outputs)
209 logger.debug ("Querying VNF {} in {}", vnfName, cloudSiteId + "/" + tenantId);
211 // Will capture execution time for metrics
212 long startTime = System.currentTimeMillis ();
213 long subStartTime = System.currentTimeMillis ();
215 DeploymentInfo deployment = null;
218 deployment = cloudifyUtils.queryDeployment(cloudSiteId, tenantId, vnfName);
220 catch (MsoCloudifyManagerNotFound e) {
221 // This site does not have a Cloudify Manager.
222 // This isn't an error, just means we won't find the VNF here.
225 catch (MsoException me) {
226 // Failed to query the Deployment due to a cloudify exception.
227 // Convert to a generic VnfException
228 me.addContext("QueryVNF");
229 String error = "Query VNF (Cloudify): " + vnfName + " in " + cloudSiteId + "/" + tenantId + ": " + me;
231 .error("{} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vnfName, cloudSiteId, tenantId,
232 CLOUDIFY, "QueryVNF", MsoLogger.ErrorCode.DataError.getValue(), "Exception - queryDeployment", me);
234 throw new VnfException(me);
237 if (deployment != null && deployment.getStatus() != DeploymentStatus.NOTFOUND) {
238 vnfExists.value = Boolean.TRUE;
239 status.value = deploymentStatusToVnfStatus(deployment);
240 vnfId.value = deployment.getId();
241 outputs.value = copyStringOutputs(deployment.getOutputs());
243 logger.debug("VNF {} found in Cloudify, ID = {}", vnfName, vnfId.value);
245 vnfExists.value = Boolean.FALSE;
246 status.value = VnfStatus.NOTFOUND;
248 outputs.value = new HashMap<String, String>(); // Return as an empty map
250 logger.debug("VNF {} not found", vnfName);
257 * This is the "Delete VNF" web service implementation.
258 * This function is now unsupported and will return an error.
262 public void deleteVnf (String cloudSiteId,
265 MsoRequest msoRequest) throws VnfException {
267 // This operation is no longer supported at the VNF level. The adapter is only called to deploy modules.
268 logger.debug("DeleteVNF command attempted but not supported");
269 throw new VnfException ("DeleteVNF: Unsupported command", MsoExceptionCategory.USERDATA);
273 * This web service endpoint will rollback a previous Create VNF operation.
274 * A rollback object is returned to the client in a successful creation
275 * response. The client can pass that object as-is back to the rollbackVnf
276 * operation to undo the creation.
278 * TODO: This should be rollbackVfModule and/or rollbackVolumeGroup,
279 * but APIs were apparently never updated.
282 public void rollbackVnf (VnfRollback rollback) throws VnfException {
283 long startTime = System.currentTimeMillis ();
284 // rollback may be null (e.g. if stack already existed when Create was called)
285 if (rollback == null) {
286 logger.info ("{} {} {}", MessageEnum.RA_ROLLBACK_NULL.toString(), "OpenStack", "rollbackVnf");
290 // Don't rollback if nothing was done originally
291 if (!rollback.getVnfCreated()) {
295 // Get the elements of the VnfRollback object for easier access
296 String cloudSiteId = rollback.getCloudSiteId ();
297 String tenantId = rollback.getTenantId ();
298 String vfModuleId = rollback.getVfModuleStackId ();
300 logger.debug("Rolling Back VF Module {} in {}", vfModuleId, cloudSiteId + "/" + tenantId);
302 DeploymentInfo deployment = null;
304 // Use the MsoCloudifyUtils to delete the deployment. Set the polling flag to true.
305 // The possible outcomes of deleteStack are a StackInfo object with status
306 // of NOTFOUND (on success) or FAILED (on error). Also, MsoOpenstackException
308 long subStartTime = System.currentTimeMillis ();
310 // KLUDGE - Cloudify requires Tenant Name for Openstack. We have the ID.
311 // Go directly to Keystone until APIs could be updated to supply the name.
312 MsoTenant msoTenant = keystoneUtils.queryTenant(tenantId, cloudSiteId);
313 String tenantName = (msoTenant != null? msoTenant.getTenantName() : tenantId);
315 // TODO: Get a reasonable timeout. Use a global property, or store the creation timeout in rollback object and use that.
316 deployment = cloudifyUtils.uninstallAndDeleteDeployment(cloudSiteId, tenantName, vfModuleId, 5);
317 logger.debug("Rolled back deployment: {}", deployment.getId());
318 } catch (MsoException me) {
319 // Failed to rollback the VNF due to a cloudify exception.
320 // Convert to a generic VnfException
321 me.addContext ("RollbackVNF");
322 String error = "Rollback VF Module: " + vfModuleId + " in " + cloudSiteId + "/" + tenantId + ": " + me;
323 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_DELETE_VNF_ERR.toString(), vfModuleId, cloudSiteId,
324 tenantId, CLOUDIFY, "DeleteDeployment", MsoLogger.ErrorCode.DataError.getValue(),
325 "Exception - DeleteDeployment", me);
327 throw new VnfException (me);
333 private VnfStatus deploymentStatusToVnfStatus (DeploymentInfo deployment) {
334 // Determine the status based on last action & status
335 // DeploymentInfo object should be enhanced to report a better status internally.
336 DeploymentStatus status = deployment.getStatus();
337 String lastAction = deployment.getLastAction();
339 if (status == null || lastAction == null) {
340 return VnfStatus.UNKNOWN;
342 else if (status == DeploymentStatus.NOTFOUND) {
343 return VnfStatus.NOTFOUND;
345 else if (status == DeploymentStatus.INSTALLED) {
346 return VnfStatus.ACTIVE;
348 else if (status == DeploymentStatus.CREATED) {
349 // Should have an INACTIVE status for this case. Shouldn't really happen, but
350 // Install was never run, or Uninstall was done but deployment didn't get deleted.
351 return VnfStatus.UNKNOWN;
353 else if (status == DeploymentStatus.FAILED) {
354 return VnfStatus.FAILED;
357 return VnfStatus.UNKNOWN;
360 private Map <String, String> copyStringOutputs (Map <String, Object> stackOutputs) {
361 Map <String, String> stringOutputs = new HashMap <String, String> ();
362 for (String key : stackOutputs.keySet ()) {
363 if (stackOutputs.get (key) instanceof String) {
364 stringOutputs.put (key, (String) stackOutputs.get (key));
365 } else if (stackOutputs.get(key) instanceof Integer) {
367 String str = "" + stackOutputs.get(key);
368 stringOutputs.put(key, str);
369 } catch (Exception e) {
370 logger.debug("Unable to add " + key + " to outputs");
372 } else if (stackOutputs.get(key) instanceof JsonNode) {
374 String str = this.convertNode((JsonNode) stackOutputs.get(key));
375 stringOutputs.put(key, str);
376 } catch (Exception e) {
377 logger.debug("Unable to add " + key + " to outputs - exception converting JsonNode");
379 } else if (stackOutputs.get(key) instanceof java.util.LinkedHashMap) {
381 String str = JSON_MAPPER.writeValueAsString(stackOutputs.get(key));
382 stringOutputs.put(key, str);
383 } catch (Exception e) {
384 logger.debug("Unable to add " + key + " to outputs - exception converting LinkedHashMap");
388 String str = stackOutputs.get(key).toString();
389 stringOutputs.put(key, str);
390 } catch (Exception e) {
391 logger.debug("Unable to add " + key + " to outputs - unable to call .toString() " + e.getMessage());
395 return stringOutputs;
399 private void sendMapToDebug(Map<String, Object> inputs, String optionalName) {
401 StringBuilder sb = new StringBuilder(optionalName == null ? "\ninputs" : "\n" + optionalName);
402 if (inputs == null) {
405 else if (inputs.size() < 1) {
406 sb.append("\tEMPTY");
408 for (String str : inputs.keySet()) {
411 outputString = inputs.get(str).toString();
412 } catch (Exception e) {
413 outputString = "Unable to call toString() on the value for " + str;
415 sb.append("\t\nitem " + i++ + ": '" + str + "'='" + outputString + "'");
418 logger.debug(sb.toString());
422 private void sendMapToDebug(Map<String, Object> inputs) {
424 StringBuilder sb = new StringBuilder("inputs:");
425 if (inputs == null) {
428 else if (inputs.size() < 1) {
429 sb.append("\tEMPTY");
431 for (String str : inputs.keySet()) {
432 sb.append("\titem " + i++ + ": " + str + "=" + inputs.get(str));
435 logger.debug(sb.toString());
439 private String convertNode(final JsonNode node) {
441 final Object obj = JSON_MAPPER.treeToValue(node, Object.class);
442 final String json = JSON_MAPPER.writeValueAsString(obj);
444 } catch (JsonParseException jpe) {
445 logger.debug("Error converting json to string " + jpe.getMessage());
446 } catch (Exception e) {
447 logger.debug("Error converting json to string " + e.getMessage());
449 return "[Error converting json to string]";
452 private Map<String, String> convertMapStringObjectToStringString(Map<String, Object> objectMap) {
453 if (objectMap == null) {
456 Map<String, String> stringMap = new HashMap<String, String>();
457 for (String key : objectMap.keySet()) {
458 if (!stringMap.containsKey(key)) {
459 Object obj = objectMap.get(key);
460 if (obj instanceof String) {
461 stringMap.put(key, (String) objectMap.get(key));
462 } else if (obj instanceof JsonNode ){
463 // This is a bit of mess - but I think it's the least impacting
464 // let's convert it BACK to a string - then it will get converted back later
466 String str = this.convertNode((JsonNode) obj);
467 stringMap.put(key, str);
468 } catch (Exception e) {
469 logger.debug("DANGER WILL ROBINSON: unable to convert value for JsonNode "+ key);
470 //okay in this instance - only string values (fqdn) are expected to be needed
472 } else if (obj instanceof java.util.LinkedHashMap) {
473 logger.debug("LinkedHashMap - this is showing up as a LinkedHashMap instead of JsonNode");
475 String str = JSON_MAPPER.writeValueAsString(obj);
476 stringMap.put(key, str);
477 } catch (Exception e) {
478 logger.debug("DANGER WILL ROBINSON: unable to convert value for LinkedHashMap "+ key);
480 } else if (obj instanceof Integer) {
482 String str = "" + obj;
483 stringMap.put(key, str);
484 } catch (Exception e) {
485 logger.debug("DANGER WILL ROBINSON: unable to convert value for Integer "+ key);
489 String str = obj.toString();
490 stringMap.put(key, str);
491 } catch (Exception e) {
492 logger.debug("DANGER WILL ROBINSON: unable to convert value "+ key + " (" + e.getMessage() + ")");
502 * This is the "Create VF Module" web service implementation.
503 * It will instantiate a new VF Module of the requested type in the specified cloud
504 * and tenant. The tenant must exist before this service is called.
506 * If a VF Module with the same name already exists, this can be considered a
507 * success or failure, depending on the value of the 'failIfExists' parameter.
509 * All VF Modules are defined in the MSO catalog. The caller must request
510 * one of the pre-defined module types or an error will be returned. Within the
511 * catalog, each VF Module references (among other things) a cloud template
512 * which is used to deploy the required artifacts (VMs, networks, etc.)
513 * to the cloud. In this adapter implementation, that artifact is expected
514 * to be a Cloudify blueprint.
516 * Depending on the blueprint, a variable set of input parameters will
517 * be defined, some of which are required. The caller is responsible to
518 * pass the necessary input data for the module or an error will be thrown.
520 * The method returns the vfModuleId, a Map of output attributes, and a VnfRollback
521 * object. This last object can be passed as-is to the rollbackVnf operation to
522 * undo everything that was created for the Module. This is useful if a VF module
523 * is successfully created but the orchestration fails on a subsequent step.
525 * @param cloudSiteId CLLI code of the cloud site in which to create the VNF
526 * @param tenantId Openstack tenant identifier
527 * @param vfModuleType VF Module type key, should match a VNF definition in catalog DB.
528 * Deprecated - should use modelCustomizationUuid
529 * @param vnfVersion VNF version key, should match a VNF definition in catalog DB
530 * Deprecated - VF Module versions also captured by modelCustomizationUuid
531 * @param genericVnfId Generic VNF ID
532 * @param vfModuleName Name to be assigned to the new VF Module
533 * @param vfModuleId Id of the new VF Module
534 * @param requestType Indicates if this is a Volume Group or Module request
535 * @param volumeGroupId Identifier (i.e. deployment ID) for a Volume Group
536 * to attach to a VF Module
537 * @param baseVfModuleId Identifier (i.e. deployment ID) of the Base Module if
538 * this is an Add-on module
539 * @param modelCustomizationUuid Unique ID for the VF Module's model. Replaces
540 * the use of vfModuleType.
541 * @param inputs Map of key=value inputs for VNF stack creation
542 * @param failIfExists Flag whether already existing VNF should be considered
543 * @param backout Flag whether to suppress automatic backout (for testing)
544 * @param msoRequest Request tracking information for logs
545 * @param vnfId Holder for output VNF Cloudify Deployment ID
546 * @param outputs Holder for Map of VNF outputs from Deployment (assigned IPs, etc)
547 * @param rollback Holder for returning VnfRollback object
550 public void createVfModule(String cloudSiteId,
558 String volumeGroupId,
559 String baseVfModuleId,
560 String modelCustomizationUuid,
561 Map <String, Object> inputs,
562 Boolean failIfExists,
564 Boolean enableBridge,
565 MsoRequest msoRequest,
566 Holder <String> vnfId,
567 Holder <Map <String, String>> outputs,
568 Holder <VnfRollback> rollback)
571 // Will capture execution time for metrics
572 long startTime = System.currentTimeMillis ();
574 // Require a model customization ID. Every VF Module definition must have one.
575 if (modelCustomizationUuid == null || modelCustomizationUuid.isEmpty()) {
576 logger.debug("Missing required input: modelCustomizationUuid");
577 String error = "Create vfModule error: Missing required input: modelCustomizationUuid";
578 logger.error("{} {} {} {} {}", MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(),
579 "VF Module ModelCustomizationUuid", CLOUDIFY, MsoLogger.ErrorCode.DataError.getValue(),
580 "Create VF Module: Missing required input: modelCustomizationUuid");
582 throw new VnfException(error, MsoExceptionCategory.USERDATA);
585 // Clean up some inputs to make comparisons easier
586 if (requestType == null)
589 if ("".equals(volumeGroupId) || "null".equals(volumeGroupId))
590 volumeGroupId = null;
592 if ("".equals(baseVfModuleId) || "null".equals(baseVfModuleId))
593 baseVfModuleId = null;
595 if (inputs == null) {
596 // Create an empty set of inputs
597 inputs = new HashMap<>();
598 logger.debug("inputs == null - setting to empty");
600 this.sendMapToDebug(inputs);
603 // Check if this is for a "Volume" module
604 boolean isVolumeRequest = false;
605 if (requestType.startsWith("VOLUME")) {
606 isVolumeRequest = true;
609 logger.debug("requestType = " + requestType + ", volumeGroupStackId = " + volumeGroupId + ", baseStackId = " +
612 // Build a default rollback object (no actions performed)
613 VnfRollback vfRollback = new VnfRollback();
614 vfRollback.setCloudSiteId(cloudSiteId);
615 vfRollback.setTenantId(tenantId);
616 vfRollback.setMsoRequest(msoRequest);
617 vfRollback.setRequestType(requestType);
618 vfRollback.setIsBase(false); // Until we know better
619 vfRollback.setVolumeGroupHeatStackId(volumeGroupId);
620 vfRollback.setBaseGroupHeatStackId(baseVfModuleId);
621 vfRollback.setModelCustomizationUuid(modelCustomizationUuid);
622 vfRollback.setMode("CFY");
624 rollback.value = vfRollback; // Default rollback - no updates performed
626 // Get the VNF/VF Module definition from the Catalog DB first.
627 // There are three relevant records: VfModule, VfModuleCustomization, VnfResource
630 VnfResource vnfResource = null;
631 VfModuleCustomization vfmc = null;
634 vfmc = vfModuleCustomRepo.findByModelCustomizationUUID(modelCustomizationUuid);
637 String error = "Create vfModule error: Unable to find vfModuleCust with modelCustomizationUuid="
638 + modelCustomizationUuid;
640 logger.error("{} {} {} {} {} {}", MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "VF Module "
641 + "ModelCustomizationUuid",
642 modelCustomizationUuid, "CatalogDb", MsoLogger.ErrorCode.DataError.getValue(), error);
643 throw new VnfException(error, MsoExceptionCategory.USERDATA);
645 logger.debug("Found vfModuleCust entry " + vfmc.toString());
648 // Get the vfModule and vnfResource records
649 vf = vfmc.getVfModule();
650 vnfResource = vfmc.getVfModule().getVnfResources();
652 catch (Exception e) {
654 logger.debug("unhandled exception in create VF - [Query]" + e.getMessage());
655 throw new VnfException("Exception during create VF " + e.getMessage());
658 // Perform a version check against cloudSite
659 // Obtain the cloud site information where we will create the VF Module
660 Optional<CloudSite> cloudSiteOp = cloudConfig.getCloudSite (cloudSiteId);
661 if (!cloudSiteOp.isPresent()) {
662 throw new VnfException (new MsoCloudSiteNotFound (cloudSiteId));
664 CloudSite cloudSite = cloudSiteOp.get();
665 MavenLikeVersioning aicV = new MavenLikeVersioning();
666 aicV.setVersion(cloudSite.getCloudVersion());
668 String vnfMin = vnfResource.getAicVersionMin();
669 String vnfMax = vnfResource.getAicVersionMax();
671 if ( (vnfMin != null && !(aicV.isMoreRecentThan(vnfMin) || aicV.isTheSameVersion(vnfMin))) ||
672 (vnfMax != null && aicV.isMoreRecentThan(vnfMax)))
675 String error = "VNF Resource type: " + vnfResource.getModelName() + ", ModelUuid=" + vnfResource.getModelUUID()
676 + " VersionMin=" + vnfMin + " VersionMax:" + vnfMax + " NOT supported on Cloud: " + cloudSiteId
677 + " with AIC_Version:" + cloudSite.getCloudVersion();
678 logger.error("{} {} {} {} {}", MessageEnum.RA_CONFIG_EXC.toString(), error, "OpenStack",
679 MsoLogger.ErrorCode.BusinessProcesssError.getValue(), "Exception - setVersion");
681 throw new VnfException(error, MsoExceptionCategory.USERDATA);
686 DeploymentInfo cloudifyDeployment = null;
688 // First, look up to see if the VF already exists.
690 long subStartTime1 = System.currentTimeMillis ();
692 cloudifyDeployment = cloudifyUtils.queryDeployment (cloudSiteId, tenantId, vfModuleName);
694 catch (MsoException me) {
695 // Failed to query the Deployment due to a cloudify exception.
696 String error = "Create VF Module: Query " + vfModuleName + " in " + cloudSiteId + "/" + tenantId + ": " + me ;
697 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vfModuleName, cloudSiteId,
698 tenantId, CLOUDIFY, "queryDeployment", MsoLogger.ErrorCode.DataError.getValue(),
699 "Exception - queryDeployment", me);
702 // Convert to a generic VnfException
703 me.addContext ("CreateVFModule");
704 throw new VnfException (me);
707 // More precise handling/messaging if the Module already exists
708 if (cloudifyDeployment != null && !(cloudifyDeployment.getStatus () == DeploymentStatus.NOTFOUND)) {
709 // CREATED, INSTALLED, INSTALLING, FAILED, UNINSTALLING, UNKNOWN
710 DeploymentStatus status = cloudifyDeployment.getStatus();
711 logger.debug ("Found Existing Deployment, status=" + status);
713 if (status == DeploymentStatus.INSTALLED) {
715 if (failIfExists != null && failIfExists) {
716 String error = "Create VF: Deployment " + vfModuleName + " already exists in " + cloudSiteId + "/" + tenantId;
717 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_VNF_ALREADY_EXIST.toString(), vfModuleName,
718 cloudSiteId, tenantId, CLOUDIFY, "queryDeployment", MsoLogger.ErrorCode.DataError.getValue(),
719 "Deployment " + vfModuleName + " already exists");
721 throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, cloudifyDeployment.getId());
723 // Found existing deployment and client has not requested "failIfExists".
724 // Populate the outputs from the existing deployment.
726 vnfId.value = cloudifyDeployment.getId();
727 outputs.value = copyStringOutputs (cloudifyDeployment.getOutputs ());
731 // Check through various detailed error cases
732 if (status == DeploymentStatus.INSTALLING || status == DeploymentStatus.UNINSTALLING) {
733 // fail - it's in progress - return meaningful error
734 String error = "Create VF: Deployment " + vfModuleName + " already exists and has status " + status.toString() + " in " + cloudSiteId + "/" + tenantId + "; please wait for it to complete, or fix manually.";
735 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_VNF_ALREADY_EXIST.toString(), vfModuleName,
736 cloudSiteId, tenantId, CLOUDIFY, "queryDeployment", MsoLogger.ErrorCode.DataError.getValue(),
737 "Deployment " + vfModuleName + " already exists");
739 throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, cloudifyDeployment.getId());
741 else if (status == DeploymentStatus.FAILED) {
742 // fail - it exists and is in a FAILED state
743 String error = "Create VF: Deployment " + vfModuleName + " already exists and is in FAILED state in " + cloudSiteId + "/" + tenantId + "; requires manual intervention.";
744 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_VNF_ALREADY_EXIST.toString(), vfModuleName,
745 cloudSiteId, tenantId, CLOUDIFY, "queryDeployment", MsoLogger.ErrorCode.DataError.getValue(),
746 "Deployment " + vfModuleName + " already " + "exists and is in FAILED state");
748 throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, cloudifyDeployment.getId());
750 else if (status == DeploymentStatus.UNKNOWN || status == DeploymentStatus.CREATED) {
751 // fail - it exists and is in a UNKNOWN state
752 String error = "Create VF: Deployment " + vfModuleName + " already exists and has status " + status.toString() + " in " + cloudSiteId + "/" + tenantId + "; requires manual intervention.";
753 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_VNF_ALREADY_EXIST.toString(), vfModuleName,
754 cloudSiteId, tenantId, CLOUDIFY, "queryDeployment", MsoLogger.ErrorCode.DataError.getValue(),
755 "Deployment " + vfModuleName + " already " + "exists and is in " + status.toString() + " state");
757 throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, cloudifyDeployment.getId());
760 // Unexpected, since all known status values have been tested for
762 "Create VF: Deployment " + vfModuleName + " already exists with unexpected status " + status
763 .toString() + " in " + cloudSiteId + "/" + tenantId + "; requires manual intervention.";
764 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_VNF_ALREADY_EXIST.toString(), vfModuleName,
765 cloudSiteId, tenantId, CLOUDIFY, "queryDeployment", MsoLogger.ErrorCode.DataError.getValue(),
766 "Deployment " + vfModuleName + " already " + "exists and is in an unknown state");
768 throw new VnfAlreadyExists(vfModuleName, cloudSiteId, tenantId, cloudifyDeployment.getId());
773 // Collect outputs from Base Modules and Volume Modules
774 Map<String, Object> baseModuleOutputs = null;
775 Map<String, Object> volumeGroupOutputs = null;
777 // If a Volume Group was provided, query its outputs for inclusion in Module input parameters
778 if (volumeGroupId != null) {
779 long subStartTime2 = System.currentTimeMillis ();
780 DeploymentInfo volumeDeployment = null;
782 volumeDeployment = cloudifyUtils.queryDeployment (cloudSiteId, tenantId, volumeGroupId);
784 catch (MsoException me) {
785 // Failed to query the Volume GroupDeployment due to a cloudify exception.
786 String error = "Create VF Module: Query Volume Group " + volumeGroupId + " in " + cloudSiteId + "/" + tenantId + ": " + me ;
787 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), volumeGroupId,
788 cloudSiteId, tenantId, CLOUDIFY, "queryDeployment(volume)",
789 MsoLogger.ErrorCode.DataError.getValue(), "Exception - queryDeployment(volume)", me);
791 // Convert to a generic VnfException
792 me.addContext ("CreateVFModule(QueryVolume)");
793 throw new VnfException (me);
796 if (volumeDeployment == null || volumeDeployment.getStatus() == DeploymentStatus.NOTFOUND) {
798 "Create VFModule: Attached Volume Group DOES NOT EXIST " + volumeGroupId + " in " + cloudSiteId + "/"
799 + tenantId + " USER ERROR";
800 logger.error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), volumeGroupId,
801 cloudSiteId, tenantId, error, CLOUDIFY, "queryDeployment(volume)",
802 MsoLogger.ErrorCode.BusinessProcesssError.getValue(),
803 "Create VFModule: Attached Volume Group DOES NOT EXIST");
805 throw new VnfException(error, MsoExceptionCategory.USERDATA);
807 logger.debug("Found nested volume group");
808 volumeGroupOutputs = volumeDeployment.getOutputs();
809 this.sendMapToDebug(volumeGroupOutputs, "volumeGroupOutputs");
813 // If this is an Add-On Module, query the Base Module outputs
814 // Note: This will be performed whether or not the current request is for an
815 // Add-On Volume Group or Add-On VF Module
817 if (vf.getIsBase()) {
818 logger.debug("This is a BASE Module request");
819 vfRollback.setIsBase(true);
821 logger.debug("This is an Add-On Module request");
823 // Add-On Modules should always have a Base, but just treat as a warning if not provided.
824 // Add-on Volume requests may or may not specify a base.
825 if (!isVolumeRequest && baseVfModuleId == null) {
826 logger.debug ("WARNING: Add-on Module request - no Base Module ID provided");
829 if (baseVfModuleId != null) {
830 long subStartTime2 = System.currentTimeMillis ();
831 DeploymentInfo baseDeployment = null;
833 baseDeployment = cloudifyUtils.queryDeployment (cloudSiteId, tenantId, baseVfModuleId);
835 catch (MsoException me) {
836 // Failed to query the Volume GroupDeployment due to a cloudify exception.
838 "Create VF Module: Query Base " + baseVfModuleId + " in " + cloudSiteId + "/" + tenantId + ": "
840 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), baseVfModuleId,
841 cloudSiteId, tenantId, CLOUDIFY, "queryDeployment(Base)",
842 MsoLogger.ErrorCode.DataError.getValue(), "Exception - queryDeployment(Base)", me);
844 // Convert to a generic VnfException
845 me.addContext("CreateVFModule(QueryBase)");
846 throw new VnfException (me);
849 if (baseDeployment == null || baseDeployment.getStatus() == DeploymentStatus.NOTFOUND) {
851 "Create VFModule: Base Module DOES NOT EXIST " + baseVfModuleId + " in " + cloudSiteId + "/"
852 + tenantId + " USER ERROR";
853 logger.error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), baseVfModuleId,
854 cloudSiteId, tenantId, error, CLOUDIFY, "queryDeployment(Base)",
855 MsoLogger.ErrorCode.BusinessProcesssError.getValue(),
856 "Create VFModule: Base " + "Module DOES NOT EXIST");
858 throw new VnfException(error, MsoExceptionCategory.USERDATA);
860 logger.debug("Found base module");
861 baseModuleOutputs = baseDeployment.getOutputs();
862 this.sendMapToDebug(baseModuleOutputs, "baseModuleOutputs");
868 // Ready to deploy the new VNF
870 // NOTE: For this section, heatTemplate is used for both HEAT templates and Cloudify blueprints.
871 // In final implementation (post-POC), the template object would either be generic or there would
872 // be a separate DB Table/Object for Blueprints.
875 // NOTE: The template is fixed for the VF Module. The environment is part of the customization.
876 HeatTemplate heatTemplate = null;
877 HeatEnvironment heatEnvironment = null;
878 if (isVolumeRequest) {
879 heatTemplate = vf.getVolumeHeatTemplate();
880 heatEnvironment = vfmc.getVolumeHeatEnv();
882 heatTemplate = vf.getModuleHeatTemplate();
883 heatEnvironment = vfmc.getHeatEnvironment();
886 if (heatTemplate == null) {
887 String error = "UpdateVF: No Heat Template ID defined in catalog database for " + vfModuleType + ", reqType="
889 logger.error("{} {} {} {} {} {}", MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "Heat Template ID", vfModuleType,
890 "OpenStack", MsoLogger.ErrorCode.DataError.getValue(), error);
891 throw new VnfException(error, MsoExceptionCategory.INTERNAL);
893 logger.debug("Got HEAT Template from DB: {}", heatTemplate.getHeatTemplate());
896 if (heatEnvironment == null) {
897 String error = "Update VNF: undefined Heat Environment. VF=" + vfModuleType;
898 logger.error("{} {} {} {} {}", MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "Heat Environment ID",
899 "OpenStack", MsoLogger.ErrorCode.DataError.getValue(), error);
900 // Alarm on this error, configuration must be fixed
901 throw new VnfException(error, MsoExceptionCategory.INTERNAL);
903 logger.debug("Got Heat Environment from DB: {}", heatEnvironment.getEnvironment());
908 // All variables converted to their native object types
909 HashMap<String, Object> goldenInputs = new HashMap<String,Object>();
910 List<String> extraInputs = new ArrayList<String>();
912 // NOTE: SKIP THIS FOR CLOUDIFY for now. Just use what was passed in.
913 // This whole section needs to be rewritten.
914 Boolean skipInputChecks = false;
916 if (skipInputChecks) {
917 goldenInputs = new HashMap<String,Object>();
918 for (String key : inputs.keySet()) {
919 goldenInputs.put(key, inputs.get(key));
923 // Build maps for the parameters (including aliases) to simplify checks
924 HashMap<String, HeatTemplateParam> params = new HashMap<String, HeatTemplateParam>();
926 Set<HeatTemplateParam> paramSet = heatTemplate.getParameters();
927 logger.debug("paramSet has {} entries", paramSet.size());
929 for (HeatTemplateParam htp : paramSet) {
930 params.put(htp.getParamName(), htp);
933 String alias = htp.getParamAlias();
934 if (alias != null && !alias.equals("") && !params.containsKey(alias)) {
935 params.put(alias, htp);
939 // First, convert all inputs to their "template" type
940 for (String key : inputs.keySet()) {
941 if (params.containsKey(key)) {
942 Object value = cloudifyUtils.convertInputValue(inputs.get(key), params.get(key));
944 goldenInputs.put(key, value);
947 logger.debug("Failed to convert input " + key + "='" + inputs.get(key) + "' to " + params.get(key)
951 extraInputs.add(key);
955 if (!extraInputs.isEmpty()) {
956 logger.debug("Ignoring extra inputs: " + extraInputs);
959 // Next add in Volume Group Outputs if there are any. Copy directly without conversions.
960 if (volumeGroupOutputs != null && !volumeGroupOutputs.isEmpty()) {
961 for (String key : volumeGroupOutputs.keySet()) {
962 if (params.containsKey(key) && !goldenInputs.containsKey(key)) {
963 goldenInputs.put(key, volumeGroupOutputs.get(key));
968 // Next add in Base Module Outputs if there are any. Copy directly without conversions.
969 if (baseModuleOutputs != null && !baseModuleOutputs.isEmpty()) {
970 for (String key : baseModuleOutputs.keySet()) {
971 if (params.containsKey(key) && !goldenInputs.containsKey(key)) {
972 goldenInputs.put(key, baseModuleOutputs.get(key));
977 // Last, add in values from the "environment" file.
978 // These are added to the inputs, since Cloudify doesn't pass an environment file like Heat.
980 // TODO: This may take a different form for Cloudify, but for now process it
981 // with Heat environment file syntax
982 StringBuilder sb = new StringBuilder(heatEnvironment.getEnvironment());
983 MsoHeatEnvironmentEntry mhee = new MsoHeatEnvironmentEntry (sb);
985 if (mhee.getParameters() != null) {
986 for (MsoHeatEnvironmentParameter envParam : mhee.getParameters()) {
987 // If this is a template input, copy to golden inputs
988 String envKey = envParam.getName();
989 if (params.containsKey(envKey) && !goldenInputs.containsKey(envKey)) {
990 Object value = cloudifyUtils.convertInputValue(envParam.getValue(), params.get(envKey));
992 goldenInputs.put(envKey, value);
995 logger.debug("Failed to convert environment parameter " + envKey + "='" + envParam.getValue() + "' to " +
996 params.get(envKey).getParamType());
1002 this.sendMapToDebug(goldenInputs, "Final inputs sent to Cloudify");
1005 // Check that required parameters have been supplied from any of the sources
1006 String missingParams = null;
1007 boolean checkRequiredParameters = true;
1009 String propertyString = this.environment.getProperty(MsoVnfCloudifyAdapterImpl.CHECK_REQD_PARAMS);
1010 if ("false".equalsIgnoreCase (propertyString) || "n".equalsIgnoreCase (propertyString)) {
1011 checkRequiredParameters = false;
1012 logger.debug("CheckRequiredParameters is FALSE. Will still check but then skip blocking... {}",
1013 MsoVnfCloudifyAdapterImpl.CHECK_REQD_PARAMS);
1015 } catch (Exception e) {
1016 // No problem - default is true
1017 logger.debug("An exception occured trying to get property {}",
1018 MsoVnfCloudifyAdapterImpl.CHECK_REQD_PARAMS, e);
1022 for (HeatTemplateParam parm : heatTemplate.getParameters ()) {
1023 if (parm.isRequired () && (!goldenInputs.containsKey (parm.getParamName ()))) {
1024 logger.debug("adding to missing parameters list: {}", parm.getParamName());
1025 if (missingParams == null) {
1026 missingParams = parm.getParamName();
1028 missingParams += "," + parm.getParamName();
1033 if (missingParams != null) {
1034 if (checkRequiredParameters) {
1035 // Problem - missing one or more required parameters
1036 String error = "Create VFModule: Missing Required inputs: " + missingParams;
1037 logger.error("{} {} {} {} {}", MessageEnum.RA_MISSING_PARAM.toString(), missingParams, CLOUDIFY,
1038 MsoLogger.ErrorCode.DataError.getValue(), "Create VFModule: Missing Required inputs");
1039 logger.debug(error);
1040 throw new VnfException(error, MsoExceptionCategory.USERDATA);
1043 "found missing parameters [" + missingParams + "] - but checkRequiredParameters is false -"
1044 + " will not block");
1047 logger.debug("No missing parameters found - ok to proceed");
1050 } // NOTE: END PARAMETER CHECKING
1052 // Ready to deploy the VF Module.
1053 // *First step - make sure the blueprint is loaded into Cloudify.
1054 String blueprintName = heatTemplate.getTemplateName();
1055 String blueprint = heatTemplate.getTemplateBody();
1056 String blueprintId = blueprintName;
1058 // Use the main blueprint name as the blueprint ID (strip yaml extensions).
1059 if (blueprintId.endsWith(".yaml"))
1060 blueprintId = blueprintId.substring(0,blueprintId.lastIndexOf(".yaml"));
1063 if (! cloudifyUtils.isBlueprintLoaded (cloudSiteId, blueprintId)) {
1064 logger.debug("Blueprint " + blueprintId + " is not loaded. Will upload it now.");
1066 Map<String,byte[]> blueprintFiles = new HashMap<String,byte[]>();
1068 blueprintFiles.put(blueprintName, blueprint.getBytes());
1070 // TODO: Implement nested blueprint logic based on Cloudify structures.
1071 // For now, just use the Heat structures.
1072 // The query returns a map of String->Object, where the map keys provide one layer of
1073 // indirection from the Heat template names. For this case, assume the map key matches
1074 // the nested blueprint name.
1075 List<HeatTemplate> nestedBlueprints = heatTemplate.getChildTemplates();
1076 if (nestedBlueprints != null) {
1077 for (HeatTemplate nestedBlueprint: nestedBlueprints) {
1078 blueprintFiles.put(nestedBlueprint.getTemplateName(), nestedBlueprint.getTemplateBody().getBytes());
1082 // TODO: Implement file artifact logic based on Cloudify structures.
1083 // For now, just use the Heat structures.
1084 List<HeatFiles> heatFiles = vf.getHeatFiles();
1085 if (heatFiles != null) {
1086 for (HeatFiles heatFile: heatFiles) {
1087 blueprintFiles.put(heatFile.getFileName(), heatFile.getFileBody().getBytes());
1091 // Upload the blueprint package
1092 cloudifyUtils.uploadBlueprint(cloudSiteId, blueprintId, blueprintName, blueprintFiles, false);
1097 catch (MsoException me) {
1098 me.addContext("CreateVFModule");
1099 String error = "Create VF Module: Upload blueprint failed. Blueprint=" + blueprintName + ": " + me;
1100 logger.error("{} {} {} {} {} {} {}", MessageEnum.RA_CREATE_VNF_ERR.toString(), vfModuleType, cloudSiteId,
1101 tenantId, CLOUDIFY, MsoLogger.ErrorCode.DataError.getValue(), "MsoException - uploadBlueprint", me);
1102 logger.debug(error);
1103 throw new VnfException(me);
1106 // Ignore MsoTenantNotFound and MsoStackAlreadyExists exceptions
1107 // because we already checked for those.
1108 long createDeploymentStarttime = System.currentTimeMillis ();
1110 // KLUDGE - Cloudify requires Tenant Name for Openstack. We have the ID.
1111 // Go directly to Keystone until APIs could be updated to supply the name.
1112 MsoTenant msoTenant = keystoneUtils.queryTenant(tenantId, cloudSiteId);
1113 String tenantName = (msoTenant != null? msoTenant.getTenantName() : tenantId);
1115 if (backout == null) {
1119 cloudifyDeployment = cloudifyUtils.createAndInstallDeployment (cloudSiteId,
1125 heatTemplate.getTimeoutMinutes (),
1126 backout.booleanValue());
1128 } catch (MsoException me) {
1129 me.addContext ("CreateVFModule");
1130 String error = "Create VF Module " + vfModuleType + " in " + cloudSiteId + "/" + tenantId + ": " + me;
1132 .error("{} {} {} {} {} {} {}", MessageEnum.RA_CREATE_VNF_ERR.toString(), vfModuleType, cloudSiteId,
1133 tenantId, CLOUDIFY, MsoLogger.ErrorCode.DataError.getValue(), "MsoException - createDeployment",
1135 logger.debug(error);
1136 throw new VnfException (me);
1137 } catch (NullPointerException npe) {
1138 String error = "Create VFModule " + vfModuleType + " in " + cloudSiteId + "/" + tenantId + ": " + npe;
1140 .error("{} {} {} {} {} {} {}", MessageEnum.RA_CREATE_VNF_ERR.toString(), vfModuleType, cloudSiteId,
1141 tenantId, CLOUDIFY, MsoLogger.ErrorCode.DataError.getValue(),
1142 "NullPointerException - createDeployment", npe);
1143 logger.debug(error);
1144 logger.debug("NULL POINTER EXCEPTION at cloudify.createAndInstallDeployment");
1145 //npe.addContext ("CreateVNF");
1146 throw new VnfException ("NullPointerException during cloudify.createAndInstallDeployment");
1147 } catch (Exception e) {
1148 logger.debug("unhandled exception at cloudify.createAndInstallDeployment");
1149 throw new VnfException("Exception during cloudify.createAndInstallDeployment! " + e.getMessage());
1151 } catch (Exception e) {
1152 logger.debug("unhandled exception in create VF");
1153 throw new VnfException("Exception during create VF " + e.getMessage());
1157 // Reach this point if create is successful.
1158 // Populate remaining rollback info and response parameters.
1159 vfRollback.setVnfCreated (true);
1160 vfRollback.setVnfId (cloudifyDeployment.getId());
1161 vnfId.value = cloudifyDeployment.getId();
1162 outputs.value = copyStringOutputs (cloudifyDeployment.getOutputs ());
1164 rollback.value = vfRollback;
1166 logger.debug("VF Module successfully created", vfModuleName);
1170 public void deleteVfModule (String cloudSiteId,
1173 MsoRequest msoRequest,
1174 Holder <Map <String, String>> outputs) throws VnfException {
1176 logger.debug ("Deleting VF " + vnfName + " in " + cloudSiteId + "/" + tenantId);
1177 // Will capture execution time for metrics
1178 long startTime = System.currentTimeMillis ();
1180 // 1702 capture the output parameters on a delete
1181 // so we'll need to query first
1182 DeploymentInfo deployment = null;
1184 deployment = cloudifyUtils.queryDeployment(cloudSiteId, tenantId, vnfName);
1185 } catch (MsoException me) {
1186 // Failed to query the deployment. Convert to a generic VnfException
1187 me.addContext ("DeleteVFModule");
1188 String error = "Delete VFModule: Query to get outputs: " + vnfName + " in " + cloudSiteId + "/" + tenantId + ": " + me;
1189 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vnfName, cloudSiteId,
1190 tenantId, CLOUDIFY, "QueryDeployment", MsoLogger.ErrorCode.DataError.getValue(),
1191 "Exception - QueryDeployment", me);
1192 logger.debug(error);
1193 throw new VnfException (me);
1195 // call method which handles the conversion from Map<String,Object> to Map<String,String> for our expected Object types
1196 outputs.value = convertMapStringObjectToStringString(deployment.getOutputs());
1198 // Use the MsoHeatUtils to delete the stack. Set the polling flag to true.
1199 // The possible outcomes of deleteStack are a StackInfo object with status
1200 // of NOTFOUND (on success) or FAILED (on error). Also, MsoOpenstackException
1202 long subStartTime = System.currentTimeMillis ();
1204 cloudifyUtils.uninstallAndDeleteDeployment(cloudSiteId, tenantId, vnfName, 5);
1205 } catch (MsoException me) {
1206 me.addContext("DeleteVfModule");
1207 // Convert to a generic VnfException
1208 String error = "Delete VF: " + vnfName + " in " + cloudSiteId + "/" + tenantId + ": " + me;
1209 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_DELETE_VNF_ERR.toString(), vnfName, cloudSiteId,
1210 tenantId, "DeleteDeployment", "DeleteDeployment", MsoLogger.ErrorCode.DataError.getValue(),
1211 "Exception - DeleteDeployment: " + me.getMessage());
1212 logger.debug(error);
1213 throw new VnfException(me);
1216 // On success, nothing is returned.
1220 // TODO: Should Update be supported for Cloudify? What would this look like?
1222 public void updateVfModule (String cloudSiteId,
1228 String volumeGroupHeatStackId,
1229 String baseVfHeatStackId,
1230 String vfModuleStackId,
1231 String modelCustomizationUuid,
1232 Map <String, Object> inputs,
1233 MsoRequest msoRequest,
1234 Holder <Map <String, String>> outputs,
1235 Holder <VnfRollback> rollback) throws VnfException
1237 // This operation is not currently supported for Cloudify-orchestrated VF Modules.
1238 logger.debug("Update VF Module command attempted but not supported");
1239 throw new VnfException ("UpdateVfModule: Unsupported command", MsoExceptionCategory.USERDATA);