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 MsoLogger.setLogContext (msoRequest);
210 MsoLogger.setServiceName ("QueryVnfCloudify");
211 logger.debug ("Querying VNF {} in {}", vnfName, cloudSiteId + "/" + tenantId);
213 // Will capture execution time for metrics
214 long startTime = System.currentTimeMillis ();
215 long subStartTime = System.currentTimeMillis ();
217 DeploymentInfo deployment = null;
220 deployment = cloudifyUtils.queryDeployment(cloudSiteId, tenantId, vnfName);
222 catch (MsoCloudifyManagerNotFound e) {
223 // This site does not have a Cloudify Manager.
224 // This isn't an error, just means we won't find the VNF here.
227 catch (MsoException me) {
228 // Failed to query the Deployment due to a cloudify exception.
229 // Convert to a generic VnfException
230 me.addContext("QueryVNF");
231 String error = "Query VNF (Cloudify): " + vnfName + " in " + cloudSiteId + "/" + tenantId + ": " + me;
233 .error("{} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vnfName, cloudSiteId, tenantId,
234 CLOUDIFY, "QueryVNF", MsoLogger.ErrorCode.DataError.getValue(), "Exception - queryDeployment", me);
236 throw new VnfException(me);
239 if (deployment != null && deployment.getStatus() != DeploymentStatus.NOTFOUND) {
240 vnfExists.value = Boolean.TRUE;
241 status.value = deploymentStatusToVnfStatus(deployment);
242 vnfId.value = deployment.getId();
243 outputs.value = copyStringOutputs(deployment.getOutputs());
245 logger.debug("VNF {} found in Cloudify, ID = {}", vnfName, vnfId.value);
247 vnfExists.value = Boolean.FALSE;
248 status.value = VnfStatus.NOTFOUND;
250 outputs.value = new HashMap<String, String>(); // Return as an empty map
252 logger.debug("VNF {} not found", vnfName);
259 * This is the "Delete VNF" web service implementation.
260 * This function is now unsupported and will return an error.
264 public void deleteVnf (String cloudSiteId,
267 MsoRequest msoRequest) throws VnfException {
268 MsoLogger.setLogContext (msoRequest);
269 MsoLogger.setServiceName ("DeleteVnf");
271 // This operation is no longer supported at the VNF level. The adapter is only called to deploy modules.
272 logger.debug("DeleteVNF command attempted but not supported");
273 throw new VnfException ("DeleteVNF: Unsupported command", MsoExceptionCategory.USERDATA);
277 * This web service endpoint will rollback a previous Create VNF operation.
278 * A rollback object is returned to the client in a successful creation
279 * response. The client can pass that object as-is back to the rollbackVnf
280 * operation to undo the creation.
282 * TODO: This should be rollbackVfModule and/or rollbackVolumeGroup,
283 * but APIs were apparently never updated.
286 public void rollbackVnf (VnfRollback rollback) throws VnfException {
287 long startTime = System.currentTimeMillis ();
288 MsoLogger.setServiceName ("RollbackVnf");
289 // rollback may be null (e.g. if stack already existed when Create was called)
290 if (rollback == null) {
291 logger.info ("{} {} {} {}", MessageEnum.RA_ROLLBACK_NULL.toString(), "OpenStack", "rollbackVnf", MsoLogger
296 // Don't rollback if nothing was done originally
297 if (!rollback.getVnfCreated()) {
301 // Get the elements of the VnfRollback object for easier access
302 String cloudSiteId = rollback.getCloudSiteId ();
303 String tenantId = rollback.getTenantId ();
304 String vfModuleId = rollback.getVfModuleStackId ();
306 MsoLogger.setLogContext (rollback.getMsoRequest());
308 logger.debug("Rolling Back VF Module {} in {}", vfModuleId, cloudSiteId + "/" + tenantId);
310 DeploymentInfo deployment = null;
312 // Use the MsoCloudifyUtils to delete the deployment. Set the polling flag to true.
313 // The possible outcomes of deleteStack are a StackInfo object with status
314 // of NOTFOUND (on success) or FAILED (on error). Also, MsoOpenstackException
316 long subStartTime = System.currentTimeMillis ();
318 // KLUDGE - Cloudify requires Tenant Name for Openstack. We have the ID.
319 // Go directly to Keystone until APIs could be updated to supply the name.
320 MsoTenant msoTenant = keystoneUtils.queryTenant(tenantId, cloudSiteId);
321 String tenantName = (msoTenant != null? msoTenant.getTenantName() : tenantId);
323 // TODO: Get a reasonable timeout. Use a global property, or store the creation timeout in rollback object and use that.
324 deployment = cloudifyUtils.uninstallAndDeleteDeployment(cloudSiteId, tenantName, vfModuleId, 5);
325 logger.debug("Rolled back deployment: {}", deployment.getId());
326 } catch (MsoException me) {
327 // Failed to rollback the VNF due to a cloudify exception.
328 // Convert to a generic VnfException
329 me.addContext ("RollbackVNF");
330 String error = "Rollback VF Module: " + vfModuleId + " in " + cloudSiteId + "/" + tenantId + ": " + me;
331 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_DELETE_VNF_ERR.toString(), vfModuleId, cloudSiteId,
332 tenantId, CLOUDIFY, "DeleteDeployment", MsoLogger.ErrorCode.DataError.getValue(),
333 "Exception - DeleteDeployment", me);
335 throw new VnfException (me);
341 private VnfStatus deploymentStatusToVnfStatus (DeploymentInfo deployment) {
342 // Determine the status based on last action & status
343 // DeploymentInfo object should be enhanced to report a better status internally.
344 DeploymentStatus status = deployment.getStatus();
345 String lastAction = deployment.getLastAction();
347 if (status == null || lastAction == null) {
348 return VnfStatus.UNKNOWN;
350 else if (status == DeploymentStatus.NOTFOUND) {
351 return VnfStatus.NOTFOUND;
353 else if (status == DeploymentStatus.INSTALLED) {
354 return VnfStatus.ACTIVE;
356 else if (status == DeploymentStatus.CREATED) {
357 // Should have an INACTIVE status for this case. Shouldn't really happen, but
358 // Install was never run, or Uninstall was done but deployment didn't get deleted.
359 return VnfStatus.UNKNOWN;
361 else if (status == DeploymentStatus.FAILED) {
362 return VnfStatus.FAILED;
365 return VnfStatus.UNKNOWN;
368 private Map <String, String> copyStringOutputs (Map <String, Object> stackOutputs) {
369 Map <String, String> stringOutputs = new HashMap <String, String> ();
370 for (String key : stackOutputs.keySet ()) {
371 if (stackOutputs.get (key) instanceof String) {
372 stringOutputs.put (key, (String) stackOutputs.get (key));
373 } else if (stackOutputs.get(key) instanceof Integer) {
375 String str = "" + stackOutputs.get(key);
376 stringOutputs.put(key, str);
377 } catch (Exception e) {
378 logger.debug("Unable to add " + key + " to outputs");
380 } else if (stackOutputs.get(key) instanceof JsonNode) {
382 String str = this.convertNode((JsonNode) stackOutputs.get(key));
383 stringOutputs.put(key, str);
384 } catch (Exception e) {
385 logger.debug("Unable to add " + key + " to outputs - exception converting JsonNode");
387 } else if (stackOutputs.get(key) instanceof java.util.LinkedHashMap) {
389 String str = JSON_MAPPER.writeValueAsString(stackOutputs.get(key));
390 stringOutputs.put(key, str);
391 } catch (Exception e) {
392 logger.debug("Unable to add " + key + " to outputs - exception converting LinkedHashMap");
396 String str = stackOutputs.get(key).toString();
397 stringOutputs.put(key, str);
398 } catch (Exception e) {
399 logger.debug("Unable to add " + key + " to outputs - unable to call .toString() " + e.getMessage());
403 return stringOutputs;
407 private void sendMapToDebug(Map<String, Object> inputs, String optionalName) {
409 StringBuilder sb = new StringBuilder(optionalName == null ? "\ninputs" : "\n" + optionalName);
410 if (inputs == null) {
413 else if (inputs.size() < 1) {
414 sb.append("\tEMPTY");
416 for (String str : inputs.keySet()) {
419 outputString = inputs.get(str).toString();
420 } catch (Exception e) {
421 outputString = "Unable to call toString() on the value for " + str;
423 sb.append("\t\nitem " + i++ + ": '" + str + "'='" + outputString + "'");
426 logger.debug(sb.toString());
430 private void sendMapToDebug(Map<String, Object> inputs) {
432 StringBuilder sb = new StringBuilder("inputs:");
433 if (inputs == null) {
436 else if (inputs.size() < 1) {
437 sb.append("\tEMPTY");
439 for (String str : inputs.keySet()) {
440 sb.append("\titem " + i++ + ": " + str + "=" + inputs.get(str));
443 logger.debug(sb.toString());
447 private String convertNode(final JsonNode node) {
449 final Object obj = JSON_MAPPER.treeToValue(node, Object.class);
450 final String json = JSON_MAPPER.writeValueAsString(obj);
452 } catch (JsonParseException jpe) {
453 logger.debug("Error converting json to string " + jpe.getMessage());
454 } catch (Exception e) {
455 logger.debug("Error converting json to string " + e.getMessage());
457 return "[Error converting json to string]";
460 private Map<String, String> convertMapStringObjectToStringString(Map<String, Object> objectMap) {
461 if (objectMap == null) {
464 Map<String, String> stringMap = new HashMap<String, String>();
465 for (String key : objectMap.keySet()) {
466 if (!stringMap.containsKey(key)) {
467 Object obj = objectMap.get(key);
468 if (obj instanceof String) {
469 stringMap.put(key, (String) objectMap.get(key));
470 } else if (obj instanceof JsonNode ){
471 // This is a bit of mess - but I think it's the least impacting
472 // let's convert it BACK to a string - then it will get converted back later
474 String str = this.convertNode((JsonNode) obj);
475 stringMap.put(key, str);
476 } catch (Exception e) {
477 logger.debug("DANGER WILL ROBINSON: unable to convert value for JsonNode "+ key);
478 //okay in this instance - only string values (fqdn) are expected to be needed
480 } else if (obj instanceof java.util.LinkedHashMap) {
481 logger.debug("LinkedHashMap - this is showing up as a LinkedHashMap instead of JsonNode");
483 String str = JSON_MAPPER.writeValueAsString(obj);
484 stringMap.put(key, str);
485 } catch (Exception e) {
486 logger.debug("DANGER WILL ROBINSON: unable to convert value for LinkedHashMap "+ key);
488 } else if (obj instanceof Integer) {
490 String str = "" + obj;
491 stringMap.put(key, str);
492 } catch (Exception e) {
493 logger.debug("DANGER WILL ROBINSON: unable to convert value for Integer "+ key);
497 String str = obj.toString();
498 stringMap.put(key, str);
499 } catch (Exception e) {
500 logger.debug("DANGER WILL ROBINSON: unable to convert value "+ key + " (" + e.getMessage() + ")");
510 * This is the "Create VF Module" web service implementation.
511 * It will instantiate a new VF Module of the requested type in the specified cloud
512 * and tenant. The tenant must exist before this service is called.
514 * If a VF Module with the same name already exists, this can be considered a
515 * success or failure, depending on the value of the 'failIfExists' parameter.
517 * All VF Modules are defined in the MSO catalog. The caller must request
518 * one of the pre-defined module types or an error will be returned. Within the
519 * catalog, each VF Module references (among other things) a cloud template
520 * which is used to deploy the required artifacts (VMs, networks, etc.)
521 * to the cloud. In this adapter implementation, that artifact is expected
522 * to be a Cloudify blueprint.
524 * Depending on the blueprint, a variable set of input parameters will
525 * be defined, some of which are required. The caller is responsible to
526 * pass the necessary input data for the module or an error will be thrown.
528 * The method returns the vfModuleId, a Map of output attributes, and a VnfRollback
529 * object. This last object can be passed as-is to the rollbackVnf operation to
530 * undo everything that was created for the Module. This is useful if a VF module
531 * is successfully created but the orchestration fails on a subsequent step.
533 * @param cloudSiteId CLLI code of the cloud site in which to create the VNF
534 * @param tenantId Openstack tenant identifier
535 * @param vfModuleType VF Module type key, should match a VNF definition in catalog DB.
536 * Deprecated - should use modelCustomizationUuid
537 * @param vnfVersion VNF version key, should match a VNF definition in catalog DB
538 * Deprecated - VF Module versions also captured by modelCustomizationUuid
539 * @param genericVnfId Generic VNF ID
540 * @param vfModuleName Name to be assigned to the new VF Module
541 * @param vfModuleId Id of the new VF Module
542 * @param requestType Indicates if this is a Volume Group or Module request
543 * @param volumeGroupId Identifier (i.e. deployment ID) for a Volume Group
544 * to attach to a VF Module
545 * @param baseVfModuleId Identifier (i.e. deployment ID) of the Base Module if
546 * this is an Add-on module
547 * @param modelCustomizationUuid Unique ID for the VF Module's model. Replaces
548 * the use of vfModuleType.
549 * @param inputs Map of key=value inputs for VNF stack creation
550 * @param failIfExists Flag whether already existing VNF should be considered
551 * @param backout Flag whether to suppress automatic backout (for testing)
552 * @param msoRequest Request tracking information for logs
553 * @param vnfId Holder for output VNF Cloudify Deployment ID
554 * @param outputs Holder for Map of VNF outputs from Deployment (assigned IPs, etc)
555 * @param rollback Holder for returning VnfRollback object
558 public void createVfModule(String cloudSiteId,
566 String volumeGroupId,
567 String baseVfModuleId,
568 String modelCustomizationUuid,
569 Map <String, Object> inputs,
570 Boolean failIfExists,
572 Boolean enableBridge,
573 MsoRequest msoRequest,
574 Holder <String> vnfId,
575 Holder <Map <String, String>> outputs,
576 Holder <VnfRollback> rollback)
579 // Will capture execution time for metrics
580 long startTime = System.currentTimeMillis ();
582 MsoLogger.setLogContext (msoRequest);
583 MsoLogger.setServiceName ("CreateVfModule");
585 // Require a model customization ID. Every VF Module definition must have one.
586 if (modelCustomizationUuid == null || modelCustomizationUuid.isEmpty()) {
587 logger.debug("Missing required input: modelCustomizationUuid");
588 String error = "Create vfModule error: Missing required input: modelCustomizationUuid";
589 logger.error("{} {} {} {} {}", MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(),
590 "VF Module ModelCustomizationUuid", CLOUDIFY, MsoLogger.ErrorCode.DataError.getValue(),
591 "Create VF Module: Missing required input: modelCustomizationUuid");
593 throw new VnfException(error, MsoExceptionCategory.USERDATA);
596 // Clean up some inputs to make comparisons easier
597 if (requestType == null)
600 if ("".equals(volumeGroupId) || "null".equals(volumeGroupId))
601 volumeGroupId = null;
603 if ("".equals(baseVfModuleId) || "null".equals(baseVfModuleId))
604 baseVfModuleId = null;
606 if (inputs == null) {
607 // Create an empty set of inputs
608 inputs = new HashMap<>();
609 logger.debug("inputs == null - setting to empty");
611 this.sendMapToDebug(inputs);
614 // Check if this is for a "Volume" module
615 boolean isVolumeRequest = false;
616 if (requestType.startsWith("VOLUME")) {
617 isVolumeRequest = true;
620 logger.debug("requestType = " + requestType + ", volumeGroupStackId = " + volumeGroupId + ", baseStackId = " +
623 // Build a default rollback object (no actions performed)
624 VnfRollback vfRollback = new VnfRollback();
625 vfRollback.setCloudSiteId(cloudSiteId);
626 vfRollback.setTenantId(tenantId);
627 vfRollback.setMsoRequest(msoRequest);
628 vfRollback.setRequestType(requestType);
629 vfRollback.setIsBase(false); // Until we know better
630 vfRollback.setVolumeGroupHeatStackId(volumeGroupId);
631 vfRollback.setBaseGroupHeatStackId(baseVfModuleId);
632 vfRollback.setModelCustomizationUuid(modelCustomizationUuid);
633 vfRollback.setMode("CFY");
635 rollback.value = vfRollback; // Default rollback - no updates performed
637 // Get the VNF/VF Module definition from the Catalog DB first.
638 // There are three relevant records: VfModule, VfModuleCustomization, VnfResource
641 VnfResource vnfResource = null;
642 VfModuleCustomization vfmc = null;
645 vfmc = vfModuleCustomRepo.findByModelCustomizationUUID(modelCustomizationUuid);
648 String error = "Create vfModule error: Unable to find vfModuleCust with modelCustomizationUuid="
649 + modelCustomizationUuid;
651 logger.error("{} {} {} {} {} {}", MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "VF Module "
652 + "ModelCustomizationUuid",
653 modelCustomizationUuid, "CatalogDb", MsoLogger.ErrorCode.DataError.getValue(), error);
654 throw new VnfException(error, MsoExceptionCategory.USERDATA);
656 logger.debug("Found vfModuleCust entry " + vfmc.toString());
659 // Get the vfModule and vnfResource records
660 vf = vfmc.getVfModule();
661 vnfResource = vfmc.getVfModule().getVnfResources();
663 catch (Exception e) {
665 logger.debug("unhandled exception in create VF - [Query]" + e.getMessage());
666 throw new VnfException("Exception during create VF " + e.getMessage());
669 // Perform a version check against cloudSite
670 // Obtain the cloud site information where we will create the VF Module
671 Optional<CloudSite> cloudSiteOp = cloudConfig.getCloudSite (cloudSiteId);
672 if (!cloudSiteOp.isPresent()) {
673 throw new VnfException (new MsoCloudSiteNotFound (cloudSiteId));
675 CloudSite cloudSite = cloudSiteOp.get();
676 MavenLikeVersioning aicV = new MavenLikeVersioning();
677 aicV.setVersion(cloudSite.getCloudVersion());
679 String vnfMin = vnfResource.getAicVersionMin();
680 String vnfMax = vnfResource.getAicVersionMax();
682 if ( (vnfMin != null && !(aicV.isMoreRecentThan(vnfMin) || aicV.isTheSameVersion(vnfMin))) ||
683 (vnfMax != null && aicV.isMoreRecentThan(vnfMax)))
686 String error = "VNF Resource type: " + vnfResource.getModelName() + ", ModelUuid=" + vnfResource.getModelUUID()
687 + " VersionMin=" + vnfMin + " VersionMax:" + vnfMax + " NOT supported on Cloud: " + cloudSiteId
688 + " with AIC_Version:" + cloudSite.getCloudVersion();
689 logger.error("{} {} {} {} {}", MessageEnum.RA_CONFIG_EXC.toString(), error, "OpenStack",
690 MsoLogger.ErrorCode.BusinessProcesssError.getValue(), "Exception - setVersion");
692 throw new VnfException(error, MsoExceptionCategory.USERDATA);
697 DeploymentInfo cloudifyDeployment = null;
699 // First, look up to see if the VF already exists.
701 long subStartTime1 = System.currentTimeMillis ();
703 cloudifyDeployment = cloudifyUtils.queryDeployment (cloudSiteId, tenantId, vfModuleName);
705 catch (MsoException me) {
706 // Failed to query the Deployment due to a cloudify exception.
707 String error = "Create VF Module: Query " + vfModuleName + " in " + cloudSiteId + "/" + tenantId + ": " + me ;
708 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vfModuleName, cloudSiteId,
709 tenantId, CLOUDIFY, "queryDeployment", MsoLogger.ErrorCode.DataError.getValue(),
710 "Exception - queryDeployment", me);
713 // Convert to a generic VnfException
714 me.addContext ("CreateVFModule");
715 throw new VnfException (me);
718 // More precise handling/messaging if the Module already exists
719 if (cloudifyDeployment != null && !(cloudifyDeployment.getStatus () == DeploymentStatus.NOTFOUND)) {
720 // CREATED, INSTALLED, INSTALLING, FAILED, UNINSTALLING, UNKNOWN
721 DeploymentStatus status = cloudifyDeployment.getStatus();
722 logger.debug ("Found Existing Deployment, status=" + status);
724 if (status == DeploymentStatus.INSTALLED) {
726 if (failIfExists != null && failIfExists) {
727 String error = "Create VF: Deployment " + vfModuleName + " already exists in " + cloudSiteId + "/" + tenantId;
728 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_VNF_ALREADY_EXIST.toString(), vfModuleName,
729 cloudSiteId, tenantId, CLOUDIFY, "queryDeployment", MsoLogger.ErrorCode.DataError.getValue(),
730 "Deployment " + vfModuleName + " already exists");
732 throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, cloudifyDeployment.getId());
734 // Found existing deployment and client has not requested "failIfExists".
735 // Populate the outputs from the existing deployment.
737 vnfId.value = cloudifyDeployment.getId();
738 outputs.value = copyStringOutputs (cloudifyDeployment.getOutputs ());
742 // Check through various detailed error cases
743 if (status == DeploymentStatus.INSTALLING || status == DeploymentStatus.UNINSTALLING) {
744 // fail - it's in progress - return meaningful error
745 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.";
746 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_VNF_ALREADY_EXIST.toString(), vfModuleName,
747 cloudSiteId, tenantId, CLOUDIFY, "queryDeployment", MsoLogger.ErrorCode.DataError.getValue(),
748 "Deployment " + vfModuleName + " already exists");
750 throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, cloudifyDeployment.getId());
752 else if (status == DeploymentStatus.FAILED) {
753 // fail - it exists and is in a FAILED state
754 String error = "Create VF: Deployment " + vfModuleName + " already exists and is in FAILED state in " + cloudSiteId + "/" + tenantId + "; requires manual intervention.";
755 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_VNF_ALREADY_EXIST.toString(), vfModuleName,
756 cloudSiteId, tenantId, CLOUDIFY, "queryDeployment", MsoLogger.ErrorCode.DataError.getValue(),
757 "Deployment " + vfModuleName + " already " + "exists and is in FAILED state");
759 throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, cloudifyDeployment.getId());
761 else if (status == DeploymentStatus.UNKNOWN || status == DeploymentStatus.CREATED) {
762 // fail - it exists and is in a UNKNOWN state
763 String error = "Create VF: Deployment " + vfModuleName + " already exists and has status " + status.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 " + status.toString() + " state");
768 throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, cloudifyDeployment.getId());
771 // Unexpected, since all known status values have been tested for
773 "Create VF: Deployment " + vfModuleName + " already exists with unexpected status " + status
774 .toString() + " in " + cloudSiteId + "/" + tenantId + "; requires manual intervention.";
775 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_VNF_ALREADY_EXIST.toString(), vfModuleName,
776 cloudSiteId, tenantId, CLOUDIFY, "queryDeployment", MsoLogger.ErrorCode.DataError.getValue(),
777 "Deployment " + vfModuleName + " already " + "exists and is in an unknown state");
779 throw new VnfAlreadyExists(vfModuleName, cloudSiteId, tenantId, cloudifyDeployment.getId());
784 // Collect outputs from Base Modules and Volume Modules
785 Map<String, Object> baseModuleOutputs = null;
786 Map<String, Object> volumeGroupOutputs = null;
788 // If a Volume Group was provided, query its outputs for inclusion in Module input parameters
789 if (volumeGroupId != null) {
790 long subStartTime2 = System.currentTimeMillis ();
791 DeploymentInfo volumeDeployment = null;
793 volumeDeployment = cloudifyUtils.queryDeployment (cloudSiteId, tenantId, volumeGroupId);
795 catch (MsoException me) {
796 // Failed to query the Volume GroupDeployment due to a cloudify exception.
797 String error = "Create VF Module: Query Volume Group " + volumeGroupId + " in " + cloudSiteId + "/" + tenantId + ": " + me ;
798 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), volumeGroupId,
799 cloudSiteId, tenantId, CLOUDIFY, "queryDeployment(volume)",
800 MsoLogger.ErrorCode.DataError.getValue(), "Exception - queryDeployment(volume)", me);
802 // Convert to a generic VnfException
803 me.addContext ("CreateVFModule(QueryVolume)");
804 throw new VnfException (me);
807 if (volumeDeployment == null || volumeDeployment.getStatus() == DeploymentStatus.NOTFOUND) {
809 "Create VFModule: Attached Volume Group DOES NOT EXIST " + volumeGroupId + " in " + cloudSiteId + "/"
810 + tenantId + " USER ERROR";
811 logger.error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), volumeGroupId,
812 cloudSiteId, tenantId, error, CLOUDIFY, "queryDeployment(volume)",
813 MsoLogger.ErrorCode.BusinessProcesssError.getValue(),
814 "Create VFModule: Attached Volume Group DOES NOT EXIST");
816 throw new VnfException(error, MsoExceptionCategory.USERDATA);
818 logger.debug("Found nested volume group");
819 volumeGroupOutputs = volumeDeployment.getOutputs();
820 this.sendMapToDebug(volumeGroupOutputs, "volumeGroupOutputs");
824 // If this is an Add-On Module, query the Base Module outputs
825 // Note: This will be performed whether or not the current request is for an
826 // Add-On Volume Group or Add-On VF Module
828 if (vf.getIsBase()) {
829 logger.debug("This is a BASE Module request");
830 vfRollback.setIsBase(true);
832 logger.debug("This is an Add-On Module request");
834 // Add-On Modules should always have a Base, but just treat as a warning if not provided.
835 // Add-on Volume requests may or may not specify a base.
836 if (!isVolumeRequest && baseVfModuleId == null) {
837 logger.debug ("WARNING: Add-on Module request - no Base Module ID provided");
840 if (baseVfModuleId != null) {
841 long subStartTime2 = System.currentTimeMillis ();
842 DeploymentInfo baseDeployment = null;
844 baseDeployment = cloudifyUtils.queryDeployment (cloudSiteId, tenantId, baseVfModuleId);
846 catch (MsoException me) {
847 // Failed to query the Volume GroupDeployment due to a cloudify exception.
849 "Create VF Module: Query Base " + baseVfModuleId + " in " + cloudSiteId + "/" + tenantId + ": "
851 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), baseVfModuleId,
852 cloudSiteId, tenantId, CLOUDIFY, "queryDeployment(Base)",
853 MsoLogger.ErrorCode.DataError.getValue(), "Exception - queryDeployment(Base)", me);
855 // Convert to a generic VnfException
856 me.addContext("CreateVFModule(QueryBase)");
857 throw new VnfException (me);
860 if (baseDeployment == null || baseDeployment.getStatus() == DeploymentStatus.NOTFOUND) {
862 "Create VFModule: Base Module DOES NOT EXIST " + baseVfModuleId + " in " + cloudSiteId + "/"
863 + tenantId + " USER ERROR";
864 logger.error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), baseVfModuleId,
865 cloudSiteId, tenantId, error, CLOUDIFY, "queryDeployment(Base)",
866 MsoLogger.ErrorCode.BusinessProcesssError.getValue(),
867 "Create VFModule: Base " + "Module DOES NOT EXIST");
869 throw new VnfException(error, MsoExceptionCategory.USERDATA);
871 logger.debug("Found base module");
872 baseModuleOutputs = baseDeployment.getOutputs();
873 this.sendMapToDebug(baseModuleOutputs, "baseModuleOutputs");
879 // Ready to deploy the new VNF
881 // NOTE: For this section, heatTemplate is used for both HEAT templates and Cloudify blueprints.
882 // In final implementation (post-POC), the template object would either be generic or there would
883 // be a separate DB Table/Object for Blueprints.
886 // NOTE: The template is fixed for the VF Module. The environment is part of the customization.
887 HeatTemplate heatTemplate = null;
888 HeatEnvironment heatEnvironment = null;
889 if (isVolumeRequest) {
890 heatTemplate = vf.getVolumeHeatTemplate();
891 heatEnvironment = vfmc.getVolumeHeatEnv();
893 heatTemplate = vf.getModuleHeatTemplate();
894 heatEnvironment = vfmc.getHeatEnvironment();
897 if (heatTemplate == null) {
898 String error = "UpdateVF: No Heat Template ID defined in catalog database for " + vfModuleType + ", reqType="
900 logger.error("{} {} {} {} {} {}", MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "Heat Template ID", vfModuleType,
901 "OpenStack", MsoLogger.ErrorCode.DataError.getValue(), error);
902 throw new VnfException(error, MsoExceptionCategory.INTERNAL);
904 logger.debug("Got HEAT Template from DB: {}", heatTemplate.getHeatTemplate());
907 if (heatEnvironment == null) {
908 String error = "Update VNF: undefined Heat Environment. VF=" + vfModuleType;
909 logger.error("{} {} {} {} {}", MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "Heat Environment ID",
910 "OpenStack", MsoLogger.ErrorCode.DataError.getValue(), error);
911 // Alarm on this error, configuration must be fixed
912 throw new VnfException(error, MsoExceptionCategory.INTERNAL);
914 logger.debug("Got Heat Environment from DB: {}", heatEnvironment.getEnvironment());
919 // All variables converted to their native object types
920 HashMap<String, Object> goldenInputs = new HashMap<String,Object>();
921 List<String> extraInputs = new ArrayList<String>();
923 // NOTE: SKIP THIS FOR CLOUDIFY for now. Just use what was passed in.
924 // This whole section needs to be rewritten.
925 Boolean skipInputChecks = false;
927 if (skipInputChecks) {
928 goldenInputs = new HashMap<String,Object>();
929 for (String key : inputs.keySet()) {
930 goldenInputs.put(key, inputs.get(key));
934 // Build maps for the parameters (including aliases) to simplify checks
935 HashMap<String, HeatTemplateParam> params = new HashMap<String, HeatTemplateParam>();
937 Set<HeatTemplateParam> paramSet = heatTemplate.getParameters();
938 logger.debug("paramSet has {} entries", paramSet.size());
940 for (HeatTemplateParam htp : paramSet) {
941 params.put(htp.getParamName(), htp);
944 String alias = htp.getParamAlias();
945 if (alias != null && !alias.equals("") && !params.containsKey(alias)) {
946 params.put(alias, htp);
950 // First, convert all inputs to their "template" type
951 for (String key : inputs.keySet()) {
952 if (params.containsKey(key)) {
953 Object value = cloudifyUtils.convertInputValue(inputs.get(key), params.get(key));
955 goldenInputs.put(key, value);
958 logger.debug("Failed to convert input " + key + "='" + inputs.get(key) + "' to " + params.get(key)
962 extraInputs.add(key);
966 if (!extraInputs.isEmpty()) {
967 logger.debug("Ignoring extra inputs: " + extraInputs);
970 // Next add in Volume Group Outputs if there are any. Copy directly without conversions.
971 if (volumeGroupOutputs != null && !volumeGroupOutputs.isEmpty()) {
972 for (String key : volumeGroupOutputs.keySet()) {
973 if (params.containsKey(key) && !goldenInputs.containsKey(key)) {
974 goldenInputs.put(key, volumeGroupOutputs.get(key));
979 // Next add in Base Module Outputs if there are any. Copy directly without conversions.
980 if (baseModuleOutputs != null && !baseModuleOutputs.isEmpty()) {
981 for (String key : baseModuleOutputs.keySet()) {
982 if (params.containsKey(key) && !goldenInputs.containsKey(key)) {
983 goldenInputs.put(key, baseModuleOutputs.get(key));
988 // Last, add in values from the "environment" file.
989 // These are added to the inputs, since Cloudify doesn't pass an environment file like Heat.
991 // TODO: This may take a different form for Cloudify, but for now process it
992 // with Heat environment file syntax
993 StringBuilder sb = new StringBuilder(heatEnvironment.getEnvironment());
994 MsoHeatEnvironmentEntry mhee = new MsoHeatEnvironmentEntry (sb);
996 if (mhee.getParameters() != null) {
997 for (MsoHeatEnvironmentParameter envParam : mhee.getParameters()) {
998 // If this is a template input, copy to golden inputs
999 String envKey = envParam.getName();
1000 if (params.containsKey(envKey) && !goldenInputs.containsKey(envKey)) {
1001 Object value = cloudifyUtils.convertInputValue(envParam.getValue(), params.get(envKey));
1002 if (value != null) {
1003 goldenInputs.put(envKey, value);
1006 logger.debug("Failed to convert environment parameter " + envKey + "='" + envParam.getValue() + "' to " +
1007 params.get(envKey).getParamType());
1013 this.sendMapToDebug(goldenInputs, "Final inputs sent to Cloudify");
1016 // Check that required parameters have been supplied from any of the sources
1017 String missingParams = null;
1018 boolean checkRequiredParameters = true;
1020 String propertyString = this.environment.getProperty(MsoVnfCloudifyAdapterImpl.CHECK_REQD_PARAMS);
1021 if ("false".equalsIgnoreCase (propertyString) || "n".equalsIgnoreCase (propertyString)) {
1022 checkRequiredParameters = false;
1023 logger.debug("CheckRequiredParameters is FALSE. Will still check but then skip blocking... {}",
1024 MsoVnfCloudifyAdapterImpl.CHECK_REQD_PARAMS);
1026 } catch (Exception e) {
1027 // No problem - default is true
1028 logger.debug("An exception occured trying to get property {}",
1029 MsoVnfCloudifyAdapterImpl.CHECK_REQD_PARAMS, e);
1033 for (HeatTemplateParam parm : heatTemplate.getParameters ()) {
1034 if (parm.isRequired () && (!goldenInputs.containsKey (parm.getParamName ()))) {
1035 logger.debug("adding to missing parameters list: {}", parm.getParamName());
1036 if (missingParams == null) {
1037 missingParams = parm.getParamName();
1039 missingParams += "," + parm.getParamName();
1044 if (missingParams != null) {
1045 if (checkRequiredParameters) {
1046 // Problem - missing one or more required parameters
1047 String error = "Create VFModule: Missing Required inputs: " + missingParams;
1048 logger.error("{} {} {} {} {}", MessageEnum.RA_MISSING_PARAM.toString(), missingParams, CLOUDIFY,
1049 MsoLogger.ErrorCode.DataError.getValue(), "Create VFModule: Missing Required inputs");
1050 logger.debug(error);
1051 throw new VnfException(error, MsoExceptionCategory.USERDATA);
1054 "found missing parameters [" + missingParams + "] - but checkRequiredParameters is false -"
1055 + " will not block");
1058 logger.debug("No missing parameters found - ok to proceed");
1061 } // NOTE: END PARAMETER CHECKING
1063 // Ready to deploy the VF Module.
1064 // *First step - make sure the blueprint is loaded into Cloudify.
1065 String blueprintName = heatTemplate.getTemplateName();
1066 String blueprint = heatTemplate.getTemplateBody();
1067 String blueprintId = blueprintName;
1069 // Use the main blueprint name as the blueprint ID (strip yaml extensions).
1070 if (blueprintId.endsWith(".yaml"))
1071 blueprintId = blueprintId.substring(0,blueprintId.lastIndexOf(".yaml"));
1074 if (! cloudifyUtils.isBlueprintLoaded (cloudSiteId, blueprintId)) {
1075 logger.debug("Blueprint " + blueprintId + " is not loaded. Will upload it now.");
1077 Map<String,byte[]> blueprintFiles = new HashMap<String,byte[]>();
1079 blueprintFiles.put(blueprintName, blueprint.getBytes());
1081 // TODO: Implement nested blueprint logic based on Cloudify structures.
1082 // For now, just use the Heat structures.
1083 // The query returns a map of String->Object, where the map keys provide one layer of
1084 // indirection from the Heat template names. For this case, assume the map key matches
1085 // the nested blueprint name.
1086 List<HeatTemplate> nestedBlueprints = heatTemplate.getChildTemplates();
1087 if (nestedBlueprints != null) {
1088 for (HeatTemplate nestedBlueprint: nestedBlueprints) {
1089 blueprintFiles.put(nestedBlueprint.getTemplateName(), nestedBlueprint.getTemplateBody().getBytes());
1093 // TODO: Implement file artifact logic based on Cloudify structures.
1094 // For now, just use the Heat structures.
1095 List<HeatFiles> heatFiles = vf.getHeatFiles();
1096 if (heatFiles != null) {
1097 for (HeatFiles heatFile: heatFiles) {
1098 blueprintFiles.put(heatFile.getFileName(), heatFile.getFileBody().getBytes());
1102 // Upload the blueprint package
1103 cloudifyUtils.uploadBlueprint(cloudSiteId, blueprintId, blueprintName, blueprintFiles, false);
1108 catch (MsoException me) {
1109 me.addContext("CreateVFModule");
1110 String error = "Create VF Module: Upload blueprint failed. Blueprint=" + blueprintName + ": " + me;
1111 logger.error("{} {} {} {} {} {} {}", MessageEnum.RA_CREATE_VNF_ERR.toString(), vfModuleType, cloudSiteId,
1112 tenantId, CLOUDIFY, MsoLogger.ErrorCode.DataError.getValue(), "MsoException - uploadBlueprint", me);
1113 logger.debug(error);
1114 throw new VnfException(me);
1117 // Ignore MsoTenantNotFound and MsoStackAlreadyExists exceptions
1118 // because we already checked for those.
1119 long createDeploymentStarttime = System.currentTimeMillis ();
1121 // KLUDGE - Cloudify requires Tenant Name for Openstack. We have the ID.
1122 // Go directly to Keystone until APIs could be updated to supply the name.
1123 MsoTenant msoTenant = keystoneUtils.queryTenant(tenantId, cloudSiteId);
1124 String tenantName = (msoTenant != null? msoTenant.getTenantName() : tenantId);
1126 if (backout == null) {
1130 cloudifyDeployment = cloudifyUtils.createAndInstallDeployment (cloudSiteId,
1136 heatTemplate.getTimeoutMinutes (),
1137 backout.booleanValue());
1139 } catch (MsoException me) {
1140 me.addContext ("CreateVFModule");
1141 String error = "Create VF Module " + vfModuleType + " in " + cloudSiteId + "/" + tenantId + ": " + me;
1143 .error("{} {} {} {} {} {} {}", MessageEnum.RA_CREATE_VNF_ERR.toString(), vfModuleType, cloudSiteId,
1144 tenantId, CLOUDIFY, MsoLogger.ErrorCode.DataError.getValue(), "MsoException - createDeployment",
1146 logger.debug(error);
1147 throw new VnfException (me);
1148 } catch (NullPointerException npe) {
1149 String error = "Create VFModule " + vfModuleType + " in " + cloudSiteId + "/" + tenantId + ": " + npe;
1151 .error("{} {} {} {} {} {} {}", MessageEnum.RA_CREATE_VNF_ERR.toString(), vfModuleType, cloudSiteId,
1152 tenantId, CLOUDIFY, MsoLogger.ErrorCode.DataError.getValue(),
1153 "NullPointerException - createDeployment", npe);
1154 logger.debug(error);
1155 logger.debug("NULL POINTER EXCEPTION at cloudify.createAndInstallDeployment");
1156 //npe.addContext ("CreateVNF");
1157 throw new VnfException ("NullPointerException during cloudify.createAndInstallDeployment");
1158 } catch (Exception e) {
1159 logger.debug("unhandled exception at cloudify.createAndInstallDeployment");
1160 throw new VnfException("Exception during cloudify.createAndInstallDeployment! " + e.getMessage());
1162 } catch (Exception e) {
1163 logger.debug("unhandled exception in create VF");
1164 throw new VnfException("Exception during create VF " + e.getMessage());
1168 // Reach this point if create is successful.
1169 // Populate remaining rollback info and response parameters.
1170 vfRollback.setVnfCreated (true);
1171 vfRollback.setVnfId (cloudifyDeployment.getId());
1172 vnfId.value = cloudifyDeployment.getId();
1173 outputs.value = copyStringOutputs (cloudifyDeployment.getOutputs ());
1175 rollback.value = vfRollback;
1177 logger.debug("VF Module successfully created", vfModuleName);
1181 public void deleteVfModule (String cloudSiteId,
1184 MsoRequest msoRequest,
1185 Holder <Map <String, String>> outputs) throws VnfException {
1186 MsoLogger.setLogContext (msoRequest);
1187 MsoLogger.setServiceName ("DeleteVf");
1188 logger.debug ("Deleting VF " + vnfName + " in " + cloudSiteId + "/" + tenantId);
1189 // Will capture execution time for metrics
1190 long startTime = System.currentTimeMillis ();
1192 // 1702 capture the output parameters on a delete
1193 // so we'll need to query first
1194 DeploymentInfo deployment = null;
1196 deployment = cloudifyUtils.queryDeployment(cloudSiteId, tenantId, vnfName);
1197 } catch (MsoException me) {
1198 // Failed to query the deployment. Convert to a generic VnfException
1199 me.addContext ("DeleteVFModule");
1200 String error = "Delete VFModule: Query to get outputs: " + vnfName + " in " + cloudSiteId + "/" + tenantId + ": " + me;
1201 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vnfName, cloudSiteId,
1202 tenantId, CLOUDIFY, "QueryDeployment", MsoLogger.ErrorCode.DataError.getValue(),
1203 "Exception - QueryDeployment", me);
1204 logger.debug(error);
1205 throw new VnfException (me);
1207 // call method which handles the conversion from Map<String,Object> to Map<String,String> for our expected Object types
1208 outputs.value = convertMapStringObjectToStringString(deployment.getOutputs());
1210 // Use the MsoHeatUtils to delete the stack. Set the polling flag to true.
1211 // The possible outcomes of deleteStack are a StackInfo object with status
1212 // of NOTFOUND (on success) or FAILED (on error). Also, MsoOpenstackException
1214 long subStartTime = System.currentTimeMillis ();
1216 cloudifyUtils.uninstallAndDeleteDeployment(cloudSiteId, tenantId, vnfName, 5);
1217 } catch (MsoException me) {
1218 me.addContext("DeleteVfModule");
1219 // Convert to a generic VnfException
1220 String error = "Delete VF: " + vnfName + " in " + cloudSiteId + "/" + tenantId + ": " + me;
1221 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_DELETE_VNF_ERR.toString(), vnfName, cloudSiteId,
1222 tenantId, "DeleteDeployment", "DeleteDeployment", MsoLogger.ErrorCode.DataError.getValue(),
1223 "Exception - DeleteDeployment: " + me.getMessage());
1224 logger.debug(error);
1225 throw new VnfException(me);
1228 // On success, nothing is returned.
1232 // TODO: Should Update be supported for Cloudify? What would this look like?
1234 public void updateVfModule (String cloudSiteId,
1240 String volumeGroupHeatStackId,
1241 String baseVfHeatStackId,
1242 String vfModuleStackId,
1243 String modelCustomizationUuid,
1244 Map <String, Object> inputs,
1245 MsoRequest msoRequest,
1246 Holder <Map <String, String>> outputs,
1247 Holder <VnfRollback> rollback) throws VnfException
1249 // This operation is not currently supported for Cloudify-orchestrated VF Modules.
1250 logger.debug("Update VF Module command attempted but not supported");
1251 throw new VnfException ("UpdateVfModule: Unsupported command", MsoExceptionCategory.USERDATA);