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.MessageEnum;
58 import org.onap.so.logger.MsoLogger;
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 tenantId Openstack tenant identifier
168 * @param vnfType VNF type key, should match a VNF definition in catalog DB
169 * @param vnfVersion VNF version key, should match a VNF definition in catalog DB
170 * @param vnfName Name to be assigned to the new VNF
171 * @param inputs Map of key=value inputs for VNF stack creation
172 * @param failIfExists Flag whether already existing VNF should be considered
173 * a success or failure
174 * @param msoRequest Request tracking information for logs
175 * @param vnfId Holder for output VNF Openstack ID
176 * @param outputs Holder for Map of VNF outputs from heat (assigned IPs, etc)
177 * @param rollback Holder for returning VnfRollback object
180 public void createVnf (String cloudSiteId,
186 String volumeGroupHeatStackId,
187 Map <String, Object> inputs,
188 Boolean failIfExists,
190 Boolean enableBridge,
191 MsoRequest msoRequest,
192 Holder <String> vnfId,
193 Holder <Map <String, String>> outputs,
194 Holder <VnfRollback> rollback) throws VnfException {
195 // parameters used for multicloud adapter
196 String genericVnfId = "";
197 String vfModuleId = "";
198 // Create a hook here to catch shortcut createVf requests:
199 if (requestType != null && requestType.startsWith("VFMOD")) {
200 logger.debug("Calling createVfModule from createVnf -- requestType=" + requestType);
201 String newRequestType = requestType.substring(5);
202 String vfVolGroupHeatStackId = "";
203 String vfBaseHeatStackId = "";
205 if (volumeGroupHeatStackId != null) {
206 vfVolGroupHeatStackId = volumeGroupHeatStackId.substring(0, volumeGroupHeatStackId.lastIndexOf('|'));
207 vfBaseHeatStackId = volumeGroupHeatStackId.substring(volumeGroupHeatStackId.lastIndexOf('|')+1);
209 } catch (Exception e) {
210 // might be ok - both are just blank
211 logger.debug("ERROR trying to parse the volumeGroupHeatStackId " + volumeGroupHeatStackId,e);
213 this.createVfModule(cloudSiteId,
221 vfVolGroupHeatStackId,
234 // createVf will know if the requestType starts with "X" that it's the "old" way
235 StringBuilder newRequestTypeSb = new StringBuilder("X");
236 String vfVolGroupHeatStackId = "";
237 String vfBaseHeatStackId = "";
238 if (requestType != null) {
239 newRequestTypeSb.append(requestType);
241 this.createVfModule(cloudSiteId,
248 newRequestTypeSb.toString(),
249 vfVolGroupHeatStackId,
261 // End createVf shortcut
265 public void updateVnf(String cloudSiteId,
271 String volumeGroupHeatStackId,
272 Map <String, Object> inputs,
273 MsoRequest msoRequest,
274 Holder <Map <String, String>> outputs,
275 Holder <VnfRollback> rollback) throws VnfException {
276 // As of 1707 - this method should no longer be called
277 MsoLogger.setLogContext (msoRequest.getRequestId (), msoRequest.getServiceInstanceId ());
278 MsoLogger.setServiceName ("UpdateVnf");
279 logger.debug("UpdateVnf called?? This should not be called any longer - update vfModule");
283 * This is the "Query VNF" web service implementation.
284 * It will look up a VNF by name or ID in the specified cloud and tenant.
286 * The method returns an indicator that the VNF exists, its Openstack internal
287 * ID, its status, and the set of outputs (from when the stack was created).
289 * @param cloudSiteId CLLI code of the cloud site in which to query
290 * @param tenantId Openstack tenant identifier
291 * @param vnfName VNF Name or Openstack ID
292 * @param msoRequest Request tracking information for logs
293 * @param vnfExists Flag reporting the result of the query
294 * @param vnfId Holder for output VNF Openstack ID
295 * @param outputs Holder for Map of VNF outputs from heat (assigned IPs, etc)
298 public void queryVnf (String cloudSiteId,
301 MsoRequest msoRequest,
302 Holder <Boolean> vnfExists,
303 Holder <String> vnfId,
304 Holder <VnfStatus> status,
305 Holder <Map <String, String>> outputs) throws VnfException {
306 MsoLogger.setLogContext (msoRequest);
307 MsoLogger.setServiceName ("QueryVnf");
308 logger.debug("Querying VNF {} in {}", vnfName, cloudSiteId + "/" + tenantId);
310 // Will capture execution time for metrics
311 long startTime = System.currentTimeMillis ();
313 StackInfo heatStack = null;
314 long subStartTime = System.currentTimeMillis ();
316 heatStack = heat.queryStack (cloudSiteId, tenantId, vnfName);
317 } catch (MsoException me) {
318 me.addContext ("QueryVNF");
319 // Failed to query the Stack due to an openstack exception.
320 // Convert to a generic VnfException
321 String error = "Query VNF: " + vnfName + " in " + cloudSiteId + "/" + tenantId + ": " + me;
322 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vnfName, cloudSiteId,
323 tenantId, "OpenStack", "QueryVNF", MsoLogger.ErrorCode.DataError.getValue(), "Exception - queryStack",
326 throw new VnfException (me);
329 // Populate the outputs based on the returned Stack information
331 if (heatStack == null || heatStack.getStatus () == HeatStatus.NOTFOUND) {
333 vnfExists.value = Boolean.FALSE;
334 status.value = VnfStatus.NOTFOUND;
336 outputs.value = new HashMap<>(); // Return as an empty map
338 logger.debug ("VNF {} not found", vnfName);
340 vnfExists.value = Boolean.TRUE;
341 status.value = stackStatusToVnfStatus (heatStack.getStatus ());
342 vnfId.value = heatStack.getCanonicalName ();
343 outputs.value = copyStringOutputs (heatStack.getOutputs ());
345 logger.debug ("VNF {} found, ID = {}", vnfName, vnfId.value);
351 * This is the "Delete VNF" web service implementation.
352 * It will delete a VNF by name or ID in the specified cloud and tenant.
354 * The method has no outputs.
356 * @param cloudSiteId CLLI code of the cloud site in which to delete
357 * @param tenantId Openstack tenant identifier
358 * @param vnfName VNF Name or Openstack ID
359 * @param msoRequest Request tracking information for logs
362 public void deleteVnf (String cloudSiteId,
365 MsoRequest msoRequest) throws VnfException {
366 MsoLogger.setLogContext (msoRequest);
367 MsoLogger.setServiceName ("DeleteVnf");
368 logger.debug("Deleting VNF {} in {}", vnfName, cloudSiteId + "/" + tenantId);
369 // Will capture execution time for metrics
370 long startTime = System.currentTimeMillis ();
372 // Use the MsoHeatUtils to delete the stack. Set the polling flag to true.
373 // The possible outcomes of deleteStack are a StackInfo object with status
374 // of NOTFOUND (on success) or FAILED (on error). Also, MsoOpenstackException
376 long subStartTime = System.currentTimeMillis ();
378 heat.deleteStack (tenantId, cloudSiteId, vnfName, true);
379 } catch (MsoException me) {
380 me.addContext ("DeleteVNF");
381 // Failed to query the Stack due to an openstack exception.
382 // Convert to a generic VnfException
383 String error = "Delete VNF: " + vnfName + " in " + cloudSiteId + "/" + tenantId + ": " + me;
384 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_DELETE_VNF_ERR.toString(), vnfName, cloudSiteId,
385 tenantId, "OpenStack", "DeleteVNF", MsoLogger.ErrorCode.DataError.getValue(), "Exception - DeleteVNF",
388 throw new VnfException (me);
391 // On success, nothing is returned.
396 * This web service endpoint will rollback a previous Create VNF operation.
397 * A rollback object is returned to the client in a successful creation
398 * response. The client can pass that object as-is back to the rollbackVnf
399 * operation to undo the creation.
402 public void rollbackVnf (VnfRollback rollback) throws VnfException {
403 long startTime = System.currentTimeMillis ();
404 MsoLogger.setServiceName ("RollbackVnf");
405 // rollback may be null (e.g. if stack already existed when Create was called)
406 if (rollback == null) {
407 logger.info(MessageEnum.RA_ROLLBACK_NULL.toString(), "OpenStack", "rollbackVnf");
411 // Get the elements of the VnfRollback object for easier access
412 String cloudSiteId = rollback.getCloudSiteId ();
413 String tenantId = rollback.getTenantId ();
414 String vnfId = rollback.getVnfId ();
416 MsoLogger.setLogContext (rollback.getMsoRequest());
418 logger.debug("Rolling Back VNF {} in {}", vnfId, cloudSiteId + "/" + tenantId);
420 // Use the MsoHeatUtils to delete the stack. Set the polling flag to true.
421 // The possible outcomes of deleteStack are a StackInfo object with status
422 // of NOTFOUND (on success) or FAILED (on error). Also, MsoOpenstackException
424 long subStartTime = System.currentTimeMillis ();
426 heat.deleteStack (tenantId, cloudSiteId, vnfId, true);
427 } catch (MsoException me) {
428 // Failed to rollback the Stack due to an openstack exception.
429 // Convert to a generic VnfException
430 me.addContext ("RollbackVNF");
431 String error = "Rollback VNF: " + vnfId + " in " + cloudSiteId + "/" + tenantId + ": " + me;
432 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_DELETE_VNF_ERR.toString(), vnfId, cloudSiteId,
433 tenantId, "OpenStack", "DeleteStack", MsoLogger.ErrorCode.DataError.getValue(),
434 "Exception - DeleteStack", me);
436 throw new VnfException (me);
441 private VnfStatus stackStatusToVnfStatus (HeatStatus stackStatus) {
442 switch (stackStatus) {
444 return VnfStatus.ACTIVE;
446 return VnfStatus.ACTIVE;
448 return VnfStatus.FAILED;
450 return VnfStatus.UNKNOWN;
454 private Map <String, String> copyStringOutputs(Map <String, Object> stackOutputs) {
455 Map <String, String> stringOutputs = new HashMap <> ();
456 for (Map.Entry<String,Object> entry : stackOutputs.entrySet ()) {
457 String key = entry.getKey();
458 Object value = entry.getValue();
460 stringOutputs.put(key, value.toString());
461 } catch (Exception e) {
462 StringBuilder msg = new StringBuilder("Unable to add " + key + " to outputs");
463 if (value instanceof Integer) { // nothing to add to the message
464 } else if (value instanceof JsonNode) {
465 msg.append(" - exception converting JsonNode");
466 } else if (value instanceof java.util.LinkedHashMap) {
467 msg.append(" exception converting LinkedHashMap");
469 msg.append(" - unable to call .toString() " + e.getMessage());
471 logger.debug(msg.toString(), e);
474 return stringOutputs;
477 private Map <String, Object> copyStringInputs (Map <String, Object> stringInputs) {
478 return new HashMap <> (stringInputs);
481 protected boolean callHeatbridge(String heatStackId) {
482 String executionDir = "/usr/local/lib/python2.7/dist-packages/heatbridge";
483 String openstackIdentityUrl = "", username = "", password = "", tenant = "", region = "", owner = "";
484 long waitTimeMs = 10000L;
487 {"/usr/bin/python", "HeatBridgeMain.py", openstackIdentityUrl, username, password, tenant, region, owner,
489 String[] envp = null;
490 File dir = new File(executionDir);
491 logger.debug("Calling HeatBridgeMain.py in {} with arguments {}", dir, Arrays.toString(cmdarray));
492 Runtime r = Runtime.getRuntime();
493 Process p = r.exec(cmdarray, envp, dir);
494 boolean wait = p.waitFor(waitTimeMs, TimeUnit.MILLISECONDS);
496 logger.debug(" HeatBridgeMain.py returned {} with code {}", wait, p.exitValue());
497 return wait && p.exitValue() == 0;
498 } catch (IOException e) {
499 logger.debug(" HeatBridgeMain.py failed with IO Exception! " + e);
501 } catch (RuntimeException e) {
502 logger.debug(" HeatBridgeMain.py failed during runtime!" + e);
505 catch (Exception e) {
506 logger.debug(" HeatBridgeMain.py failed for unknown reasons! " + e);
511 private String convertNode(final JsonNode node) {
513 final Object obj = JSON_MAPPER.treeToValue(node, Object.class);
514 return JSON_MAPPER.writeValueAsString(obj);
515 } catch (JsonParseException jpe) {
516 logger.debug("Error converting json to string " + jpe.getMessage(),jpe);
517 } catch (Exception e) {
518 logger.debug("Error converting json to string " + e.getMessage(),e);
520 return "[Error converting json to string]";
523 private Map<String, String> convertMapStringObjectToStringString(Map<String, Object> objectMap) {
524 if (objectMap == null) {
527 Map<String, String> stringMap = new HashMap<>();
528 for (String key : objectMap.keySet()) {
529 if (!stringMap.containsKey(key)) {
530 Object obj = objectMap.get(key);
531 if (obj instanceof String) {
532 stringMap.put(key, (String) objectMap.get(key));
533 } else if (obj instanceof JsonNode ){
534 // This is a bit of mess - but I think it's the least impacting
535 // let's convert it BACK to a string - then it will get converted back later
537 String str = this.convertNode((JsonNode) obj);
538 stringMap.put(key, str);
539 } catch (Exception e) {
540 logger.debug("DANGER WILL ROBINSON: unable to convert value for JsonNode "+ key,e);
541 //okay in this instance - only string values (fqdn) are expected to be needed
543 } else if (obj instanceof java.util.LinkedHashMap) {
544 logger.debug("LinkedHashMap - this is showing up as a LinkedHashMap instead of JsonNode");
546 String str = JSON_MAPPER.writeValueAsString(obj);
547 stringMap.put(key, str);
548 } catch (Exception e) {
549 logger.debug("DANGER WILL ROBINSON: unable to convert value for LinkedHashMap "+ key,e);
551 } else if (obj instanceof Integer) {
553 String str = "" + obj;
554 stringMap.put(key, str);
555 } catch (Exception e) {
556 logger.debug("DANGER WILL ROBINSON: unable to convert value for Integer "+ key,e);
560 String str = obj.toString();
561 stringMap.put(key, str);
562 } catch (Exception e) {
563 logger.debug("DANGER WILL ROBINSON: unable to convert value "+ key + " (" + e.getMessage() + ")",e);
573 public void createVfModule(String cloudSiteId,
577 String genericVnfName,
581 String volumeGroupHeatStackId,
582 String baseVfHeatStackId,
583 String modelCustomizationUuid,
584 Map <String, Object> inputs,
585 Boolean failIfExists,
587 Boolean enableBridge,
588 MsoRequest msoRequest,
589 Holder <String> vnfId,
590 Holder <Map <String, String>> outputs,
591 Holder <VnfRollback> rollback) throws VnfException {
592 String vfModuleName = vnfName;
593 String vfModuleType = vnfType;
594 String vfVersion = vnfVersion;
595 String mcu = modelCustomizationUuid;
596 boolean useMCUuid = false;
597 if (mcu != null && !mcu.isEmpty()) {
598 if ("null".equalsIgnoreCase(mcu)) {
599 logger.debug("modelCustomizationUuid: passed in as the string 'null' - will ignore: " + modelCustomizationUuid);
603 logger.debug("Found modelCustomizationUuid! Will use that: " + mcu);
607 MsoLogger.setLogContext (msoRequest);
608 MsoLogger.setServiceName ("CreateVfModule");
609 String requestTypeString = "";
610 if (requestType != null && !"".equals(requestType)) {
611 requestTypeString = requestType;
613 String nestedStackId = null;
614 if (volumeGroupHeatStackId != null && !"".equals(volumeGroupHeatStackId) && !"null".equalsIgnoreCase(volumeGroupHeatStackId)) {
615 nestedStackId = volumeGroupHeatStackId;
617 String nestedBaseStackId = null;
618 if (baseVfHeatStackId != null && !"".equals(baseVfHeatStackId) && !"null".equalsIgnoreCase(baseVfHeatStackId)) {
619 nestedBaseStackId = baseVfHeatStackId;
622 //This method will also handle doing things the "old" way - i.e., just orchestrate a VNF
623 boolean oldWay = false;
624 if (requestTypeString.startsWith("X")) {
626 logger.debug("orchestrating a VNF - *NOT* a module!");
627 requestTypeString = requestTypeString.substring(1);
630 // 1607 - let's parse out the request type we're being sent
631 boolean isBaseRequest = false;
632 boolean isVolumeRequest = false;
633 if (requestTypeString.startsWith("VOLUME")) {
634 isVolumeRequest = true;
637 logger.debug("requestTypeString = " + requestTypeString + ", nestedStackId = " + nestedStackId + ", nestedBaseStackId = " + nestedBaseStackId);
638 // Will capture execution time for metrics
639 long startTime = System.currentTimeMillis ();
641 // Build a default rollback object (no actions performed)
642 VnfRollback vfRollback = new VnfRollback();
643 vfRollback.setCloudSiteId(cloudSiteId);
644 vfRollback.setTenantId(tenantId);
645 vfRollback.setMsoRequest(msoRequest);
646 vfRollback.setRequestType(requestTypeString);
647 vfRollback.setVolumeGroupHeatStackId(volumeGroupHeatStackId);
648 vfRollback.setBaseGroupHeatStackId(baseVfHeatStackId);
649 vfRollback.setIsBase(isBaseRequest);
650 vfRollback.setModelCustomizationUuid(mcu);
652 // Put data into A&AI through Heatstack
653 if(enableBridge != null && enableBridge) {
654 callHeatbridge(baseVfHeatStackId);
657 StackInfo heatStack = null;
658 long subStartTime1 = System.currentTimeMillis ();
660 heatStack = heat.queryStack (cloudSiteId, tenantId, vfModuleName);
661 } catch (MsoException me) {
662 String error = "Create VF Module: Query " + vfModuleName + " in " + cloudSiteId + "/" + tenantId + ": " + me ;
663 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vfModuleName, cloudSiteId,
664 tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError.getValue(), "Exception - queryStack",
667 // Failed to query the Stack due to an openstack exception.
668 // Convert to a generic VnfException
669 me.addContext ("CreateVFModule");
670 throw new VnfException (me);
672 // New with 1607 - more precise handling/messaging if the stack already exists
673 if (heatStack != null && heatStack.getStatus() != HeatStatus.NOTFOUND) {
674 // INIT, CREATED, NOTFOUND, FAILED, BUILDING, DELETING, UNKNOWN, UPDATING, UPDATED
675 HeatStatus status = heatStack.getStatus();
676 if (status == HeatStatus.INIT || status == HeatStatus.BUILDING || status == HeatStatus.DELETING || status == HeatStatus.UPDATING) {
677 // fail - it's in progress - return meaningful error
678 String error = "Create VF: Stack " + vfModuleName + " already exists and has status " + status.toString() + " in " + cloudSiteId + "/" + tenantId + "; please wait for it to complete, or fix manually.";
679 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_VNF_ALREADY_EXIST.toString(), vfModuleName,
680 cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError.getValue(),
681 "Stack " + vfModuleName + " already exists");
683 throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, heatStack.getCanonicalName ());
685 if (status == HeatStatus.FAILED) {
686 // fail - it exists and is in a FAILED state
687 String error = "Create VF: Stack " + vfModuleName + " already exists and is in FAILED state in " + cloudSiteId + "/" + tenantId + "; requires manual intervention.";
688 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_VNF_ALREADY_EXIST.toString(), vfModuleName,
689 cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError.getValue(),
690 "Stack " + vfModuleName + " already exists and is " + "in FAILED state");
692 throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, heatStack.getCanonicalName ());
694 if (status == HeatStatus.UNKNOWN || status == HeatStatus.UPDATED) {
695 // fail - it exists and is in a FAILED state
697 "Create VF: Stack " + vfModuleName + " already exists and has status " + status.toString() + " in "
698 + cloudSiteId + "/" + tenantId + "; requires manual intervention.";
699 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_VNF_ALREADY_EXIST.toString(), vfModuleName,
700 cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError.getValue(),
701 "Stack " + vfModuleName + " already exists and is " + "in UPDATED or UNKNOWN state");
703 throw new VnfAlreadyExists(vfModuleName, cloudSiteId, tenantId, heatStack.getCanonicalName());
705 if (status == HeatStatus.CREATED) {
707 if (failIfExists != null && failIfExists) {
709 "Create VF: Stack " + vfModuleName + " already exists in " + cloudSiteId + "/" + tenantId;
710 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_VNF_ALREADY_EXIST.toString(), vfModuleName,
711 cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError.getValue(),
712 "Stack " + vfModuleName + " already exists");
714 throw new VnfAlreadyExists(vfModuleName, cloudSiteId, tenantId, heatStack.getCanonicalName());
716 logger.debug ("Found Existing stack, status={}", heatStack.getStatus ());
717 // Populate the outputs from the existing stack.
718 vnfId.value = heatStack.getCanonicalName ();
719 outputs.value = copyStringOutputs (heatStack.getOutputs ());
720 rollback.value = vfRollback; // Default rollback - no updates performed
727 // handle a nestedStackId if sent- this one would be for the volume - so applies to both Vf and Vnf
728 StackInfo nestedHeatStack = null;
729 long subStartTime2 = System.currentTimeMillis ();
730 Map<String, Object> nestedVolumeOutputs = null;
731 if (nestedStackId != null) {
733 logger.debug("Querying for nestedStackId = {}", nestedStackId);
734 nestedHeatStack = heat.queryStack(cloudSiteId, tenantId, nestedStackId);
735 } catch (MsoException me) {
736 // Failed to query the Stack due to an openstack exception.
737 // Convert to a generic VnfException
738 me.addContext ("CreateVFModule");
739 String error = "Create VFModule: Attached heatStack ID Query " + nestedStackId + " in " + cloudSiteId + "/" + tenantId + ": " + me ;
740 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vfModuleName, cloudSiteId,
741 tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.BusinessProcesssError.getValue(),
742 "MsoException trying to query nested stack", me);
743 logger.debug("ERROR trying to query nested stack= {}", error);
744 throw new VnfException (me);
746 if (nestedHeatStack == null || nestedHeatStack.getStatus() == HeatStatus.NOTFOUND) {
747 String error = "Create VFModule: Attached heatStack ID DOES NOT EXIST " + nestedStackId + " in " + cloudSiteId + "/" + tenantId + " USER ERROR" ;
748 logger.error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vfModuleName,
749 cloudSiteId, tenantId, error, "OpenStack", "queryStack",
750 MsoLogger.ErrorCode.BusinessProcesssError.getValue(),
751 "Create VFModule: Attached heatStack ID " + "DOES NOT EXIST");
753 throw new VnfException (error, MsoExceptionCategory.USERDATA);
755 logger.debug("Found nested volume heat stack - copying values to inputs *later*");
756 nestedVolumeOutputs = nestedHeatStack.getOutputs();
760 // handle a nestedBaseStackId if sent- this is the stack ID of the base. Should be null for VNF requests
761 StackInfo nestedBaseHeatStack = null;
762 long subStartTime3 = System.currentTimeMillis ();
763 Map<String, Object> baseStackOutputs = null;
764 if (nestedBaseStackId != null) {
766 logger.debug("Querying for nestedBaseStackId = {}", nestedBaseStackId);
767 nestedBaseHeatStack = heat.queryStack(cloudSiteId, tenantId, nestedBaseStackId);
768 } catch (MsoException me) {
769 // Failed to query the Stack due to an openstack exception.
770 // Convert to a generic VnfException
771 me.addContext ("CreateVFModule");
772 String error = "Create VFModule: Attached baseHeatStack ID Query " + nestedBaseStackId + " in " + cloudSiteId + "/" + tenantId + ": " + me ;
774 .error("{} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vfModuleName, cloudSiteId,
775 tenantId, "OpenStack", "QueryStack", MsoLogger.ErrorCode.BusinessProcesssError.getValue(),
776 "MsoException trying to query nested base stack", me);
777 logger.debug("ERROR trying to query nested base stack= {}", error);
778 throw new VnfException (me);
780 if (nestedBaseHeatStack == null || nestedBaseHeatStack.getStatus() == HeatStatus.NOTFOUND) {
781 String error = "Create VFModule: Attached base heatStack ID DOES NOT EXIST " + nestedBaseStackId + " in " + cloudSiteId + "/" + tenantId + " USER ERROR" ;
782 logger.error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vfModuleName,
783 cloudSiteId, tenantId, error, "OpenStack", "QueryStack",
784 MsoLogger.ErrorCode.BusinessProcesssError.getValue(),
785 "Create VFModule: Attached base heatStack ID DOES NOT EXIST");
786 logger.debug("Exception occurred", error);
787 throw new VnfException (error, MsoExceptionCategory.USERDATA);
789 logger.debug("Found nested base heat stack - these values will be copied to inputs *later*");
790 baseStackOutputs = nestedBaseHeatStack.getOutputs();
794 // Ready to deploy the new VNF
801 VnfResource vnfResource = null;
802 VfModuleCustomization vfmc = null;
803 logger.debug("version: {}", vfVersion);
805 // 1707 - db refactoring
806 vfmc = vfModuleCustomRepo.findByModelCustomizationUUID(mcu);
808 vf=vfmc.getVfModule();
812 // 1702 - this will be the new way going forward. We find the vf by mcu - otherwise, code is the same.
814 logger.debug("Unable to find vfModuleCust with modelCustomizationUuid={}", mcu);
815 String error = "Create vfModule error: Unable to find vfModuleCust with modelCustomizationUuid=" + mcu;
816 logger.error("{} {} {} {} {} {}", MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(),
817 "VF Module ModelCustomizationUuid", modelCustomizationUuid, "OpenStack",
818 MsoLogger.ErrorCode.DataError.getValue(),
819 "Create VF Module: Unable to find vfModule with " + "modelCustomizationUuid=" + mcu);
821 throw new VnfException(error, MsoExceptionCategory.USERDATA);
823 logger.trace("Found vfModuleCust entry {}", vfmc.toString());
825 if (vf.getIsBase()) {
826 isBaseRequest = true;
827 logger.debug("This is a BASE VF request!");
829 logger.debug("This is *not* a BASE VF request!");
830 if (!isVolumeRequest && nestedBaseStackId == null) {
831 logger.debug("DANGER WILL ROBINSON! This is unexpected - no nestedBaseStackId with this non-base request");
836 else { // This is to support gamma only - get info from vnf_resource table
837 if (vfVersion != null && !vfVersion.isEmpty()) {
838 vnfResource = vnfResourceRepo.findByModelNameAndModelVersion(vnfType, vnfVersion);
840 vnfResource = vnfResourceRepo.findByModelName(vnfType);
842 if (vnfResource == null) {
843 String error = "Create VNF: Unknown VNF Type: " + vnfType;
844 logger.error("{} {} {} {} {} {}", MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "VNF Type", vnfType,
845 "OpenStack", MsoLogger.ErrorCode.DataError.getValue(), "Create VNF: Unknown VNF Type");
847 throw new VnfException(error, MsoExceptionCategory.USERDATA);
849 logger.debug("Got VNF module definition from Catalog: {}", vnfResource.toString());
851 // By here - we have either a vf or vnfResource
853 //1607 - Add version check
854 // First - see if it's in the VnfResource record
855 // if we have a vf Module - then we have to query to get the VnfResource record.
856 if (!oldWay && vf.getVnfResources() != null) {
857 vnfResource = vf.getVnfResources();
858 if (vnfResource == null) {
859 logger.debug("Unable to find vnfResource will not error for now...");
862 String minVersionVnf = null;
863 String maxVersionVnf = null;
864 if (vnfResource != null) {
866 minVersionVnf = vnfResource.getAicVersionMin();
867 maxVersionVnf = vnfResource.getAicVersionMax();
868 } catch (Exception e) {
869 logger.debug("Unable to pull min/max version for this VNF Resource entry",e);
870 minVersionVnf = null;
871 maxVersionVnf = null;
873 if (minVersionVnf != null && "".equals(minVersionVnf)) {
874 minVersionVnf = null;
876 if (maxVersionVnf != null && "".equals(maxVersionVnf)) {
877 maxVersionVnf = null;
880 if (minVersionVnf != null && maxVersionVnf != null) {
881 MavenLikeVersioning aicV = new MavenLikeVersioning();
884 if (this.cloudConfig != null) {
885 Optional<CloudSite> cloudSiteOpt = this.cloudConfig.getCloudSite(cloudSiteId);
886 if (cloudSiteOpt.isPresent()) {
887 aicV.setVersion(cloudSiteOpt.get().getCloudVersion());
888 // Add code to handle unexpected values in here
889 boolean moreThanMin = true;
890 boolean equalToMin = true;
891 boolean moreThanMax = true;
892 boolean equalToMax = true;
893 boolean doNotTest = false;
895 moreThanMin = aicV.isMoreRecentThan(minVersionVnf);
896 equalToMin = aicV.isTheSameVersion(minVersionVnf);
897 moreThanMax = aicV.isMoreRecentThan(maxVersionVnf);
898 equalToMax = aicV.isTheSameVersion(maxVersionVnf);
899 } catch (Exception e) {
900 logger.debug("An exception occurred while trying to test AIC Version {} - will default to not check",
905 if ((moreThanMin || equalToMin) // aic >= min
906 && (equalToMax || !(moreThanMax))) { //aic <= max
908 "VNF Resource " + vnfResource.getModelName() + ", ModelUuid=" + vnfResource.getModelUUID()
909 + " VersionMin=" + minVersionVnf + " VersionMax:" + maxVersionVnf + " supported on Cloud: "
910 + cloudSiteId + " with AIC_Version:" + cloudSiteOpt.get().getCloudVersion());
913 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();
914 logger.error("{} {} {} {} {}", MessageEnum.RA_CONFIG_EXC.toString(), error, "OpenStack",
915 MsoLogger.ErrorCode.BusinessProcesssError.getValue(), "Exception - setVersion");
917 throw new VnfException(error, MsoExceptionCategory.USERDATA);
920 logger.debug("bypassing testing AIC version...");
922 } // let this error out downstream to avoid introducing uncertainty at this stage
924 logger.debug("cloudConfig is NULL - cannot check cloud site version");
927 logger.debug("AIC Version not set in VNF_Resource - this is expected thru 1607 - do not error here - not checked"
930 // End Version check 1607
935 // By the time we get here - heatTemplateId and heatEnvtId should be populated (or null)
936 HeatTemplate heatTemplate = null;
937 HeatEnvironment heatEnvironment = null;
939 //This will handle old Gamma BrocadeVCE VNF
940 heatTemplate = vnfResource.getHeatTemplates();
944 if (isVolumeRequest) {
945 heatTemplate = vf.getVolumeHeatTemplate();
946 heatEnvironment = vfmc.getVolumeHeatEnv();
948 heatTemplate = vf.getModuleHeatTemplate();
949 heatEnvironment = vfmc.getHeatEnvironment();
954 if (heatTemplate == null) {
955 String error = "UpdateVF: No Heat Template ID defined in catalog database for " + vfModuleType + ", reqType=" + requestTypeString;
957 .error("{} {} {} {} {} {}", MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "Heat Template ID", vfModuleType,
958 "OpenStack", MsoLogger.ErrorCode.DataError.getValue(), error);
960 throw new VnfException(error, MsoExceptionCategory.INTERNAL);
962 logger.debug("Got HEAT Template from DB: {}", heatTemplate.getHeatTemplate());
966 //This will handle old Gamma BrocadeVCE VNF
967 logger.debug("No environment parameter found for this Type " + vfModuleType);
969 if (heatEnvironment == null) {
970 String error = "Update VNF: undefined Heat Environment. VF=" + vfModuleType;
971 logger.error("{} {} {} {} {}", MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "Heat Environment ID",
972 "OpenStack", MsoLogger.ErrorCode.DataError.getValue(), error);
974 throw new VnfException (error, MsoExceptionCategory.INTERNAL);
976 logger.debug("Got Heat Environment from DB: {}", heatEnvironment.getEnvironment());
980 logger.debug("In MsoVnfAdapterImpl, about to call db.getNestedTemplates avec templateId="
981 + heatTemplate.getArtifactUuid ());
984 List<HeatTemplate> nestedTemplates = heatTemplate.getChildTemplates();
985 Map <String, Object> nestedTemplatesChecked = new HashMap <> ();
986 if (nestedTemplates != null && !nestedTemplates.isEmpty()) {
987 // for debugging print them out
988 logger.debug("Contents of nestedTemplates - to be added to files: on stack:");
989 for (HeatTemplate entry : nestedTemplates) {
990 nestedTemplatesChecked.put (entry.getTemplateName(), entry.getTemplateBody());
991 logger.debug(entry.getTemplateName() + " -> " + entry.getTemplateBody());
994 logger.debug("No nested templates found - nothing to do here");
995 nestedTemplatesChecked = null;
998 // 1510 - Also add the files: for any get_files associated with this vnf_resource_id
999 // *if* there are any
1000 List<HeatFiles> heatFiles = null;
1002 Map<String, Object> heatFilesObjects = new HashMap<>();
1004 // Add ability to turn on adding get_files with volume requests (by property).
1005 boolean addGetFilesOnVolumeReq = false;
1007 String propertyString = this.environment.getProperty(MsoVnfAdapterImpl.ADD_GET_FILES_ON_VOLUME_REQ);
1008 if ("true".equalsIgnoreCase(propertyString) || "y".equalsIgnoreCase(propertyString)) {
1009 addGetFilesOnVolumeReq = true;
1010 logger.debug("AddGetFilesOnVolumeReq - setting to true! {}", propertyString);
1012 } catch (Exception e) {
1013 logger.debug("An error occured trying to get property " + MsoVnfAdapterImpl.ADD_GET_FILES_ON_VOLUME_REQ
1014 + " - default to false", e);
1017 if (!isVolumeRequest || addGetFilesOnVolumeReq) {
1019 logger.debug("In MsoVnfAdapterImpl createVfModule, this should not happen - old way is gamma only - no heat "
1022 // 1607 - now use VF_MODULE_TO_HEAT_FILES table
1023 logger.debug("In MsoVnfAdapterImpl createVfModule, about to call db.getHeatFilesForVfModule avec vfModuleId="
1024 + vf.getModelUUID());
1025 heatFiles = vf.getHeatFiles();
1027 if (heatFiles != null && !heatFiles.isEmpty()) {
1028 // add these to stack - to be done in createStack
1029 // here, we will map them to Map<String, Object> from
1030 // Map<String, HeatFiles>
1031 // this will match the nested templates format
1032 logger.debug("Contents of heatFiles - to be added to files: on stack");
1034 for (HeatFiles heatfile : heatFiles) {
1035 logger.debug(heatfile.getFileName() + " -> " + heatfile.getFileBody());
1036 heatFilesObjects.put(heatfile.getFileName(), heatfile.getFileBody());
1039 logger.debug("No heat files found -nothing to do here");
1040 heatFilesObjects = null;
1044 // Check that required parameters have been supplied
1045 String missingParams = null;
1046 List <String> paramList = new ArrayList <> ();
1048 // New for 1510 - consult the PARAM_ALIAS field to see if we've been
1049 // supplied an alias. Only check if we don't find it initially.
1050 // Also new in 1510 - don't flag missing parameters if there's an environment - because they might be there.
1051 // And also new - add parameter to turn off checking all together if we find we're blocking orders we
1053 boolean checkRequiredParameters = true;
1055 String propertyString = this.environment.getProperty (MsoVnfAdapterImpl.CHECK_REQD_PARAMS);
1056 if ("false".equalsIgnoreCase (propertyString) || "n".equalsIgnoreCase (propertyString)) {
1057 checkRequiredParameters = false;
1058 logger.debug("CheckRequiredParameters is FALSE. Will still check but then skip blocking..."
1059 + MsoVnfAdapterImpl.CHECK_REQD_PARAMS);
1061 } catch (Exception e) {
1062 // No problem - default is true
1063 logger.debug("An exception occured trying to get property {}", MsoVnfAdapterImpl.CHECK_REQD_PARAMS, e);
1065 // 1604 - Add enhanced environment & parameter checking
1066 // Part 1: parse envt entries to see if reqd parameter is there (before used a simple grep
1067 // Part 2: only submit to openstack the parameters in the envt that are in the heat template
1068 // Note this also removes any comments
1069 MsoHeatEnvironmentEntry mhee = null;
1070 if (heatEnvironment != null && heatEnvironment.getEnvironment() != null && heatEnvironment.getEnvironment().contains ("parameters:")) {
1072 logger.debug("Enhanced environment checking enabled - 1604");
1073 StringBuilder sb = new StringBuilder(heatEnvironment.getEnvironment());
1075 mhee = new MsoHeatEnvironmentEntry(sb);
1076 StringBuilder sb2 = new StringBuilder("\nHeat Template Parameters:\n");
1077 for (HeatTemplateParam parm : heatTemplate.getParameters()) {
1078 sb2.append("\t" + parm.getParamName() + ", required=" + parm.isRequired());
1080 if (!mhee.isValid()) {
1081 sb2.append("Environment says it's not valid! " + mhee.getErrorString());
1083 sb2.append("\nEnvironment:");
1084 sb2.append(mhee.toFullString());
1086 logger.debug(sb2.toString());
1088 logger.debug("NO ENVIRONMENT for this entry");
1090 // New with 1707 - all variables converted to their native object types
1091 Map<String, Object> goldenInputs = null;
1093 logger.debug("Now handle the inputs....first convert");
1094 ArrayList<String> parameterNames = new ArrayList<>();
1095 HashMap<String, String> aliasToParam = new HashMap<>();
1096 StringBuilder sb = new StringBuilder("\nTemplate Parameters:\n");
1099 for (HeatTemplateParam htp : heatTemplate.getParameters()) {
1100 sb.append("param[" + cntr++ + "]=" + htp.getParamName());
1101 parameterNames.add(htp.getParamName());
1102 if (htp.getParamAlias() != null && !"".equals(htp.getParamAlias())) {
1103 aliasToParam.put(htp.getParamAlias(), htp.getParamName());
1104 sb.append(" ** (alias=" + htp.getParamAlias() + ")");
1108 logger.debug(sb.toString());
1109 } catch (Exception e) {
1110 logger.debug("??An exception occurred trying to go through Parameter Names {}", e.getMessage(),e);
1112 // Step 1 - convert what we got as inputs (Map<String, String>) to a
1113 // Map<String, Object> - where the object matches the param type identified in the template
1114 // This will also not copy over params that aren't identified in the template
1115 goldenInputs = heat.convertInputMap(inputs, heatTemplate);
1116 // Step 2 - now simply add the outputs as we received them - no need to convert to string
1117 logger.debug("Now add in the base stack outputs if applicable");
1118 heat.copyBaseOutputsToInputs(goldenInputs, baseStackOutputs, parameterNames, aliasToParam);
1119 // Step 3 - add the volume inputs if any
1120 logger.debug("Now add in the volume stack outputs if applicable");
1121 heat.copyBaseOutputsToInputs(goldenInputs, nestedVolumeOutputs, parameterNames, aliasToParam);
1123 for (HeatTemplateParam parm : heatTemplate.getParameters ()) {
1125 "Parameter:'" + parm.getParamName() + "', isRequired=" + parm.isRequired() + ", alias=" + parm
1128 if (parm.isRequired () && (goldenInputs == null || !goldenInputs.containsKey (parm.getParamName ()))) {
1129 // The check for an alias was moved to the method in MsoHeatUtils - when we converted the Map<String, String> to Map<String, Object>
1130 logger.debug("**Parameter " + parm.getParamName() + " is required and not in the inputs...check "
1132 if (mhee != null && mhee.containsParameter(parm.getParamName())) {
1133 logger.debug("Required parameter {} appears to be in environment - do not count as missing",
1134 parm.getParamName());
1136 logger.debug("adding to missing parameters list: {}", parm.getParamName());
1137 if (missingParams == null) {
1138 missingParams = parm.getParamName ();
1140 missingParams += "," + parm.getParamName ();
1144 paramList.add (parm.getParamName ());
1146 if (missingParams != null) {
1147 if (checkRequiredParameters) {
1148 // Problem - missing one or more required parameters
1149 String error = "Create VFModule: Missing Required inputs: " + missingParams;
1150 logger.error("{} {} {} {} {}", MessageEnum.RA_MISSING_PARAM.toString(), missingParams, "OpenStack",
1151 MsoLogger.ErrorCode.DataError.getValue(), "Create VFModule: Missing Required inputs");
1152 logger.debug(error);
1153 throw new VnfException (error, MsoExceptionCategory.USERDATA);
1155 logger.debug ("found missing parameters - but checkRequiredParameters is false - will not block");
1158 logger.debug ("No missing parameters found - ok to proceed");
1160 // We can now remove the recreating of the ENV with only legit params - that check is done for us,
1161 // and it causes problems with json that has arrays
1162 String newEnvironmentString = null;
1164 newEnvironmentString = mhee.getRawEntry().toString();
1167 // "Fix" the template if it has CR/LF (getting this from Oracle)
1168 String template = heatTemplate.getHeatTemplate ();
1169 template = template.replaceAll ("\r\n", "\n");
1172 boolean isValetEnabled = this.checkBooleanProperty(MsoVnfAdapterImpl.VALET_ENABLED, false);
1173 boolean failRequestOnValetFailure = this.checkBooleanProperty(MsoVnfAdapterImpl.FAIL_REQUESTS_ON_VALET_FAILURE, false);
1174 logger.debug("isValetEnabled={}, failRequestsOnValetFailure={}", isValetEnabled, failRequestOnValetFailure);
1175 if (oldWay || isVolumeRequest) {
1176 isValetEnabled = false;
1177 logger.debug("do not send to valet for volume requests or brocade");
1179 boolean sendResponseToValet = false;
1180 if (isValetEnabled) {
1181 Holder<Map<String, Object>> valetModifiedParamsHolder = new Holder<>();
1182 sendResponseToValet = this.valetCreateRequest(cloudSiteId, tenantId, heatFilesObjects,
1183 nestedTemplatesChecked, vfModuleName, backout, heatTemplate, newEnvironmentString, goldenInputs,
1184 msoRequest, inputs, failRequestOnValetFailure, valetModifiedParamsHolder);
1185 if (sendResponseToValet) {
1186 goldenInputs = valetModifiedParamsHolder.value;
1190 // Have the tenant. Now deploy the stack itself
1191 // Ignore MsoTenantNotFound and MsoStackAlreadyExists exceptions
1192 // because we already checked for those.
1193 long createStackStarttime = System.currentTimeMillis ();
1195 // heatStack = heat.createStack(cloudSiteId, tenantId, vnfName, template, inputs, true,
1196 // heatTemplate.getTimeoutMinutes());
1197 if (backout == null) {
1201 logger.debug("heat is not null!!");
1203 heatStack = heat.createStack (cloudSiteId,
1209 heatTemplate.getTimeoutMinutes(),
1210 newEnvironmentString,
1211 nestedTemplatesChecked,
1213 backout.booleanValue());
1216 logger.debug("heat is null!");
1217 throw new MsoHeatNotFoundException();
1219 } catch (MsoException me) {
1220 me.addContext ("CreateVFModule");
1221 String error = "Create VF Module " + vfModuleType + " in " + cloudSiteId + "/" + tenantId + ": " + me;
1223 .error("{} {} {} {} {} {} {}", MessageEnum.RA_CREATE_VNF_ERR.toString(), vfModuleType, cloudSiteId,
1224 tenantId, "OpenStack", MsoLogger.ErrorCode.DataError.getValue(), "MsoException - createStack",
1226 logger.debug(error);
1227 if (isValetEnabled && sendResponseToValet) {
1228 logger.debug("valet is enabled, the orchestration failed - now sending rollback to valet");
1230 GenericValetResponse<ValetRollbackResponse> gvr = this.vci.callValetRollbackRequest(msoRequest.getRequestId(), null, backout, me.getMessage());
1231 // Nothing to really do here whether it succeeded or not other than log it.
1232 logger.debug("Return code from Rollback response is {}", gvr.getStatusCode());
1233 } catch (Exception e) {
1234 logger.error("Exception encountered while sending Rollback to Valet ", e);
1237 throw new VnfException (me);
1238 } catch (NullPointerException npe) {
1239 String error = "Create VFModule " + vfModuleType + " in " + cloudSiteId + "/" + tenantId + ": " + npe;
1241 .error("{} {} {} {} {} {} {}", MessageEnum.RA_CREATE_VNF_ERR.toString(), vfModuleType, cloudSiteId,
1242 tenantId, "OpenStack", MsoLogger.ErrorCode.DataError.getValue(),
1243 "NullPointerException - createStack", npe);
1244 logger.debug(error);
1245 logger.debug("NULL POINTER EXCEPTION at heat.createStack");
1246 //npe.addContext ("CreateVNF");
1247 throw new VnfException ("NullPointerException during heat.createStack");
1248 } catch (Exception e) {
1249 logger.debug("unhandled exception at heat.createStack",e);
1250 throw new VnfException("Exception during heat.createStack! " + e.getMessage());
1252 // Reach this point if createStack is successful.
1253 // Populate remaining rollback info and response parameters.
1254 vfRollback.setVnfId (heatStack.getCanonicalName ());
1255 vfRollback.setVnfCreated (true);
1257 vnfId.value = heatStack.getCanonicalName ();
1258 outputs.value = copyStringOutputs (heatStack.getOutputs ());
1259 rollback.value = vfRollback;
1260 if (isValetEnabled && sendResponseToValet) {
1261 logger.debug("valet is enabled, the orchestration succeeded - now send confirm to valet with stack id");
1263 GenericValetResponse<ValetConfirmResponse> gvr = this.vci.callValetConfirmRequest(msoRequest.getRequestId(), heatStack.getCanonicalName());
1264 // Nothing to really do here whether it succeeded or not other than log it.
1265 logger.debug("Return code from Confirm response is {}", gvr.getStatusCode());
1266 } catch (Exception e) {
1267 logger.error("Exception encountered while sending Confirm to Valet ", e);
1270 logger.debug("VF Module {} successfully created", vfModuleName);
1272 } catch (Exception e) {
1273 logger.debug("unhandled exception in create VF",e);
1274 throw new VnfException("Exception during create VF " + e.getMessage());
1279 public void deleteVfModule (String cloudSiteId,
1282 MsoRequest msoRequest,
1283 Holder <Map <String, String>> outputs) throws VnfException {
1285 logger.debug("Deleting VF {} in ", vnfName, cloudSiteId + "/" + tenantId);
1286 // Will capture execution time for metrics
1287 long startTime = System.currentTimeMillis ();
1289 // 1702 capture the output parameters on a delete
1290 // so we'll need to query first
1291 Map<String, Object> stackOutputs = null;
1293 stackOutputs = heat.queryStackForOutputs(cloudSiteId, tenantId, vnfName);
1294 } catch (MsoException me) {
1295 // Failed to query the Stack due to an openstack exception.
1296 // Convert to a generic VnfException
1297 me.addContext ("DeleteVFModule");
1298 String error = "Delete VFModule: Query to get outputs: " + vnfName + " in " + cloudSiteId + "/" + tenantId + ": " + me;
1299 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vnfName, cloudSiteId,
1300 tenantId, "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError.getValue(), "Exception - QueryStack",
1302 logger.debug(error);
1303 throw new VnfException (me);
1305 // call method which handles the conversion from Map<String,Object> to Map<String,String> for our expected Object types
1306 outputs.value = this.convertMapStringObjectToStringString(stackOutputs);
1308 boolean isValetEnabled = this.checkBooleanProperty(MsoVnfAdapterImpl.VALET_ENABLED, false);
1309 boolean failRequestOnValetFailure = this.checkBooleanProperty(MsoVnfAdapterImpl.FAIL_REQUESTS_ON_VALET_FAILURE, false);
1310 logger.debug("isValetEnabled={}, failRequestsOnValetFailure={}", isValetEnabled, failRequestOnValetFailure);
1311 boolean valetDeleteRequestSucceeded = false;
1312 if (isValetEnabled) {
1313 valetDeleteRequestSucceeded = this.valetDeleteRequest(cloudSiteId, tenantId, vnfName, msoRequest, failRequestOnValetFailure);
1316 // Use the MsoHeatUtils to delete the stack. Set the polling flag to true.
1317 // The possible outcomes of deleteStack are a StackInfo object with status
1318 // of NOTFOUND (on success) or FAILED (on error). Also, MsoOpenstackException
1320 long subStartTime = System.currentTimeMillis ();
1322 heat.deleteStack (tenantId, cloudSiteId, vnfName, true);
1323 } catch (MsoException me) {
1324 me.addContext ("DeleteVNF");
1325 // Failed to query the Stack due to an openstack exception.
1326 // Convert to a generic VnfException
1327 String error = "Delete VF: " + vnfName + " in " + cloudSiteId + "/" + tenantId + ": " + me;
1328 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_DELETE_VNF_ERR.toString(), vnfName, cloudSiteId,
1329 tenantId, "OpenStack", "DeleteStack", MsoLogger.ErrorCode.DataError.getValue(),
1330 "Exception - deleteStack", me);
1331 logger.debug(error);
1332 if (isValetEnabled && valetDeleteRequestSucceeded) {
1333 logger.debug("valet is enabled, the orchestration failed - now sending rollback to valet");
1335 GenericValetResponse<ValetRollbackResponse> gvr = this.vci.callValetRollbackRequest(msoRequest.getRequestId(), vnfName, false, me.getMessage());
1336 // Nothing to really do here whether it succeeded or not other than log it.
1337 logger.debug("Return code from Rollback response is {}", gvr.getStatusCode());
1338 } catch (Exception e) {
1339 logger.error("Exception encountered while sending Rollback to Valet ", e);
1342 throw new VnfException (me);
1344 if (isValetEnabled && valetDeleteRequestSucceeded) {
1345 // only if the original request succeeded do we send a confirm
1346 logger.debug("valet is enabled, the delete succeeded - now send confirm to valet");
1348 GenericValetResponse<ValetConfirmResponse> gvr = this.vci.callValetConfirmRequest(msoRequest.getRequestId(), vnfName);
1349 // Nothing to really do here whether it succeeded or not other than log it.
1350 logger.debug("Return code from Confirm response is {}", gvr.getStatusCode());
1351 } catch (Exception e) {
1352 logger.error("Exception encountered while sending Confirm to Valet ", e);
1356 // On success, nothing is returned.
1361 public void updateVfModule (String cloudSiteId,
1367 String volumeGroupHeatStackId,
1368 String baseVfHeatStackId,
1369 String vfModuleStackId,
1370 String modelCustomizationUuid,
1371 Map <String, Object> inputs,
1372 MsoRequest msoRequest,
1373 Holder <Map <String, String>> outputs,
1374 Holder <VnfRollback> rollback) throws VnfException {
1375 String vfModuleName = vnfName;
1376 String vfModuleType = vnfType;
1377 String methodName = "updateVfModule";
1378 MsoLogger.setLogContext (msoRequest.getRequestId (), msoRequest.getServiceInstanceId ());
1379 String serviceName = VNF_ADAPTER_SERVICE_NAME + methodName;
1380 MsoLogger.setServiceName (serviceName);
1382 StringBuilder sbInit = new StringBuilder();
1383 sbInit.append("updateVfModule: \n");
1384 sbInit.append("cloudSiteId=" + cloudSiteId + "\n");
1385 sbInit.append("tenantId=" + tenantId + "\n");
1386 sbInit.append("vnfType=" + vnfType + "\n");
1387 sbInit.append("vnfVersion=" + vnfVersion + "\n");
1388 sbInit.append("vnfName=" + vnfName + "\n");
1389 sbInit.append("requestType=" + requestType + "\n");
1390 sbInit.append("volumeGroupHeatStackId=" + volumeGroupHeatStackId + "\n");
1391 sbInit.append("baseVfHeatStackId=" + baseVfHeatStackId + "\n");
1392 sbInit.append("vfModuleStackId=" + vfModuleStackId + "\n");
1393 sbInit.append("modelCustomizationUuid=" + modelCustomizationUuid + "\n");
1394 logger.debug(sbInit.toString());
1396 String mcu = modelCustomizationUuid;
1397 boolean useMCUuid = false;
1398 if (mcu != null && !mcu.isEmpty()) {
1399 if ("null".equalsIgnoreCase(mcu)) {
1400 logger.debug("modelCustomizationUuid: passed in as the string 'null' - will ignore: {}",
1401 modelCustomizationUuid);
1405 logger.debug("Found modelCustomizationUuid! Will use that: {}", mcu);
1410 String requestTypeString = "";
1411 if (requestType != null && !"".equals(requestType)) {
1412 requestTypeString = requestType;
1415 String nestedStackId = null;
1416 if (volumeGroupHeatStackId != null && !"".equals(volumeGroupHeatStackId) && !"null".equalsIgnoreCase(volumeGroupHeatStackId)) {
1417 nestedStackId = volumeGroupHeatStackId;
1419 String nestedBaseStackId = null;
1420 if (baseVfHeatStackId != null && !"".equals(baseVfHeatStackId) && !"null".equalsIgnoreCase(baseVfHeatStackId)) {
1421 nestedBaseStackId = baseVfHeatStackId;
1424 if (inputs == null) {
1425 // Create an empty set of inputs
1426 inputs = new HashMap<>();
1427 logger.debug("inputs == null - setting to empty");
1430 boolean isBaseRequest = false;
1431 boolean isVolumeRequest = false;
1432 if (requestTypeString.startsWith("VOLUME")) {
1433 isVolumeRequest = true;
1435 if ((vfModuleName == null || "".equals(vfModuleName.trim())) && vfModuleStackId != null) {
1436 vfModuleName = this.getVfModuleNameFromModuleStackId(vfModuleStackId);
1439 logger.debug ("Updating VFModule: " + vfModuleName + " of type " + vfModuleType + "in " + cloudSiteId + "/" + tenantId);
1440 logger.debug("requestTypeString = " + requestTypeString + ", nestedVolumeStackId = " + nestedStackId + ", nestedBaseStackId = " + nestedBaseStackId);
1442 // Will capture execution time for metrics
1443 long startTime = System.currentTimeMillis ();
1445 // Build a default rollback object (no actions performed)
1446 VnfRollback vfRollback = new VnfRollback ();
1447 vfRollback.setCloudSiteId (cloudSiteId);
1448 vfRollback.setTenantId (tenantId);
1449 vfRollback.setMsoRequest (msoRequest);
1450 vfRollback.setRequestType(requestTypeString);
1451 vfRollback.setVolumeGroupHeatStackId(volumeGroupHeatStackId);
1452 vfRollback.setBaseGroupHeatStackId(baseVfHeatStackId);
1453 vfRollback.setIsBase(isBaseRequest);
1454 vfRollback.setVfModuleStackId(vfModuleStackId);
1455 vfRollback.setModelCustomizationUuid(mcu);
1457 StackInfo heatStack = null;
1458 long queryStackStarttime = System.currentTimeMillis ();
1459 logger.debug("UpdateVfModule - querying for {}", vfModuleName);
1461 heatStack = heat.queryStack (cloudSiteId, tenantId, vfModuleName);
1462 } catch (MsoException me) {
1463 // Failed to query the Stack due to an openstack exception.
1464 // Convert to a generic VnfException
1465 me.addContext ("UpdateVFModule");
1466 String error = "Update VFModule: Query " + vfModuleName + " in " + cloudSiteId + "/" + tenantId + ": " + me;
1467 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vfModuleName, cloudSiteId,
1468 tenantId, "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError.getValue(), "Exception - QueryStack",
1470 logger.debug(error);
1471 throw new VnfException (me);
1474 //TODO - do we need to check for the other status possibilities?
1475 if (heatStack == null || heatStack.getStatus () == HeatStatus.NOTFOUND) {
1477 String error = "Update VF: Stack " + vfModuleName + " does not exist in " + cloudSiteId + "/" + tenantId;
1478 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_VNF_NOT_EXIST.toString(), vfModuleName, cloudSiteId,
1479 tenantId, "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError.getValue(), error);
1480 throw new VnfNotFound (cloudSiteId, tenantId, vfModuleName);
1482 logger.debug("Found Existing stack, status={}", heatStack.getStatus());
1483 // Populate the outputs from the existing stack.
1484 outputs.value = copyStringOutputs (heatStack.getOutputs ());
1485 rollback.value = vfRollback; // Default rollback - no updates performed
1488 // 1604 Cinder Volume support - handle a nestedStackId if sent (volumeGroupHeatStackId):
1489 StackInfo nestedHeatStack = null;
1490 long queryStackStarttime2 = System.currentTimeMillis ();
1491 Map<String, Object> nestedVolumeOutputs = null;
1492 if (nestedStackId != null) {
1494 logger.debug("Querying for nestedStackId = {}", nestedStackId);
1495 nestedHeatStack = heat.queryStack(cloudSiteId, tenantId, nestedStackId);
1496 } catch (MsoException me) {
1497 // Failed to query the Stack due to an openstack exception.
1498 // Convert to a generic VnfException
1499 me.addContext ("UpdateVFModule");
1500 String error = "Update VF: Attached heatStack ID Query " + nestedStackId + " in " + cloudSiteId + "/" + tenantId + ": " + me ;
1501 logger.error("{} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vnfName, cloudSiteId,
1502 tenantId, "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError.getValue(), "Exception - " + error,
1504 logger.debug("ERROR trying to query nested stack= {}", error);
1505 throw new VnfException (me);
1507 if (nestedHeatStack == null || nestedHeatStack.getStatus() == HeatStatus.NOTFOUND) {
1508 MsoLogger.setServiceName (serviceName);
1509 String error = "Update VFModule: Attached volume heatStack ID DOES NOT EXIST " + nestedStackId + " in " + cloudSiteId + "/" + tenantId + " USER ERROR" ;
1510 logger.error("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vnfName, cloudSiteId,
1511 tenantId, error, "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError.getValue(), error);
1512 logger.debug(error);
1513 throw new VnfException (error, MsoExceptionCategory.USERDATA);
1515 logger.debug("Found nested heat stack - copying values to inputs *later*");
1516 nestedVolumeOutputs = nestedHeatStack.getOutputs();
1517 heat.copyStringOutputsToInputs(inputs, nestedHeatStack.getOutputs(), false);
1520 // handle a nestedBaseStackId if sent - this is the stack ID of the base.
1521 StackInfo nestedBaseHeatStack = null;
1522 Map<String, Object> baseStackOutputs = null;
1523 if (nestedBaseStackId != null) {
1524 long queryStackStarttime3 = System.currentTimeMillis ();
1526 logger.debug("Querying for nestedBaseStackId = {}", nestedBaseStackId);
1527 nestedBaseHeatStack = heat.queryStack(cloudSiteId, tenantId, nestedBaseStackId);
1528 } catch (MsoException me) {
1529 // Failed to query the Stack due to an openstack exception.
1530 // Convert to a generic VnfException
1531 me.addContext ("UpdateVfModule");
1532 String error = "Update VFModule: Attached baseHeatStack ID Query " + nestedBaseStackId + " in " + cloudSiteId + "/" + tenantId + ": " + me ;
1534 .error("{} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vfModuleName, cloudSiteId,
1535 tenantId, "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError.getValue(),
1536 "Exception - " + error, me);
1537 logger.debug("ERROR trying to query nested base stack= {}", error);
1538 throw new VnfException (me);
1540 if (nestedBaseHeatStack == null || nestedBaseHeatStack.getStatus() == HeatStatus.NOTFOUND) {
1541 MsoLogger.setServiceName (serviceName);
1542 String error = "Update VFModule: Attached base heatStack ID DOES NOT EXIST " + nestedBaseStackId + " in " + cloudSiteId + "/" + tenantId + " USER ERROR" ;
1543 logger.error ("{} {} {} {} {} {} {} {} {}", MessageEnum.RA_QUERY_VNF_ERR.toString(), vfModuleName,
1544 cloudSiteId, tenantId, error, "OpenStack",
1545 "QueryStack", MsoLogger.ErrorCode.DataError.getValue(), error);
1546 logger.debug(error);
1547 throw new VnfException (error, MsoExceptionCategory.USERDATA);
1549 logger.debug("Found nested base heat stack - copying values to inputs *later*");
1550 baseStackOutputs = nestedBaseHeatStack.getOutputs();
1551 heat.copyStringOutputsToInputs(inputs, nestedBaseHeatStack.getOutputs(), false);
1555 // Ready to deploy the new VNF
1559 // Retrieve the VF definition
1560 VnfResource vnfResource = null;
1562 VfModuleCustomization vfmc = null;
1564 vfmc = vfModuleCustomRepo.findByModelCustomizationUUID(modelCustomizationUuid);
1565 vf = vfmc != null ? vfmc.getVfModule() : null;
1567 logger.debug("Unable to find a vfModule matching modelCustomizationUuid={}", mcu);
1570 logger.debug("1707 and later - MUST PROVIDE Model Customization UUID!");
1573 String error = "Update VfModule: unable to find vfModule with modelCustomizationUuid=" + mcu;
1574 logger.error("{} {} {} {} {} {}", MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "VF Module Type",
1575 vfModuleType, "OpenStack", MsoLogger.ErrorCode.DataError.getValue(), error);
1576 throw new VnfException(error, MsoExceptionCategory.USERDATA);
1578 logger.debug("Got VF module definition from Catalog: {}", vf.toString());
1579 if (vf.getIsBase()) {
1580 isBaseRequest = true;
1581 logger.debug("This a BASE update request");
1583 logger.debug("This is *not* a BASE VF update request");
1584 if (!isVolumeRequest && nestedBaseStackId == null) {
1585 logger.debug("DANGER WILL ROBINSON! This is unexpected - no nestedBaseStackId with this non-base request");
1589 //1607 - Add version check
1590 // First - see if it's in the VnfResource record
1591 // if we have a vf Module - then we have to query to get the VnfResource record.
1592 if (vf.getModelUUID() != null) {
1593 String vnfResourceModelUuid = vf.getModelUUID();
1595 vnfResource = vf.getVnfResources();
1596 if (vnfResource == null) {
1597 logger.debug("Unable to find vnfResource at ? will not error for now...", vnfResourceModelUuid);
1601 String minVersionVnf = null;
1602 String maxVersionVnf = null;
1603 if (vnfResource != null) {
1605 minVersionVnf = vnfResource.getAicVersionMin();
1606 maxVersionVnf = vnfResource.getAicVersionMax();
1607 } catch (Exception e) {
1608 logger.debug("Unable to pull min/max version for this VNF Resource entry",e);
1609 minVersionVnf = null;
1610 maxVersionVnf = null;
1612 if (minVersionVnf != null && "".equals(minVersionVnf)) {
1613 minVersionVnf = null;
1615 if (maxVersionVnf != null && "".equals(maxVersionVnf)) {
1616 maxVersionVnf = null;
1619 if (minVersionVnf != null && maxVersionVnf != null) {
1620 MavenLikeVersioning aicV = new MavenLikeVersioning();
1623 if (this.cloudConfig != null) {
1624 Optional<CloudSite> cloudSiteOpt = this.cloudConfig.getCloudSite(cloudSiteId);
1625 if (cloudSiteOpt.isPresent()) {
1626 aicV.setVersion(cloudSiteOpt.get().getCloudVersion());
1627 boolean moreThanMin = true;
1628 boolean equalToMin = true;
1629 boolean moreThanMax = true;
1630 boolean equalToMax = true;
1631 boolean doNotTest = false;
1633 moreThanMin = aicV.isMoreRecentThan(minVersionVnf);
1634 equalToMin = aicV.isTheSameVersion(minVersionVnf);
1635 moreThanMax = aicV.isMoreRecentThan(maxVersionVnf);
1636 equalToMax = aicV.isTheSameVersion(maxVersionVnf);
1637 } catch (Exception e) {
1638 logger.debug("An exception occured while trying to test AIC Version {} - will default to not check",
1643 if ((moreThanMin || equalToMin) // aic >= min
1644 && ((equalToMax) || !(moreThanMax))) { // aic <= max
1646 "VNF Resource " + vnfResource.getModelName() + " VersionMin=" + minVersionVnf + " VersionMax:"
1647 + maxVersionVnf + " supported on Cloud: " + cloudSiteId + " with AIC_Version:" + aicV);
1650 String error = "VNF Resource type: " + vnfResource.getModelName() + " VersionMin="
1651 + minVersionVnf + " VersionMax:" + maxVersionVnf + " NOT supported on Cloud: "
1652 + cloudSiteId + " with AIC_Version:" + aicV;
1653 logger.error("{} {} {} {} {}", MessageEnum.RA_CONFIG_EXC.toString(), error, "OpenStack",
1654 MsoLogger.ErrorCode.BusinessProcesssError.getValue(), "Exception - setVersion");
1655 logger.debug(error);
1656 throw new VnfException(error, MsoExceptionCategory.USERDATA);
1659 logger.debug("bypassing testing AIC version...");
1661 } // let this error out downstream to avoid introducing uncertainty at this stage
1663 logger.debug("cloudConfig is NULL - cannot check cloud site version");
1667 logger.debug("AIC Version not set in VNF_Resource - do not error for now - not checked.");
1669 // End Version check 1607
1671 HeatTemplate heatTemplate = null;
1672 HeatEnvironment heatEnvironment = null;
1673 if (isVolumeRequest) {
1674 heatTemplate = vf.getVolumeHeatTemplate();
1675 heatEnvironment = vfmc.getVolumeHeatEnv();
1677 heatTemplate = vf.getModuleHeatTemplate();
1678 heatEnvironment = vfmc.getHeatEnvironment();
1681 if (heatTemplate == null) {
1682 String error = "UpdateVF: No Heat Template ID defined in catalog database for " + vfModuleType + ", reqType=" + requestTypeString;
1684 .error("{} {} {} {} {} {}", MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "Heat Template ID", vfModuleType,
1685 "OpenStack", MsoLogger.ErrorCode.DataError.getValue(), error);
1686 throw new VnfException(error, MsoExceptionCategory.INTERNAL);
1688 logger.debug("Got HEAT Template from DB: {}", heatTemplate.getHeatTemplate());
1691 if (heatEnvironment == null) {
1692 String error = "Update VNF: undefined Heat Environment. VF=" + vfModuleType;
1693 logger.error("{} {} {} {} {}", MessageEnum.RA_VNF_UNKNOWN_PARAM.toString(), "Heat Environment ID",
1694 "OpenStack", MsoLogger.ErrorCode.DataError.getValue(), error);
1695 throw new VnfException (error, MsoExceptionCategory.INTERNAL);
1697 logger.debug ("Got Heat Environment from DB: {}", heatEnvironment.getEnvironment());
1700 logger.debug("In MsoVnfAdapterImpl, about to call db.getNestedTemplates avec templateId={}",
1701 heatTemplate.getArtifactUuid());
1704 List<HeatTemplate> nestedTemplates = heatTemplate.getChildTemplates();
1705 Map <String, Object> nestedTemplatesChecked = new HashMap <> ();
1706 if (nestedTemplates != null && !nestedTemplates.isEmpty()) {
1707 // for debugging print them out
1708 logger.debug("Contents of nestedTemplates - to be added to files: on stack:");
1709 for (HeatTemplate entry : nestedTemplates) {
1711 nestedTemplatesChecked.put (entry.getTemplateName(), entry.getTemplateBody());
1712 logger.debug(entry.getTemplateName() + " -> " + entry.getTemplateBody());
1715 logger.debug("No nested templates found - nothing to do here");
1716 nestedTemplatesChecked = null;
1719 // Also add the files: for any get_files associated with this VfModule
1720 // *if* there are any
1721 logger.debug("In MsoVnfAdapterImpl.updateVfModule, about to call db.getHeatFiles avec vfModuleId={}",
1724 List<HeatFiles> heatFiles = null;
1725 Map <String, Object> heatFilesObjects = new HashMap <> ();
1727 // Add ability to turn on adding get_files with volume requests (by property).
1728 boolean addGetFilesOnVolumeReq = false;
1730 String propertyString = this.environment.getProperty(MsoVnfAdapterImpl.ADD_GET_FILES_ON_VOLUME_REQ);
1731 if ("true".equalsIgnoreCase(propertyString) || "y".equalsIgnoreCase(propertyString)) {
1732 addGetFilesOnVolumeReq = true;
1733 logger.debug("AddGetFilesOnVolumeReq - setting to true! {}", propertyString);
1735 } catch (Exception e) {
1736 logger.debug("An error occured trying to get property {} - default to false",
1737 MsoVnfAdapterImpl.ADD_GET_FILES_ON_VOLUME_REQ, e);
1739 if (!isVolumeRequest || addGetFilesOnVolumeReq) {
1740 logger.debug("In MsoVnfAdapterImpl updateVfModule, about to call db.getHeatFilesForVfModule avec "
1741 + "vfModuleId={}", vf.getModelUUID());
1743 heatFiles = vf.getHeatFiles();
1744 if (heatFiles != null && !heatFiles.isEmpty()) {
1745 // add these to stack - to be done in createStack
1746 // here, we will map them to Map<String, Object> from Map<String, HeatFiles>
1747 // this will match the nested templates format
1748 logger.debug("Contents of heatFiles - to be added to files: on stack:");
1749 for (HeatFiles heatfile : heatFiles) {
1750 logger.debug(heatfile.getFileName() + " -> " + heatfile.getFileBody());
1751 heatFilesObjects.put(heatfile.getFileName(), heatfile.getFileBody());
1754 logger.debug("No heat files found -nothing to do here");
1755 heatFilesObjects = null;
1759 // Check that required parameters have been supplied
1760 String missingParams = null;
1761 List <String> paramList = new ArrayList <> ();
1763 // New for 1510 - consult the PARAM_ALIAS field to see if we've been
1764 // supplied an alias. Only check if we don't find it initially.
1765 // Also new in 1510 - don't flag missing parameters if there's an environment - because they might be there.
1766 // And also new - add parameter to turn off checking all together if we find we're blocking orders we
1768 boolean checkRequiredParameters = true;
1770 String propertyString = this.environment.getProperty (MsoVnfAdapterImpl.CHECK_REQD_PARAMS);
1771 if ("false".equalsIgnoreCase (propertyString) || "n".equalsIgnoreCase (propertyString)) {
1772 checkRequiredParameters = false;
1773 logger.debug("CheckRequiredParameters is FALSE. Will still check but then skip blocking...",
1774 MsoVnfAdapterImpl.CHECK_REQD_PARAMS);
1776 } catch (Exception e) {
1777 // No problem - default is true
1778 logger.debug ("An exception occured trying to get property {}", MsoVnfAdapterImpl.CHECK_REQD_PARAMS,
1781 // 1604 - Add enhanced environment & parameter checking
1782 // Part 1: parse envt entries to see if reqd parameter is there (before used a simple grep
1783 // Part 2: only submit to openstack the parameters in the envt that are in the heat template
1784 // Note this also removes any comments
1785 MsoHeatEnvironmentEntry mhee = null;
1786 if (heatEnvironment != null && heatEnvironment.getEnvironment().toLowerCase ().contains ("parameters:")) {
1787 logger.debug("Enhanced environment checking enabled - 1604");
1788 StringBuilder sb = new StringBuilder(heatEnvironment.getEnvironment());
1789 mhee = new MsoHeatEnvironmentEntry(sb);
1790 StringBuilder sb2 = new StringBuilder("\nHeat Template Parameters:\n");
1791 for (HeatTemplateParam parm : heatTemplate.getParameters()) {
1792 sb2.append("\t" + parm.getParamName() + ", required=" + parm.isRequired());
1794 if (!mhee.isValid()) {
1795 sb2.append("Environment says it's not valid! " + mhee.getErrorString());
1797 sb2.append("\nEnvironment:");
1798 sb2.append(mhee.toFullString());
1800 logger.debug(sb2.toString());
1802 logger.debug("NO ENVIRONMENT for this entry");
1804 // New for 1607 - support params of json type
1805 HashMap<String, JsonNode> jsonParams = new HashMap<>();
1806 boolean hasJson = false;
1808 for (HeatTemplateParam parm : heatTemplate.getParameters ()) {
1809 logger.debug ("Parameter:'" + parm.getParamName ()
1811 + parm.isRequired ()
1813 + parm.getParamAlias ());
1815 String parameterType = parm.getParamType();
1816 if (parameterType == null || "".equals(parameterType.trim())) {
1817 parameterType = "String";
1819 JsonNode jsonNode = null;
1820 if ("json".equalsIgnoreCase(parameterType) && inputs != null) {
1821 if (inputs.containsKey(parm.getParamName()) ) {
1823 String jsonString = null;
1825 jsonString = JSON_MAPPER.writeValueAsString(inputs.get(parm.getParamName()));
1826 jsonNode = JSON_MAPPER.readTree(jsonString);
1827 } catch (JsonParseException jpe) {
1828 //TODO - what to do here?
1829 //for now - send the error to debug, but just leave it as a String
1830 String errorMessage = jpe.getMessage();
1831 logger.debug("Json Error Converting " + parm.getParamName() + " - " + errorMessage,jpe);
1834 } catch (Exception e) {
1836 logger.debug("Json Error Converting " + parm.getParamName() + " " + e.getMessage(), e);
1840 if (jsonNode != null) {
1841 jsonParams.put(parm.getParamName(), jsonNode);
1843 } else if (inputs.containsKey(parm.getParamAlias())) {
1845 String jsonString = null;
1847 jsonString = (String)inputs.get(parm.getParamAlias());
1848 jsonNode = JSON_MAPPER.readTree(jsonString);
1849 } catch (JsonParseException jpe) {
1850 //TODO - what to do here?
1851 //for now - send the error to debug, but just leave it as a String
1852 String errorMessage = jpe.getMessage();
1853 logger.debug("Json Error Converting " + parm.getParamName() + " - " + errorMessage,jpe);
1856 } catch (Exception e) {
1858 logger.debug("Json Error Converting " + parm.getParamName() + " " + e.getMessage(), e);
1862 if (jsonNode != null) {
1863 // Notice here - we add it to the jsonParams hashMap with the actual name -
1864 // then manipulate the inputs so when we check for aliases below - it will not
1866 jsonParams.put(parm.getParamName(), jsonNode);
1867 inputs.remove(parm.getParamAlias());
1868 inputs.put(parm.getParamName(), jsonString);
1870 } //TODO add a check for the parameter in the env file
1873 if (parm.isRequired () && (inputs == null || !inputs.containsKey (parm.getParamName ()))) {
1874 if (inputs.containsKey (parm.getParamAlias ())) {
1875 // They've submitted using an alias name. Remove that from inputs, and add back using real name.
1876 String realParamName = parm.getParamName ();
1877 String alias = parm.getParamAlias ();
1878 Object value = inputs.get (alias);
1879 logger.debug ("*Found an Alias: paramName=" + realParamName
1884 inputs.remove (alias);
1885 inputs.put (realParamName, value);
1886 logger.debug ("{} entry removed from inputs, added back using {}", alias, realParamName);
1888 // enhanced - check if it's in the Environment (note: that method
1889 else if (mhee != null && mhee.containsParameter(parm.getParamName())) {
1891 logger.debug("Required parameter {} appears to be in environment - do not count as missing",
1892 parm.getParamName());
1895 logger.debug("adding to missing parameters list: {}", parm.getParamName());
1896 if (missingParams == null) {
1897 missingParams = parm.getParamName ();
1899 missingParams += "," + parm.getParamName ();
1903 paramList.add (parm.getParamName ());
1907 if (missingParams != null) {
1908 // Problem - missing one or more required parameters
1909 if (checkRequiredParameters) {
1910 String error = "Update VNF: Missing Required inputs: " + missingParams;
1911 logger.error("{} {} {} {} {}", MessageEnum.RA_MISSING_PARAM.toString(), missingParams, "OpenStack",
1912 MsoLogger.ErrorCode.DataError.getValue(), error);
1913 throw new VnfException (error, MsoExceptionCategory.USERDATA);
1915 logger.debug("found missing parameters - but checkRequiredParameters is false - will not block");
1918 logger.debug("No missing parameters found - ok to proceed");
1921 // Just submit the envt entry as received from the database
1922 String newEnvironmentString = null;
1924 newEnvironmentString = mhee.getRawEntry().toString();
1926 // Remove any extraneous parameters (don't throw an error)
1927 if (inputs != null) {
1928 List <String> extraParams = new ArrayList <> ();
1929 extraParams.addAll (inputs.keySet ());
1930 // This is not a valid parameter for this template
1931 extraParams.removeAll (paramList);
1932 if (!extraParams.isEmpty ()) {
1933 logger.warn("{} {} {} {} {} {}", MessageEnum.RA_VNF_EXTRA_PARAM.toString(), vnfType,
1934 extraParams.toString(), "OpenStack", MsoLogger.ErrorCode.DataError.getValue(), "Extra params");
1935 inputs.keySet ().removeAll (extraParams);
1938 Map<String, Object> goldenInputs = copyStringInputs(inputs);
1939 // 1607 - when we get here - we have clean inputs. Create inputsTwo in case we have json
1940 Map<String, Object> inputsTwo = null;
1941 if (hasJson && jsonParams.size() > 0) {
1942 inputsTwo = new HashMap<>();
1943 for (Map.Entry<String, Object> entry : inputs.entrySet()) {
1944 String keyParamName = entry.getKey();
1945 Object value = entry.getValue();
1946 if (jsonParams.containsKey(keyParamName)) {
1947 inputsTwo.put(keyParamName, jsonParams.get(keyParamName));
1949 inputsTwo.put(keyParamName, value);
1952 goldenInputs = inputsTwo;
1955 // "Fix" the template if it has CR/LF (getting this from Oracle)
1956 String template = heatTemplate.getHeatTemplate ();
1957 template = template.replaceAll ("\r\n", "\n");
1959 boolean isValetEnabled = this.checkBooleanProperty(MsoVnfAdapterImpl.VALET_ENABLED, false);
1960 boolean failRequestOnValetFailure = this.checkBooleanProperty(MsoVnfAdapterImpl.FAIL_REQUESTS_ON_VALET_FAILURE, false);
1961 logger.debug("isValetEnabled={}, failRequestsOnValetFailure={}", isValetEnabled, failRequestOnValetFailure);
1962 if (isVolumeRequest) {
1963 isValetEnabled = false;
1964 logger.debug("never send a volume request to valet");
1966 boolean sendResponseToValet = false;
1967 if (isValetEnabled) {
1968 Holder<Map<String, Object>> valetModifiedParamsHolder = new Holder<>();
1969 String parsedVfModuleName = this.getVfModuleNameFromModuleStackId(vfModuleStackId);
1970 // Make sure it is set to something.
1971 if (parsedVfModuleName == null || parsedVfModuleName.isEmpty()) {
1972 parsedVfModuleName = "unknown";
1974 sendResponseToValet = this.valetUpdateRequest(cloudSiteId, tenantId, heatFilesObjects,
1975 nestedTemplatesChecked, parsedVfModuleName, false, heatTemplate, newEnvironmentString, (HashMap<String, Object>) goldenInputs,
1976 msoRequest, inputs, failRequestOnValetFailure, valetModifiedParamsHolder);
1977 if (sendResponseToValet) {
1978 goldenInputs = valetModifiedParamsHolder.value;
1982 // Have the tenant. Now deploy the stack itself
1983 // Ignore MsoTenantNotFound and MsoStackAlreadyExists exceptions
1984 // because we already checked for those.
1985 long updateStackStarttime = System.currentTimeMillis ();
1987 heatStack = heatU.updateStack(
1994 heatTemplate.getTimeoutMinutes(),
1995 newEnvironmentString,
1996 //heatEnvironmentString,
1997 nestedTemplatesChecked,
2000 } catch (MsoException me) {
2001 me.addContext ("UpdateVFModule");
2002 String error = "Update VFModule " + vfModuleType + " in " + cloudSiteId + "/" + tenantId + ": " + me;
2004 .error("{} {} {} {} {} {} {}", MessageEnum.RA_UPDATE_VNF_ERR.toString(), vfModuleType, cloudSiteId,
2005 tenantId, "OpenStack", MsoLogger.ErrorCode.DataError.getValue(), "Exception - " + error, me);
2006 if (isValetEnabled && sendResponseToValet) {
2007 logger.debug("valet is enabled, the orchestration failed - now sending rollback to valet");
2009 GenericValetResponse<ValetRollbackResponse> gvr = this.vci.callValetRollbackRequest(msoRequest.getRequestId(), null, false, me.getMessage());
2010 // Nothing to really do here whether it succeeded or not other than log it.
2011 logger.debug("Return code from Rollback response is {}", gvr.getStatusCode());
2012 } catch (Exception e) {
2013 logger.error("Exception encountered while sending Rollback to Valet ", e);
2016 throw new VnfException (me);
2020 // Reach this point if updateStack is successful.
2021 // Populate remaining rollback info and response parameters.
2022 vfRollback.setVnfId (heatStack.getCanonicalName ());
2023 vfRollback.setVnfCreated (true);
2025 if (isValetEnabled && sendResponseToValet) {
2026 logger.debug("valet is enabled, the update succeeded - now send confirm to valet with stack id");
2028 GenericValetResponse<ValetConfirmResponse> gvr = this.vci.callValetConfirmRequest(msoRequest.getRequestId(), heatStack.getCanonicalName());
2029 // Nothing to really do here whether it succeeded or not other than log it.
2030 logger.debug("Return code from Confirm response is {}", gvr.getStatusCode());
2031 } catch (Exception e) {
2032 logger.error("Exception encountered while sending Confirm to Valet ", e);
2036 outputs.value = copyStringOutputs (heatStack.getOutputs ());
2037 rollback.value = vfRollback;
2041 private String getVfModuleNameFromModuleStackId(String vfModuleStackId) {
2042 // expected format of vfModuleStackId is "MSOTEST51-vSAMP3_base_module-0/1fc1f86c-7b35-447f-99a6-c23ec176ae24"
2043 // before the "/" is the vfModuleName and after the "/" is the heat stack id in Openstack
2044 if (vfModuleStackId == null)
2046 int index = vfModuleStackId.lastIndexOf('/');
2049 String vfModuleName = null;
2051 vfModuleName = vfModuleStackId.substring(0, index);
2052 } catch (Exception e) {
2053 logger.debug("Exception", e);
2054 vfModuleName = null;
2056 return vfModuleName;
2060 * Helper method to check a boolean property value - on error return provided default
2062 private boolean checkBooleanProperty(String propertyName, boolean defaultValue) {
2063 boolean property = defaultValue;
2065 String propertyString = this.environment.getProperty(propertyName);
2066 if ("true".equalsIgnoreCase(propertyString) || "y".equalsIgnoreCase(propertyString)) {
2068 } else if ("false".equalsIgnoreCase(propertyString) || "n".equalsIgnoreCase(propertyString)) {
2071 } catch (Exception e) {
2072 logger.debug("An exception occured trying to get property {} - defaulting to ", propertyName, defaultValue, e);
2073 property = defaultValue;
2079 * Helper method to combine getFiles and nestedTemplates in to a single Map
2081 private Map<String, Object> combineGetFilesAndNestedTemplates(Map<String, Object> getFiles, Map<String, Object> nestedTemplates) {
2082 boolean haveGetFiles = true;
2083 boolean haveNestedTemplates = true;
2084 Map<String, Object> files = new HashMap<String, Object>();
2085 if (getFiles == null || getFiles.isEmpty()) {
2086 haveGetFiles = false;
2088 if (nestedTemplates == null || nestedTemplates.isEmpty()) {
2089 haveNestedTemplates = false;
2091 if (haveGetFiles && haveNestedTemplates) {
2092 for (String keyString : getFiles.keySet ()) {
2093 files.put (keyString, getFiles.get (keyString));
2095 for (String keyString : nestedTemplates.keySet ()) {
2096 files.put (keyString, nestedTemplates.get (keyString));
2099 // Handle if we only have one or neither:
2103 if (haveNestedTemplates) {
2104 files = nestedTemplates;
2111 * Valet Create request
2113 private boolean valetCreateRequest(String cloudSiteId, String tenantId, Map<String, Object> heatFilesObjects, Map<String, Object> nestedTemplatesChecked,
2114 String vfModuleName, boolean backout, HeatTemplate heatTemplate, String newEnvironmentString, Map<String, Object> goldenInputs,
2115 MsoRequest msoRequest, Map<String, Object> inputs, boolean failRequestOnValetFailure, Holder<Map<String, Object>> valetModifiedParamsHolder) throws VnfException {
2116 boolean valetSucceeded = false;
2117 String valetErrorMessage = "more detail not available";
2119 String keystoneUrl = heat.getCloudSiteKeystoneUrl(cloudSiteId);
2120 Map<String, Object> files = this.combineGetFilesAndNestedTemplates(heatFilesObjects,
2121 nestedTemplatesChecked);
2122 HeatRequest heatRequest = new HeatRequest(vfModuleName, backout, heatTemplate.getTimeoutMinutes(),
2123 heatTemplate.getTemplateBody(), newEnvironmentString, files, goldenInputs);
2124 GenericValetResponse<ValetCreateResponse> createReq = this.vci.callValetCreateRequest(msoRequest.getRequestId(),
2125 cloudSiteId, tenantId, msoRequest.getServiceInstanceId(), (String)inputs.get("vnf_id"),
2126 (String)inputs.get("vnf_name"), (String)inputs.get("vf_module_id"), (String)inputs.get("vf_module_name"), keystoneUrl,
2128 ValetCreateResponse vcr = createReq.getReturnObject();
2129 if (vcr != null && createReq.getStatusCode() == 200) {
2130 ValetStatus status = vcr.getStatus();
2131 if (status != null) {
2132 String statusCode = status.getStatus(); // "ok" or "failed"
2133 if ("ok".equalsIgnoreCase(statusCode)) {
2134 Map<String, Object> newInputs = vcr.getParameters();
2135 if (newInputs != null) {
2136 Map<String, Object> oldGold = goldenInputs;
2137 logger.debug("parameters before being modified by valet:{}", oldGold.toString());
2138 goldenInputs = new HashMap<String, Object>();
2139 for (String key : newInputs.keySet()) {
2140 goldenInputs.put(key, newInputs.get(key));
2142 valetModifiedParamsHolder.value = goldenInputs;
2143 logger.debug("parameters after being modified by valet:{}", goldenInputs.toString());
2144 valetSucceeded = true;
2147 valetErrorMessage = status.getMessage();
2151 logger.debug("Got a bad response back from valet");
2152 valetErrorMessage = "Bad response back from Valet";
2153 valetSucceeded = false;
2155 } catch (Exception e) {
2156 logger.error("An exception occurred trying to call valet ...", e);
2157 valetSucceeded = false;
2158 valetErrorMessage = e.getMessage();
2160 if (failRequestOnValetFailure && !valetSucceeded) {
2161 // The valet request failed - and property says to fail the request
2162 //TODO Create a new exception class for valet?
2163 throw new VnfException("A failure occurred with Valet: " + valetErrorMessage);
2165 return valetSucceeded;
2169 * Valet update request
2172 private boolean valetUpdateRequest(String cloudSiteId, String tenantId,
2173 Map<String, Object> heatFilesObjects, Map<String, Object> nestedTemplatesChecked, String vfModuleName,
2174 boolean backout, HeatTemplate heatTemplate, String newEnvironmentString,
2175 Map<String, Object> goldenInputs, MsoRequest msoRequest, Map<String, Object> inputs,
2176 boolean failRequestOnValetFailure, Holder<Map<String, Object>> valetModifiedParamsHolder) throws VnfException {
2178 boolean valetSucceeded = false;
2179 String valetErrorMessage = "more detail not available";
2181 String keystoneUrl = heat.getCloudSiteKeystoneUrl(cloudSiteId);
2182 Map<String, Object> files = this.combineGetFilesAndNestedTemplates(heatFilesObjects,
2183 nestedTemplatesChecked);
2184 HeatRequest heatRequest = new HeatRequest(vfModuleName, false, heatTemplate.getTimeoutMinutes(),
2185 heatTemplate.getTemplateBody(), newEnvironmentString, files, goldenInputs);
2186 // vnf name is not sent to MSO on update requests - so we will set it to the vf module name for now
2187 GenericValetResponse<ValetUpdateResponse> updateReq = this.vci.callValetUpdateRequest(msoRequest.getRequestId(),
2188 cloudSiteId, tenantId, msoRequest.getServiceInstanceId(), (String)inputs.get("vnf_id"),
2189 vfModuleName, (String)inputs.get("vf_module_id"), vfModuleName, keystoneUrl,
2191 ValetUpdateResponse vur = updateReq.getReturnObject();
2192 if (vur != null && updateReq.getStatusCode() == 200) {
2193 ValetStatus status = vur.getStatus();
2194 if (status != null) {
2195 String statusCode = status.getStatus(); // "ok" or "failed"
2196 if ("ok".equalsIgnoreCase(statusCode)) {
2197 Map<String, Object> newInputs = vur.getParameters();
2198 if (newInputs != null) {
2199 Map<String, Object> oldGold = goldenInputs;
2200 logger.debug("parameters before being modified by valet:{}", oldGold.toString());
2201 goldenInputs = new HashMap<String, Object>();
2202 for (String key : newInputs.keySet()) {
2203 goldenInputs.put(key, newInputs.get(key));
2205 valetModifiedParamsHolder.value = goldenInputs;
2206 logger.debug("parameters after being modified by valet:{}", goldenInputs.toString());
2207 valetSucceeded = true;
2210 valetErrorMessage = status.getMessage();
2214 logger.debug("Got a bad response back from valet");
2215 valetErrorMessage = "Got a bad response back from valet";
2216 valetSucceeded = false;
2218 } catch (Exception e) {
2219 logger.error("An exception occurred trying to call valet - will continue processing for now...", e);
2220 valetErrorMessage = e.getMessage();
2221 valetSucceeded = false;
2223 if (failRequestOnValetFailure && !valetSucceeded) {
2224 // The valet request failed - and property says to fail the request
2225 // TODO Create a new exception class for valet?
2226 throw new VnfException("A failure occurred with Valet: " + valetErrorMessage);
2228 return valetSucceeded;
2232 * Valet delete request
2234 private boolean valetDeleteRequest(String cloudSiteId, String tenantId, String vnfName,
2235 MsoRequest msoRequest, boolean failRequestOnValetFailure) {
2236 boolean valetDeleteRequestSucceeded = false;
2237 String valetErrorMessage = "more detail not available";
2239 String vfModuleId = vnfName;
2240 String vfModuleName = vnfName;
2242 vfModuleName = vnfName.substring(0, vnfName.indexOf('/'));
2243 vfModuleId = vnfName.substring(vnfName.indexOf('/') + 1);
2244 } catch (Exception e) {
2245 // do nothing - send what we got for vnfName for both to valet
2246 logger.error("An exception occurred trying to call MsoVnfAdapterImpl.valetDeleteRequest() method", e);
2248 GenericValetResponse<ValetDeleteResponse> deleteReq = this.vci.callValetDeleteRequest(msoRequest.getRequestId(),
2249 cloudSiteId, tenantId, vfModuleId, vfModuleName);
2250 ValetDeleteResponse vdr = deleteReq.getReturnObject();
2251 if (vdr != null && deleteReq.getStatusCode() == 200) {
2252 ValetStatus status = vdr.getStatus();
2253 if (status != null) {
2254 String statusCode = status.getStatus(); // "ok" or "failed"
2255 if ("ok".equalsIgnoreCase(statusCode)) {
2256 logger.debug("delete request to valet returned success");
2257 valetDeleteRequestSucceeded = true;
2259 logger.debug("delete request to valet returned failure");
2260 valetDeleteRequestSucceeded = false;
2261 valetErrorMessage = status.getMessage();
2265 logger.debug("Got a bad response back from valet - delete request failed");
2266 valetDeleteRequestSucceeded = false;
2267 valetErrorMessage = "Got a bad response back from valet - delete request failed";
2269 } catch (Exception e) {
2270 logger.error("An exception occurred trying to call valet - valetDeleteRequest failed", e);
2271 valetDeleteRequestSucceeded = false;
2272 valetErrorMessage = e.getMessage();
2274 if (valetDeleteRequestSucceeded == false && failRequestOnValetFailure == true) {
2275 logger.error("ValetDeleteRequestFailed - del req still will be sent to openstack", new VnfException
2276 ("ValetDeleteRequestFailedError"));
2278 return valetDeleteRequestSucceeded;