2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * Copyright (C) 2017 Huawei Technologies Co., Ltd. All rights reserved.
7 * ================================================================================
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;
28 import java.io.IOException;
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.HashMap;
32 import java.util.List;
34 import java.util.Optional;
35 import java.util.concurrent.TimeUnit;
37 import javax.jws.WebService;
38 import javax.xml.ws.Holder;
40 import org.onap.so.adapters.vnf.exceptions.VnfAlreadyExists;
41 import org.onap.so.adapters.vnf.exceptions.VnfException;
42 import org.onap.so.adapters.vnf.exceptions.VnfNotFound;
43 import org.onap.so.cloud.CloudConfig;
44 import org.onap.so.db.catalog.beans.CloudSite;
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.data.repository.VnfResourceRepository;
54 import org.onap.so.db.catalog.utils.MavenLikeVersioning;
55 import org.onap.so.entity.MsoRequest;
56 import org.onap.so.logger.ErrorCode;
57 import org.onap.so.logger.MessageEnum;
59 import org.onap.so.openstack.beans.HeatStatus;
60 import org.onap.so.openstack.beans.StackInfo;
61 import org.onap.so.openstack.beans.VnfRollback;
62 import org.onap.so.openstack.beans.VnfStatus;
63 import org.onap.so.openstack.exceptions.MsoException;
64 import org.onap.so.openstack.exceptions.MsoExceptionCategory;
65 import org.onap.so.openstack.exceptions.MsoHeatNotFoundException;
66 import org.onap.so.openstack.utils.MsoHeatEnvironmentEntry;
67 import org.onap.so.openstack.utils.MsoHeatUtils;
68 import org.onap.so.openstack.utils.MsoHeatUtilsWithUpdate;
69 import org.onap.so.adapters.valet.ValetClient;
70 import org.onap.so.adapters.valet.beans.HeatRequest;
71 import org.onap.so.adapters.valet.beans.ValetConfirmResponse;
72 import org.onap.so.adapters.valet.beans.ValetCreateResponse;
73 import org.onap.so.adapters.valet.beans.ValetDeleteResponse;
74 import org.onap.so.adapters.valet.beans.ValetRollbackResponse;
75 import org.onap.so.adapters.valet.beans.ValetStatus;
76 import org.onap.so.adapters.valet.beans.ValetUpdateResponse;
77 import org.onap.so.adapters.valet.GenericValetResponse;
78 import org.slf4j.Logger;
79 import org.slf4j.LoggerFactory;
80 import org.springframework.beans.factory.annotation.Autowired;
81 import org.springframework.core.env.Environment;
82 import org.springframework.stereotype.Component;
83 import org.springframework.transaction.annotation.Transactional;
85 import com.fasterxml.jackson.core.JsonParseException;
86 import com.fasterxml.jackson.databind.JsonNode;
87 import com.fasterxml.jackson.databind.ObjectMapper;
89 @WebService(serviceName = "VnfAdapter", endpointInterface = "org.onap.so.adapters.vnf.MsoVnfAdapter", targetNamespace = "http://org.onap.so/vnf")
92 public class MsoVnfAdapterImpl implements MsoVnfAdapter {
95 private CloudConfig cloudConfig;
98 private Environment environment;
100 private static final Logger logger = LoggerFactory.getLogger(MsoVnfAdapterImpl.class);
102 private static final String MSO_CONFIGURATION_ERROR = "MsoConfigurationError";
103 private static final String VNF_ADAPTER_SERVICE_NAME = "MSO-BPMN:MSO-VnfAdapter.";
104 private static final String CHECK_REQD_PARAMS = "org.onap.so.adapters.vnf.checkRequiredParameters";
105 private static final String ADD_GET_FILES_ON_VOLUME_REQ = "org.onap.so.adapters.vnf.addGetFilesOnVolumeReq";
106 private static final ObjectMapper JSON_MAPPER = new ObjectMapper();
107 private static final String VALET_ENABLED = "org.onap.so.adapters.vnf.valet_enabled";
108 private static final String FAIL_REQUESTS_ON_VALET_FAILURE = "org.onap.so.adapters.vnf.fail_requests_on_valet_failure";
109 private static final String SUCCESS_MSG = "Successfully received response from Open Stack";
112 private VFModuleCustomizationRepository vfModuleCustomRepo;
116 private VnfResourceRepository vnfResourceRepo;
119 private MsoHeatUtilsWithUpdate heatU;
121 private MsoHeatUtils heat;
123 private ValetClient vci;
126 * DO NOT use that constructor to instantiate this class, the msoPropertiesfactory will be NULL.
127 * @see MsoVnfAdapterImpl#MsoVnfAdapterImpl(MsoPropertiesFactory, CloudConfigFactory)
129 public MsoVnfAdapterImpl() {
131 //DO NOT use that constructor to instantiate this class, the msoPropertiesfactory will be NULL.
135 * Health Check web method. Does nothing but return to show the adapter is deployed.
138 public void healthCheck () {
139 logger.debug ("Health check call in VNF Adapter");
143 * This is the "Create VNF" web service implementation.
144 * It will create a new VNF of the requested type in the specified cloud
145 * and tenant. The tenant must exist before this service is called.
147 * If a VNF with the same name already exists, this can be considered a
148 * success or failure, depending on the value of the 'failIfExists' parameter.
150 * All VNF types will be defined in the MSO catalog. The caller must request
151 * one of these pre-defined types or an error will be returned. Within the
152 * catalog, each VNF type references (among other things) a Heat template
153 * which is used to deploy the required VNF artifacts (VMs, networks, etc.)
156 * Depending on the Heat template, a variable set of input parameters will
157 * be defined, some of which are required. The caller is responsible to
158 * pass the necessary input data for the VNF or an error will be thrown.
160 * The method returns the vnfId (the canonical name), a Map of VNF output
161 * attributes, and a VnfRollback object. This last object can be passed
162 * as-is to the rollbackVnf operation to undo everything that was created
163 * for the VNF. This is useful if a VNF is successfully created but the
164 * orchestrator fails on a subsequent operation.
166 * @param cloudSiteId CLLI code of the cloud site in which to create the VNF
167 * @param cloudOwner cloud owner of the cloud region in which to create the VNF
168 * @param tenantId Openstack tenant identifier
169 * @param vnfType VNF type key, should match a VNF definition in catalog DB
170 * @param vnfVersion VNF version key, should match a VNF definition in catalog DB
171 * @param vnfName Name to be assigned to the new VNF
172 * @param inputs Map of key=value inputs for VNF stack creation
173 * @param failIfExists Flag whether already existing VNF should be considered
174 * a success or failure
175 * @param msoRequest Request tracking information for logs
176 * @param vnfId Holder for output VNF Openstack ID
177 * @param outputs Holder for Map of VNF outputs from heat (assigned IPs, etc)
178 * @param rollback Holder for returning VnfRollback object
181 public void createVnf (String cloudSiteId,
188 String volumeGroupHeatStackId,
189 Map <String, Object> inputs,
190 Boolean failIfExists,
192 Boolean enableBridge,
193 MsoRequest msoRequest,
194 Holder <String> vnfId,
195 Holder <Map <String, String>> outputs,
196 Holder <VnfRollback> rollback) throws VnfException {
197 // parameters used for multicloud adapter
198 String genericVnfId = "";
199 String vfModuleId = "";
200 // Create a hook here to catch shortcut createVf requests:
201 if (requestType != null && requestType.startsWith("VFMOD")) {
202 logger.debug("Calling createVfModule from createVnf -- requestType=" + requestType);
203 String newRequestType = requestType.substring(5);
204 String vfVolGroupHeatStackId = "";
205 String vfBaseHeatStackId = "";
207 if (volumeGroupHeatStackId != null) {
208 vfVolGroupHeatStackId = volumeGroupHeatStackId.substring(0, volumeGroupHeatStackId.lastIndexOf('|'));
209 vfBaseHeatStackId = volumeGroupHeatStackId.substring(volumeGroupHeatStackId.lastIndexOf('|')+1);
211 } catch (Exception e) {
212 // might be ok - both are just blank
213 logger.debug("ERROR trying to parse the volumeGroupHeatStackId " + volumeGroupHeatStackId,e);
215 this.createVfModule(cloudSiteId,
224 vfVolGroupHeatStackId,
237 // createVf will know if the requestType starts with "X" that it's the "old" way
238 StringBuilder newRequestTypeSb = new StringBuilder("X");
239 String vfVolGroupHeatStackId = "";
240 String vfBaseHeatStackId = "";
241 if (requestType != null) {
242 newRequestTypeSb.append(requestType);
244 this.createVfModule(cloudSiteId,
252 newRequestTypeSb.toString(),
253 vfVolGroupHeatStackId,
265 // End createVf shortcut
269 public void updateVnf(String cloudSiteId,
276 String volumeGroupHeatStackId,
277 Map <String, Object> inputs,
278 MsoRequest msoRequest,
279 Holder <Map <String, String>> outputs,
280 Holder <VnfRollback> rollback) throws VnfException {
281 // As of 1707 - this method should no longer be called
282 logger.debug("UpdateVnf called?? This should not be called any longer - update vfModule");
286 * This is the "Query VNF" web service implementation.
287 * It will look up a VNF by name or ID in the specified cloud and tenant.
289 * The method returns an indicator that the VNF exists, its Openstack internal
290 * ID, its status, and the set of outputs (from when the stack was created).
292 * @param cloudSiteId CLLI code of the cloud site in which to query
293 * @param tenantId Openstack tenant identifier
294 * @param vnfName VNF Name or Openstack ID
295 * @param msoRequest Request tracking information for logs
296 * @param vnfExists Flag reporting the result of the query
297 * @param vnfId Holder for output VNF Openstack ID
298 * @param outputs Holder for Map of VNF outputs from heat (assigned IPs, etc)
301 public void queryVnf (String cloudSiteId,
305 MsoRequest msoRequest,
306 Holder <Boolean> vnfExists,
307 Holder <String> vnfId,
308 Holder <VnfStatus> status,
309 Holder <Map <String, String>> outputs) throws VnfException {
311 logger.debug("Querying VNF {} in {}", vnfName, cloudSiteId + "/" + tenantId);
313 // Will capture execution time for metrics
314 long startTime = System.currentTimeMillis ();
316 StackInfo heatStack = null;
317 long subStartTime = System.currentTimeMillis ();
319 heatStack = heat.queryStack (cloudSiteId, cloudOwner, tenantId, vnfName);
320 } catch (MsoException me) {
321 me.addContext ("QueryVNF");
322 // Failed to query the Stack due to an openstack exception.
323 // Convert to a generic VnfException
324 String error = "Query VNF: " + vnfName + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + ": " + me;
325 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vnfName, cloudSiteId,
326 tenantId, "OpenStack", "QueryVNF", ErrorCode.DataError.getValue(), "Exception - queryStack",
329 throw new VnfException (me);
332 // Populate the outputs based on the returned Stack information
334 if (heatStack == null || heatStack.getStatus () == HeatStatus.NOTFOUND) {
336 vnfExists.value = Boolean.FALSE;
337 status.value = VnfStatus.NOTFOUND;
339 outputs.value = new HashMap<>(); // Return as an empty map
341 logger.debug ("VNF {} not found", vnfName);
343 vnfExists.value = Boolean.TRUE;
344 status.value = stackStatusToVnfStatus (heatStack.getStatus ());
345 vnfId.value = heatStack.getCanonicalName ();
346 outputs.value = copyStringOutputs (heatStack.getOutputs ());
348 logger.debug ("VNF {} found, ID = {}", vnfName, vnfId.value);
354 * This is the "Delete VNF" web service implementation.
355 * It will delete a VNF by name or ID in the specified cloud and tenant.
357 * The method has no outputs.
359 * @param cloudSiteId CLLI code of the cloud site in which to delete
360 * @param cloudOwner cloud owner of the cloud region in which to delete
361 * @param tenantId Openstack tenant identifier
362 * @param vnfName VNF Name or Openstack ID
363 * @param msoRequest Request tracking information for logs
366 public void deleteVnf (String cloudSiteId,
370 MsoRequest msoRequest) throws VnfException {
372 logger.debug("Deleting VNF {} in {}", vnfName, cloudSiteId + "/" + tenantId);
373 // Will capture execution time for metrics
374 long startTime = System.currentTimeMillis ();
376 // Use the MsoHeatUtils to delete the stack. Set the polling flag to true.
377 // The possible outcomes of deleteStack are a StackInfo object with status
378 // of NOTFOUND (on success) or FAILED (on error). Also, MsoOpenstackException
380 long subStartTime = System.currentTimeMillis ();
382 heat.deleteStack (tenantId, cloudOwner, cloudSiteId, vnfName, true);
383 } catch (MsoException me) {
384 me.addContext ("DeleteVNF");
385 // Failed to query the Stack due to an openstack exception.
386 // Convert to a generic VnfException
387 String error = "Delete VNF: " + vnfName + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + ": " + me;
388 logger.error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_DELETE_VNF_ERR.toString(), vnfName, cloudOwner, cloudSiteId,
389 tenantId, "OpenStack", "DeleteVNF", ErrorCode.DataError.getValue(), "Exception - DeleteVNF",
392 throw new VnfException (me);
395 // On success, nothing is returned.
400 * This web service endpoint will rollback a previous Create VNF operation.
401 * A rollback object is returned to the client in a successful creation
402 * response. The client can pass that object as-is back to the rollbackVnf
403 * operation to undo the creation.
406 public void rollbackVnf (VnfRollback rollback) throws VnfException {
407 long startTime = System.currentTimeMillis ();
408 // rollback may be null (e.g. if stack already existed when Create was called)
409 if (rollback == null) {
410 logger.info(MessageEnum.RA_ROLLBACK_NULL.toString(), "OpenStack", "rollbackVnf");
414 // Get the elements of the VnfRollback object for easier access
415 String cloudSiteId = rollback.getCloudSiteId ();
416 String cloudOwner = rollback.getCloudOwner ();
417 String tenantId = rollback.getTenantId ();
418 String vnfId = rollback.getVnfId ();
420 logger.debug("Rolling Back VNF {} in {}", vnfId, cloudOwner + "/" + cloudSiteId + "/" + tenantId);
422 // Use the MsoHeatUtils to delete the stack. Set the polling flag to true.
423 // The possible outcomes of deleteStack are a StackInfo object with status
424 // of NOTFOUND (on success) or FAILED (on error). Also, MsoOpenstackException
427 heat.deleteStack (tenantId, cloudOwner, cloudSiteId, vnfId, true);
428 } catch (MsoException me) {
429 // Failed to rollback the Stack due to an openstack exception.
430 // Convert to a generic VnfException
431 me.addContext ("RollbackVNF");
432 String error = "Rollback VNF: " + vnfId + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + ": " + me;
433 logger.error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_DELETE_VNF_ERR.toString(), vnfId, cloudOwner, cloudSiteId,
434 tenantId, "OpenStack", "DeleteStack", ErrorCode.DataError.getValue(),
435 "Exception - DeleteStack", me);
437 throw new VnfException (me);
442 private VnfStatus stackStatusToVnfStatus (HeatStatus stackStatus) {
443 switch (stackStatus) {
445 return VnfStatus.ACTIVE;
447 return VnfStatus.ACTIVE;
449 return VnfStatus.FAILED;
451 return VnfStatus.UNKNOWN;
455 private Map <String, String> copyStringOutputs(Map <String, Object> stackOutputs) {
456 Map <String, String> stringOutputs = new HashMap <> ();
457 for (Map.Entry<String,Object> entry : stackOutputs.entrySet ()) {
458 String key = entry.getKey();
459 Object value = entry.getValue();
461 stringOutputs.put(key, value.toString());
462 } catch (Exception e) {
463 StringBuilder msg = new StringBuilder("Unable to add " + key + " to outputs");
464 if (value instanceof Integer) { // nothing to add to the message
465 } else if (value instanceof JsonNode) {
466 msg.append(" - exception converting JsonNode");
467 } else if (value instanceof java.util.LinkedHashMap) {
468 msg.append(" exception converting LinkedHashMap");
470 msg.append(" - unable to call .toString() " + e.getMessage());
472 logger.debug(msg.toString(), e);
475 return stringOutputs;
478 private Map <String, Object> copyStringInputs (Map <String, Object> stringInputs) {
479 return new HashMap <> (stringInputs);
482 protected boolean callHeatbridge(String heatStackId) {
483 String executionDir = "/usr/local/lib/python2.7/dist-packages/heatbridge";
484 String openstackIdentityUrl = "", username = "", password = "", tenant = "", region = "", owner = "";
485 long waitTimeMs = 10000L;
488 {"/usr/bin/python", "HeatBridgeMain.py", openstackIdentityUrl, username, password, tenant, region, owner,
490 String[] envp = null;
491 File dir = new File(executionDir);
492 logger.debug("Calling HeatBridgeMain.py in {} with arguments {}", dir, Arrays.toString(cmdarray));
493 Runtime r = Runtime.getRuntime();
494 Process p = r.exec(cmdarray, envp, dir);
495 boolean wait = p.waitFor(waitTimeMs, TimeUnit.MILLISECONDS);
497 logger.debug(" HeatBridgeMain.py returned {} with code {}", wait, p.exitValue());
498 return wait && p.exitValue() == 0;
499 } catch (IOException e) {
500 logger.debug(" HeatBridgeMain.py failed with IO Exception! " + e);
502 } catch (RuntimeException e) {
503 logger.debug(" HeatBridgeMain.py failed during runtime!" + e);
506 catch (Exception e) {
507 logger.debug(" HeatBridgeMain.py failed for unknown reasons! " + e);
512 private String convertNode(final JsonNode node) {
514 final Object obj = JSON_MAPPER.treeToValue(node, Object.class);
515 return JSON_MAPPER.writeValueAsString(obj);
516 } catch (JsonParseException jpe) {
517 logger.debug("Error converting json to string " + jpe.getMessage(),jpe);
518 } catch (Exception e) {
519 logger.debug("Error converting json to string " + e.getMessage(),e);
521 return "[Error converting json to string]";
524 private Map<String, String> convertMapStringObjectToStringString(Map<String, Object> objectMap) {
525 if (objectMap == null) {
528 Map<String, String> stringMap = new HashMap<>();
529 for (String key : objectMap.keySet()) {
530 if (!stringMap.containsKey(key)) {
531 Object obj = objectMap.get(key);
532 if (obj instanceof String) {
533 stringMap.put(key, (String) objectMap.get(key));
534 } else if (obj instanceof JsonNode ){
535 // This is a bit of mess - but I think it's the least impacting
536 // let's convert it BACK to a string - then it will get converted back later
538 String str = this.convertNode((JsonNode) obj);
539 stringMap.put(key, str);
540 } catch (Exception e) {
541 logger.debug("DANGER WILL ROBINSON: unable to convert value for JsonNode "+ key,e);
542 //okay in this instance - only string values (fqdn) are expected to be needed
544 } else if (obj instanceof java.util.LinkedHashMap) {
545 logger.debug("LinkedHashMap - this is showing up as a LinkedHashMap instead of JsonNode");
547 String str = JSON_MAPPER.writeValueAsString(obj);
548 stringMap.put(key, str);
549 } catch (Exception e) {
550 logger.debug("DANGER WILL ROBINSON: unable to convert value for LinkedHashMap "+ key,e);
552 } else if (obj instanceof Integer) {
554 String str = "" + obj;
555 stringMap.put(key, str);
556 } catch (Exception e) {
557 logger.debug("DANGER WILL ROBINSON: unable to convert value for Integer "+ key,e);
561 String str = obj.toString();
562 stringMap.put(key, str);
563 } catch (Exception e) {
564 logger.debug("DANGER WILL ROBINSON: unable to convert value "+ key + " (" + e.getMessage() + ")",e);
574 public void createVfModule(String cloudSiteId,
579 String genericVnfName,
583 String volumeGroupHeatStackId,
584 String baseVfHeatStackId,
585 String modelCustomizationUuid,
586 Map <String, Object> inputs,
587 Boolean failIfExists,
589 Boolean enableBridge,
590 MsoRequest msoRequest,
591 Holder <String> vnfId,
592 Holder <Map <String, String>> outputs,
593 Holder <VnfRollback> rollback) throws VnfException {
594 String vfModuleName = vnfName;
595 String vfModuleType = vnfType;
596 String vfVersion = vnfVersion;
597 String mcu = modelCustomizationUuid;
598 boolean useMCUuid = false;
599 if (mcu != null && !mcu.isEmpty()) {
600 if ("null".equalsIgnoreCase(mcu)) {
601 logger.debug("modelCustomizationUuid: passed in as the string 'null' - will ignore: " + modelCustomizationUuid);
605 logger.debug("Found modelCustomizationUuid! Will use that: " + mcu);
610 String requestTypeString = "";
611 if (requestType != null && !"".equals(requestType)) {
612 requestTypeString = requestType;
614 String nestedStackId = null;
615 if (volumeGroupHeatStackId != null && !"".equals(volumeGroupHeatStackId) && !"null".equalsIgnoreCase(volumeGroupHeatStackId)) {
616 nestedStackId = volumeGroupHeatStackId;
618 String nestedBaseStackId = null;
619 if (baseVfHeatStackId != null && !"".equals(baseVfHeatStackId) && !"null".equalsIgnoreCase(baseVfHeatStackId)) {
620 nestedBaseStackId = baseVfHeatStackId;
623 //This method will also handle doing things the "old" way - i.e., just orchestrate a VNF
624 boolean oldWay = false;
625 if (requestTypeString.startsWith("X")) {
627 logger.debug("orchestrating a VNF - *NOT* a module!");
628 requestTypeString = requestTypeString.substring(1);
631 // 1607 - let's parse out the request type we're being sent
632 boolean isBaseRequest = false;
633 boolean isVolumeRequest = false;
634 if (requestTypeString.startsWith("VOLUME")) {
635 isVolumeRequest = true;
638 logger.debug("requestTypeString = " + requestTypeString + ", nestedStackId = " + nestedStackId + ", nestedBaseStackId = " + nestedBaseStackId);
639 // Will capture execution time for metrics
640 long startTime = System.currentTimeMillis ();
642 // Build a default rollback object (no actions performed)
643 VnfRollback vfRollback = new VnfRollback();
644 vfRollback.setCloudSiteId(cloudSiteId);
645 vfRollback.setCloudOwner(cloudOwner);
646 vfRollback.setTenantId(tenantId);
647 vfRollback.setMsoRequest(msoRequest);
648 vfRollback.setRequestType(requestTypeString);
649 vfRollback.setVolumeGroupHeatStackId(volumeGroupHeatStackId);
650 vfRollback.setBaseGroupHeatStackId(baseVfHeatStackId);
651 vfRollback.setIsBase(isBaseRequest);
652 vfRollback.setModelCustomizationUuid(mcu);
654 // Put data into A&AI through Heatstack
655 if(enableBridge != null && enableBridge) {
656 callHeatbridge(baseVfHeatStackId);
659 StackInfo heatStack = null;
660 long subStartTime1 = System.currentTimeMillis ();
662 heatStack = heat.queryStack (cloudSiteId, cloudOwner, tenantId, vfModuleName);
663 } catch (MsoException me) {
664 String error = "Create VF Module: Query " + vfModuleName + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + ": " + me ;
665 logger.error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vfModuleName, cloudOwner, cloudSiteId,
666 tenantId, "OpenStack", "queryStack", ErrorCode.DataError.getValue(), "Exception - queryStack",
669 // Failed to query the Stack due to an openstack exception.
670 // Convert to a generic VnfException
671 me.addContext ("CreateVFModule");
672 throw new VnfException (me);
674 // New with 1607 - more precise handling/messaging if the stack already exists
675 if (heatStack != null && heatStack.getStatus() != HeatStatus.NOTFOUND) {
676 // INIT, CREATED, NOTFOUND, FAILED, BUILDING, DELETING, UNKNOWN, UPDATING, UPDATED
677 HeatStatus status = heatStack.getStatus();
678 if (status == HeatStatus.INIT || status == HeatStatus.BUILDING || status == HeatStatus.DELETING || status == HeatStatus.UPDATING) {
679 // fail - it's in progress - return meaningful error
680 String error = "Create VF: Stack " + vfModuleName + " already exists and has status " + status.toString() + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + "; please wait for it to complete, or fix manually.";
681 logger.error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_VNF_ALREADY_EXIST.toString(), vfModuleName,
682 cloudOwner, cloudSiteId, tenantId, "OpenStack", "queryStack", ErrorCode.DataError.getValue(),
683 "Stack " + vfModuleName + " already exists");
685 throw new VnfAlreadyExists (vfModuleName, cloudOwner, cloudSiteId, tenantId, heatStack.getCanonicalName ());
687 if (status == HeatStatus.FAILED) {
688 // fail - it exists and is in a FAILED state
689 String error = "Create VF: Stack " + vfModuleName + " already exists and is in FAILED state in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + "; requires manual intervention.";
690 logger.error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_VNF_ALREADY_EXIST.toString(), vfModuleName,
691 cloudOwner, cloudSiteId, tenantId, "OpenStack", "queryStack", ErrorCode.DataError.getValue(),
692 "Stack " + vfModuleName + " already exists and is " + "in FAILED state");
694 throw new VnfAlreadyExists (vfModuleName, cloudOwner, cloudSiteId, tenantId, heatStack.getCanonicalName ());
696 if (status == HeatStatus.UNKNOWN || status == HeatStatus.UPDATED) {
697 // fail - it exists and is in a FAILED state
699 "Create VF: Stack " + vfModuleName + " already exists and has status " + status.toString() + " in "
700 + cloudOwner + "/" + cloudSiteId + "/" + tenantId + "; requires manual intervention.";
701 logger.error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_VNF_ALREADY_EXIST.toString(), vfModuleName,
702 cloudOwner, cloudSiteId, tenantId, "OpenStack", "queryStack", ErrorCode.DataError.getValue(),
703 "Stack " + vfModuleName + " already exists and is " + "in UPDATED or UNKNOWN state");
705 throw new VnfAlreadyExists(vfModuleName, cloudOwner, cloudSiteId, tenantId, heatStack.getCanonicalName());
707 if (status == HeatStatus.CREATED) {
709 if (failIfExists != null && failIfExists) {
711 "Create VF: Stack " + vfModuleName + " already exists in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId;
712 logger.error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_VNF_ALREADY_EXIST.toString(), vfModuleName,
713 cloudOwner, cloudSiteId, tenantId, "OpenStack", "queryStack", ErrorCode.DataError.getValue(),
714 "Stack " + vfModuleName + " already exists");
716 throw new VnfAlreadyExists(vfModuleName, cloudOwner, cloudSiteId, tenantId, heatStack.getCanonicalName());
718 logger.debug ("Found Existing stack, status={}", heatStack.getStatus ());
719 // Populate the outputs from the existing stack.
720 vnfId.value = heatStack.getCanonicalName ();
721 outputs.value = copyStringOutputs (heatStack.getOutputs ());
722 rollback.value = vfRollback; // Default rollback - no updates performed
729 // handle a nestedStackId if sent- this one would be for the volume - so applies to both Vf and Vnf
730 StackInfo nestedHeatStack = null;
731 long subStartTime2 = System.currentTimeMillis ();
732 Map<String, Object> nestedVolumeOutputs = null;
733 if (nestedStackId != null) {
735 logger.debug("Querying for nestedStackId = {}", nestedStackId);
736 nestedHeatStack = heat.queryStack(cloudSiteId, cloudOwner, tenantId, nestedStackId);
737 } catch (MsoException me) {
738 // Failed to query the Stack due to an openstack exception.
739 // Convert to a generic VnfException
740 me.addContext ("CreateVFModule");
741 String error = "Create VFModule: Attached heatStack ID Query " + nestedStackId + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + ": " + me ;
742 logger.error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vfModuleName, cloudOwner, cloudSiteId,
743 tenantId, "OpenStack", "queryStack", ErrorCode.BusinessProcesssError.getValue(),
744 "MsoException trying to query nested stack", me);
745 logger.debug("ERROR trying to query nested stack= {}", error);
746 throw new VnfException (me);
748 if (nestedHeatStack == null || nestedHeatStack.getStatus() == HeatStatus.NOTFOUND) {
749 String error = "Create VFModule: Attached heatStack ID DOES NOT EXIST " + nestedStackId + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + " USER ERROR" ;
750 logger.error("{} {} {} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vfModuleName,
751 cloudOwner, cloudSiteId, tenantId, error, "OpenStack", "queryStack",
752 ErrorCode.BusinessProcesssError.getValue(),
753 "Create VFModule: Attached heatStack ID " + "DOES NOT EXIST");
755 throw new VnfException (error, MsoExceptionCategory.USERDATA);
757 logger.debug("Found nested volume heat stack - copying values to inputs *later*");
758 nestedVolumeOutputs = nestedHeatStack.getOutputs();
762 // handle a nestedBaseStackId if sent- this is the stack ID of the base. Should be null for VNF requests
763 StackInfo nestedBaseHeatStack = null;
764 long subStartTime3 = System.currentTimeMillis ();
765 Map<String, Object> baseStackOutputs = null;
766 if (nestedBaseStackId != null) {
768 logger.debug("Querying for nestedBaseStackId = {}", nestedBaseStackId);
769 nestedBaseHeatStack = heat.queryStack(cloudSiteId, cloudOwner, tenantId, nestedBaseStackId);
770 } catch (MsoException me) {
771 // Failed to query the Stack due to an openstack exception.
772 // Convert to a generic VnfException
773 me.addContext ("CreateVFModule");
774 String error = "Create VFModule: Attached baseHeatStack ID Query " + nestedBaseStackId + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + ": " + me ;
776 .error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vfModuleName, cloudOwner, cloudSiteId,
777 tenantId, "OpenStack", "QueryStack", ErrorCode.BusinessProcesssError.getValue(),
778 "MsoException trying to query nested base stack", me);
779 logger.debug("ERROR trying to query nested base stack= {}", error);
780 throw new VnfException (me);
782 if (nestedBaseHeatStack == null || nestedBaseHeatStack.getStatus() == HeatStatus.NOTFOUND) {
783 String error = "Create VFModule: Attached base heatStack ID DOES NOT EXIST " + nestedBaseStackId + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + " USER ERROR" ;
784 logger.error("{} {} {} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vfModuleName,
785 cloudOwner, cloudSiteId, tenantId, error, "OpenStack", "QueryStack",
786 ErrorCode.BusinessProcesssError.getValue(),
787 "Create VFModule: Attached base heatStack ID DOES NOT EXIST");
788 logger.debug("Exception occurred", error);
789 throw new VnfException (error, MsoExceptionCategory.USERDATA);
791 logger.debug("Found nested base heat stack - these values will be copied to inputs *later*");
792 baseStackOutputs = nestedBaseHeatStack.getOutputs();
796 // Ready to deploy the new VNF
803 VnfResource vnfResource = null;
804 VfModuleCustomization vfmc = null;
805 logger.debug("version: {}", vfVersion);
807 // 1707 - db refactoring
808 vfmc = vfModuleCustomRepo.findByModelCustomizationUUID(mcu);
810 vf=vfmc.getVfModule();
814 // 1702 - this will be the new way going forward. We find the vf by mcu - otherwise, code is the same.
816 logger.debug("Unable to find vfModuleCust with modelCustomizationUuid={}", mcu);
817 String error = "Create vfModule error: Unable to find vfModuleCust with modelCustomizationUuid=" + mcu;
818 logger.error("{} {} {} {} {} {}", MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(),
819 "VF Module ModelCustomizationUuid", modelCustomizationUuid, "OpenStack",
820 ErrorCode.DataError.getValue(),
821 "Create VF Module: Unable to find vfModule with " + "modelCustomizationUuid=" + mcu);
823 throw new VnfException(error, MsoExceptionCategory.USERDATA);
825 logger.trace("Found vfModuleCust entry {}", vfmc.toString());
827 if (vf.getIsBase()) {
828 isBaseRequest = true;
829 logger.debug("This is a BASE VF request!");
831 logger.debug("This is *not* a BASE VF request!");
832 if (!isVolumeRequest && nestedBaseStackId == null) {
833 logger.debug("DANGER WILL ROBINSON! This is unexpected - no nestedBaseStackId with this non-base request");
838 else { // This is to support gamma only - get info from vnf_resource table
839 if (vfVersion != null && !vfVersion.isEmpty()) {
840 vnfResource = vnfResourceRepo.findByModelNameAndModelVersion(vnfType, vnfVersion);
842 vnfResource = vnfResourceRepo.findByModelName(vnfType);
844 if (vnfResource == null) {
845 String error = "Create VNF: Unknown VNF Type: " + vnfType;
846 logger.error("{} {} {} {} {} {}", MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "VNF Type", vnfType,
847 "OpenStack", ErrorCode.DataError.getValue(), "Create VNF: Unknown VNF Type");
849 throw new VnfException(error, MsoExceptionCategory.USERDATA);
851 logger.debug("Got VNF module definition from Catalog: {}", vnfResource.toString());
853 // By here - we have either a vf or vnfResource
855 //1607 - Add version check
856 // First - see if it's in the VnfResource record
857 // if we have a vf Module - then we have to query to get the VnfResource record.
858 if (!oldWay && vf.getVnfResources() != null) {
859 vnfResource = vf.getVnfResources();
860 if (vnfResource == null) {
861 logger.debug("Unable to find vnfResource will not error for now...");
864 String minVersionVnf = null;
865 String maxVersionVnf = null;
866 if (vnfResource != null) {
868 minVersionVnf = vnfResource.getAicVersionMin();
869 maxVersionVnf = vnfResource.getAicVersionMax();
870 } catch (Exception e) {
871 logger.debug("Unable to pull min/max version for this VNF Resource entry",e);
872 minVersionVnf = null;
873 maxVersionVnf = null;
875 if (minVersionVnf != null && "".equals(minVersionVnf)) {
876 minVersionVnf = null;
878 if (maxVersionVnf != null && "".equals(maxVersionVnf)) {
879 maxVersionVnf = null;
882 if (minVersionVnf != null && maxVersionVnf != null) {
883 MavenLikeVersioning aicV = new MavenLikeVersioning();
886 if (this.cloudConfig != null) {
887 Optional<CloudSite> cloudSiteOpt = this.cloudConfig.getCloudSite(cloudSiteId);
888 if (cloudSiteOpt.isPresent()) {
889 aicV.setVersion(cloudSiteOpt.get().getCloudVersion());
890 // Add code to handle unexpected values in here
891 boolean moreThanMin = true;
892 boolean equalToMin = true;
893 boolean moreThanMax = true;
894 boolean equalToMax = true;
895 boolean doNotTest = false;
897 moreThanMin = aicV.isMoreRecentThan(minVersionVnf);
898 equalToMin = aicV.isTheSameVersion(minVersionVnf);
899 moreThanMax = aicV.isMoreRecentThan(maxVersionVnf);
900 equalToMax = aicV.isTheSameVersion(maxVersionVnf);
901 } catch (Exception e) {
902 logger.debug("An exception occurred while trying to test AIC Version {} - will default to not check",
907 if ((moreThanMin || equalToMin) // aic >= min
908 && (equalToMax || !(moreThanMax))) { //aic <= max
910 "VNF Resource " + vnfResource.getModelName() + ", ModelUuid=" + vnfResource.getModelUUID()
911 + " VersionMin=" + minVersionVnf + " VersionMax:" + maxVersionVnf + " supported on Cloud: "
912 + cloudSiteId + " with AIC_Version:" + cloudSiteOpt.get().getCloudVersion());
915 String error = "VNF Resource type: " + vnfResource.getModelName() + ", ModelUuid=" + vnfResource.getModelUUID() + " VersionMin=" + minVersionVnf + " VersionMax:" + maxVersionVnf + " NOT supported on Cloud: " + cloudSiteId + " with AIC_Version:" + cloudSiteOpt.get().getCloudVersion();
916 logger.error("{} {} {} {} {}", MessageEnum.RA_CONFIG_EXC.toString(), error, "OpenStack",
917 ErrorCode.BusinessProcesssError.getValue(), "Exception - setVersion");
919 throw new VnfException(error, MsoExceptionCategory.USERDATA);
922 logger.debug("bypassing testing AIC version...");
924 } // let this error out downstream to avoid introducing uncertainty at this stage
926 logger.debug("cloudConfig is NULL - cannot check cloud site version");
929 logger.debug("AIC Version not set in VNF_Resource - this is expected thru 1607 - do not error here - not checked"
932 // End Version check 1607
937 // By the time we get here - heatTemplateId and heatEnvtId should be populated (or null)
938 HeatTemplate heatTemplate = null;
939 HeatEnvironment heatEnvironment = null;
941 //This will handle old Gamma BrocadeVCE VNF
942 heatTemplate = vnfResource.getHeatTemplates();
946 if (isVolumeRequest) {
947 heatTemplate = vf.getVolumeHeatTemplate();
948 heatEnvironment = vfmc.getVolumeHeatEnv();
950 heatTemplate = vf.getModuleHeatTemplate();
951 heatEnvironment = vfmc.getHeatEnvironment();
956 if (heatTemplate == null) {
957 String error = "UpdateVF: No Heat Template ID defined in catalog database for " + vfModuleType + ", reqType=" + requestTypeString;
959 .error("{} {} {} {} {} {}", MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "Heat Template ID", vfModuleType,
960 "OpenStack", ErrorCode.DataError.getValue(), error);
962 throw new VnfException(error, MsoExceptionCategory.INTERNAL);
964 logger.debug("Got HEAT Template from DB: {}", heatTemplate.getHeatTemplate());
968 //This will handle old Gamma BrocadeVCE VNF
969 logger.debug("No environment parameter found for this Type " + vfModuleType);
971 if (heatEnvironment == null) {
972 String error = "Update VNF: undefined Heat Environment. VF=" + vfModuleType;
973 logger.error("{} {} {} {} {}", MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "Heat Environment ID",
974 "OpenStack", ErrorCode.DataError.getValue(), error);
976 throw new VnfException (error, MsoExceptionCategory.INTERNAL);
978 logger.debug("Got Heat Environment from DB: {}", heatEnvironment.getEnvironment());
982 logger.debug("In MsoVnfAdapterImpl, about to call db.getNestedTemplates avec templateId="
983 + heatTemplate.getArtifactUuid ());
986 List<HeatTemplate> nestedTemplates = heatTemplate.getChildTemplates();
987 Map <String, Object> nestedTemplatesChecked = new HashMap <> ();
988 if (nestedTemplates != null && !nestedTemplates.isEmpty()) {
989 // for debugging print them out
990 logger.debug("Contents of nestedTemplates - to be added to files: on stack:");
991 for (HeatTemplate entry : nestedTemplates) {
992 nestedTemplatesChecked.put (entry.getTemplateName(), entry.getTemplateBody());
993 logger.debug(entry.getTemplateName() + " -> " + entry.getTemplateBody());
996 logger.debug("No nested templates found - nothing to do here");
997 nestedTemplatesChecked = null;
1000 // 1510 - Also add the files: for any get_files associated with this vnf_resource_id
1001 // *if* there are any
1002 List<HeatFiles> heatFiles = null;
1004 Map<String, Object> heatFilesObjects = new HashMap<>();
1006 // Add ability to turn on adding get_files with volume requests (by property).
1007 boolean addGetFilesOnVolumeReq = false;
1009 String propertyString = this.environment.getProperty(MsoVnfAdapterImpl.ADD_GET_FILES_ON_VOLUME_REQ);
1010 if ("true".equalsIgnoreCase(propertyString) || "y".equalsIgnoreCase(propertyString)) {
1011 addGetFilesOnVolumeReq = true;
1012 logger.debug("AddGetFilesOnVolumeReq - setting to true! {}", propertyString);
1014 } catch (Exception e) {
1015 logger.debug("An error occured trying to get property " + MsoVnfAdapterImpl.ADD_GET_FILES_ON_VOLUME_REQ
1016 + " - default to false", e);
1019 if (!isVolumeRequest || addGetFilesOnVolumeReq) {
1021 logger.debug("In MsoVnfAdapterImpl createVfModule, this should not happen - old way is gamma only - no heat "
1024 // 1607 - now use VF_MODULE_TO_HEAT_FILES table
1025 logger.debug("In MsoVnfAdapterImpl createVfModule, about to call db.getHeatFilesForVfModule avec vfModuleId="
1026 + vf.getModelUUID());
1027 heatFiles = vf.getHeatFiles();
1029 if (heatFiles != null && !heatFiles.isEmpty()) {
1030 // add these to stack - to be done in createStack
1031 // here, we will map them to Map<String, Object> from
1032 // Map<String, HeatFiles>
1033 // this will match the nested templates format
1034 logger.debug("Contents of heatFiles - to be added to files: on stack");
1036 for (HeatFiles heatfile : heatFiles) {
1037 logger.debug(heatfile.getFileName() + " -> " + heatfile.getFileBody());
1038 heatFilesObjects.put(heatfile.getFileName(), heatfile.getFileBody());
1041 logger.debug("No heat files found -nothing to do here");
1042 heatFilesObjects = null;
1046 // Check that required parameters have been supplied
1047 String missingParams = null;
1048 List <String> paramList = new ArrayList <> ();
1050 // New for 1510 - consult the PARAM_ALIAS field to see if we've been
1051 // supplied an alias. Only check if we don't find it initially.
1052 // Also new in 1510 - don't flag missing parameters if there's an environment - because they might be there.
1053 // And also new - add parameter to turn off checking all together if we find we're blocking orders we
1055 boolean checkRequiredParameters = true;
1057 String propertyString = this.environment.getProperty (MsoVnfAdapterImpl.CHECK_REQD_PARAMS);
1058 if ("false".equalsIgnoreCase (propertyString) || "n".equalsIgnoreCase (propertyString)) {
1059 checkRequiredParameters = false;
1060 logger.debug("CheckRequiredParameters is FALSE. Will still check but then skip blocking..."
1061 + MsoVnfAdapterImpl.CHECK_REQD_PARAMS);
1063 } catch (Exception e) {
1064 // No problem - default is true
1065 logger.debug("An exception occured trying to get property {}", MsoVnfAdapterImpl.CHECK_REQD_PARAMS, e);
1067 // 1604 - Add enhanced environment & parameter checking
1068 // Part 1: parse envt entries to see if reqd parameter is there (before used a simple grep
1069 // Part 2: only submit to openstack the parameters in the envt that are in the heat template
1070 // Note this also removes any comments
1071 MsoHeatEnvironmentEntry mhee = null;
1072 if (heatEnvironment != null && heatEnvironment.getEnvironment() != null && heatEnvironment.getEnvironment().contains ("parameters:")) {
1074 logger.debug("Enhanced environment checking enabled - 1604");
1075 StringBuilder sb = new StringBuilder(heatEnvironment.getEnvironment());
1077 mhee = new MsoHeatEnvironmentEntry(sb);
1078 StringBuilder sb2 = new StringBuilder("\nHeat Template Parameters:\n");
1079 for (HeatTemplateParam parm : heatTemplate.getParameters()) {
1080 sb2.append("\t" + parm.getParamName() + ", required=" + parm.isRequired());
1082 if (!mhee.isValid()) {
1083 sb2.append("Environment says it's not valid! " + mhee.getErrorString());
1085 sb2.append("\nEnvironment:");
1086 sb2.append(mhee.toFullString());
1088 logger.debug(sb2.toString());
1090 logger.debug("NO ENVIRONMENT for this entry");
1092 // New with 1707 - all variables converted to their native object types
1093 Map<String, Object> goldenInputs = null;
1095 logger.debug("Now handle the inputs....first convert");
1096 ArrayList<String> parameterNames = new ArrayList<>();
1097 HashMap<String, String> aliasToParam = new HashMap<>();
1098 StringBuilder sb = new StringBuilder("\nTemplate Parameters:\n");
1101 for (HeatTemplateParam htp : heatTemplate.getParameters()) {
1102 sb.append("param[" + cntr++ + "]=" + htp.getParamName());
1103 parameterNames.add(htp.getParamName());
1104 if (htp.getParamAlias() != null && !"".equals(htp.getParamAlias())) {
1105 aliasToParam.put(htp.getParamAlias(), htp.getParamName());
1106 sb.append(" ** (alias=" + htp.getParamAlias() + ")");
1110 logger.debug(sb.toString());
1111 } catch (Exception e) {
1112 logger.debug("??An exception occurred trying to go through Parameter Names {}", e.getMessage(),e);
1114 // Step 1 - convert what we got as inputs (Map<String, String>) to a
1115 // Map<String, Object> - where the object matches the param type identified in the template
1116 // This will also not copy over params that aren't identified in the template
1117 goldenInputs = heat.convertInputMap(inputs, heatTemplate);
1118 // Step 2 - now simply add the outputs as we received them - no need to convert to string
1119 logger.debug("Now add in the base stack outputs if applicable");
1120 heat.copyBaseOutputsToInputs(goldenInputs, baseStackOutputs, parameterNames, aliasToParam);
1121 // Step 3 - add the volume inputs if any
1122 logger.debug("Now add in the volume stack outputs if applicable");
1123 heat.copyBaseOutputsToInputs(goldenInputs, nestedVolumeOutputs, parameterNames, aliasToParam);
1125 for (HeatTemplateParam parm : heatTemplate.getParameters ()) {
1127 "Parameter:'" + parm.getParamName() + "', isRequired=" + parm.isRequired() + ", alias=" + parm
1130 if (parm.isRequired () && (goldenInputs == null || !goldenInputs.containsKey (parm.getParamName ()))) {
1131 // The check for an alias was moved to the method in MsoHeatUtils - when we converted the Map<String, String> to Map<String, Object>
1132 logger.debug("**Parameter " + parm.getParamName() + " is required and not in the inputs...check "
1134 if (mhee != null && mhee.containsParameter(parm.getParamName())) {
1135 logger.debug("Required parameter {} appears to be in environment - do not count as missing",
1136 parm.getParamName());
1138 logger.debug("adding to missing parameters list: {}", parm.getParamName());
1139 if (missingParams == null) {
1140 missingParams = parm.getParamName ();
1142 missingParams += "," + parm.getParamName ();
1146 paramList.add (parm.getParamName ());
1148 if (missingParams != null) {
1149 if (checkRequiredParameters) {
1150 // Problem - missing one or more required parameters
1151 String error = "Create VFModule: Missing Required inputs: " + missingParams;
1152 logger.error("{} {} {} {} {}", MessageEnum.RA_MISSING_PARAM.toString(), missingParams, "OpenStack",
1153 ErrorCode.DataError.getValue(), "Create VFModule: Missing Required inputs");
1154 logger.debug(error);
1155 throw new VnfException (error, MsoExceptionCategory.USERDATA);
1157 logger.debug ("found missing parameters - but checkRequiredParameters is false - will not block");
1160 logger.debug ("No missing parameters found - ok to proceed");
1162 // We can now remove the recreating of the ENV with only legit params - that check is done for us,
1163 // and it causes problems with json that has arrays
1164 String newEnvironmentString = null;
1166 newEnvironmentString = mhee.getRawEntry().toString();
1169 // "Fix" the template if it has CR/LF (getting this from Oracle)
1170 String template = heatTemplate.getHeatTemplate ();
1171 template = template.replaceAll ("\r\n", "\n");
1174 boolean isValetEnabled = this.checkBooleanProperty(MsoVnfAdapterImpl.VALET_ENABLED, false);
1175 boolean failRequestOnValetFailure = this.checkBooleanProperty(MsoVnfAdapterImpl.FAIL_REQUESTS_ON_VALET_FAILURE, false);
1176 logger.debug("isValetEnabled={}, failRequestsOnValetFailure={}", isValetEnabled, failRequestOnValetFailure);
1177 if (oldWay || isVolumeRequest) {
1178 isValetEnabled = false;
1179 logger.debug("do not send to valet for volume requests or brocade");
1181 boolean sendResponseToValet = false;
1182 if (isValetEnabled) {
1183 Holder<Map<String, Object>> valetModifiedParamsHolder = new Holder<>();
1184 sendResponseToValet = this.valetCreateRequest(cloudSiteId, cloudOwner, tenantId, heatFilesObjects,
1185 nestedTemplatesChecked, vfModuleName, backout, heatTemplate, newEnvironmentString, goldenInputs,
1186 msoRequest, inputs, failRequestOnValetFailure, valetModifiedParamsHolder);
1187 if (sendResponseToValet) {
1188 goldenInputs = valetModifiedParamsHolder.value;
1192 // Have the tenant. Now deploy the stack itself
1193 // Ignore MsoTenantNotFound and MsoStackAlreadyExists exceptions
1194 // because we already checked for those.
1195 long createStackStarttime = System.currentTimeMillis ();
1197 // heatStack = heat.createStack(cloudSiteId, tenantId, vnfName, template, inputs, true,
1198 // heatTemplate.getTimeoutMinutes());
1199 if (backout == null) {
1203 logger.debug("heat is not null!!");
1205 heatStack = heat.createStack (cloudSiteId,
1213 heatTemplate.getTimeoutMinutes(),
1214 newEnvironmentString,
1215 nestedTemplatesChecked,
1217 backout.booleanValue());
1220 logger.debug("heat is null!");
1221 throw new MsoHeatNotFoundException();
1223 } catch (MsoException me) {
1224 me.addContext ("CreateVFModule");
1225 String error = "Create VF Module " + vfModuleType + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + ": " + me;
1227 .error("{} {} {} {} {} {} {} {}", MessageEnum.RA_CREATE_VNF_ERR.toString(), vfModuleType, cloudOwner, cloudSiteId,
1228 tenantId, "OpenStack", ErrorCode.DataError.getValue(), "MsoException - createStack",
1230 logger.debug(error);
1231 if (isValetEnabled && sendResponseToValet) {
1232 logger.debug("valet is enabled, the orchestration failed - now sending rollback to valet");
1234 GenericValetResponse<ValetRollbackResponse> gvr = this.vci.callValetRollbackRequest(msoRequest.getRequestId(), null, backout, me.getMessage());
1235 // Nothing to really do here whether it succeeded or not other than log it.
1236 logger.debug("Return code from Rollback response is {}", gvr.getStatusCode());
1237 } catch (Exception e) {
1238 logger.error("Exception encountered while sending Rollback to Valet ", e);
1241 throw new VnfException (me);
1242 } catch (NullPointerException npe) {
1243 String error = "Create VFModule " + vfModuleType + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + ": " + npe;
1245 .error("{} {} {} {} {} {} {} {}", MessageEnum.RA_CREATE_VNF_ERR.toString(), vfModuleType, cloudOwner, cloudSiteId,
1246 tenantId, "OpenStack", ErrorCode.DataError.getValue(),
1247 "NullPointerException - createStack", npe);
1248 logger.debug(error);
1249 logger.debug("NULL POINTER EXCEPTION at heat.createStack");
1250 //npe.addContext ("CreateVNF");
1251 throw new VnfException ("NullPointerException during heat.createStack");
1252 } catch (Exception e) {
1253 logger.debug("unhandled exception at heat.createStack",e);
1254 throw new VnfException("Exception during heat.createStack! " + e.getMessage());
1256 // Reach this point if createStack is successful.
1257 // Populate remaining rollback info and response parameters.
1258 vfRollback.setVnfId (heatStack.getCanonicalName ());
1259 vfRollback.setVnfCreated (true);
1261 vnfId.value = heatStack.getCanonicalName ();
1262 outputs.value = copyStringOutputs (heatStack.getOutputs ());
1263 rollback.value = vfRollback;
1264 if (isValetEnabled && sendResponseToValet) {
1265 logger.debug("valet is enabled, the orchestration succeeded - now send confirm to valet with stack id");
1267 GenericValetResponse<ValetConfirmResponse> gvr = this.vci.callValetConfirmRequest(msoRequest.getRequestId(), heatStack.getCanonicalName());
1268 // Nothing to really do here whether it succeeded or not other than log it.
1269 logger.debug("Return code from Confirm response is {}", gvr.getStatusCode());
1270 } catch (Exception e) {
1271 logger.error("Exception encountered while sending Confirm to Valet ", e);
1274 logger.debug("VF Module {} successfully created", vfModuleName);
1276 } catch (Exception e) {
1277 logger.debug("unhandled exception in create VF",e);
1278 throw new VnfException("Exception during create VF " + e.getMessage());
1283 public void deleteVfModule (String cloudSiteId,
1287 MsoRequest msoRequest,
1288 Holder <Map <String, String>> outputs) throws VnfException {
1290 logger.debug("Deleting VF {} in ", vnfName, cloudOwner + "/" + cloudSiteId + "/" + tenantId);
1291 // Will capture execution time for metrics
1292 long startTime = System.currentTimeMillis ();
1294 // 1702 capture the output parameters on a delete
1295 // so we'll need to query first
1296 Map<String, Object> stackOutputs = null;
1298 stackOutputs = heat.queryStackForOutputs(cloudSiteId, cloudOwner, tenantId, vnfName);
1299 } catch (MsoException me) {
1300 // Failed to query the Stack due to an openstack exception.
1301 // Convert to a generic VnfException
1302 me.addContext ("DeleteVFModule");
1303 String error = "Delete VFModule: Query to get outputs: " + vnfName + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + ": " + me;
1304 logger.error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vnfName, cloudOwner, cloudSiteId,
1305 tenantId, "OpenStack", "QueryStack", ErrorCode.DataError.getValue(), "Exception - QueryStack",
1307 logger.debug(error);
1308 throw new VnfException (me);
1310 // call method which handles the conversion from Map<String,Object> to Map<String,String> for our expected Object types
1311 outputs.value = this.convertMapStringObjectToStringString(stackOutputs);
1313 boolean isValetEnabled = this.checkBooleanProperty(MsoVnfAdapterImpl.VALET_ENABLED, false);
1314 boolean failRequestOnValetFailure = this.checkBooleanProperty(MsoVnfAdapterImpl.FAIL_REQUESTS_ON_VALET_FAILURE, false);
1315 logger.debug("isValetEnabled={}, failRequestsOnValetFailure={}", isValetEnabled, failRequestOnValetFailure);
1316 boolean valetDeleteRequestSucceeded = false;
1317 if (isValetEnabled) {
1318 valetDeleteRequestSucceeded = this.valetDeleteRequest(cloudSiteId, cloudOwner, tenantId, vnfName, msoRequest, failRequestOnValetFailure);
1321 // Use the MsoHeatUtils to delete the stack. Set the polling flag to true.
1322 // The possible outcomes of deleteStack are a StackInfo object with status
1323 // of NOTFOUND (on success) or FAILED (on error). Also, MsoOpenstackException
1325 long subStartTime = System.currentTimeMillis ();
1327 heat.deleteStack (tenantId, cloudOwner, cloudSiteId, vnfName, true);
1328 } catch (MsoException me) {
1329 me.addContext ("DeleteVNF");
1330 // Failed to query the Stack due to an openstack exception.
1331 // Convert to a generic VnfException
1332 String error = "Delete VF: " + vnfName + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + ": " + me;
1333 logger.error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_DELETE_VNF_ERR.toString(), vnfName, cloudOwner, cloudSiteId,
1334 tenantId, "OpenStack", "DeleteStack", ErrorCode.DataError.getValue(),
1335 "Exception - deleteStack", me);
1336 logger.debug(error);
1337 if (isValetEnabled && valetDeleteRequestSucceeded) {
1338 logger.debug("valet is enabled, the orchestration failed - now sending rollback to valet");
1340 GenericValetResponse<ValetRollbackResponse> gvr = this.vci.callValetRollbackRequest(msoRequest.getRequestId(), vnfName, false, me.getMessage());
1341 // Nothing to really do here whether it succeeded or not other than log it.
1342 logger.debug("Return code from Rollback response is {}", gvr.getStatusCode());
1343 } catch (Exception e) {
1344 logger.error("Exception encountered while sending Rollback to Valet ", e);
1347 throw new VnfException (me);
1349 if (isValetEnabled && valetDeleteRequestSucceeded) {
1350 // only if the original request succeeded do we send a confirm
1351 logger.debug("valet is enabled, the delete succeeded - now send confirm to valet");
1353 GenericValetResponse<ValetConfirmResponse> gvr = this.vci.callValetConfirmRequest(msoRequest.getRequestId(), vnfName);
1354 // Nothing to really do here whether it succeeded or not other than log it.
1355 logger.debug("Return code from Confirm response is {}", gvr.getStatusCode());
1356 } catch (Exception e) {
1357 logger.error("Exception encountered while sending Confirm to Valet ", e);
1361 // On success, nothing is returned.
1366 public void updateVfModule (String cloudSiteId,
1373 String volumeGroupHeatStackId,
1374 String baseVfHeatStackId,
1375 String vfModuleStackId,
1376 String modelCustomizationUuid,
1377 Map <String, Object> inputs,
1378 MsoRequest msoRequest,
1379 Holder <Map <String, String>> outputs,
1380 Holder <VnfRollback> rollback) throws VnfException {
1381 String vfModuleName = vnfName;
1382 String vfModuleType = vnfType;
1383 String methodName = "updateVfModule";
1384 String serviceName = VNF_ADAPTER_SERVICE_NAME + methodName;
1386 StringBuilder sbInit = new StringBuilder();
1387 sbInit.append("updateVfModule: \n");
1388 sbInit.append("cloudOwner=" + cloudOwner + "\n");
1389 sbInit.append("cloudSiteId=" + cloudSiteId + "\n");
1390 sbInit.append("tenantId=" + tenantId + "\n");
1391 sbInit.append("vnfType=" + vnfType + "\n");
1392 sbInit.append("vnfVersion=" + vnfVersion + "\n");
1393 sbInit.append("vnfName=" + vnfName + "\n");
1394 sbInit.append("requestType=" + requestType + "\n");
1395 sbInit.append("volumeGroupHeatStackId=" + volumeGroupHeatStackId + "\n");
1396 sbInit.append("baseVfHeatStackId=" + baseVfHeatStackId + "\n");
1397 sbInit.append("vfModuleStackId=" + vfModuleStackId + "\n");
1398 sbInit.append("modelCustomizationUuid=" + modelCustomizationUuid + "\n");
1399 logger.debug(sbInit.toString());
1401 String mcu = modelCustomizationUuid;
1402 boolean useMCUuid = false;
1403 if (mcu != null && !mcu.isEmpty()) {
1404 if ("null".equalsIgnoreCase(mcu)) {
1405 logger.debug("modelCustomizationUuid: passed in as the string 'null' - will ignore: {}",
1406 modelCustomizationUuid);
1410 logger.debug("Found modelCustomizationUuid! Will use that: {}", mcu);
1415 String requestTypeString = "";
1416 if (requestType != null && !"".equals(requestType)) {
1417 requestTypeString = requestType;
1420 String nestedStackId = null;
1421 if (volumeGroupHeatStackId != null && !"".equals(volumeGroupHeatStackId) && !"null".equalsIgnoreCase(volumeGroupHeatStackId)) {
1422 nestedStackId = volumeGroupHeatStackId;
1424 String nestedBaseStackId = null;
1425 if (baseVfHeatStackId != null && !"".equals(baseVfHeatStackId) && !"null".equalsIgnoreCase(baseVfHeatStackId)) {
1426 nestedBaseStackId = baseVfHeatStackId;
1429 if (inputs == null) {
1430 // Create an empty set of inputs
1431 inputs = new HashMap<>();
1432 logger.debug("inputs == null - setting to empty");
1435 boolean isBaseRequest = false;
1436 boolean isVolumeRequest = false;
1437 if (requestTypeString.startsWith("VOLUME")) {
1438 isVolumeRequest = true;
1440 if ((vfModuleName == null || "".equals(vfModuleName.trim())) && vfModuleStackId != null) {
1441 vfModuleName = this.getVfModuleNameFromModuleStackId(vfModuleStackId);
1444 logger.debug ("Updating VFModule: " + vfModuleName + " of type " + vfModuleType + "in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId);
1445 logger.debug("requestTypeString = " + requestTypeString + ", nestedVolumeStackId = " + nestedStackId + ", nestedBaseStackId = " + nestedBaseStackId);
1447 // Will capture execution time for metrics
1448 long startTime = System.currentTimeMillis ();
1450 // Build a default rollback object (no actions performed)
1451 VnfRollback vfRollback = new VnfRollback ();
1452 vfRollback.setCloudSiteId (cloudSiteId);
1453 vfRollback.setCloudOwner (cloudOwner);
1454 vfRollback.setTenantId (tenantId);
1455 vfRollback.setMsoRequest (msoRequest);
1456 vfRollback.setRequestType(requestTypeString);
1457 vfRollback.setVolumeGroupHeatStackId(volumeGroupHeatStackId);
1458 vfRollback.setBaseGroupHeatStackId(baseVfHeatStackId);
1459 vfRollback.setIsBase(isBaseRequest);
1460 vfRollback.setVfModuleStackId(vfModuleStackId);
1461 vfRollback.setModelCustomizationUuid(mcu);
1463 StackInfo heatStack = null;
1464 long queryStackStarttime = System.currentTimeMillis ();
1465 logger.debug("UpdateVfModule - querying for {}", vfModuleName);
1467 heatStack = heat.queryStack (cloudSiteId, cloudOwner, tenantId, vfModuleName);
1468 } catch (MsoException me) {
1469 // Failed to query the Stack due to an openstack exception.
1470 // Convert to a generic VnfException
1471 me.addContext ("UpdateVFModule");
1472 String error = "Update VFModule: Query " + vfModuleName + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + ": " + me;
1473 logger.error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vfModuleName, cloudOwner, cloudSiteId,
1474 tenantId, "OpenStack", "QueryStack", ErrorCode.DataError.getValue(), "Exception - QueryStack",
1476 logger.debug(error);
1477 throw new VnfException (me);
1480 //TODO - do we need to check for the other status possibilities?
1481 if (heatStack == null || heatStack.getStatus () == HeatStatus.NOTFOUND) {
1483 String error = "Update VF: Stack " + vfModuleName + " does not exist in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId;
1484 logger.error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_VNF_NOT_EXIST.toString(), vfModuleName, cloudOwner, cloudSiteId,
1485 tenantId, "OpenStack", "QueryStack", ErrorCode.DataError.getValue(), error);
1486 throw new VnfNotFound (cloudSiteId, cloudOwner, tenantId, vfModuleName);
1488 logger.debug("Found Existing stack, status={}", heatStack.getStatus());
1489 // Populate the outputs from the existing stack.
1490 outputs.value = copyStringOutputs (heatStack.getOutputs ());
1491 rollback.value = vfRollback; // Default rollback - no updates performed
1494 // 1604 Cinder Volume support - handle a nestedStackId if sent (volumeGroupHeatStackId):
1495 StackInfo nestedHeatStack = null;
1496 long queryStackStarttime2 = System.currentTimeMillis ();
1497 Map<String, Object> nestedVolumeOutputs = null;
1498 if (nestedStackId != null) {
1500 logger.debug("Querying for nestedStackId = {}", nestedStackId);
1501 nestedHeatStack = heat.queryStack(cloudSiteId, cloudOwner, tenantId, nestedStackId);
1502 } catch (MsoException me) {
1503 // Failed to query the Stack due to an openstack exception.
1504 // Convert to a generic VnfException
1505 me.addContext ("UpdateVFModule");
1506 String error = "Update VF: Attached heatStack ID Query " + nestedStackId + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + ": " + me ;
1507 logger.error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vnfName, cloudOwner, cloudSiteId,
1508 tenantId, "OpenStack", "QueryStack", ErrorCode.DataError.getValue(), "Exception - " + error,
1510 logger.debug("ERROR trying to query nested stack= {}", error);
1511 throw new VnfException (me);
1513 if (nestedHeatStack == null || nestedHeatStack.getStatus() == HeatStatus.NOTFOUND) {
1514 String error = "Update VFModule: Attached volume heatStack ID DOES NOT EXIST " + nestedStackId + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + " USER ERROR" ;
1515 logger.error("{} {} {} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vnfName, cloudOwner, cloudSiteId,
1516 tenantId, error, "OpenStack", "QueryStack", ErrorCode.DataError.getValue(), error);
1517 logger.debug(error);
1518 throw new VnfException (error, MsoExceptionCategory.USERDATA);
1520 logger.debug("Found nested heat stack - copying values to inputs *later*");
1521 nestedVolumeOutputs = nestedHeatStack.getOutputs();
1522 heat.copyStringOutputsToInputs(inputs, nestedHeatStack.getOutputs(), false);
1525 // handle a nestedBaseStackId if sent - this is the stack ID of the base.
1526 StackInfo nestedBaseHeatStack = null;
1527 Map<String, Object> baseStackOutputs = null;
1528 if (nestedBaseStackId != null) {
1529 long queryStackStarttime3 = System.currentTimeMillis ();
1531 logger.debug("Querying for nestedBaseStackId = {}", nestedBaseStackId);
1532 nestedBaseHeatStack = heat.queryStack(cloudSiteId, cloudOwner, tenantId, nestedBaseStackId);
1533 } catch (MsoException me) {
1534 // Failed to query the Stack due to an openstack exception.
1535 // Convert to a generic VnfException
1536 me.addContext ("UpdateVfModule");
1537 String error = "Update VFModule: Attached baseHeatStack ID Query " + nestedBaseStackId + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + ": " + me ;
1539 .error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vfModuleName, cloudOwner, cloudSiteId,
1540 tenantId, "OpenStack", "QueryStack", ErrorCode.DataError.getValue(),
1541 "Exception - " + error, me);
1542 logger.debug("ERROR trying to query nested base stack= {}", error);
1543 throw new VnfException (me);
1545 if (nestedBaseHeatStack == null || nestedBaseHeatStack.getStatus() == HeatStatus.NOTFOUND) {
1546 String error = "Update VFModule: Attached base heatStack ID DOES NOT EXIST " + nestedBaseStackId + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + " USER ERROR" ;
1547 logger.error ("{} {} {} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vfModuleName,
1548 cloudOwner, cloudSiteId, tenantId, error, "OpenStack",
1549 "QueryStack", ErrorCode.DataError.getValue(), error);
1550 logger.debug(error);
1551 throw new VnfException (error, MsoExceptionCategory.USERDATA);
1553 logger.debug("Found nested base heat stack - copying values to inputs *later*");
1554 baseStackOutputs = nestedBaseHeatStack.getOutputs();
1555 heat.copyStringOutputsToInputs(inputs, nestedBaseHeatStack.getOutputs(), false);
1559 // Ready to deploy the new VNF
1563 // Retrieve the VF definition
1564 VnfResource vnfResource = null;
1566 VfModuleCustomization vfmc = null;
1568 vfmc = vfModuleCustomRepo.findByModelCustomizationUUID(modelCustomizationUuid);
1569 vf = vfmc != null ? vfmc.getVfModule() : null;
1571 logger.debug("Unable to find a vfModule matching modelCustomizationUuid={}", mcu);
1574 logger.debug("1707 and later - MUST PROVIDE Model Customization UUID!");
1577 String error = "Update VfModule: unable to find vfModule with modelCustomizationUuid=" + mcu;
1578 logger.error("{} {} {} {} {} {}", MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "VF Module Type",
1579 vfModuleType, "OpenStack", ErrorCode.DataError.getValue(), error);
1580 throw new VnfException(error, MsoExceptionCategory.USERDATA);
1582 logger.debug("Got VF module definition from Catalog: {}", vf.toString());
1583 if (vf.getIsBase()) {
1584 isBaseRequest = true;
1585 logger.debug("This a BASE update request");
1587 logger.debug("This is *not* a BASE VF update request");
1588 if (!isVolumeRequest && nestedBaseStackId == null) {
1589 logger.debug("DANGER WILL ROBINSON! This is unexpected - no nestedBaseStackId with this non-base request");
1593 //1607 - Add version check
1594 // First - see if it's in the VnfResource record
1595 // if we have a vf Module - then we have to query to get the VnfResource record.
1596 if (vf.getModelUUID() != null) {
1597 String vnfResourceModelUuid = vf.getModelUUID();
1599 vnfResource = vf.getVnfResources();
1600 if (vnfResource == null) {
1601 logger.debug("Unable to find vnfResource at ? will not error for now...", vnfResourceModelUuid);
1605 String minVersionVnf = null;
1606 String maxVersionVnf = null;
1607 if (vnfResource != null) {
1609 minVersionVnf = vnfResource.getAicVersionMin();
1610 maxVersionVnf = vnfResource.getAicVersionMax();
1611 } catch (Exception e) {
1612 logger.debug("Unable to pull min/max version for this VNF Resource entry",e);
1613 minVersionVnf = null;
1614 maxVersionVnf = null;
1616 if (minVersionVnf != null && "".equals(minVersionVnf)) {
1617 minVersionVnf = null;
1619 if (maxVersionVnf != null && "".equals(maxVersionVnf)) {
1620 maxVersionVnf = null;
1623 if (minVersionVnf != null && maxVersionVnf != null) {
1624 MavenLikeVersioning aicV = new MavenLikeVersioning();
1627 if (this.cloudConfig != null) {
1628 Optional<CloudSite> cloudSiteOpt = this.cloudConfig.getCloudSite(cloudSiteId);
1629 if (cloudSiteOpt.isPresent()) {
1630 aicV.setVersion(cloudSiteOpt.get().getCloudVersion());
1631 boolean moreThanMin = true;
1632 boolean equalToMin = true;
1633 boolean moreThanMax = true;
1634 boolean equalToMax = true;
1635 boolean doNotTest = false;
1637 moreThanMin = aicV.isMoreRecentThan(minVersionVnf);
1638 equalToMin = aicV.isTheSameVersion(minVersionVnf);
1639 moreThanMax = aicV.isMoreRecentThan(maxVersionVnf);
1640 equalToMax = aicV.isTheSameVersion(maxVersionVnf);
1641 } catch (Exception e) {
1642 logger.debug("An exception occured while trying to test AIC Version {} - will default to not check",
1647 if ((moreThanMin || equalToMin) // aic >= min
1648 && ((equalToMax) || !(moreThanMax))) { // aic <= max
1650 "VNF Resource " + vnfResource.getModelName() + " VersionMin=" + minVersionVnf + " VersionMax:"
1651 + maxVersionVnf + " supported on Cloud: " + cloudSiteId + " with AIC_Version:" + aicV);
1654 String error = "VNF Resource type: " + vnfResource.getModelName() + " VersionMin="
1655 + minVersionVnf + " VersionMax:" + maxVersionVnf + " NOT supported on Cloud: "
1656 + cloudSiteId + " with AIC_Version:" + aicV;
1657 logger.error("{} {} {} {} {}", MessageEnum.RA_CONFIG_EXC.toString(), error, "OpenStack",
1658 ErrorCode.BusinessProcesssError.getValue(), "Exception - setVersion");
1659 logger.debug(error);
1660 throw new VnfException(error, MsoExceptionCategory.USERDATA);
1663 logger.debug("bypassing testing AIC version...");
1665 } // let this error out downstream to avoid introducing uncertainty at this stage
1667 logger.debug("cloudConfig is NULL - cannot check cloud site version");
1671 logger.debug("AIC Version not set in VNF_Resource - do not error for now - not checked.");
1673 // End Version check 1607
1675 HeatTemplate heatTemplate = null;
1676 HeatEnvironment heatEnvironment = null;
1677 if (isVolumeRequest) {
1678 heatTemplate = vf.getVolumeHeatTemplate();
1679 heatEnvironment = vfmc.getVolumeHeatEnv();
1681 heatTemplate = vf.getModuleHeatTemplate();
1682 heatEnvironment = vfmc.getHeatEnvironment();
1685 if (heatTemplate == null) {
1686 String error = "UpdateVF: No Heat Template ID defined in catalog database for " + vfModuleType + ", reqType=" + requestTypeString;
1688 .error("{} {} {} {} {} {}", MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "Heat Template ID", vfModuleType,
1689 "OpenStack", ErrorCode.DataError.getValue(), error);
1690 throw new VnfException(error, MsoExceptionCategory.INTERNAL);
1692 logger.debug("Got HEAT Template from DB: {}", heatTemplate.getHeatTemplate());
1695 if (heatEnvironment == null) {
1696 String error = "Update VNF: undefined Heat Environment. VF=" + vfModuleType;
1697 logger.error("{} {} {} {} {}", MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "Heat Environment ID",
1698 "OpenStack", ErrorCode.DataError.getValue(), error);
1699 throw new VnfException (error, MsoExceptionCategory.INTERNAL);
1701 logger.debug ("Got Heat Environment from DB: {}", heatEnvironment.getEnvironment());
1704 logger.debug("In MsoVnfAdapterImpl, about to call db.getNestedTemplates avec templateId={}",
1705 heatTemplate.getArtifactUuid());
1708 List<HeatTemplate> nestedTemplates = heatTemplate.getChildTemplates();
1709 Map <String, Object> nestedTemplatesChecked = new HashMap <> ();
1710 if (nestedTemplates != null && !nestedTemplates.isEmpty()) {
1711 // for debugging print them out
1712 logger.debug("Contents of nestedTemplates - to be added to files: on stack:");
1713 for (HeatTemplate entry : nestedTemplates) {
1715 nestedTemplatesChecked.put (entry.getTemplateName(), entry.getTemplateBody());
1716 logger.debug(entry.getTemplateName() + " -> " + entry.getTemplateBody());
1719 logger.debug("No nested templates found - nothing to do here");
1720 nestedTemplatesChecked = null;
1723 // Also add the files: for any get_files associated with this VfModule
1724 // *if* there are any
1725 logger.debug("In MsoVnfAdapterImpl.updateVfModule, about to call db.getHeatFiles avec vfModuleId={}",
1728 List<HeatFiles> heatFiles = null;
1729 Map <String, Object> heatFilesObjects = new HashMap <> ();
1731 // Add ability to turn on adding get_files with volume requests (by property).
1732 boolean addGetFilesOnVolumeReq = false;
1734 String propertyString = this.environment.getProperty(MsoVnfAdapterImpl.ADD_GET_FILES_ON_VOLUME_REQ);
1735 if ("true".equalsIgnoreCase(propertyString) || "y".equalsIgnoreCase(propertyString)) {
1736 addGetFilesOnVolumeReq = true;
1737 logger.debug("AddGetFilesOnVolumeReq - setting to true! {}", propertyString);
1739 } catch (Exception e) {
1740 logger.debug("An error occured trying to get property {} - default to false",
1741 MsoVnfAdapterImpl.ADD_GET_FILES_ON_VOLUME_REQ, e);
1743 if (!isVolumeRequest || addGetFilesOnVolumeReq) {
1744 logger.debug("In MsoVnfAdapterImpl updateVfModule, about to call db.getHeatFilesForVfModule avec "
1745 + "vfModuleId={}", vf.getModelUUID());
1747 heatFiles = vf.getHeatFiles();
1748 if (heatFiles != null && !heatFiles.isEmpty()) {
1749 // add these to stack - to be done in createStack
1750 // here, we will map them to Map<String, Object> from Map<String, HeatFiles>
1751 // this will match the nested templates format
1752 logger.debug("Contents of heatFiles - to be added to files: on stack:");
1753 for (HeatFiles heatfile : heatFiles) {
1754 logger.debug(heatfile.getFileName() + " -> " + heatfile.getFileBody());
1755 heatFilesObjects.put(heatfile.getFileName(), heatfile.getFileBody());
1758 logger.debug("No heat files found -nothing to do here");
1759 heatFilesObjects = null;
1763 // Check that required parameters have been supplied
1764 String missingParams = null;
1765 List <String> paramList = new ArrayList <> ();
1767 // New for 1510 - consult the PARAM_ALIAS field to see if we've been
1768 // supplied an alias. Only check if we don't find it initially.
1769 // Also new in 1510 - don't flag missing parameters if there's an environment - because they might be there.
1770 // And also new - add parameter to turn off checking all together if we find we're blocking orders we
1772 boolean checkRequiredParameters = true;
1774 String propertyString = this.environment.getProperty (MsoVnfAdapterImpl.CHECK_REQD_PARAMS);
1775 if ("false".equalsIgnoreCase (propertyString) || "n".equalsIgnoreCase (propertyString)) {
1776 checkRequiredParameters = false;
1777 logger.debug("CheckRequiredParameters is FALSE. Will still check but then skip blocking...",
1778 MsoVnfAdapterImpl.CHECK_REQD_PARAMS);
1780 } catch (Exception e) {
1781 // No problem - default is true
1782 logger.debug ("An exception occured trying to get property {}", MsoVnfAdapterImpl.CHECK_REQD_PARAMS,
1785 // 1604 - Add enhanced environment & parameter checking
1786 // Part 1: parse envt entries to see if reqd parameter is there (before used a simple grep
1787 // Part 2: only submit to openstack the parameters in the envt that are in the heat template
1788 // Note this also removes any comments
1789 MsoHeatEnvironmentEntry mhee = null;
1790 if (heatEnvironment != null && heatEnvironment.getEnvironment().toLowerCase ().contains ("parameters:")) {
1791 logger.debug("Enhanced environment checking enabled - 1604");
1792 StringBuilder sb = new StringBuilder(heatEnvironment.getEnvironment());
1793 mhee = new MsoHeatEnvironmentEntry(sb);
1794 StringBuilder sb2 = new StringBuilder("\nHeat Template Parameters:\n");
1795 for (HeatTemplateParam parm : heatTemplate.getParameters()) {
1796 sb2.append("\t" + parm.getParamName() + ", required=" + parm.isRequired());
1798 if (!mhee.isValid()) {
1799 sb2.append("Environment says it's not valid! " + mhee.getErrorString());
1801 sb2.append("\nEnvironment:");
1802 sb2.append(mhee.toFullString());
1804 logger.debug(sb2.toString());
1806 logger.debug("NO ENVIRONMENT for this entry");
1808 // New for 1607 - support params of json type
1809 HashMap<String, JsonNode> jsonParams = new HashMap<>();
1810 boolean hasJson = false;
1812 for (HeatTemplateParam parm : heatTemplate.getParameters ()) {
1813 logger.debug ("Parameter:'" + parm.getParamName ()
1815 + parm.isRequired ()
1817 + parm.getParamAlias ());
1819 String parameterType = parm.getParamType();
1820 if (parameterType == null || "".equals(parameterType.trim())) {
1821 parameterType = "String";
1823 JsonNode jsonNode = null;
1824 if ("json".equalsIgnoreCase(parameterType) && inputs != null) {
1825 if (inputs.containsKey(parm.getParamName()) ) {
1827 String jsonString = null;
1829 jsonString = JSON_MAPPER.writeValueAsString(inputs.get(parm.getParamName()));
1830 jsonNode = JSON_MAPPER.readTree(jsonString);
1831 } catch (JsonParseException jpe) {
1832 //TODO - what to do here?
1833 //for now - send the error to debug, but just leave it as a String
1834 String errorMessage = jpe.getMessage();
1835 logger.debug("Json Error Converting " + parm.getParamName() + " - " + errorMessage,jpe);
1838 } catch (Exception e) {
1840 logger.debug("Json Error Converting " + parm.getParamName() + " " + e.getMessage(), e);
1844 if (jsonNode != null) {
1845 jsonParams.put(parm.getParamName(), jsonNode);
1847 } else if (inputs.containsKey(parm.getParamAlias())) {
1849 String jsonString = null;
1851 jsonString = (String)inputs.get(parm.getParamAlias());
1852 jsonNode = JSON_MAPPER.readTree(jsonString);
1853 } catch (JsonParseException jpe) {
1854 //TODO - what to do here?
1855 //for now - send the error to debug, but just leave it as a String
1856 String errorMessage = jpe.getMessage();
1857 logger.debug("Json Error Converting " + parm.getParamName() + " - " + errorMessage,jpe);
1860 } catch (Exception e) {
1862 logger.debug("Json Error Converting " + parm.getParamName() + " " + e.getMessage(), e);
1866 if (jsonNode != null) {
1867 // Notice here - we add it to the jsonParams hashMap with the actual name -
1868 // then manipulate the inputs so when we check for aliases below - it will not
1870 jsonParams.put(parm.getParamName(), jsonNode);
1871 inputs.remove(parm.getParamAlias());
1872 inputs.put(parm.getParamName(), jsonString);
1874 } //TODO add a check for the parameter in the env file
1877 if (parm.isRequired () && (inputs == null || !inputs.containsKey (parm.getParamName ()))) {
1878 if (inputs.containsKey (parm.getParamAlias ())) {
1879 // They've submitted using an alias name. Remove that from inputs, and add back using real name.
1880 String realParamName = parm.getParamName ();
1881 String alias = parm.getParamAlias ();
1882 Object value = inputs.get (alias);
1883 logger.debug ("*Found an Alias: paramName=" + realParamName
1888 inputs.remove (alias);
1889 inputs.put (realParamName, value);
1890 logger.debug ("{} entry removed from inputs, added back using {}", alias, realParamName);
1892 // enhanced - check if it's in the Environment (note: that method
1893 else if (mhee != null && mhee.containsParameter(parm.getParamName())) {
1895 logger.debug("Required parameter {} appears to be in environment - do not count as missing",
1896 parm.getParamName());
1899 logger.debug("adding to missing parameters list: {}", parm.getParamName());
1900 if (missingParams == null) {
1901 missingParams = parm.getParamName ();
1903 missingParams += "," + parm.getParamName ();
1907 paramList.add (parm.getParamName ());
1911 if (missingParams != null) {
1912 // Problem - missing one or more required parameters
1913 if (checkRequiredParameters) {
1914 String error = "Update VNF: Missing Required inputs: " + missingParams;
1915 logger.error("{} {} {} {} {}", MessageEnum.RA_MISSING_PARAM.toString(), missingParams, "OpenStack",
1916 ErrorCode.DataError.getValue(), error);
1917 throw new VnfException (error, MsoExceptionCategory.USERDATA);
1919 logger.debug("found missing parameters - but checkRequiredParameters is false - will not block");
1922 logger.debug("No missing parameters found - ok to proceed");
1925 // Just submit the envt entry as received from the database
1926 String newEnvironmentString = null;
1928 newEnvironmentString = mhee.getRawEntry().toString();
1930 // Remove any extraneous parameters (don't throw an error)
1931 if (inputs != null) {
1932 List <String> extraParams = new ArrayList <> ();
1933 extraParams.addAll (inputs.keySet ());
1934 // This is not a valid parameter for this template
1935 extraParams.removeAll (paramList);
1936 if (!extraParams.isEmpty ()) {
1937 logger.warn("{} {} {} {} {} {}", MessageEnum.RA_VNF_EXTRA_PARAM.toString(), vnfType,
1938 extraParams.toString(), "OpenStack", ErrorCode.DataError.getValue(), "Extra params");
1939 inputs.keySet ().removeAll (extraParams);
1942 Map<String, Object> goldenInputs = copyStringInputs(inputs);
1943 // 1607 - when we get here - we have clean inputs. Create inputsTwo in case we have json
1944 Map<String, Object> inputsTwo = null;
1945 if (hasJson && jsonParams.size() > 0) {
1946 inputsTwo = new HashMap<>();
1947 for (Map.Entry<String, Object> entry : inputs.entrySet()) {
1948 String keyParamName = entry.getKey();
1949 Object value = entry.getValue();
1950 if (jsonParams.containsKey(keyParamName)) {
1951 inputsTwo.put(keyParamName, jsonParams.get(keyParamName));
1953 inputsTwo.put(keyParamName, value);
1956 goldenInputs = inputsTwo;
1959 // "Fix" the template if it has CR/LF (getting this from Oracle)
1960 String template = heatTemplate.getHeatTemplate ();
1961 template = template.replaceAll ("\r\n", "\n");
1963 boolean isValetEnabled = this.checkBooleanProperty(MsoVnfAdapterImpl.VALET_ENABLED, false);
1964 boolean failRequestOnValetFailure = this.checkBooleanProperty(MsoVnfAdapterImpl.FAIL_REQUESTS_ON_VALET_FAILURE, false);
1965 logger.debug("isValetEnabled={}, failRequestsOnValetFailure={}", isValetEnabled, failRequestOnValetFailure);
1966 if (isVolumeRequest) {
1967 isValetEnabled = false;
1968 logger.debug("never send a volume request to valet");
1970 boolean sendResponseToValet = false;
1971 if (isValetEnabled) {
1972 Holder<Map<String, Object>> valetModifiedParamsHolder = new Holder<>();
1973 String parsedVfModuleName = this.getVfModuleNameFromModuleStackId(vfModuleStackId);
1974 // Make sure it is set to something.
1975 if (parsedVfModuleName == null || parsedVfModuleName.isEmpty()) {
1976 parsedVfModuleName = "unknown";
1978 sendResponseToValet = this.valetUpdateRequest(cloudSiteId, cloudOwner, tenantId, heatFilesObjects,
1979 nestedTemplatesChecked, parsedVfModuleName, false, heatTemplate, newEnvironmentString, (HashMap<String, Object>) goldenInputs,
1980 msoRequest, inputs, failRequestOnValetFailure, valetModifiedParamsHolder);
1981 if (sendResponseToValet) {
1982 goldenInputs = valetModifiedParamsHolder.value;
1986 // Have the tenant. Now deploy the stack itself
1987 // Ignore MsoTenantNotFound and MsoStackAlreadyExists exceptions
1988 // because we already checked for those.
1989 long updateStackStarttime = System.currentTimeMillis ();
1991 heatStack = heatU.updateStack(
1999 heatTemplate.getTimeoutMinutes(),
2000 newEnvironmentString,
2001 //heatEnvironmentString,
2002 nestedTemplatesChecked,
2005 } catch (MsoException me) {
2006 me.addContext ("UpdateVFModule");
2007 String error = "Update VFModule " + vfModuleType + " in " + cloudOwner + "/" + cloudSiteId + "/" + tenantId + ": " + me;
2009 .error("{} {} {} {} {} {} {} {}", MessageEnum.RA_UPDATE_VNF_ERR.toString(), vfModuleType, cloudOwner, cloudSiteId,
2010 tenantId, "OpenStack", ErrorCode.DataError.getValue(), "Exception - " + error, me);
2011 if (isValetEnabled && sendResponseToValet) {
2012 logger.debug("valet is enabled, the orchestration failed - now sending rollback to valet");
2014 GenericValetResponse<ValetRollbackResponse> gvr = this.vci.callValetRollbackRequest(msoRequest.getRequestId(), null, false, me.getMessage());
2015 // Nothing to really do here whether it succeeded or not other than log it.
2016 logger.debug("Return code from Rollback response is {}", gvr.getStatusCode());
2017 } catch (Exception e) {
2018 logger.error("Exception encountered while sending Rollback to Valet ", e);
2021 throw new VnfException (me);
2025 // Reach this point if updateStack is successful.
2026 // Populate remaining rollback info and response parameters.
2027 vfRollback.setVnfId (heatStack.getCanonicalName ());
2028 vfRollback.setVnfCreated (true);
2030 if (isValetEnabled && sendResponseToValet) {
2031 logger.debug("valet is enabled, the update succeeded - now send confirm to valet with stack id");
2033 GenericValetResponse<ValetConfirmResponse> gvr = this.vci.callValetConfirmRequest(msoRequest.getRequestId(), heatStack.getCanonicalName());
2034 // Nothing to really do here whether it succeeded or not other than log it.
2035 logger.debug("Return code from Confirm response is {}", gvr.getStatusCode());
2036 } catch (Exception e) {
2037 logger.error("Exception encountered while sending Confirm to Valet ", e);
2041 outputs.value = copyStringOutputs (heatStack.getOutputs ());
2042 rollback.value = vfRollback;
2046 private String getVfModuleNameFromModuleStackId(String vfModuleStackId) {
2047 // expected format of vfModuleStackId is "MSOTEST51-vSAMP3_base_module-0/1fc1f86c-7b35-447f-99a6-c23ec176ae24"
2048 // before the "/" is the vfModuleName and after the "/" is the heat stack id in Openstack
2049 if (vfModuleStackId == null)
2051 int index = vfModuleStackId.lastIndexOf('/');
2054 String vfModuleName = null;
2056 vfModuleName = vfModuleStackId.substring(0, index);
2057 } catch (Exception e) {
2058 logger.debug("Exception", e);
2059 vfModuleName = null;
2061 return vfModuleName;
2065 * Helper method to check a boolean property value - on error return provided default
2067 private boolean checkBooleanProperty(String propertyName, boolean defaultValue) {
2068 boolean property = defaultValue;
2070 String propertyString = this.environment.getProperty(propertyName);
2071 if ("true".equalsIgnoreCase(propertyString) || "y".equalsIgnoreCase(propertyString)) {
2073 } else if ("false".equalsIgnoreCase(propertyString) || "n".equalsIgnoreCase(propertyString)) {
2076 } catch (Exception e) {
2077 logger.debug("An exception occured trying to get property {} - defaulting to ", propertyName, defaultValue, e);
2078 property = defaultValue;
2084 * Helper method to combine getFiles and nestedTemplates in to a single Map
2086 private Map<String, Object> combineGetFilesAndNestedTemplates(Map<String, Object> getFiles, Map<String, Object> nestedTemplates) {
2087 boolean haveGetFiles = true;
2088 boolean haveNestedTemplates = true;
2089 Map<String, Object> files = new HashMap<String, Object>();
2090 if (getFiles == null || getFiles.isEmpty()) {
2091 haveGetFiles = false;
2093 if (nestedTemplates == null || nestedTemplates.isEmpty()) {
2094 haveNestedTemplates = false;
2096 if (haveGetFiles && haveNestedTemplates) {
2097 for (String keyString : getFiles.keySet ()) {
2098 files.put (keyString, getFiles.get (keyString));
2100 for (String keyString : nestedTemplates.keySet ()) {
2101 files.put (keyString, nestedTemplates.get (keyString));
2104 // Handle if we only have one or neither:
2108 if (haveNestedTemplates) {
2109 files = nestedTemplates;
2116 * Valet Create request
2118 private boolean valetCreateRequest(String cloudSiteId, String cloudOwner, String tenantId, Map<String, Object> heatFilesObjects, Map<String, Object> nestedTemplatesChecked,
2119 String vfModuleName, boolean backout, HeatTemplate heatTemplate, String newEnvironmentString, Map<String, Object> goldenInputs,
2120 MsoRequest msoRequest, Map<String, Object> inputs, boolean failRequestOnValetFailure, Holder<Map<String, Object>> valetModifiedParamsHolder) throws VnfException {
2121 boolean valetSucceeded = false;
2122 String valetErrorMessage = "more detail not available";
2124 String keystoneUrl = heat.getCloudSiteKeystoneUrl(cloudSiteId);
2125 Map<String, Object> files = this.combineGetFilesAndNestedTemplates(heatFilesObjects,
2126 nestedTemplatesChecked);
2127 HeatRequest heatRequest = new HeatRequest(vfModuleName, backout, heatTemplate.getTimeoutMinutes(),
2128 heatTemplate.getTemplateBody(), newEnvironmentString, files, goldenInputs);
2129 GenericValetResponse<ValetCreateResponse> createReq = this.vci.callValetCreateRequest(msoRequest.getRequestId(),
2130 cloudSiteId, cloudOwner, tenantId, msoRequest.getServiceInstanceId(), (String)inputs.get("vnf_id"),
2131 (String)inputs.get("vnf_name"), (String)inputs.get("vf_module_id"), (String)inputs.get("vf_module_name"), keystoneUrl,
2133 ValetCreateResponse vcr = createReq.getReturnObject();
2134 if (vcr != null && createReq.getStatusCode() == 200) {
2135 ValetStatus status = vcr.getStatus();
2136 if (status != null) {
2137 String statusCode = status.getStatus(); // "ok" or "failed"
2138 if ("ok".equalsIgnoreCase(statusCode)) {
2139 Map<String, Object> newInputs = vcr.getParameters();
2140 if (newInputs != null) {
2141 Map<String, Object> oldGold = goldenInputs;
2142 logger.debug("parameters before being modified by valet:{}", oldGold.toString());
2143 goldenInputs = new HashMap<String, Object>();
2144 for (String key : newInputs.keySet()) {
2145 goldenInputs.put(key, newInputs.get(key));
2147 valetModifiedParamsHolder.value = goldenInputs;
2148 logger.debug("parameters after being modified by valet:{}", goldenInputs.toString());
2149 valetSucceeded = true;
2152 valetErrorMessage = status.getMessage();
2156 logger.debug("Got a bad response back from valet");
2157 valetErrorMessage = "Bad response back from Valet";
2158 valetSucceeded = false;
2160 } catch (Exception e) {
2161 logger.error("An exception occurred trying to call valet ...", e);
2162 valetSucceeded = false;
2163 valetErrorMessage = e.getMessage();
2165 if (failRequestOnValetFailure && !valetSucceeded) {
2166 // The valet request failed - and property says to fail the request
2167 //TODO Create a new exception class for valet?
2168 throw new VnfException("A failure occurred with Valet: " + valetErrorMessage);
2170 return valetSucceeded;
2174 * Valet update request
2177 private boolean valetUpdateRequest(String cloudSiteId, String cloudOwnerId, String tenantId,
2178 Map<String, Object> heatFilesObjects, Map<String, Object> nestedTemplatesChecked, String vfModuleName,
2179 boolean backout, HeatTemplate heatTemplate, String newEnvironmentString,
2180 Map<String, Object> goldenInputs, MsoRequest msoRequest, Map<String, Object> inputs,
2181 boolean failRequestOnValetFailure, Holder<Map<String, Object>> valetModifiedParamsHolder) throws VnfException {
2183 boolean valetSucceeded = false;
2184 String valetErrorMessage = "more detail not available";
2186 String keystoneUrl = heat.getCloudSiteKeystoneUrl(cloudSiteId);
2187 Map<String, Object> files = this.combineGetFilesAndNestedTemplates(heatFilesObjects,
2188 nestedTemplatesChecked);
2189 HeatRequest heatRequest = new HeatRequest(vfModuleName, false, heatTemplate.getTimeoutMinutes(),
2190 heatTemplate.getTemplateBody(), newEnvironmentString, files, goldenInputs);
2191 // vnf name is not sent to MSO on update requests - so we will set it to the vf module name for now
2192 GenericValetResponse<ValetUpdateResponse> updateReq = this.vci.callValetUpdateRequest(msoRequest.getRequestId(),
2193 cloudSiteId, cloudOwnerId, tenantId, msoRequest.getServiceInstanceId(), (String)inputs.get("vnf_id"),
2194 vfModuleName, (String)inputs.get("vf_module_id"), vfModuleName, keystoneUrl,
2196 ValetUpdateResponse vur = updateReq.getReturnObject();
2197 if (vur != null && updateReq.getStatusCode() == 200) {
2198 ValetStatus status = vur.getStatus();
2199 if (status != null) {
2200 String statusCode = status.getStatus(); // "ok" or "failed"
2201 if ("ok".equalsIgnoreCase(statusCode)) {
2202 Map<String, Object> newInputs = vur.getParameters();
2203 if (newInputs != null) {
2204 Map<String, Object> oldGold = goldenInputs;
2205 logger.debug("parameters before being modified by valet:{}", oldGold.toString());
2206 goldenInputs = new HashMap<String, Object>();
2207 for (String key : newInputs.keySet()) {
2208 goldenInputs.put(key, newInputs.get(key));
2210 valetModifiedParamsHolder.value = goldenInputs;
2211 logger.debug("parameters after being modified by valet:{}", goldenInputs.toString());
2212 valetSucceeded = true;
2215 valetErrorMessage = status.getMessage();
2219 logger.debug("Got a bad response back from valet");
2220 valetErrorMessage = "Got a bad response back from valet";
2221 valetSucceeded = false;
2223 } catch (Exception e) {
2224 logger.error("An exception occurred trying to call valet - will continue processing for now...", e);
2225 valetErrorMessage = e.getMessage();
2226 valetSucceeded = false;
2228 if (failRequestOnValetFailure && !valetSucceeded) {
2229 // The valet request failed - and property says to fail the request
2230 // TODO Create a new exception class for valet?
2231 throw new VnfException("A failure occurred with Valet: " + valetErrorMessage);
2233 return valetSucceeded;
2237 * Valet delete request
2239 private boolean valetDeleteRequest(String cloudSiteId, String cloudOwnerId, String tenantId, String vnfName,
2240 MsoRequest msoRequest, boolean failRequestOnValetFailure) {
2241 boolean valetDeleteRequestSucceeded = false;
2242 String valetErrorMessage = "more detail not available";
2244 String vfModuleId = vnfName;
2245 String vfModuleName = vnfName;
2247 vfModuleName = vnfName.substring(0, vnfName.indexOf('/'));
2248 vfModuleId = vnfName.substring(vnfName.indexOf('/') + 1);
2249 } catch (Exception e) {
2250 // do nothing - send what we got for vnfName for both to valet
2251 logger.error("An exception occurred trying to call MsoVnfAdapterImpl.valetDeleteRequest() method", e);
2253 GenericValetResponse<ValetDeleteResponse> deleteReq = this.vci.callValetDeleteRequest(msoRequest.getRequestId(),
2254 cloudSiteId, cloudOwnerId, tenantId, vfModuleId, vfModuleName);
2255 ValetDeleteResponse vdr = deleteReq.getReturnObject();
2256 if (vdr != null && deleteReq.getStatusCode() == 200) {
2257 ValetStatus status = vdr.getStatus();
2258 if (status != null) {
2259 String statusCode = status.getStatus(); // "ok" or "failed"
2260 if ("ok".equalsIgnoreCase(statusCode)) {
2261 logger.debug("delete request to valet returned success");
2262 valetDeleteRequestSucceeded = true;
2264 logger.debug("delete request to valet returned failure");
2265 valetDeleteRequestSucceeded = false;
2266 valetErrorMessage = status.getMessage();
2270 logger.debug("Got a bad response back from valet - delete request failed");
2271 valetDeleteRequestSucceeded = false;
2272 valetErrorMessage = "Got a bad response back from valet - delete request failed";
2274 } catch (Exception e) {
2275 logger.error("An exception occurred trying to call valet - valetDeleteRequest failed", e);
2276 valetDeleteRequestSucceeded = false;
2277 valetErrorMessage = e.getMessage();
2279 if (valetDeleteRequestSucceeded == false && failRequestOnValetFailure == true) {
2280 logger.error("ValetDeleteRequestFailed - del req still will be sent to openstack", new VnfException
2281 ("ValetDeleteRequestFailedError"));
2283 return valetDeleteRequestSucceeded;