2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.mso.adapters.vnf;
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.List;
28 import java.util.Scanner;
29 import java.util.regex.Matcher;
30 import java.util.regex.Pattern;
32 import javax.jws.WebService;
33 import javax.xml.ws.Holder;
35 import org.openecomp.mso.adapters.vnf.exceptions.VnfAlreadyExists;
36 import org.openecomp.mso.adapters.vnf.exceptions.VnfException;
37 import org.openecomp.mso.adapters.vnf.exceptions.VnfNotFound;
38 import org.openecomp.mso.cloud.CloudConfigFactory;
39 import org.openecomp.mso.cloud.CloudConfig;
40 import org.openecomp.mso.cloud.CloudSite;
41 import org.openecomp.mso.db.catalog.utils.MavenLikeVersioning;
42 import org.openecomp.mso.db.catalog.CatalogDatabase;
43 import org.openecomp.mso.db.catalog.beans.HeatEnvironment;
44 import org.openecomp.mso.db.catalog.beans.HeatFiles;
45 import org.openecomp.mso.db.catalog.beans.HeatTemplate;
46 import org.openecomp.mso.db.catalog.beans.HeatTemplateParam;
47 import org.openecomp.mso.db.catalog.beans.VnfResource;
48 import org.openecomp.mso.db.catalog.beans.VfModule;
49 import org.openecomp.mso.db.catalog.beans.VnfComponent;
50 import org.openecomp.mso.entity.MsoRequest;
51 import org.openecomp.mso.logger.MessageEnum;
52 import org.openecomp.mso.logger.MsoAlarmLogger;
53 import org.openecomp.mso.logger.MsoLogger;
54 import org.openecomp.mso.openstack.beans.HeatStatus;
55 import org.openecomp.mso.openstack.beans.StackInfo;
56 import org.openecomp.mso.openstack.beans.VnfStatus;
57 import org.openecomp.mso.openstack.beans.VnfRollback;
58 import org.openecomp.mso.openstack.exceptions.MsoException;
59 import org.openecomp.mso.openstack.exceptions.MsoExceptionCategory;
60 import org.openecomp.mso.openstack.utils.MsoHeatUtils;
61 import org.openecomp.mso.openstack.utils.MsoHeatUtilsWithUpdate;
62 import org.openecomp.mso.openstack.utils.MsoHeatEnvironmentEntry;
63 import org.openecomp.mso.properties.MsoPropertiesFactory;
65 import org.codehaus.jackson.JsonFactory;
66 import org.codehaus.jackson.JsonNode;
67 import org.codehaus.jackson.JsonParser;
68 import org.codehaus.jackson.JsonParseException;
69 import org.codehaus.jackson.map.ObjectMapper;
71 @WebService(serviceName = "VnfAdapter", endpointInterface = "org.openecomp.mso.adapters.vnf.MsoVnfAdapter", targetNamespace = "http://com.att.mso/vnf")
72 public class MsoVnfAdapterImpl implements MsoVnfAdapter {
74 CloudConfigFactory cloudConfigFactory = new CloudConfigFactory();
75 protected CloudConfig cloudConfig = null;
77 MsoPropertiesFactory msoPropertiesFactory=new MsoPropertiesFactory();
79 private static final String MSO_PROP_VNF_ADAPTER = "MSO_PROP_VNF_ADAPTER";
80 private static final String MSO_CONFIGURATION_ERROR = "MsoConfigurationError";
81 private static final String VNF_ADAPTER_SERVICE_NAME = "MSO-BPMN:MSO-VnfAdapter.";
82 private static final String LOG_REPLY_NAME = "MSO-VnfAdapter:MSO-BPMN.";
83 private static MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA);
84 private static MsoAlarmLogger alarmLogger = new MsoAlarmLogger ();
85 private static final String CHECK_REQD_PARAMS = "org.openecomp.mso.adapters.vnf.checkRequiredParameters";
86 private static final String ADD_GET_FILES_ON_VOLUME_REQ = "org.openecomp.mso.adapters.vnf.addGetFilesOnVolumeReq";
89 * Health Check web method. Does nothing but return to show the adapter is deployed.
92 public void healthCheck () {
93 LOGGER.debug ("Health check call in VNF Adapter");
97 * DO NOT use that constructor to instantiate this class, the msoPropertiesfactory will be NULL.
98 * @see MsoVnfAdapterImpl#MsoVnfAdapterImpl(MsoPropertiesFactory, CloudConfigFactory)
100 public MsoVnfAdapterImpl() {
105 * This constructor MUST be used if this class is called with the new operator.
106 * @param msoPropFactory
108 public MsoVnfAdapterImpl(MsoPropertiesFactory msoPropFactory, CloudConfigFactory cloudConfigFact) {
109 this.msoPropertiesFactory = msoPropFactory;
110 this.cloudConfigFactory = cloudConfigFact;
114 * This is the "Create VNF" web service implementation.
115 * It will create a new VNF of the requested type in the specified cloud
116 * and tenant. The tenant must exist before this service is called.
118 * If a VNF with the same name already exists, this can be considered a
119 * success or failure, depending on the value of the 'failIfExists' parameter.
121 * All VNF types will be defined in the MSO catalog. The caller must request
122 * one of these pre-defined types or an error will be returned. Within the
123 * catalog, each VNF type references (among other things) a Heat template
124 * which is used to deploy the required VNF artifacts (VMs, networks, etc.)
127 * Depending on the Heat template, a variable set of input parameters will
128 * be defined, some of which are required. The caller is responsible to
129 * pass the necessary input data for the VNF or an error will be thrown.
131 * The method returns the vnfId (the canonical name), a Map of VNF output
132 * attributes, and a VnfRollback object. This last object can be passed
133 * as-is to the rollbackVnf operation to undo everything that was created
134 * for the VNF. This is useful if a VNF is successfully created but the
135 * orchestrator fails on a subsequent operation.
137 * @param cloudSiteId CLLI code of the cloud site in which to create the VNF
138 * @param tenantId Openstack tenant identifier
139 * @param vnfType VNF type key, should match a VNF definition in catalog DB
140 * @param vnfVersion VNF version key, should match a VNF definition in catalog DB
141 * @param vnfName Name to be assigned to the new VNF
142 * @param inputs Map of key=value inputs for VNF stack creation
143 * @param failIfExists Flag whether already existing VNF should be considered
144 * a success or failure
145 * @param msoRequest Request tracking information for logs
146 * @param vnfId Holder for output VNF Openstack ID
147 * @param outputs Holder for Map of VNF outputs from heat (assigned IPs, etc)
148 * @param rollback Holder for returning VnfRollback object
151 public void createVnf (String cloudSiteId,
157 String volumeGroupHeatStackId,
158 Map <String, String> inputs,
159 Boolean failIfExists,
161 MsoRequest msoRequest,
162 Holder <String> vnfId,
163 Holder <Map <String, String>> outputs,
164 Holder <VnfRollback> rollback) throws VnfException {
165 // Create a hook here to catch shortcut createVf requests:
166 if (requestType != null) {
167 if (requestType.startsWith("VFMOD")) {
168 LOGGER.debug("Calling createVfModule from createVnf -- requestType=" + requestType);
169 String newRequestType = requestType.substring(5);
170 String vfVolGroupHeatStackId = "";
171 String vfBaseHeatStackId = "";
173 if (volumeGroupHeatStackId != null) {
174 vfVolGroupHeatStackId = volumeGroupHeatStackId.substring(0, volumeGroupHeatStackId.lastIndexOf("|"));
175 vfBaseHeatStackId = volumeGroupHeatStackId.substring(volumeGroupHeatStackId.lastIndexOf("|")+1);
177 } catch (Exception e) {
178 // might be ok - both are just blank
179 LOGGER.debug("ERROR trying to parse the volumeGroupHeatStackId " + volumeGroupHeatStackId);
181 this.createVfModule(cloudSiteId,
187 vfVolGroupHeatStackId,
199 // createVf will know if the requestType starts with "X" that it's the "old" way
200 StringBuilder newRequestTypeSb = new StringBuilder("X");
201 String vfVolGroupHeatStackId = "";
202 String vfBaseHeatStackId = "";
203 if (requestType != null) {
204 newRequestTypeSb.append(requestType);
206 this.createVfModule(cloudSiteId,
211 newRequestTypeSb.toString(),
212 vfVolGroupHeatStackId,
222 // End createVf shortcut
226 public void updateVnf (String cloudSiteId,
232 String volumeGroupHeatStackId,
233 Map <String, String> inputs,
234 MsoRequest msoRequest,
235 Holder <Map <String, String>> outputs,
236 Holder <VnfRollback> rollback) throws VnfException {
237 MsoLogger.setLogContext (msoRequest.getRequestId (), msoRequest.getServiceInstanceId ());
238 MsoLogger.setServiceName ("UpdateVnf");
239 String requestTypeString = "";
240 if (requestType != null && !requestType.equals("")) {
241 requestTypeString = requestType;
243 String nestedStackId = null;
244 if (volumeGroupHeatStackId != null && !volumeGroupHeatStackId.equals("")) {
245 nestedStackId = volumeGroupHeatStackId;
248 LOGGER.debug ("Updating VNF: " + vnfName + " of type " + vnfType + "in " + cloudSiteId + "/" + tenantId);
249 LOGGER.debug("requestTypeString = " + requestTypeString + ", nestedStackId = " + nestedStackId);
251 // Will capture execution time for metrics
252 long startTime = System.currentTimeMillis ();
254 // Build a default rollback object (no actions performed)
255 VnfRollback vnfRollback = new VnfRollback ();
256 vnfRollback.setCloudSiteId (cloudSiteId);
257 vnfRollback.setTenantId (tenantId);
258 vnfRollback.setMsoRequest (msoRequest);
259 vnfRollback.setRequestType(requestTypeString);
261 // First, look up to see if the VNF already exists.
262 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_VNF_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
263 MsoHeatUtilsWithUpdate heatU = new MsoHeatUtilsWithUpdate (MSO_PROP_VNF_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
265 StackInfo heatStack = null;
266 long queryStackStarttime1 = System.currentTimeMillis ();
268 heatStack = heat.queryStack (cloudSiteId, tenantId, vnfName);
269 LOGGER.recordMetricEvent (queryStackStarttime1, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", vnfName);
270 } catch (MsoException me) {
271 // Failed to query the Stack due to an openstack exception.
272 // Convert to a generic VnfException
273 me.addContext ("UpdateVNF");
274 String error = "Update VNF: Query " + vnfName + " in " + cloudSiteId + "/" + tenantId + ": " + me;
275 LOGGER.recordMetricEvent (queryStackStarttime1, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryStack", vnfName);
276 LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vnfName, cloudSiteId, tenantId, "OpenStack", "QueryStack", MsoLogger.ErrorCode.BusinessProcesssError, "Exception in updateVnf", me);
277 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
278 throw new VnfException (me);
281 if (heatStack == null || heatStack.getStatus () == HeatStatus.NOTFOUND) {
283 String error = "Update VNF: Stack " + vnfName + " does not exist in " + cloudSiteId + "/" + tenantId;
284 LOGGER.error (MessageEnum.RA_VNF_NOT_EXIST, vnfName, cloudSiteId, tenantId, "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, "Update VNF: Stack " + vnfName + " does not exist");
285 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
286 throw new VnfNotFound (cloudSiteId, tenantId, vnfName);
288 LOGGER.debug ("Found Existing stack, status=" + heatStack.getStatus ());
289 // Populate the outputs from the existing stack.
290 outputs.value = copyStringOutputs (heatStack.getOutputs ());
291 rollback.value = vnfRollback; // Default rollback - no updates performed
294 // 1604 Cinder Volume support - handle a nestedStackId if sent (volumeGroupHeatStackId):
295 StackInfo nestedHeatStack = null;
296 long queryStackStarttime2 = System.currentTimeMillis ();
297 if (nestedStackId != null) {
299 LOGGER.debug("Querying for nestedStackId = " + nestedStackId);
300 nestedHeatStack = heat.queryStack(cloudSiteId, tenantId, nestedStackId);
301 LOGGER.recordMetricEvent (queryStackStarttime2, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", vnfName);
302 } catch (MsoException me) {
303 // Failed to query the Stack due to an openstack exception.
304 // Convert to a generic VnfException
305 me.addContext ("UpdateVNF");
306 String error = "Update VNF: Attached heatStack ID Query " + nestedStackId + " in " + cloudSiteId + "/" + tenantId + ": " + me ;
307 LOGGER.recordMetricEvent (queryStackStarttime2, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryStack", vnfName);
308 LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vnfName, cloudSiteId, tenantId, "OpenStack", "QueryStack", MsoLogger.ErrorCode.AvailabilityError, "Exception trying to query nested stack", me);
309 LOGGER.debug("ERROR trying to query nested stack= " + error);
310 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
311 throw new VnfException (me);
313 if (nestedHeatStack == null || nestedHeatStack.getStatus() == HeatStatus.NOTFOUND) {
314 String error = "Update VNF: Attached heatStack ID DOES NOT EXIST " + nestedStackId + " in " + cloudSiteId + "/" + tenantId + " USER ERROR" ;
315 LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vnfName, cloudSiteId, tenantId, error, "OpenStack", "QueryStack", MsoLogger.ErrorCode.AvailabilityError, "Attached heatStack ID DOES NOT EXIST");
316 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
318 throw new VnfException (error, MsoExceptionCategory.USERDATA);
320 LOGGER.debug("Found nested heat stack - copying values to inputs");
321 this.sendMapToDebug(inputs);
322 heat.copyStringOutputsToInputs(inputs, nestedHeatStack.getOutputs(), false);
323 this.sendMapToDebug(inputs);
327 // Ready to deploy the new VNF
329 try(CatalogDatabase db = new CatalogDatabase ()) {
330 // Retrieve the VNF definition
332 if (vnfVersion != null && !vnfVersion.isEmpty ()) {
333 vnf = db.getVnfResource (vnfType, vnfVersion);
335 vnf = db.getVnfResource (vnfType);
338 String error = "Update VNF: Unknown VNF Type: " + vnfType;
339 LOGGER.error (MessageEnum.RA_VNF_UNKNOWN_PARAM, "VNF Type", vnfType, "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, "Update VNF: Unknown VNF Type");
340 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
341 throw new VnfException (error, MsoExceptionCategory.USERDATA);
343 LOGGER.debug ("Got VNF definition from Catalog: " + vnf.toString ());
345 // Currently, all VNFs are orchestrated via HEAT
346 if (!"HEAT".equals (vnf.getOrchestrationMode ())) {
347 String error = "Update VNF: Configuration error: VNF=" + vnfType;
348 LOGGER.error (MessageEnum.RA_CONFIG_EXC, " VNF=" + vnfType, "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, "Update VNF: Configuration error");
349 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
350 // Alarm on this error, configuration must be fixed
351 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
352 throw new VnfException (error, MsoExceptionCategory.INTERNAL);
355 //1604 - Need to handle an updateVolume request.
356 VnfComponent vnfComponent = null;
357 if (requestTypeString != null && !requestTypeString.equals("")) {
358 LOGGER.debug("About to query for vnfComponent id = " + vnf.getId() + ", type = " + requestTypeString.toUpperCase());
359 vnfComponent = db.getVnfComponent(vnf.getId(), requestTypeString.toUpperCase());
360 if (vnfComponent == null) {
361 String error = "Update VNF: Cannot find VNF Component entry for: " + vnfType + ", type = " + requestTypeString.toUpperCase();
362 LOGGER.error (MessageEnum.RA_VNF_UNKNOWN_PARAM, "VNF Type", vnfType, "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, "Update VNF: Cannot find VNF Component entry");
363 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
364 throw new VnfException (error, MsoExceptionCategory.USERDATA);
366 LOGGER.debug("FOUND VnfComponent: " + vnfComponent.toString());
369 HeatTemplate heatTemplate = db.getHeatTemplate (vnf.getTemplateId ());
370 if (heatTemplate == null) {
371 String error = "Update VNF: undefined Heat Template. VNF=" + vnfType;
372 LOGGER.error (MessageEnum.RA_VNF_UNKNOWN_PARAM, "Heat Template ID", String.valueOf(vnf.getTemplateId ()), "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, "Update VNF: undefined Heat Template");
373 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
374 // Alarm on this error, configuration must be fixed
375 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
377 throw new VnfException (error, MsoExceptionCategory.INTERNAL);
380 // If this is a component request - get the template associated for volumes
381 // May change this - for now get both templates - but volume will be 2nd, which makes sense
382 // for the rest of the code. Same with envt later
383 if (vnfComponent != null) {
384 LOGGER.debug("Querying db to find component template " + vnfComponent.getHeatTemplateId());
385 heatTemplate = db.getHeatTemplate(vnfComponent
386 .getHeatTemplateId());
387 if (heatTemplate == null) {
388 String error = "Update VNF: undefined Heat Template for Volume Component. VNF="
390 LOGGER.error(MessageEnum.RA_VNF_UNKNOWN_PARAM,
392 String.valueOf(vnfComponent.getHeatTemplateId()), "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, "Update VNF: undefined Heat Template for Volume Component");
393 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
394 alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR,
395 MsoAlarmLogger.CRITICAL, error);
396 throw new VnfException(error, MsoExceptionCategory.INTERNAL);
400 LOGGER.debug ("Got HEAT Template from DB: " + heatTemplate.toString ());
402 // Add check for any Environment variable
403 HeatEnvironment heatEnvironment = null;
404 String heatEnvironmentString = null;
406 if (vnf.getEnvironmentId () != null) {
407 LOGGER.debug ("about to call getHeatEnvironment with :" + vnf.getEnvironmentId () + ":");
408 heatEnvironment = db.getHeatEnvironment (vnf.getEnvironmentId ());
409 if (heatEnvironment == null) {
411 String error = "Create VNF: undefined Heat Environment. VNF=" + vnfType
412 + ", Environment ID="
413 + vnf.getEnvironmentId ();
414 LOGGER.error (MessageEnum.RA_VNF_UNKNOWN_PARAM, "Heat Environment ID", String.valueOf(vnf.getEnvironmentId ()), "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, "Create VNF: undefined Heat Environment");
415 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
416 // Alarm on this error, configuration must be fixed
417 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
419 throw new VnfException (error, MsoExceptionCategory.INTERNAL);
421 LOGGER.debug ("Got Heat Environment from DB: " + heatEnvironment.toString ());
422 heatEnvironmentString = heatEnvironment.getEnvironment (); //this.parseEnvironment (heatEnvironment.getEnvironment ());
423 LOGGER.debug ("After parsing: " + heatEnvironmentString);
426 LOGGER.debug ("no environment parameter for this VNF " + vnfType);
429 //1604 - override the VNF environment with the one for the component
430 if(vnfComponent != null) {
431 if (vnfComponent.getHeatEnvironmentId () != null) {
432 LOGGER.debug ("about to call getHeatEnvironment with :" + vnfComponent.getHeatEnvironmentId () + ":");
433 heatEnvironment = db.getHeatEnvironment (vnfComponent.getHeatEnvironmentId ());
434 if (heatEnvironment == null) {
435 String error = "Update VNF: undefined Heat Environment. VNF=" + vnfType
436 + ", Environment ID="
437 + vnfComponent.getHeatEnvironmentId ();
438 LOGGER.error (MessageEnum.RA_VNF_UNKNOWN_PARAM, "Heat Environment ID", String.valueOf(vnfComponent.getHeatEnvironmentId ()), "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, "Update VNF: undefined Heat Environment");
439 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
440 // Alarm on this error, configuration must be fixed
441 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
443 throw new VnfException (error, MsoExceptionCategory.INTERNAL);
445 LOGGER.debug ("Got Heat Environment from DB: " + heatEnvironment.toString ());
446 heatEnvironmentString = heatEnvironment.getEnvironment (); //this.parseEnvironment (heatEnvironment.getEnvironment ());
447 LOGGER.debug ("after parsing: " + heatEnvironmentString);
450 LOGGER.debug ("no environment parameter for this VNF VOLUME component " + vnfType);
456 LOGGER.debug ("In MsoVnfAdapterImpl, about to call db.getNestedTemplates avec templateId="
457 + heatTemplate.getId ());
458 Map <String, Object> nestedTemplates = db.getNestedTemplates (heatTemplate.getId ());
459 Map <String, Object> nestedTemplatesChecked = new HashMap <String, Object> ();
460 if (nestedTemplates != null) {
461 // for debugging print them out
462 LOGGER.debug ("Contents of nestedTemplates - to be added to files: on stack:");
463 for (String providerResourceFile : nestedTemplates.keySet ()) {
464 String providerResourceFileChecked = providerResourceFile; //this.enforceFilePrefix (providerResourceFile);
465 String childTemplateBody = (String) nestedTemplates.get (providerResourceFile);
466 nestedTemplatesChecked.put (providerResourceFileChecked, childTemplateBody);
467 LOGGER.debug (providerResourceFileChecked + " -> " + childTemplateBody);
470 LOGGER.debug ("No nested templates found - nothing to do here");
471 nestedTemplatesChecked = null;
474 // Also add the files: for any get_files associated with this vnf_resource_id
475 // *if* there are any
476 LOGGER.debug ("In MsoVnfAdapterImpl.updateVnf, about to call db.getHeatFiles avec vnfResourceId="
478 Map <String, HeatFiles> heatFiles = db.getHeatFiles (vnf.getId ());
479 Map <String, Object> heatFilesObjects = new HashMap <String, Object> ();
480 if (heatFiles != null) {
481 // add these to stack - to be done in createStack
482 // here, we will map them to Map<String, Object> from Map<String, HeatFiles>
483 // this will match the nested templates format
484 LOGGER.debug ("Contents of heatFiles - to be added to files: on stack:");
486 for (String heatFileName : heatFiles.keySet ()) {
487 String heatFileBody = heatFiles.get (heatFileName).getFileBody ();
488 // Remove the file:/// enforcement for get_file:
489 //String heatFileNameChecked = this.enforceFilePrefix (heatFileName);
490 String heatFileNameChecked = heatFileName;
491 LOGGER.debug (heatFileNameChecked + " -> " + heatFileBody);
492 heatFilesObjects.put (heatFileNameChecked, heatFileBody);
495 LOGGER.debug ("No heat files found -nothing to do here");
496 heatFilesObjects = null;
499 // Check that required parameters have been supplied
500 String missingParams = null;
501 List <String> paramList = new ArrayList <String> ();
503 // New for 1510 - consult the PARAM_ALIAS field to see if we've been
504 // supplied an alias. Only check if we don't find it initially.
505 // Also new in 1510 - don't flag missing parameters if there's an environment - because they might be there.
506 // And also new - add parameter to turn off checking all together if we find we're blocking orders we
508 boolean haveEnvironmentParameters = false;
509 boolean checkRequiredParameters = true;
511 String propertyString = msoPropertiesFactory.getMsoJavaProperties (MSO_PROP_VNF_ADAPTER)
512 .getProperty (MsoVnfAdapterImpl.CHECK_REQD_PARAMS,null);
513 if ("false".equalsIgnoreCase (propertyString) || "n".equalsIgnoreCase (propertyString)) {
514 checkRequiredParameters = false;
515 LOGGER.debug ("CheckRequiredParameters is FALSE. Will still check but then skip blocking..."
516 + MsoVnfAdapterImpl.CHECK_REQD_PARAMS);
518 } catch (Exception e) {
519 // No problem - default is true
520 LOGGER.debug ("An exception occured trying to get property " + MsoVnfAdapterImpl.CHECK_REQD_PARAMS, e);
522 // 1604 - Add enhanced environment & parameter checking
523 // Part 1: parse envt entries to see if reqd parameter is there (before used a simple grep
524 // Part 2: only submit to openstack the parameters in the envt that are in the heat template
525 // Note this also removes any comments
526 MsoHeatEnvironmentEntry mhee = null;
527 if (heatEnvironmentString != null && heatEnvironmentString.toLowerCase ().contains ("parameters:")) {
528 LOGGER.debug("Enhanced environment checking enabled - 1604");
529 haveEnvironmentParameters = true;
530 StringBuilder sb = new StringBuilder(heatEnvironmentString);
531 //LOGGER.debug("About to create MHEE with " + sb);
532 mhee = new MsoHeatEnvironmentEntry(sb);
533 StringBuilder sb2 = new StringBuilder("\nHeat Template Parameters:\n");
534 for (HeatTemplateParam parm : heatTemplate.getParameters()) {
535 sb2.append("\t" + parm.getParamName() + ", required=" + parm.isRequired());
537 if (!mhee.isValid()) {
538 sb2.append("Environment says it's not valid! " + mhee.getErrorString());
540 sb2.append("\nEnvironment:");
541 sb2.append(mhee.toFullString());
543 LOGGER.debug(sb2.toString());
545 LOGGER.debug("NO ENVIRONMENT for this entry");
548 for (HeatTemplateParam parm : heatTemplate.getParameters ()) {
549 LOGGER.debug ("Parameter:'" + parm.getParamName ()
553 + parm.getParamAlias ());
554 if (parm.isRequired () && (inputs == null || !inputs.containsKey (parm.getParamName ()))) {
555 if (inputs.containsKey (parm.getParamAlias ())) {
556 // They've submitted using an alias name. Remove that from inputs, and add back using real name.
557 String realParamName = parm.getParamName ();
558 String alias = parm.getParamAlias ();
559 String value = inputs.get (alias);
560 LOGGER.debug ("*Found an Alias: paramName=" + realParamName
565 inputs.remove (alias);
566 inputs.put (realParamName, value);
567 LOGGER.debug (alias + " entry removed from inputs, added back using " + realParamName);
569 // enhanced - check if it's in the Environment (note: that method
570 else if (mhee != null && mhee.containsParameter(parm.getParamName())) {
572 LOGGER.debug ("Required parameter " + parm.getParamName ()
573 + " appears to be in environment - do not count as missing");
576 LOGGER.debug ("adding to missing parameters list: " + parm.getParamName ());
577 if (missingParams == null) {
578 missingParams = parm.getParamName ();
580 missingParams += "," + parm.getParamName ();
584 paramList.add (parm.getParamName ());
586 if (missingParams != null) {
587 // Problem - missing one or more required parameters
588 if (checkRequiredParameters) {
589 String error = "Update VNF: Missing Required inputs: " + missingParams;
590 LOGGER.error (MessageEnum.RA_MISSING_PARAM, missingParams, "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, "Update VNF: Missing Required inputs");
591 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
592 throw new VnfException (error, MsoExceptionCategory.USERDATA);
594 LOGGER.debug ("found missing parameters - but checkRequiredParameters is false - will not block");
597 LOGGER.debug ("No missing parameters found - ok to proceed");
600 // Here - modify heatEnvironmentString
601 StringBuilder parsedEnvironmentString = null;
602 String newEnvironmentString = null;
604 LOGGER.debug("Environment before:\n" + heatEnvironmentString);
605 parsedEnvironmentString = mhee.toFullStringExcludeNonParams(heatTemplate.getParameters());
606 LOGGER.debug("Environment after:\n" + parsedEnvironmentString.toString());
607 newEnvironmentString = parsedEnvironmentString.toString();
610 // Remove any extraneous parameters (don't throw an error)
611 if (inputs != null) {
612 List <String> extraParams = new ArrayList <String> ();
613 extraParams.addAll (inputs.keySet ());
614 // This is not a valid parameter for this template
615 extraParams.removeAll (paramList);
616 if (!extraParams.isEmpty ()) {
617 LOGGER.warn (MessageEnum.RA_VNF_EXTRA_PARAM, vnfType, extraParams.toString(), "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, "VNF Extra params");
618 inputs.keySet ().removeAll (extraParams);
622 // "Fix" the template if it has CR/LF (getting this from Oracle)
623 String template = heatTemplate.getHeatTemplate ();
624 template = template.replaceAll ("\r\n", "\n");
626 // Have the tenant. Now deploy the stack itself
627 // Ignore MsoTenantNotFound and MsoStackAlreadyExists exceptions
628 // because we already checked for those.
629 long updateStackStarttime = System.currentTimeMillis ();
631 heatStack = heatU.updateStack (cloudSiteId,
635 copyStringInputs (inputs),
637 heatTemplate.getTimeoutMinutes (),
638 newEnvironmentString,
639 //heatEnvironmentString,
640 nestedTemplatesChecked,
642 LOGGER.recordMetricEvent (updateStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "UpdateStack", vnfName);
643 } catch (MsoException me) {
644 me.addContext ("UpdateVNF");
645 String error = "Update VNF " + vnfType + " in " + cloudSiteId + "/" + tenantId + ": " + me;
646 LOGGER.recordMetricEvent (updateStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "UpdateStack", vnfName);
647 LOGGER.error (MessageEnum.RA_UPDATE_VNF_ERR, vnfType, cloudSiteId, tenantId, "OpenStack", "updateStack", MsoLogger.ErrorCode.DataError, "Exception - updateStack", me);
648 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
649 throw new VnfException (me);
653 // Reach this point if updateStack is successful.
654 // Populate remaining rollback info and response parameters.
655 vnfRollback.setVnfId (heatStack.getCanonicalName ());
656 vnfRollback.setVnfCreated (true);
658 outputs.value = copyStringOutputs (heatStack.getOutputs ());
659 rollback.value = vnfRollback;
660 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully update VNF");
665 * This is the "Query VNF" web service implementation.
666 * It will look up a VNF by name or ID in the specified cloud and tenant.
668 * The method returns an indicator that the VNF exists, its Openstack internal
669 * ID, its status, and the set of outputs (from when the stack was created).
671 * @param cloudSiteId CLLI code of the cloud site in which to query
672 * @param tenantId Openstack tenant identifier
673 * @param vnfName VNF Name or Openstack ID
674 * @param msoRequest Request tracking information for logs
675 * @param vnfExists Flag reporting the result of the query
676 * @param vnfId Holder for output VNF Openstack ID
677 * @param outputs Holder for Map of VNF outputs from heat (assigned IPs, etc)
680 public void queryVnf (String cloudSiteId,
683 MsoRequest msoRequest,
684 Holder <Boolean> vnfExists,
685 Holder <String> vnfId,
686 Holder <VnfStatus> status,
687 Holder <Map <String, String>> outputs) throws VnfException {
688 MsoLogger.setLogContext (msoRequest);
689 MsoLogger.setServiceName ("QueryVnf");
690 LOGGER.debug ("Querying VNF " + vnfName + " in " + cloudSiteId + "/" + tenantId);
692 // Will capture execution time for metrics
693 long startTime = System.currentTimeMillis ();
695 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_VNF_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
697 StackInfo heatStack = null;
698 long subStartTime = System.currentTimeMillis ();
700 heatStack = heat.queryStack (cloudSiteId, tenantId, vnfName);
701 LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", vnfName);
702 } catch (MsoException me) {
703 me.addContext ("QueryVNF");
704 // Failed to query the Stack due to an openstack exception.
705 // Convert to a generic VnfException
706 String error = "Query VNF: " + vnfName + " in " + cloudSiteId + "/" + tenantId + ": " + me;
707 LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryStack", vnfName);
708 LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vnfName, cloudSiteId, tenantId, "OpenStack", "QueryVNF", MsoLogger.ErrorCode.DataError, "Exception - queryStack", me);
709 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
710 throw new VnfException (me);
713 // Populate the outputs based on the returned Stack information
715 if (heatStack == null || heatStack.getStatus () == HeatStatus.NOTFOUND) {
717 vnfExists.value = Boolean.FALSE;
718 status.value = VnfStatus.NOTFOUND;
720 outputs.value = new HashMap <String, String> (); // Return as an empty map
722 LOGGER.debug ("VNF " + vnfName + " not found");
724 vnfExists.value = Boolean.TRUE;
725 status.value = stackStatusToVnfStatus (heatStack.getStatus ());
726 vnfId.value = heatStack.getCanonicalName ();
727 outputs.value = copyStringOutputs (heatStack.getOutputs ());
729 LOGGER.debug ("VNF " + vnfName + " found, ID = " + vnfId.value);
731 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully query VNF");
736 * This is the "Delete VNF" web service implementation.
737 * It will delete a VNF by name or ID in the specified cloud and tenant.
739 * The method has no outputs.
741 * @param cloudSiteId CLLI code of the cloud site in which to delete
742 * @param tenantId Openstack tenant identifier
743 * @param vnfName VNF Name or Openstack ID
744 * @param msoRequest Request tracking information for logs
747 public void deleteVnf (String cloudSiteId,
750 MsoRequest msoRequest) throws VnfException {
751 MsoLogger.setLogContext (msoRequest);
752 MsoLogger.setServiceName ("DeleteVnf");
753 LOGGER.debug ("Deleting VNF " + vnfName + " in " + cloudSiteId + "/" + tenantId);
754 // Will capture execution time for metrics
755 long startTime = System.currentTimeMillis ();
757 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_VNF_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
759 // Use the MsoHeatUtils to delete the stack. Set the polling flag to true.
760 // The possible outcomes of deleteStack are a StackInfo object with status
761 // of NOTFOUND (on success) or FAILED (on error). Also, MsoOpenstackException
763 long subStartTime = System.currentTimeMillis ();
765 heat.deleteStack (tenantId, cloudSiteId, vnfName, true);
766 LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteStack", vnfName);
767 } catch (MsoException me) {
768 me.addContext ("DeleteVNF");
769 // Failed to query the Stack due to an openstack exception.
770 // Convert to a generic VnfException
771 String error = "Delete VNF: " + vnfName + " in " + cloudSiteId + "/" + tenantId + ": " + me;
772 LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteStack", vnfName);
773 LOGGER.error (MessageEnum.RA_DELETE_VNF_ERR, vnfName, cloudSiteId, tenantId, "OpenStack", "DeleteVNF", MsoLogger.ErrorCode.DataError, "Exception - DeleteVNF", me);
774 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
775 throw new VnfException (me);
778 // On success, nothing is returned.
779 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully delete VNF");
784 * This web service endpoint will rollback a previous Create VNF operation.
785 * A rollback object is returned to the client in a successful creation
786 * response. The client can pass that object as-is back to the rollbackVnf
787 * operation to undo the creation.
790 public void rollbackVnf (VnfRollback rollback) throws VnfException {
791 long startTime = System.currentTimeMillis ();
792 MsoLogger.setServiceName ("RollbackVnf");
793 // rollback may be null (e.g. if stack already existed when Create was called)
794 if (rollback == null) {
795 LOGGER.info (MessageEnum.RA_ROLLBACK_NULL, "OpenStack", "rollbackVnf");
796 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, "Rollback request content is null");
800 // Get the elements of the VnfRollback object for easier access
801 String cloudSiteId = rollback.getCloudSiteId ();
802 String tenantId = rollback.getTenantId ();
803 String vnfId = rollback.getVnfId ();
805 MsoLogger.setLogContext (rollback.getMsoRequest());
807 LOGGER.debug ("Rolling Back VNF " + vnfId + " in " + cloudSiteId + "/" + tenantId);
809 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_VNF_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
811 // Use the MsoHeatUtils to delete the stack. Set the polling flag to true.
812 // The possible outcomes of deleteStack are a StackInfo object with status
813 // of NOTFOUND (on success) or FAILED (on error). Also, MsoOpenstackException
815 long subStartTime = System.currentTimeMillis ();
817 heat.deleteStack (tenantId, cloudSiteId, vnfId, true);
818 LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteStack", null);
819 } catch (MsoException me) {
820 // Failed to rollback the Stack due to an openstack exception.
821 // Convert to a generic VnfException
822 me.addContext ("RollbackVNF");
823 String error = "Rollback VNF: " + vnfId + " in " + cloudSiteId + "/" + tenantId + ": " + me;
824 LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteStack", null);
825 LOGGER.error (MessageEnum.RA_DELETE_VNF_ERR, vnfId, cloudSiteId, tenantId, "OpenStack", "DeleteStack", MsoLogger.ErrorCode.DataError, "Exception - DeleteStack", me);
826 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
827 throw new VnfException (me);
829 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully roll back VNF");
833 private VnfStatus stackStatusToVnfStatus (HeatStatus stackStatus) {
834 switch (stackStatus) {
836 return VnfStatus.ACTIVE;
838 return VnfStatus.ACTIVE;
840 return VnfStatus.FAILED;
842 return VnfStatus.UNKNOWN;
846 private Map <String, String> copyStringOutputs (Map <String, Object> stackOutputs) {
847 Map <String, String> stringOutputs = new HashMap <String, String> ();
848 for (String key : stackOutputs.keySet ()) {
849 if (stackOutputs.get (key) instanceof String) {
850 stringOutputs.put (key, (String) stackOutputs.get (key));
853 return stringOutputs;
856 private Map <String, Object> copyStringInputs (Map <String, String> stringInputs) {
857 return new HashMap <String, Object> (stringInputs);
861 * a helper method to make sure that any resource_registry entry of the format
862 * "xx::xx" : yyy.yaml (or yyy.template)
863 * has the file name prepended with "file:///"
864 * Return a String of the environment body that's passed in.
865 * Have to be careful not to mess up the original formatting.
867 private String parseEnvironment (String environment) {
868 StringBuilder sb = new StringBuilder ();
869 try (Scanner scanner = new Scanner (environment)) {
870 scanner.useDelimiter ("\n");
872 Pattern resource = Pattern.compile ("\\s*\"\\w+::\\S+\"\\s*:");
873 LOGGER.debug ("regex pattern for finding a resource_registry: \\s*\"\\w+::\\S+\"\\s*:");
874 while (scanner.hasNextLine ()) {
875 line = scanner.nextLine ();
876 if (line.toLowerCase ().contains ("resource_registry")) {
877 sb.append (line + "\n");
878 boolean done = false;
879 // basically keep scanning until EOF or parameters: section
880 while (scanner.hasNextLine () && !done) {
881 line = scanner.nextLine ();
882 if ("parameters:".equalsIgnoreCase (line.trim ())) {
883 sb.append (line + "\n");
887 Matcher m = resource.matcher (line);
889 sb.append (m.group ());
890 String secondPart = line.substring (m.end ()).trim ();
891 String output = secondPart;
892 if (secondPart.endsWith (".yaml")
893 || secondPart.endsWith (".template") && !secondPart.startsWith ("file:///")) {
894 output = "file:///" + secondPart;
895 LOGGER.debug ("changed " + secondPart + " to " + output);
896 } // don't do anything if it's not .yaml or .template
897 sb.append (" " + output + "\n");
899 sb.append (line + "\n");
903 sb.append (line + "\n");
908 } catch (Exception e) {
909 LOGGER.debug ("Error trying to scan " + environment, e);
912 return sb.toString ();
916 * helper class to add file:/// to the Provider_Resource_File entry in HEAT_NESTED_TEMPLATE
917 * and the File_Name entry in HEAT_FILES if the file:/// part is missing.
919 private String enforceFilePrefix (String string) {
920 if (string.trim ().startsWith ("file:///")) {
924 if (string.trim ().endsWith (".yaml") || string.trim ().endsWith (".template")) {
925 // only .yaml or .template are valid anyway - otherwise don't bother
926 return "file:///" + string.trim ();
928 LOGGER.debug (string + " is NOT a .yaml or .template file");
933 private void sendMapToDebug(Map<String, String> inputs) {
935 StringBuilder sb = new StringBuilder("inputs:");
936 if (inputs == null) {
939 else if (inputs.size() < 1) {
940 sb.append("\tEMPTY");
942 for (String str : inputs.keySet()) {
943 sb.append("\titem " + i++ + ": " + str + "=" + inputs.get(str));
946 LOGGER.debug(sb.toString());
950 public void createVfModule(String cloudSiteId,
956 String volumeGroupHeatStackId,
957 String baseVfHeatStackId,
958 Map <String, String> inputs,
959 Boolean failIfExists,
961 MsoRequest msoRequest,
962 Holder <String> vnfId,
963 Holder <Map <String, String>> outputs,
964 Holder <VnfRollback> rollback) throws VnfException {
965 String vfModuleName = vnfName;
966 String vfModuleType = vnfType;
967 String vfVersion = vnfVersion;
968 MsoLogger.setLogContext (msoRequest);
969 MsoLogger.setServiceName ("CreateVfModule");
970 String requestTypeString = "";
971 if (requestType != null && !requestType.equals("")) {
972 requestTypeString = requestType;
974 String nestedStackId = null;
975 if (volumeGroupHeatStackId != null && !volumeGroupHeatStackId.equals("")) {
976 if (!volumeGroupHeatStackId.equalsIgnoreCase("null")) {
977 nestedStackId = volumeGroupHeatStackId;
980 String nestedBaseStackId = null;
981 if (baseVfHeatStackId != null && !baseVfHeatStackId.equals("")) {
982 if (!baseVfHeatStackId.equalsIgnoreCase("null")) {
983 nestedBaseStackId = baseVfHeatStackId;
987 if (inputs == null) {
988 // Create an empty set of inputs
989 inputs = new HashMap<String,String>();
990 LOGGER.debug("inputs == null - setting to empty");
992 this.sendMapToDebug(inputs);
994 //This method will also handle doing things the "old" way - i.e., just orchestrate a VNF
995 boolean oldWay = false;
996 if (requestTypeString.startsWith("X")) {
998 LOGGER.debug("orchestrating a VNF - *NOT* a module!");
999 requestTypeString = requestTypeString.substring(1);
1002 // 1607 - let's parse out the request type we're being sent
1003 boolean isBaseRequest = false;
1004 boolean isVolumeRequest = false;
1005 if (requestTypeString.startsWith("VOLUME")) {
1006 isVolumeRequest = true;
1009 LOGGER.debug("requestTypeString = " + requestTypeString + ", nestedStackId = " + nestedStackId + ", nestedBaseStackId = " + nestedBaseStackId);
1010 // Will capture execution time for metrics
1011 long startTime = System.currentTimeMillis ();
1013 // Build a default rollback object (no actions performed)
1014 VnfRollback vfRollback = new VnfRollback();
1015 vfRollback.setCloudSiteId(cloudSiteId);
1016 vfRollback.setTenantId(tenantId);
1017 vfRollback.setMsoRequest(msoRequest);
1018 vfRollback.setRequestType(requestTypeString);
1019 vfRollback.setVolumeGroupHeatStackId(volumeGroupHeatStackId);
1020 vfRollback.setBaseGroupHeatStackId(baseVfHeatStackId);
1021 vfRollback.setIsBase(isBaseRequest);
1023 // First, look up to see if the VF already exists.
1024 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_VNF_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
1026 StackInfo heatStack = null;
1027 long subStartTime1 = System.currentTimeMillis ();
1029 heatStack = heat.queryStack (cloudSiteId, tenantId, vfModuleName);
1030 LOGGER.recordMetricEvent (subStartTime1, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", vfModuleName);
1031 } catch (MsoException me) {
1032 String error = "Create VF Module: Query " + vfModuleName + " in " + cloudSiteId + "/" + tenantId + ": " + me ;
1033 LOGGER.recordMetricEvent (subStartTime1, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryStack", vfModuleName);
1034 LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vfModuleName, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Exception - queryStack", me);
1035 // Failed to query the Stack due to an openstack exception.
1036 // Convert to a generic VnfException
1037 me.addContext ("CreateVFModule");
1038 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1039 throw new VnfException (me);
1041 // New with 1607 - more precise handling/messaging if the stack already exists
1042 if (heatStack != null && !(heatStack.getStatus () == HeatStatus.NOTFOUND)) {
1043 // INIT, CREATED, NOTFOUND, FAILED, BUILDING, DELETING, UNKNOWN, UPDATING, UPDATED
1044 HeatStatus status = heatStack.getStatus();
1045 if (status == HeatStatus.INIT || status == HeatStatus.BUILDING || status == HeatStatus.DELETING || status == HeatStatus.UPDATING) {
1046 // fail - it's in progress - return meaningful error
1047 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.";
1048 LOGGER.error (MessageEnum.RA_VNF_ALREADY_EXIST, vfModuleName, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Stack " + vfModuleName + " already exists");
1049 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
1050 throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, heatStack.getCanonicalName ());
1052 if (status == HeatStatus.FAILED) {
1053 // fail - it exists and is in a FAILED state
1054 String error = "Create VF: Stack " + vfModuleName + " already exists and is in FAILED state in " + cloudSiteId + "/" + tenantId + "; requires manual intervention.";
1055 LOGGER.error (MessageEnum.RA_VNF_ALREADY_EXIST, vfModuleName, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Stack " + vfModuleName + " already exists and is in FAILED state");
1056 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
1057 throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, heatStack.getCanonicalName ());
1059 if (status == HeatStatus.UNKNOWN || status == HeatStatus.UPDATED) {
1060 // fail - it exists and is in a FAILED state
1061 String error = "Create VF: Stack " + vfModuleName + " already exists and has status " + status.toString() + " in " + cloudSiteId + "/" + tenantId + "; requires manual intervention.";
1062 LOGGER.error (MessageEnum.RA_VNF_ALREADY_EXIST, vfModuleName, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Stack " + vfModuleName + " already exists and is in UPDATED or UNKNOWN state");
1063 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
1064 throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, heatStack.getCanonicalName ());
1066 if (status == HeatStatus.CREATED) {
1068 if (failIfExists != null && failIfExists) {
1069 String error = "Create VF: Stack " + vfModuleName + " already exists in " + cloudSiteId + "/" + tenantId;
1070 LOGGER.error (MessageEnum.RA_VNF_ALREADY_EXIST, vfModuleName, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Stack " + vfModuleName + " already exists");
1071 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
1072 throw new VnfAlreadyExists (vfModuleName, cloudSiteId, tenantId, heatStack.getCanonicalName ());
1074 LOGGER.debug ("Found Existing stack, status=" + heatStack.getStatus ());
1075 // Populate the outputs from the existing stack.
1076 vnfId.value = heatStack.getCanonicalName ();
1077 outputs.value = copyStringOutputs (heatStack.getOutputs ());
1078 rollback.value = vfRollback; // Default rollback - no updates performed
1081 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully create VF Module");
1086 // handle a nestedStackId if sent- this one would be for the volume - so applies to both Vf and Vnf
1087 StackInfo nestedHeatStack = null;
1088 long subStartTime2 = System.currentTimeMillis ();
1089 if (nestedStackId != null) {
1091 LOGGER.debug("Querying for nestedStackId = " + nestedStackId);
1092 nestedHeatStack = heat.queryStack(cloudSiteId, tenantId, nestedStackId);
1093 LOGGER.recordMetricEvent (subStartTime2, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", vfModuleName);
1094 } catch (MsoException me) {
1095 // Failed to query the Stack due to an openstack exception.
1096 // Convert to a generic VnfException
1097 me.addContext ("CreateVFModule");
1098 String error = "Create VFModule: Attached heatStack ID Query " + nestedStackId + " in " + cloudSiteId + "/" + tenantId + ": " + me ;
1099 LOGGER.recordMetricEvent (subStartTime2, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryStack", vfModuleName);
1100 LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vfModuleName, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.BusinessProcesssError, "MsoException trying to query nested stack", me);
1101 LOGGER.debug("ERROR trying to query nested stack= " + error);
1102 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1103 throw new VnfException (me);
1105 if (nestedHeatStack == null || nestedHeatStack.getStatus() == HeatStatus.NOTFOUND) {
1106 String error = "Create VFModule: Attached heatStack ID DOES NOT EXIST " + nestedStackId + " in " + cloudSiteId + "/" + tenantId + " USER ERROR" ;
1107 LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vfModuleName, cloudSiteId, tenantId, error, "OpenStack", "queryStack", MsoLogger.ErrorCode.BusinessProcesssError, "Create VFModule: Attached heatStack ID DOES NOT EXIST");
1108 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
1109 LOGGER.debug(error);
1110 throw new VnfException (error, MsoExceptionCategory.USERDATA);
1112 LOGGER.debug("Found nested volume heat stack - copying values to inputs");
1113 this.sendMapToDebug(inputs);
1114 heat.copyStringOutputsToInputs(inputs, nestedHeatStack.getOutputs(), false);
1115 this.sendMapToDebug(inputs);
1119 // handle a nestedBaseStackId if sent- this is the stack ID of the base. Should be null for VNF requests
1120 StackInfo nestedBaseHeatStack = null;
1121 long subStartTime3 = System.currentTimeMillis ();
1122 if (nestedBaseStackId != null) {
1124 LOGGER.debug("Querying for nestedBaseStackId = " + nestedBaseStackId);
1125 nestedBaseHeatStack = heat.queryStack(cloudSiteId, tenantId, nestedBaseStackId);
1126 LOGGER.recordMetricEvent (subStartTime3, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", vfModuleName);
1127 } catch (MsoException me) {
1128 // Failed to query the Stack due to an openstack exception.
1129 // Convert to a generic VnfException
1130 me.addContext ("CreateVFModule");
1131 String error = "Create VFModule: Attached baseHeatStack ID Query " + nestedBaseStackId + " in " + cloudSiteId + "/" + tenantId + ": " + me ;
1132 LOGGER.recordMetricEvent (subStartTime3, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryStack", vfModuleName);
1133 LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vfModuleName, cloudSiteId, tenantId, "OpenStack", "QueryStack", MsoLogger.ErrorCode.BusinessProcesssError, "MsoException trying to query nested base stack", me);
1134 LOGGER.debug("ERROR trying to query nested base stack= " + error);
1135 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1136 throw new VnfException (me);
1138 if (nestedBaseHeatStack == null || nestedBaseHeatStack.getStatus() == HeatStatus.NOTFOUND) {
1139 String error = "Create VFModule: Attached base heatStack ID DOES NOT EXIST " + nestedBaseStackId + " in " + cloudSiteId + "/" + tenantId + " USER ERROR" ;
1140 LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vfModuleName, cloudSiteId, tenantId, error, "OpenStack", "QueryStack", MsoLogger.ErrorCode.BusinessProcesssError, "Create VFModule: Attached base heatStack ID DOES NOT EXIST");
1141 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
1142 LOGGER.debug(error);
1143 throw new VnfException (error, MsoExceptionCategory.USERDATA);
1145 LOGGER.debug("Found nested base heat stack - copying values to inputs");
1146 this.sendMapToDebug(inputs);
1147 heat.copyStringOutputsToInputs(inputs, nestedBaseHeatStack.getOutputs(), false);
1148 this.sendMapToDebug(inputs);
1152 // Ready to deploy the new VNF
1154 try (CatalogDatabase db = new CatalogDatabase()) {
1157 VnfResource vnfResource = null;
1158 LOGGER.debug("version: " + vfVersion);
1160 // Need to handle old and new schema methods - for a time. Try the new way first.
1161 if (vfVersion != null && !vfVersion.isEmpty()) {
1162 vf = db.getVfModuleType(vfModuleType, vfVersion);
1164 LOGGER.debug("Unable to find " + vfModuleType + " and version=" + vfVersion + " in the TYPE column - will try in MODEL_NAME");
1165 vf = db.getVfModuleModelName(vfModuleType, vfVersion);
1167 LOGGER.debug("Unable to find " + vfModuleType + " and version=" + vfVersion + " in the MODEL_NAME field either - ERROR");
1171 vf = db.getVfModuleType(vfModuleType);
1173 LOGGER.debug("Unable to find " + vfModuleType + " in the TYPE column - will try in MODEL_NAME");
1174 vf = db.getVfModuleModelName(vfModuleType);
1176 LOGGER.debug("Unable to find " + vfModuleType + " in the MODEL_NAME field either - ERROR");
1181 String error = "Create VF Module: Unable to determine specific VF Module Type: "
1183 if (vfVersion != null && !vfVersion.isEmpty()) {
1184 error += " with version = " + vfVersion;
1186 LOGGER.error(MessageEnum.RA_VNF_UNKNOWN_PARAM,
1187 "VF Module Type", vfModuleType, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Create VF Module: Unable to determine specific VF Module Type");
1188 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
1189 throw new VnfException(error, MsoExceptionCategory.USERDATA);
1191 LOGGER.debug("Got VF module definition from Catalog: "
1195 isBaseRequest = true;
1196 LOGGER.debug("This is a BASE VF request!");
1198 LOGGER.debug("This is *not* a BASE VF request!");
1199 if (!isVolumeRequest && nestedBaseStackId == null) {
1200 LOGGER.debug("DANGER WILL ROBINSON! This is unexpected - no nestedBaseStackId with this non-base request");
1204 if (vfVersion != null && !vfVersion.isEmpty()) {
1205 vnfResource = db.getVnfResource(vnfType, vnfVersion);
1207 vnfResource = db.getVnfResource(vnfType);
1209 if (vnfResource == null) {
1210 String error = "Create VNF: Unknown VNF Type: " + vnfType;
1211 LOGGER.error(MessageEnum.RA_VNF_UNKNOWN_PARAM, "VNF Type",
1212 vnfType, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Create VNF: Unknown VNF Type");
1213 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
1214 throw new VnfException(error, MsoExceptionCategory.USERDATA);
1216 LOGGER.debug("Got VNF module definition from Catalog: "
1217 + vnfResource.toString());
1219 // By here - we have either a vf or vnfResource
1221 //1607 - Add version check
1222 // First - see if it's in the VnfResource record
1223 // if we have a vf Module - then we have to query to get the VnfResource record.
1225 if (vf.getVnfResourceId() != null) {
1226 int vnfResourceId = vf.getVnfResourceId();
1227 vnfResource = db.getVnfResourceById(vnfResourceId);
1228 if (vnfResource == null) {
1229 LOGGER.debug("Unable to find vnfResource at " + vnfResourceId + " will not error for now...");
1233 String minVersionVnf = null;
1234 String maxVersionVnf = null;
1235 if (vnfResource != null) {
1237 minVersionVnf = vnfResource.getAicVersionMin();
1238 maxVersionVnf = vnfResource.getAicVersionMax();
1239 } catch (Exception e) {
1240 LOGGER.debug("Unable to pull min/max version for this VNF Resource entry");
1241 minVersionVnf = null;
1242 maxVersionVnf = null;
1244 if (minVersionVnf != null && minVersionVnf.equals("")) {
1245 minVersionVnf = null;
1247 if (maxVersionVnf != null && maxVersionVnf.equals("")) {
1248 maxVersionVnf = null;
1251 if (minVersionVnf != null && maxVersionVnf != null) {
1252 MavenLikeVersioning aicV = new MavenLikeVersioning();
1253 CloudSite cloudSite = null;
1254 String aicVersion = "";
1255 if (this.cloudConfig == null) {
1256 this.cloudConfig = this.cloudConfigFactory.getCloudConfig();
1259 if (this.cloudConfig != null) {
1260 cloudSite = this.cloudConfig.getCloudSite(cloudSiteId);
1261 if (cloudSite != null) {
1262 aicV.setVersion(cloudSite.getAic_version());
1263 if ((aicV.isMoreRecentThan(minVersionVnf) || aicV.isTheSameVersion(minVersionVnf)) // aic >= min
1264 && (aicV.isTheSameVersion(maxVersionVnf) || !(aicV.isMoreRecentThan(maxVersionVnf)))) { //aic <= max
1265 LOGGER.debug("VNF Resource " + vnfResource.getVnfType() + " VersionMin=" + minVersionVnf + " VersionMax:" + maxVersionVnf + " supported on Cloud: " + cloudSite.getId() + " with AIC_Version:" + cloudSite.getAic_version());
1268 String error = "VNF Resource type: " + vnfResource.getVnfType() + " VersionMin=" + minVersionVnf + " VersionMax:" + maxVersionVnf + " NOT supported on Cloud: " + cloudSite.getId() + " with AIC_Version:" + cloudSite.getAic_version();
1269 LOGGER.error(MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - setVersion");
1270 LOGGER.debug(error);
1271 throw new VnfException(error, MsoExceptionCategory.USERDATA);
1273 } // let this error out downstream to avoid introducing uncertainty at this stage
1275 LOGGER.debug("cloudConfig is NULL - cannot check cloud site version");
1279 LOGGER.debug("AIC Version not set in VNF_Resource - this is expected thru 1607 - do not error here - not checked.");
1281 // End Version check 1607
1283 // with VF_MODULE - we have both the non-vol and vol template/envs in that object
1284 // with VNF_RESOURCE - we use the old methods.
1285 Integer heatTemplateId = null;
1286 Integer heatEnvtId = null;
1289 if (isVolumeRequest) {
1290 heatTemplateId = vf.getVolTemplateId();
1291 heatEnvtId = vf.getVolEnvironmentId();
1293 heatTemplateId = vf.getTemplateId();
1294 heatEnvtId = vf.getEnvironmentId();
1297 if (isVolumeRequest) {
1298 VnfComponent vnfComponent = null;
1299 vnfComponent = db.getVnfComponent(vnfResource.getId(), "VOLUME");
1300 if (vnfComponent == null) {
1301 String error = "Create VNF: Cannot find VNF Component entry for: " + vnfType + ", type = VOLUME";
1302 LOGGER.error (MessageEnum.RA_VNF_UNKNOWN_PARAM, "VNF Type", vnfType, "OpenStack", "getVnfComponent", MsoLogger.ErrorCode.DataError, "Create VNF: Cannot find VNF Component entry");
1303 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
1304 throw new VnfException (error, MsoExceptionCategory.USERDATA);
1306 heatTemplateId = vnfComponent.getHeatTemplateId();
1307 heatEnvtId = vnfComponent.getHeatEnvironmentId();
1310 heatTemplateId = vnfResource.getTemplateId();
1311 heatEnvtId = vnfResource.getEnvironmentId();
1314 // By the time we get here - heatTemplateId and heatEnvtId should be populated (or null)
1315 HeatTemplate heatTemplate = null;
1316 if (heatTemplateId == null) {
1317 String error = "Create: No Heat Template ID defined in catalog database for " + vnfType + ", reqType=" + requestTypeString;
1318 LOGGER.error(MessageEnum.RA_VNF_UNKNOWN_PARAM, "Heat Template ID", vnfType, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Create: No Heat Template ID defined in catalog database");
1319 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
1320 alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR,
1321 MsoAlarmLogger.CRITICAL, error);
1322 throw new VnfException(error, MsoExceptionCategory.INTERNAL);
1324 heatTemplate = db.getHeatTemplate(heatTemplateId);
1326 if (heatTemplate == null) {
1327 String error = "Create VF/VNF: no entry found for heat template ID = " + heatTemplateId;
1328 LOGGER.error(MessageEnum.RA_VNF_UNKNOWN_PARAM,
1330 String.valueOf(heatTemplateId), "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Create VF/VNF: no entry found for heat template ID = " + heatTemplateId);
1331 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
1332 alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR,
1333 MsoAlarmLogger.CRITICAL, error);
1334 throw new VnfException(error, MsoExceptionCategory.INTERNAL);
1336 LOGGER.debug("Got HEAT Template from DB");
1338 HeatEnvironment heatEnvironment = null;
1339 String heatEnvironmentString = null;
1341 if (heatEnvtId != null && heatEnvtId != 0) {
1342 LOGGER.debug ("about to call getHeatEnvironment with :" + heatEnvtId + ":");
1343 heatEnvironment = db.getHeatEnvironment (heatEnvtId);
1344 if (heatEnvironment == null) {
1345 String error = "Create VFModule: undefined Heat Environment. VFModule=" + vfModuleType
1346 + ", Environment ID="
1348 LOGGER.error (MessageEnum.RA_VNF_UNKNOWN_PARAM, "Heat Environment ID", String.valueOf(heatEnvtId), "OpenStack", "getHeatEnvironment", MsoLogger.ErrorCode.BusinessProcesssError, "Create VFModule: undefined Heat Environment");
1349 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
1350 // Alarm on this error, configuration must be fixed
1351 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
1353 throw new VnfException (error, MsoExceptionCategory.INTERNAL);
1355 LOGGER.debug ("Got Heat Environment from DB: " + heatEnvironment.toString ());
1356 heatEnvironmentString = heatEnvironment.getEnvironment (); //this.parseEnvironment (heatEnvironment.getEnvironment ());
1357 LOGGER.debug ("after parsing: " + heatEnvironmentString);
1360 LOGGER.debug ("no environment parameter found for this Type " + vfModuleType);
1363 // 1510 - Add the files: for nested templates *if* there are any
1364 LOGGER.debug ("In MsoVnfAdapterImpl, createVfModule about to call db.getNestedTemplates avec templateId="
1365 + heatTemplate.getId ());
1366 Map <String, Object> nestedTemplates = db.getNestedTemplates (heatTemplate.getId ());
1367 Map <String, Object> nestedTemplatesChecked = new HashMap <String, Object> ();
1368 if (nestedTemplates != null) {
1369 // for debugging print them out
1370 LOGGER.debug ("Contents of nestedTemplates - to be added to files: on stack:");
1371 for (String providerResourceFile : nestedTemplates.keySet ()) {
1372 String providerResourceFileChecked = providerResourceFile; //this.enforceFilePrefix (providerResourceFile);
1373 String childTemplateBody = (String) nestedTemplates.get (providerResourceFile);
1374 LOGGER.debug (providerResourceFileChecked + " -> " + childTemplateBody);
1375 nestedTemplatesChecked.put (providerResourceFileChecked, childTemplateBody);
1378 LOGGER.debug ("No nested templates found - nothing to do here");
1379 nestedTemplatesChecked = null; // just to make sure
1382 // 1510 - Also add the files: for any get_files associated with this vnf_resource_id
1383 // *if* there are any
1384 Map<String, HeatFiles> heatFiles = null;
1385 Map<String, Object> heatFilesObjects = new HashMap<String, Object>();
1387 // Add ability to turn on adding get_files with volume requests (by property).
1388 boolean addGetFilesOnVolumeReq = false;
1390 String propertyString = msoPropertiesFactory.getMsoJavaProperties(MSO_PROP_VNF_ADAPTER).getProperty(MsoVnfAdapterImpl.ADD_GET_FILES_ON_VOLUME_REQ, null);
1391 if ("true".equalsIgnoreCase(propertyString) || "y".equalsIgnoreCase(propertyString)) {
1392 addGetFilesOnVolumeReq = true;
1393 LOGGER.debug("AddGetFilesOnVolumeReq - setting to true! " + propertyString);
1395 } catch (Exception e) {
1396 LOGGER.debug("An error occured trying to get property " + MsoVnfAdapterImpl.ADD_GET_FILES_ON_VOLUME_REQ + " - default to false", e);
1399 if (!isVolumeRequest || addGetFilesOnVolumeReq) {
1401 LOGGER.debug("In MsoVnfAdapterImpl createVfModule, about to call db.getHeatFiles avec vnfResourceId="
1402 + vnfResource.getId());
1403 heatFiles = db.getHeatFiles(vnfResource.getId());
1405 // 1607 - now use VF_MODULE_TO_HEAT_FILES table
1406 LOGGER.debug("In MsoVnfAdapterImpl createVfModule, about to call db.getHeatFilesForVfModule avec vfModuleId="
1409 .getHeatFilesForVfModule(vf.getId());
1411 if (heatFiles != null) {
1412 // add these to stack - to be done in createStack
1413 // here, we will map them to Map<String, Object> from
1414 // Map<String, HeatFiles>
1415 // this will match the nested templates format
1416 LOGGER.debug("Contents of heatFiles - to be added to files: on stack:");
1418 for (String heatFileName : heatFiles.keySet()) {
1419 if (heatFileName.startsWith("_ERROR|")) {
1420 // This means there was an invalid entry in VF_MODULE_TO_HEAT_FILES table - the heat file it pointed to could not be found.
1421 String heatFileId = heatFileName.substring(heatFileName.lastIndexOf("|")+1);
1422 String error = "Create: No HEAT_FILES entry in catalog database for " + vfModuleType + " at HEAT_FILES index=" + heatFileId;
1423 LOGGER.debug(error);
1424 LOGGER.error (MessageEnum.RA_VNF_UNKNOWN_PARAM, "HEAT_FILES entry not found at " + heatFileId, vfModuleType, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "HEAT_FILES entry not found");
1425 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
1426 // Alarm on this error, configuration must be fixed
1427 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
1428 throw new VnfException (error, MsoExceptionCategory.INTERNAL);
1430 String heatFileBody = heatFiles.get(heatFileName)
1432 String heatFileNameChecked = heatFileName;
1433 LOGGER.debug(heatFileNameChecked + " -> "
1435 heatFilesObjects.put(heatFileNameChecked, heatFileBody);
1438 LOGGER.debug("No heat files found -nothing to do here");
1439 heatFilesObjects = null;
1442 LOGGER.debug("Volume request - DO NOT CHECK for HEAT_FILES");
1445 // Check that required parameters have been supplied
1446 String missingParams = null;
1447 List <String> paramList = new ArrayList <String> ();
1449 // New for 1510 - consult the PARAM_ALIAS field to see if we've been
1450 // supplied an alias. Only check if we don't find it initially.
1451 // Also new in 1510 - don't flag missing parameters if there's an environment - because they might be there.
1452 // And also new - add parameter to turn off checking all together if we find we're blocking orders we
1454 boolean haveEnvironmentParameters = false;
1455 boolean checkRequiredParameters = true;
1457 String propertyString = msoPropertiesFactory.getMsoJavaProperties (MSO_PROP_VNF_ADAPTER)
1458 .getProperty (MsoVnfAdapterImpl.CHECK_REQD_PARAMS,null);
1459 if ("false".equalsIgnoreCase (propertyString) || "n".equalsIgnoreCase (propertyString)) {
1460 checkRequiredParameters = false;
1461 LOGGER.debug ("CheckRequiredParameters is FALSE. Will still check but then skip blocking..."
1462 + MsoVnfAdapterImpl.CHECK_REQD_PARAMS);
1464 } catch (Exception e) {
1465 // No problem - default is true
1466 LOGGER.debug ("An exception occured trying to get property " + MsoVnfAdapterImpl.CHECK_REQD_PARAMS, e);
1468 // 1604 - Add enhanced environment & parameter checking
1469 // Part 1: parse envt entries to see if reqd parameter is there (before used a simple grep
1470 // Part 2: only submit to openstack the parameters in the envt that are in the heat template
1471 // Note this also removes any comments
1472 MsoHeatEnvironmentEntry mhee = null;
1473 if (heatEnvironmentString != null && heatEnvironmentString.contains ("parameters:")) {
1474 //LOGGER.debug ("Have an Environment argument with a parameters: section - will bypass checking for valid params - but will still check for aliases");
1475 LOGGER.debug("Enhanced environment checking enabled - 1604");
1476 haveEnvironmentParameters = true;
1477 StringBuilder sb = new StringBuilder(heatEnvironmentString);
1478 //LOGGER.debug("About to create MHEE with " + sb);
1479 mhee = new MsoHeatEnvironmentEntry(sb);
1480 StringBuilder sb2 = new StringBuilder("\nHeat Template Parameters:\n");
1481 for (HeatTemplateParam parm : heatTemplate.getParameters()) {
1482 sb2.append("\t" + parm.getParamName() + ", required=" + parm.isRequired());
1484 if (!mhee.isValid()) {
1485 sb2.append("Environment says it's not valid! " + mhee.getErrorString());
1487 sb2.append("\nEnvironment:");
1488 sb2.append(mhee.toFullString());
1490 LOGGER.debug(sb2.toString());
1492 LOGGER.debug("NO ENVIRONMENT for this entry");
1494 // This is kind of a mess. inputs is a Map<String, String> --
1495 // if one of the parameters is json - we need to pass String, JsonNode -
1496 // so we will store off the parameters that are json in its own HashMap
1497 // if there are any json params - then we convert inputs to a Map<String, Object>
1498 // and pass that to createStack
1499 HashMap<String, JsonNode> jsonParams = new HashMap<String, JsonNode>();
1500 boolean hasJson = false;
1502 for (HeatTemplateParam parm : heatTemplate.getParameters ()) {
1503 LOGGER.debug ("Parameter:'" + parm.getParamName ()
1505 + parm.isRequired ()
1507 + parm.getParamAlias ());
1508 // New 1607 - support json type
1509 String parameterType = parm.getParamType();
1510 if (parameterType == null || parameterType.trim().equals("")) {
1511 parameterType = "String";
1513 JsonNode jsonNode = null;
1514 if (parameterType.equalsIgnoreCase("json") && inputs != null) {
1515 if (inputs.containsKey(parm.getParamName()) ) {
1517 String jsonString = null;
1519 jsonString = inputs.get(parm.getParamName());
1520 jsonNode = new ObjectMapper().readTree(jsonString);
1521 } catch (JsonParseException jpe) {
1522 //TODO - what to do here?
1523 //for now - send the error to debug, but just leave it as a String
1524 String errorMessage = jpe.getMessage();
1525 LOGGER.debug("Json Error Converting " + parm.getParamName() + " - " + errorMessage);
1528 } catch (Exception e) {
1530 LOGGER.debug("Json Error Converting " + parm.getParamName() + " " + e.getMessage());
1534 if (jsonNode != null) {
1535 jsonParams.put(parm.getParamName(), jsonNode);
1537 } else if (inputs.containsKey(parm.getParamAlias())) {
1539 String jsonString = null;
1541 jsonString = inputs.get(parm.getParamAlias());
1542 jsonNode = new ObjectMapper().readTree(jsonString);
1543 } catch (JsonParseException jpe) {
1544 //TODO - what to do here?
1545 //for now - send the error to debug, but just leave it as a String
1546 String errorMessage = jpe.getMessage();
1547 LOGGER.debug("Json Error Converting " + parm.getParamName() + " - " + errorMessage);
1550 } catch (Exception e) {
1552 LOGGER.debug("Json Error Converting " + parm.getParamName() + " " + e.getMessage());
1556 if (jsonNode != null) {
1557 // Notice here - we add it to the jsonParams hashMap with the actual name -
1558 // then manipulate the inputs so when we check for aliases below - it will not
1560 jsonParams.put(parm.getParamName(), jsonNode);
1561 inputs.remove(parm.getParamAlias());
1562 inputs.put(parm.getParamName(), jsonString);
1564 } //TODO add a check for the parameter in the env file
1566 if (parm.isRequired () && (inputs == null || !inputs.containsKey (parm.getParamName ()))) {
1567 // Check if they have an alias
1568 LOGGER.debug("**Parameter " + parm.getParamName() + " is required and not in the inputs...");
1569 if (inputs.containsKey (parm.getParamAlias ())) {
1570 // They've submitted using an alias name. Remove that from inputs, and add back using real name.
1571 String realParamName = parm.getParamName ();
1572 String alias = parm.getParamAlias ();
1573 String value = inputs.get (alias);
1574 LOGGER.debug ("*Found an Alias: paramName=" + realParamName
1579 inputs.remove (alias);
1580 inputs.put (realParamName, value);
1581 LOGGER.debug (alias + " entry removed from inputs, added back using " + realParamName);
1583 // enhanced - check if it's in the Environment (note: that method
1584 else if (mhee != null && mhee.containsParameter(parm.getParamName())) {
1586 LOGGER.debug ("Required parameter " + parm.getParamName ()
1587 + " appears to be in environment - do not count as missing");
1589 LOGGER.debug ("adding to missing parameters list: " + parm.getParamName ());
1590 if (missingParams == null) {
1591 missingParams = parm.getParamName ();
1593 missingParams += "," + parm.getParamName ();
1597 paramList.add (parm.getParamName ());
1599 if (missingParams != null) {
1600 if (checkRequiredParameters) {
1601 // Problem - missing one or more required parameters
1602 String error = "Create VFModule: Missing Required inputs: " + missingParams;
1603 LOGGER.error (MessageEnum.RA_MISSING_PARAM, missingParams, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Create VFModule: Missing Required inputs");
1604 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
1605 throw new VnfException (error, MsoExceptionCategory.USERDATA);
1607 LOGGER.debug ("found missing parameters - but checkRequiredParameters is false - will not block");
1610 LOGGER.debug ("No missing parameters found - ok to proceed");
1613 // Here - modify heatEnvironmentString
1614 StringBuilder parsedEnvironmentString = null;
1615 String newEnvironmentString = null;
1617 LOGGER.debug("Environment before:\n" + heatEnvironmentString);
1618 parsedEnvironmentString = mhee.toFullStringExcludeNonParams(heatTemplate.getParameters());
1619 LOGGER.debug("Environment after:\n" + parsedEnvironmentString.toString());
1620 newEnvironmentString = parsedEnvironmentString.toString();
1623 // Remove any extraneous parameters (don't throw an error)
1624 if (inputs != null) {
1625 List <String> extraParams = new ArrayList <String> ();
1626 extraParams.addAll (inputs.keySet ());
1627 extraParams.removeAll (paramList);
1628 if (!extraParams.isEmpty ()) {
1629 LOGGER.warn (MessageEnum.RA_VNF_EXTRA_PARAM, vnfType, extraParams.toString(), "OpenStack", "", MsoLogger.ErrorCode.DataError, "Extra params");
1630 inputs.keySet ().removeAll (extraParams);
1633 // 1607 - when we get here - we have clean inputs. Check if we have
1634 Map<String, Object> inputsTwo = null;
1635 if (hasJson && jsonParams.size() > 0) {
1636 inputsTwo = new HashMap<String, Object>();
1637 for (String keyParamName : inputs.keySet()) {
1638 if (jsonParams.containsKey(keyParamName)) {
1639 inputsTwo.put(keyParamName, jsonParams.get(keyParamName));
1641 inputsTwo.put(keyParamName, inputs.get(keyParamName));
1646 // "Fix" the template if it has CR/LF (getting this from Oracle)
1647 String template = heatTemplate.getHeatTemplate ();
1648 template = template.replaceAll ("\r\n", "\n");
1650 // Have the tenant. Now deploy the stack itself
1651 // Ignore MsoTenantNotFound and MsoStackAlreadyExists exceptions
1652 // because we already checked for those.
1653 long createStackStarttime = System.currentTimeMillis ();
1655 // heatStack = heat.createStack(cloudSiteId, tenantId, vnfName, template, inputs, true,
1656 // heatTemplate.getTimeoutMinutes());
1657 if (backout == null) {
1661 LOGGER.debug("heat is not null!!");
1665 heatStack = heat.createStack (cloudSiteId,
1671 heatTemplate.getTimeoutMinutes (),
1672 newEnvironmentString,
1673 //heatEnvironmentString,
1674 nestedTemplatesChecked,
1676 backout.booleanValue());
1677 LOGGER.recordMetricEvent (createStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "CreateStack", vfModuleName);
1679 heatStack = heat.createStack (cloudSiteId,
1685 heatTemplate.getTimeoutMinutes (),
1686 newEnvironmentString,
1687 //heatEnvironmentString,
1688 nestedTemplatesChecked,
1690 backout.booleanValue());
1693 LOGGER.recordMetricEvent (createStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "CreateStack", vfModuleName);
1694 } catch (MsoException me) {
1695 me.addContext ("CreateVFModule");
1696 String error = "Create VF Module " + vfModuleType + " in " + cloudSiteId + "/" + tenantId + ": " + me;
1697 LOGGER.recordMetricEvent (createStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "CreateStack", vfModuleName);
1698 LOGGER.error (MessageEnum.RA_CREATE_VNF_ERR, vfModuleType, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "MsoException - createStack", me);
1699 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1700 throw new VnfException (me);
1701 } catch (NullPointerException npe) {
1702 String error = "Create VFModule " + vfModuleType + " in " + cloudSiteId + "/" + tenantId + ": " + npe;
1703 LOGGER.recordMetricEvent (createStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "CreateStack", vfModuleName);
1704 LOGGER.error (MessageEnum.RA_CREATE_VNF_ERR, vfModuleType, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "NullPointerException - createStack", npe);
1705 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1706 LOGGER.debug("NULL POINTER EXCEPTION at heat.createStack");
1707 //npe.addContext ("CreateVNF");
1708 throw new VnfException ("NullPointerException during heat.createStack");
1709 } catch (Exception e) {
1710 LOGGER.recordMetricEvent (createStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while creating stack with OpenStack", "OpenStack", "CreateStack", vfModuleName);
1711 LOGGER.debug("unhandled exception at heat.createStack");
1712 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while creating stack with OpenStack");
1713 throw new VnfException("Exception during heat.createStack! " + e.getMessage());
1715 } catch (Exception e) {
1716 LOGGER.debug("unhandled exception in create VF");
1717 throw new VnfException("Exception during create VF " + e.getMessage());
1721 // Reach this point if createStack is successful.
1722 // Populate remaining rollback info and response parameters.
1723 vfRollback.setVnfId (heatStack.getCanonicalName ());
1724 vfRollback.setVnfCreated (true);
1726 vnfId.value = heatStack.getCanonicalName ();
1727 outputs.value = copyStringOutputs (heatStack.getOutputs ());
1728 rollback.value = vfRollback;
1730 LOGGER.debug ("VF Module " + vfModuleName + " successfully created");
1731 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully create VF Module");
1737 public void deleteVfModule (String cloudSiteId,
1740 MsoRequest msoRequest) throws VnfException {
1741 MsoLogger.setLogContext (msoRequest);
1742 MsoLogger.setServiceName ("DeleteVf");
1743 LOGGER.debug ("Deleting VF " + vnfName + " in " + cloudSiteId + "/" + tenantId);
1744 // Will capture execution time for metrics
1745 long startTime = System.currentTimeMillis ();
1747 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_VNF_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
1749 // Use the MsoHeatUtils to delete the stack. Set the polling flag to true.
1750 // The possible outcomes of deleteStack are a StackInfo object with status
1751 // of NOTFOUND (on success) or FAILED (on error). Also, MsoOpenstackException
1753 long subStartTime = System.currentTimeMillis ();
1755 heat.deleteStack (tenantId, cloudSiteId, vnfName, true);
1756 LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteStack", vnfName);
1757 } catch (MsoException me) {
1758 me.addContext ("DeleteVNF");
1759 // Failed to query the Stack due to an openstack exception.
1760 // Convert to a generic VnfException
1761 String error = "Delete VF: " + vnfName + " in " + cloudSiteId + "/" + tenantId + ": " + me;
1762 LOGGER.recordMetricEvent (subStartTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteStack", vnfName);
1763 LOGGER.error (MessageEnum.RA_DELETE_VNF_ERR, vnfName, cloudSiteId, tenantId, "OpenStack", "DeleteStack", MsoLogger.ErrorCode.DataError, "Exception - deleteStack", me);
1764 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1765 throw new VnfException (me);
1768 // On success, nothing is returned.
1769 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully delete VF");
1774 public void updateVfModule (String cloudSiteId,
1780 String volumeGroupHeatStackId,
1781 String baseVfHeatStackId,
1782 String vfModuleStackId,
1783 Map <String, String> inputs,
1784 MsoRequest msoRequest,
1785 Holder <Map <String, String>> outputs,
1786 Holder <VnfRollback> rollback) throws VnfException {
1787 String vfModuleName = vnfName;
1788 String vfModuleType = vnfType;
1789 String vfVersion = vnfVersion;
1790 String methodName = "updateVfModule";
1791 MsoLogger.setLogContext (msoRequest.getRequestId (), msoRequest.getServiceInstanceId ());
1792 String serviceName = VNF_ADAPTER_SERVICE_NAME + methodName;
1793 MsoLogger.setServiceName (serviceName);
1795 String requestTypeString = "";
1796 if (requestType != null && !requestType.equals("")) {
1797 requestTypeString = requestType;
1799 String nestedStackId = null;
1800 if (volumeGroupHeatStackId != null && !volumeGroupHeatStackId.equals("")) {
1801 if (!volumeGroupHeatStackId.equalsIgnoreCase("null")) {
1802 nestedStackId = volumeGroupHeatStackId;
1805 String nestedBaseStackId = null;
1806 if (baseVfHeatStackId != null && !baseVfHeatStackId.equals("")) {
1807 if (!baseVfHeatStackId.equalsIgnoreCase("null")) {
1808 nestedBaseStackId = baseVfHeatStackId;
1812 if (inputs == null) {
1813 // Create an empty set of inputs
1814 inputs = new HashMap<String,String>();
1815 LOGGER.debug("inputs == null - setting to empty");
1817 this.sendMapToDebug(inputs);
1819 boolean isBaseRequest = false;
1820 boolean isVolumeRequest = false;
1821 if (requestTypeString.startsWith("VOLUME")) {
1822 isVolumeRequest = true;
1824 if (vfModuleName == null || vfModuleName.trim().equals("")) {
1825 if (vfModuleStackId != null) {
1826 vfModuleName = this.getVfModuleNameFromModuleStackId(vfModuleStackId);
1830 LOGGER.debug ("Updating VFModule: " + vfModuleName + " of type " + vfModuleType + "in " + cloudSiteId + "/" + tenantId);
1831 LOGGER.debug("requestTypeString = " + requestTypeString + ", nestedStackId = " + nestedStackId + ", nestedBaseStackId = " + nestedBaseStackId);
1833 // Will capture execution time for metrics
1834 long startTime = System.currentTimeMillis ();
1836 // Build a default rollback object (no actions performed)
1837 VnfRollback vfRollback = new VnfRollback ();
1838 vfRollback.setCloudSiteId (cloudSiteId);
1839 vfRollback.setTenantId (tenantId);
1840 vfRollback.setMsoRequest (msoRequest);
1841 vfRollback.setRequestType(requestTypeString);
1842 vfRollback.setVolumeGroupHeatStackId(volumeGroupHeatStackId);
1843 vfRollback.setBaseGroupHeatStackId(baseVfHeatStackId);
1844 vfRollback.setIsBase(isBaseRequest);
1845 vfRollback.setVfModuleStackId(vfModuleStackId);
1847 // First, look up to see if the VNF already exists.
1848 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_VNF_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
1849 MsoHeatUtilsWithUpdate heatU = new MsoHeatUtilsWithUpdate (MSO_PROP_VNF_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
1851 StackInfo heatStack = null;
1852 long queryStackStarttime = System.currentTimeMillis ();
1853 LOGGER.debug("UpdateVfModule - querying for " + vfModuleName);
1855 heatStack = heat.queryStack (cloudSiteId, tenantId, vfModuleName);
1856 LOGGER.recordMetricEvent (queryStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully receive response from Open Stack", "OpenStack", "QueryStack", null);
1857 } catch (MsoException me) {
1858 // Failed to query the Stack due to an openstack exception.
1859 // Convert to a generic VnfException
1860 me.addContext ("UpdateVFModule");
1861 String error = "Update VFModule: Query " + vfModuleName + " in " + cloudSiteId + "/" + tenantId + ": " + me;
1862 LOGGER.recordMetricEvent (queryStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryStack", null);
1863 LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vfModuleName, cloudSiteId, tenantId, "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, "Exception - QueryStack", me);
1864 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1865 throw new VnfException (me);
1868 //TODO - do we need to check for the other status possibilities?
1869 if (heatStack == null || heatStack.getStatus () == HeatStatus.NOTFOUND) {
1871 String error = "Update VF: Stack " + vfModuleName + " does not exist in " + cloudSiteId + "/" + tenantId;
1872 LOGGER.error (MessageEnum.RA_VNF_NOT_EXIST, vfModuleName, cloudSiteId, tenantId, "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, error);
1873 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
1874 throw new VnfNotFound (cloudSiteId, tenantId, vfModuleName);
1876 LOGGER.debug ("Found Existing stack, status=" + heatStack.getStatus ());
1877 // Populate the outputs from the existing stack.
1878 outputs.value = copyStringOutputs (heatStack.getOutputs ());
1879 rollback.value = vfRollback; // Default rollback - no updates performed
1882 // 1604 Cinder Volume support - handle a nestedStackId if sent (volumeGroupHeatStackId):
1883 StackInfo nestedHeatStack = null;
1884 long queryStackStarttime2 = System.currentTimeMillis ();
1885 if (nestedStackId != null) {
1887 LOGGER.debug("Querying for nestedStackId = " + nestedStackId);
1888 nestedHeatStack = heat.queryStack(cloudSiteId, tenantId, nestedStackId);
1889 LOGGER.recordMetricEvent (queryStackStarttime2, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully receive response from Open Stack", "OpenStack", "QueryStack", null);
1890 } catch (MsoException me) {
1891 // Failed to query the Stack due to an openstack exception.
1892 // Convert to a generic VnfException
1893 me.addContext ("UpdateVFModule");
1894 String error = "Update VF: Attached heatStack ID Query " + nestedStackId + " in " + cloudSiteId + "/" + tenantId + ": " + me ;
1895 LOGGER.recordMetricEvent (queryStackStarttime2, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryStack", null);
1896 LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vnfName, cloudSiteId, tenantId, "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, "Exception - " + error, me);
1897 LOGGER.debug("ERROR trying to query nested stack= " + error);
1898 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1899 throw new VnfException (me);
1901 if (nestedHeatStack == null || nestedHeatStack.getStatus() == HeatStatus.NOTFOUND) {
1902 MsoLogger.setServiceName (serviceName);
1903 String error = "Update VFModule: Attached volume heatStack ID DOES NOT EXIST " + nestedStackId + " in " + cloudSiteId + "/" + tenantId + " USER ERROR" ;
1904 LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vnfName, cloudSiteId, tenantId, error, "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, error);
1905 LOGGER.debug(error);
1906 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
1907 throw new VnfException (error, MsoExceptionCategory.USERDATA);
1909 LOGGER.debug("Found nested heat stack - copying values to inputs");
1910 this.sendMapToDebug(inputs);
1911 heat.copyStringOutputsToInputs(inputs, nestedHeatStack.getOutputs(), false);
1912 this.sendMapToDebug(inputs);
1915 // handle a nestedBaseStackId if sent - this is the stack ID of the base.
1916 StackInfo nestedBaseHeatStack = null;
1917 if (nestedBaseStackId != null) {
1918 long queryStackStarttime3 = System.currentTimeMillis ();
1920 LOGGER.debug("Querying for nestedBaseStackId = " + nestedBaseStackId);
1921 nestedBaseHeatStack = heat.queryStack(cloudSiteId, tenantId, nestedBaseStackId);
1922 LOGGER.recordMetricEvent (queryStackStarttime3, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully receive response from Open Stack", "OpenStack", "QueryStack", null);
1923 } catch (MsoException me) {
1924 // Failed to query the Stack due to an openstack exception.
1925 // Convert to a generic VnfException
1926 me.addContext ("UpdateVfModule");
1927 String error = "Update VFModule: Attached baseHeatStack ID Query " + nestedBaseStackId + " in " + cloudSiteId + "/" + tenantId + ": " + me ;
1928 LOGGER.recordMetricEvent (queryStackStarttime3, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryStack", null);
1929 LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vfModuleName, cloudSiteId, tenantId, "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, "Exception - " + error, me);
1930 LOGGER.debug("ERROR trying to query nested base stack= " + error);
1931 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1932 throw new VnfException (me);
1934 if (nestedBaseHeatStack == null || nestedBaseHeatStack.getStatus() == HeatStatus.NOTFOUND) {
1935 MsoLogger.setServiceName (serviceName);
1936 String error = "Update VFModule: Attached base heatStack ID DOES NOT EXIST " + nestedBaseStackId + " in " + cloudSiteId + "/" + tenantId + " USER ERROR" ;
1937 LOGGER.error (MessageEnum.RA_QUERY_VNF_ERR, vfModuleName, cloudSiteId, tenantId, error, "OpenStack", "QueryStack", MsoLogger.ErrorCode.DataError, error);
1938 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
1939 LOGGER.debug(error);
1940 throw new VnfException (error, MsoExceptionCategory.USERDATA);
1942 LOGGER.debug("Found nested base heat stack - copying values to inputs");
1943 this.sendMapToDebug(inputs);
1944 heat.copyStringOutputsToInputs(inputs, nestedBaseHeatStack.getOutputs(), false);
1945 this.sendMapToDebug(inputs);
1949 // Ready to deploy the new VNF
1951 try (CatalogDatabase db = new CatalogDatabase ()) {
1952 // Retrieve the VF definition
1955 if (vfVersion != null && !vfVersion.isEmpty ()) {
1956 vf = db.getVfModuleType(vfModuleType, vfVersion);
1958 LOGGER.debug("Unable to find " + vfModuleType + " and version = " + vfVersion + " in the TYPE column - will try in MODEL_NAME");
1959 vf = db.getVfModuleModelName(vfModuleType, vfVersion);
1961 LOGGER.debug("Unable to find " + vfModuleType + " and version = " + vfVersion + " in the MODEL_NAME field either - ERROR");
1965 vf = db.getVfModuleType(vfModuleType);
1967 LOGGER.debug("Unable to find " + vfModuleType + " in the TYPE column - will try in MODEL_NAME");
1968 vf = db.getVfModuleModelName(vfModuleType);
1970 LOGGER.debug("Unable to find " + vfModuleType + " in the MODEL_NAME field either - ERROR");
1975 String error = "Update VFModule: Unknown VF Module Type: " + vfModuleType;
1976 if (vfVersion != null && !vfVersion.isEmpty()) {
1977 error += " with version = " + vfVersion;
1979 LOGGER.error (MessageEnum.RA_VNF_UNKNOWN_PARAM, "VF Module Type", vfModuleType, "OpenStack", "", MsoLogger.ErrorCode.DataError, error);
1980 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
1981 throw new VnfException (error, MsoExceptionCategory.USERDATA);
1983 LOGGER.debug ("Got VF module definition from Catalog: " + vf.toString ());
1985 HeatTemplate heatTemplate = null;
1986 Integer heatTemplateId = null;
1987 Integer heatEnvtId = null;
1988 if (!isVolumeRequest) {
1989 heatTemplateId = vf.getTemplateId();
1990 heatEnvtId = vf.getEnvironmentId();
1992 heatTemplateId = vf.getVolTemplateId();
1993 heatEnvtId = vf.getVolEnvironmentId();
1995 if (heatTemplateId == null) {
1996 String error = "UpdateVF: No Heat Template ID defined in catalog database for " + vfModuleType + ", reqType=" + requestTypeString;
1997 LOGGER.error(MessageEnum.RA_VNF_UNKNOWN_PARAM, "Heat Template ID", vfModuleType, "OpenStack", "", MsoLogger.ErrorCode.DataError, error);
1998 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
1999 alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR,
2000 MsoAlarmLogger.CRITICAL, error);
2001 throw new VnfException(error, MsoExceptionCategory.INTERNAL);
2003 heatTemplate = db.getHeatTemplate(heatTemplateId);
2006 if (heatTemplate == null) {
2007 String error = "Update VNF: undefined Heat Template. VF="
2008 + vfModuleType + ", heat template id = " + heatTemplateId;
2009 LOGGER.error(MessageEnum.RA_VNF_UNKNOWN_PARAM,
2011 String.valueOf(heatTemplateId), "OpenStack", "", MsoLogger.ErrorCode.DataError, error);
2012 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
2013 // Alarm on this error, configuration must be fixed
2014 alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR,
2015 MsoAlarmLogger.CRITICAL, error);
2017 throw new VnfException(error, MsoExceptionCategory.INTERNAL);
2020 LOGGER.debug ("Got HEAT Template from DB: " + heatTemplate.toString ());
2022 // Add check for any Environment variable
2023 HeatEnvironment heatEnvironment = null;
2024 String heatEnvironmentString = null;
2026 if (heatEnvtId != null) {
2027 LOGGER.debug ("about to call getHeatEnvironment with :" + heatEnvtId + ":");
2028 heatEnvironment = db.getHeatEnvironment (heatEnvtId);
2029 if (heatEnvironment == null) {
2031 String error = "Update VNF: undefined Heat Environment. VF=" + vfModuleType
2032 + ", Environment ID="
2034 LOGGER.error (MessageEnum.RA_VNF_UNKNOWN_PARAM, "Heat Environment ID", String.valueOf(heatEnvtId), "OpenStack", "", MsoLogger.ErrorCode.DataError, error);
2035 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
2036 // Alarm on this error, configuration must be fixed
2037 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
2039 throw new VnfException (error, MsoExceptionCategory.INTERNAL);
2041 LOGGER.debug ("Got Heat Environment from DB: " + heatEnvironment.toString ());
2042 heatEnvironmentString = heatEnvironment.getEnvironment (); //this.parseEnvironment (heatEnvironment.getEnvironment ());
2043 LOGGER.debug ("After parsing: " + heatEnvironmentString);
2046 LOGGER.debug ("no environment parameter for this VFModuleType " + vfModuleType);
2050 LOGGER.debug ("In MsoVnfAdapterImpl, about to call db.getNestedTemplates avec templateId="
2051 + heatTemplate.getId ());
2052 Map <String, Object> nestedTemplates = db.getNestedTemplates (heatTemplate.getId ());
2053 Map <String, Object> nestedTemplatesChecked = new HashMap <String, Object> ();
2054 if (nestedTemplates != null) {
2055 // for debugging print them out
2056 LOGGER.debug ("Contents of nestedTemplates - to be added to files: on stack:");
2057 for (String providerResourceFile : nestedTemplates.keySet ()) {
2058 String providerResourceFileChecked = providerResourceFile; //this.enforceFilePrefix (providerResourceFile);
2059 String childTemplateBody = (String) nestedTemplates.get (providerResourceFile);
2060 nestedTemplatesChecked.put (providerResourceFileChecked, childTemplateBody);
2061 LOGGER.debug (providerResourceFileChecked + " -> " + childTemplateBody);
2064 LOGGER.debug ("No nested templates found - nothing to do here");
2065 nestedTemplatesChecked = null;
2068 // Also add the files: for any get_files associated with this VfModule
2069 // *if* there are any
2070 LOGGER.debug ("In MsoVnfAdapterImpl.updateVfModule, about to call db.getHeatFiles avec vfModuleId="
2073 Map <String, HeatFiles> heatFiles = null;
2074 // Map <String, HeatFiles> heatFiles = db.getHeatFiles (vnf.getId ());
2075 Map <String, Object> heatFilesObjects = new HashMap <String, Object> ();
2077 // Add ability to turn on adding get_files with volume requests (by property).
2078 boolean addGetFilesOnVolumeReq = false;
2080 String propertyString = msoPropertiesFactory.getMsoJavaProperties(MSO_PROP_VNF_ADAPTER).getProperty(MsoVnfAdapterImpl.ADD_GET_FILES_ON_VOLUME_REQ, null);
2081 if ("true".equalsIgnoreCase(propertyString) || "y".equalsIgnoreCase(propertyString)) {
2082 addGetFilesOnVolumeReq = true;
2083 LOGGER.debug("AddGetFilesOnVolumeReq - setting to true! " + propertyString);
2085 } catch (Exception e) {
2086 LOGGER.debug("An error occured trying to get property " + MsoVnfAdapterImpl.ADD_GET_FILES_ON_VOLUME_REQ + " - default to false", e);
2088 if (!isVolumeRequest || addGetFilesOnVolumeReq) {
2089 heatFiles = db.getHeatFilesForVfModule(vf.getId());
2090 if (heatFiles != null) {
2091 // add these to stack - to be done in createStack
2092 // here, we will map them to Map<String, Object> from Map<String, HeatFiles>
2093 // this will match the nested templates format
2094 LOGGER.debug ("Contents of heatFiles - to be added to files: on stack:");
2096 for (String heatFileName : heatFiles.keySet ()) {
2097 if (heatFileName.startsWith("_ERROR|")) {
2098 // This means there was an invalid entry in VF_MODULE_TO_HEAT_FILES table - the heat file it pointed to could not be found.
2099 String heatFileId = heatFileName.substring(heatFileName.lastIndexOf("|")+1);
2100 String error = "Create: No HEAT_FILES entry in catalog database for " + vfModuleType + " at HEAT_FILES index=" + heatFileId;
2101 LOGGER.debug(error);
2102 LOGGER.error (MessageEnum.RA_VNF_UNKNOWN_PARAM, "HEAT_FILES entry not found at " + heatFileId, vfModuleType, "OpenStack", "", MsoLogger.ErrorCode.DataError, error);
2103 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
2104 // Alarm on this error, configuration must be fixed
2105 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
2106 throw new VnfException (error, MsoExceptionCategory.INTERNAL);
2108 String heatFileBody = heatFiles.get (heatFileName).getFileBody ();
2109 LOGGER.debug (heatFileName + " -> " + heatFileBody);
2110 heatFilesObjects.put (heatFileName, heatFileBody);
2113 LOGGER.debug ("No heat files found -nothing to do here");
2114 heatFilesObjects = null;
2118 // Check that required parameters have been supplied
2119 String missingParams = null;
2120 List <String> paramList = new ArrayList <String> ();
2122 // New for 1510 - consult the PARAM_ALIAS field to see if we've been
2123 // supplied an alias. Only check if we don't find it initially.
2124 // Also new in 1510 - don't flag missing parameters if there's an environment - because they might be there.
2125 // And also new - add parameter to turn off checking all together if we find we're blocking orders we
2127 boolean haveEnvironmentParameters = false;
2128 boolean checkRequiredParameters = true;
2130 String propertyString = msoPropertiesFactory.getMsoJavaProperties (MSO_PROP_VNF_ADAPTER)
2131 .getProperty (MsoVnfAdapterImpl.CHECK_REQD_PARAMS,null);
2132 if ("false".equalsIgnoreCase (propertyString) || "n".equalsIgnoreCase (propertyString)) {
2133 checkRequiredParameters = false;
2134 LOGGER.debug ("CheckRequiredParameters is FALSE. Will still check but then skip blocking..."
2135 + MsoVnfAdapterImpl.CHECK_REQD_PARAMS);
2137 } catch (Exception e) {
2138 // No problem - default is true
2139 LOGGER.debug ("An exception occured trying to get property " + MsoVnfAdapterImpl.CHECK_REQD_PARAMS, e);
2141 // 1604 - Add enhanced environment & parameter checking
2142 // Part 1: parse envt entries to see if reqd parameter is there (before used a simple grep
2143 // Part 2: only submit to openstack the parameters in the envt that are in the heat template
2144 // Note this also removes any comments
2145 MsoHeatEnvironmentEntry mhee = null;
2146 if (heatEnvironmentString != null && heatEnvironmentString.toLowerCase ().contains ("parameters:")) {
2147 LOGGER.debug("Enhanced environment checking enabled - 1604");
2148 haveEnvironmentParameters = true;
2149 StringBuilder sb = new StringBuilder(heatEnvironmentString);
2150 //LOGGER.debug("About to create MHEE with " + sb);
2151 mhee = new MsoHeatEnvironmentEntry(sb);
2152 StringBuilder sb2 = new StringBuilder("\nHeat Template Parameters:\n");
2153 for (HeatTemplateParam parm : heatTemplate.getParameters()) {
2154 sb2.append("\t" + parm.getParamName() + ", required=" + parm.isRequired());
2156 if (!mhee.isValid()) {
2157 sb2.append("Environment says it's not valid! " + mhee.getErrorString());
2159 sb2.append("\nEnvironment:");
2160 sb2.append(mhee.toFullString());
2162 LOGGER.debug(sb2.toString());
2164 LOGGER.debug("NO ENVIRONMENT for this entry");
2167 // New for 1607 - support params of json type
2168 HashMap<String, JsonNode> jsonParams = new HashMap<String, JsonNode>();
2169 boolean hasJson = false;
2171 for (HeatTemplateParam parm : heatTemplate.getParameters ()) {
2172 LOGGER.debug ("Parameter:'" + parm.getParamName ()
2174 + parm.isRequired ()
2176 + parm.getParamAlias ());
2178 String parameterType = parm.getParamType();
2179 if (parameterType == null || parameterType.trim().equals("")) {
2180 parameterType = "String";
2182 JsonNode jsonNode = null;
2183 if (parameterType.equalsIgnoreCase("json") && inputs != null) {
2184 if (inputs.containsKey(parm.getParamName()) ) {
2186 String jsonString = null;
2188 jsonString = inputs.get(parm.getParamName());
2189 jsonNode = new ObjectMapper().readTree(jsonString);
2190 } catch (JsonParseException jpe) {
2191 //TODO - what to do here?
2192 //for now - send the error to debug, but just leave it as a String
2193 String errorMessage = jpe.getMessage();
2194 LOGGER.debug("Json Error Converting " + parm.getParamName() + " - " + errorMessage);
2197 } catch (Exception e) {
2199 LOGGER.debug("Json Error Converting " + parm.getParamName() + " " + e.getMessage());
2203 if (jsonNode != null) {
2204 jsonParams.put(parm.getParamName(), jsonNode);
2206 } else if (inputs.containsKey(parm.getParamAlias())) {
2208 String jsonString = null;
2210 jsonString = inputs.get(parm.getParamAlias());
2211 jsonNode = new ObjectMapper().readTree(jsonString);
2212 } catch (JsonParseException jpe) {
2213 //TODO - what to do here?
2214 //for now - send the error to debug, but just leave it as a String
2215 String errorMessage = jpe.getMessage();
2216 LOGGER.debug("Json Error Converting " + parm.getParamName() + " - " + errorMessage);
2219 } catch (Exception e) {
2221 LOGGER.debug("Json Error Converting " + parm.getParamName() + " " + e.getMessage());
2225 if (jsonNode != null) {
2226 // Notice here - we add it to the jsonParams hashMap with the actual name -
2227 // then manipulate the inputs so when we check for aliases below - it will not
2229 jsonParams.put(parm.getParamName(), jsonNode);
2230 inputs.remove(parm.getParamAlias());
2231 inputs.put(parm.getParamName(), jsonString);
2233 } //TODO add a check for the parameter in the env file
2236 if (parm.isRequired () && (inputs == null || !inputs.containsKey (parm.getParamName ()))) {
2237 if (inputs.containsKey (parm.getParamAlias ())) {
2238 // They've submitted using an alias name. Remove that from inputs, and add back using real name.
2239 String realParamName = parm.getParamName ();
2240 String alias = parm.getParamAlias ();
2241 String value = inputs.get (alias);
2242 LOGGER.debug ("*Found an Alias: paramName=" + realParamName
2247 inputs.remove (alias);
2248 inputs.put (realParamName, value);
2249 LOGGER.debug (alias + " entry removed from inputs, added back using " + realParamName);
2251 // enhanced - check if it's in the Environment (note: that method
2252 else if (mhee != null && mhee.containsParameter(parm.getParamName())) {
2254 LOGGER.debug ("Required parameter " + parm.getParamName ()
2255 + " appears to be in environment - do not count as missing");
2258 LOGGER.debug ("adding to missing parameters list: " + parm.getParamName ());
2259 if (missingParams == null) {
2260 missingParams = parm.getParamName ();
2262 missingParams += "," + parm.getParamName ();
2266 paramList.add (parm.getParamName ());
2268 if (missingParams != null) {
2269 // Problem - missing one or more required parameters
2270 if (checkRequiredParameters) {
2271 String error = "Update VNF: Missing Required inputs: " + missingParams;
2272 LOGGER.error (MessageEnum.RA_MISSING_PARAM, missingParams, "OpenStack", "", MsoLogger.ErrorCode.DataError, error);
2273 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
2274 throw new VnfException (error, MsoExceptionCategory.USERDATA);
2276 LOGGER.debug ("found missing parameters - but checkRequiredParameters is false - will not block");
2279 LOGGER.debug ("No missing parameters found - ok to proceed");
2282 // Here - modify heatEnvironmentString
2283 StringBuilder parsedEnvironmentString = null;
2284 String newEnvironmentString = null;
2286 LOGGER.debug("Environment before:\n" + heatEnvironmentString);
2287 parsedEnvironmentString = mhee.toFullStringExcludeNonParams(heatTemplate.getParameters());
2288 LOGGER.debug("Environment after:\n" + parsedEnvironmentString.toString());
2289 newEnvironmentString = parsedEnvironmentString.toString();
2292 // Remove any extraneous parameters (don't throw an error)
2293 if (inputs != null) {
2294 List <String> extraParams = new ArrayList <String> ();
2295 extraParams.addAll (inputs.keySet ());
2296 // This is not a valid parameter for this template
2297 extraParams.removeAll (paramList);
2298 if (!extraParams.isEmpty ()) {
2299 LOGGER.warn (MessageEnum.RA_VNF_EXTRA_PARAM, vnfType, extraParams.toString(), "OpenStack", "", MsoLogger.ErrorCode.DataError, "Extra params");
2300 inputs.keySet ().removeAll (extraParams);
2303 // 1607 - when we get here - we have clean inputs. Create inputsTwo in case we have json
2304 Map<String, Object> inputsTwo = null;
2305 if (hasJson && jsonParams.size() > 0) {
2306 inputsTwo = new HashMap<String, Object>();
2307 for (String keyParamName : inputs.keySet()) {
2308 if (jsonParams.containsKey(keyParamName)) {
2309 inputsTwo.put(keyParamName, jsonParams.get(keyParamName));
2311 inputsTwo.put(keyParamName, inputs.get(keyParamName));
2316 // "Fix" the template if it has CR/LF (getting this from Oracle)
2317 String template = heatTemplate.getHeatTemplate ();
2318 template = template.replaceAll ("\r\n", "\n");
2320 // Have the tenant. Now deploy the stack itself
2321 // Ignore MsoTenantNotFound and MsoStackAlreadyExists exceptions
2322 // because we already checked for those.
2323 long updateStackStarttime = System.currentTimeMillis ();
2326 heatStack = heatU.updateStack (cloudSiteId,
2330 copyStringInputs (inputs),
2332 heatTemplate.getTimeoutMinutes (),
2333 newEnvironmentString,
2334 //heatEnvironmentString,
2335 nestedTemplatesChecked,
2337 LOGGER.recordMetricEvent (updateStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully receive response from Open Stack", "OpenStack", "UpdateStack", null);
2339 heatStack = heatU.updateStack (cloudSiteId,
2345 heatTemplate.getTimeoutMinutes (),
2346 newEnvironmentString,
2347 //heatEnvironmentString,
2348 nestedTemplatesChecked,
2350 LOGGER.recordMetricEvent (updateStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully receive response from Open Stack", "OpenStack", "UpdateStack", null);
2353 } catch (MsoException me) {
2354 me.addContext ("UpdateVFModule");
2355 String error = "Update VFModule " + vfModuleType + " in " + cloudSiteId + "/" + tenantId + ": " + me;
2356 LOGGER.recordMetricEvent (updateStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "UpdateStack", null);
2357 LOGGER.error (MessageEnum.RA_UPDATE_VNF_ERR, vfModuleType, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - " + error, me);
2358 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
2359 throw new VnfException (me);
2363 // Reach this point if updateStack is successful.
2364 // Populate remaining rollback info and response parameters.
2365 vfRollback.setVnfId (heatStack.getCanonicalName ());
2366 vfRollback.setVnfCreated (true);
2368 outputs.value = copyStringOutputs (heatStack.getOutputs ());
2369 rollback.value = vfRollback;
2370 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully update VF Module");
2374 private String getVfModuleNameFromModuleStackId(String vfModuleStackId) {
2375 // expected format of vfModuleStackId is "MSOTEST51-vSAMP3_base_module-0/1fc1f86c-7b35-447f-99a6-c23ec176ae24"
2376 // before the "/" is the vfModuleName and after the "/" is the heat stack id in Openstack
2377 if (vfModuleStackId == null)
2379 int index = vfModuleStackId.lastIndexOf('/');
2382 String vfModuleName = null;
2384 vfModuleName = vfModuleStackId.substring(0, index);
2385 } catch (Exception e) {
2386 vfModuleName = null;
2388 return vfModuleName;