2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * Copyright (C) 2017 Huawei Technologies Co., Ltd. All rights reserved.
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
22 package org.openecomp.mso.adapters.network;
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.List;
29 import javax.jws.WebService;
30 import javax.xml.ws.Holder;
32 import org.codehaus.jackson.JsonNode;
33 import org.codehaus.jackson.map.ObjectMapper;
35 import org.openecomp.mso.adapters.network.exceptions.NetworkException;
36 import org.openecomp.mso.cloud.CloudConfig;
37 import org.openecomp.mso.cloud.CloudConfigFactory;
38 import org.openecomp.mso.cloud.CloudSite;
39 import org.openecomp.mso.db.catalog.CatalogDatabase;
40 import org.openecomp.mso.db.catalog.beans.HeatTemplate;
41 import org.openecomp.mso.db.catalog.beans.NetworkResource;
42 import org.openecomp.mso.db.catalog.utils.MavenLikeVersioning;
43 import org.openecomp.mso.entity.MsoRequest;
44 import org.openecomp.mso.logger.MessageEnum;
45 import org.openecomp.mso.logger.MsoAlarmLogger;
46 import org.openecomp.mso.logger.MsoLogger;
47 import org.openecomp.mso.openstack.beans.HeatStatus;
48 import org.openecomp.mso.openstack.beans.NetworkInfo;
49 import org.openecomp.mso.openstack.beans.NetworkRollback;
50 import org.openecomp.mso.openstack.beans.NetworkStatus;
51 import org.openecomp.mso.openstack.beans.Pool;
52 import org.openecomp.mso.openstack.beans.StackInfo;
53 import org.openecomp.mso.openstack.beans.Subnet;
54 import org.openecomp.mso.openstack.exceptions.MsoAdapterException;
55 import org.openecomp.mso.openstack.exceptions.MsoException;
56 import org.openecomp.mso.openstack.exceptions.MsoExceptionCategory;
57 import org.openecomp.mso.openstack.utils.MsoHeatUtils;
58 import org.openecomp.mso.openstack.utils.MsoHeatUtilsWithUpdate;
59 import org.openecomp.mso.openstack.utils.MsoNeutronUtils;
60 import org.openecomp.mso.openstack.utils.MsoNeutronUtils.NetworkType;
61 import org.openecomp.mso.properties.MsoPropertiesException;
62 import org.openecomp.mso.properties.MsoPropertiesFactory;
64 import static org.openecomp.mso.openstack.utils.MsoCommonUtils.isNullOrEmpty;
66 @WebService(serviceName = "NetworkAdapter", endpointInterface = "org.openecomp.mso.adapters.network.MsoNetworkAdapter", targetNamespace = "http://org.openecomp.mso/network")
67 public class MsoNetworkAdapterImpl implements MsoNetworkAdapter {
69 MsoPropertiesFactory msoPropertiesFactory=new MsoPropertiesFactory();
71 CloudConfigFactory cloudConfigFactory=new CloudConfigFactory();
73 private static final String AIC3_NW_PROPERTY= "org.openecomp.mso.adapters.network.aic3nw";
74 private static final String AIC3_NW="OS::ContrailV2::VirtualNetwork";
75 public static final String MSO_PROP_NETWORK_ADAPTER="MSO_PROP_NETWORK_ADAPTER";
76 private static final String VLANS = "vlans";
77 private static final String PHYSICAL_NETWORK = "physical_network";
78 private static final String UPDATE_NETWORK_CONTEXT = "UpdateNetwork";
79 private static final String NETWORK_ID = "network_id";
80 private static final String NETWORK_FQDN = "network_fqdn";
81 private static final String CREATE_NETWORK_CONTEXT = "CreateNetwork";
82 private static final String MSO_CONFIGURATION_ERROR = "MsoConfigurationError";
83 private static final String NEUTRON_MODE = "NEUTRON";
84 private static MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA);
85 private static MsoAlarmLogger alarmLogger = new MsoAlarmLogger ();
86 protected CloudConfig cloudConfig;
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 Network Adapter");
97 * Do not use this constructor or the msoPropertiesFactory will be NULL.
99 * @see MsoNetworkAdapterImpl#MsoNetworkAdapterImpl(MsoPropertiesFactory)
101 public MsoNetworkAdapterImpl() {
105 * This constructor MUST be used if this class if called with the new operator.
106 * @param msoPropFactory
109 public MsoNetworkAdapterImpl(MsoPropertiesFactory msoPropFactory,CloudConfigFactory cloudConfigFact) {
110 this.msoPropertiesFactory = msoPropFactory;
111 this.cloudConfigFactory=cloudConfigFact;
112 cloudConfig = cloudConfigFactory.getCloudConfig ();
116 public void createNetwork (String cloudSiteId,
119 String modelCustomizationUuid,
121 String physicalNetworkName,
122 List <Integer> vlans,
123 Boolean failIfExists,
125 List <Subnet> subnets,
126 MsoRequest msoRequest,
127 Holder <String> networkId,
128 Holder <String> neutronNetworkId,
129 Holder <Map <String, String>> subnetIdMap,
130 Holder <NetworkRollback> rollback) throws NetworkException {
131 Holder <String> networkFqdn = new Holder <> ();
132 createNetwork (cloudSiteId,
135 modelCustomizationUuid,
156 public void createNetworkContrail (String cloudSiteId,
159 String modelCustomizationUuid,
161 List <String> routeTargets,
164 Boolean failIfExists,
166 List <Subnet> subnets,
167 List <String> policyFqdns,
168 List<String> routeTableFqdns,
169 MsoRequest msoRequest,
170 Holder <String> networkId,
171 Holder <String> neutronNetworkId,
172 Holder <String> networkFqdn,
173 Holder <Map <String, String>> subnetIdMap,
174 Holder <NetworkRollback> rollback) throws NetworkException {
175 createNetwork (cloudSiteId,
178 modelCustomizationUuid,
199 * This is the "Create Network" web service implementation.
200 * It will create a new Network of the requested type in the specified cloud
201 * and tenant. The tenant must exist at the time this service is called.
203 * If a network with the same name already exists, this can be considered a
204 * success or failure, depending on the value of the 'failIfExists' parameter.
206 * There will be a pre-defined set of network types defined in the MSO Catalog.
207 * All such networks will have a similar configuration, based on the allowable
208 * Openstack networking definitions. This includes basic networks, provider
209 * networks (with a single VLAN), and multi-provider networks (one or more VLANs)
211 * Initially, all provider networks must be "vlan" type, and multiple segments in
212 * a multi-provider network must be multiple VLANs on the same physical network.
214 * This service supports two modes of Network creation/update:
215 * - via Heat Templates
217 * The network orchestration mode for each network type is declared in its
218 * catalog definition. All Heat-based templates must support some subset of
219 * the same input parameters: network_name, physical_network, vlan(s).
221 * The method returns the network ID and a NetworkRollback object. This latter
222 * object can be passed as-is to the rollbackNetwork operation to undo everything
223 * that was created. This is useful if a network is successfully created but
224 * the orchestration fails on a subsequent operation.
227 private void createNetwork (String cloudSiteId,
230 String modelCustomizationUuid,
232 String physicalNetworkName,
233 List <Integer> vlans,
234 List <String> routeTargets,
237 Boolean failIfExists,
239 List <Subnet> subnets,
240 List <String> policyFqdns,
241 List <String> routeTableFqdns,
242 MsoRequest msoRequest,
243 Holder <String> networkId,
244 Holder <String> neutronNetworkId,
245 Holder <String> networkFqdn,
246 Holder <Map <String, String>> subnetIdMap,
247 Holder <NetworkRollback> rollback) throws NetworkException {
248 MsoLogger.setLogContext (msoRequest);
249 MsoLogger.setServiceName ("CreateNetwork");
251 LOGGER.debug ("*** CREATE Network: " + networkName
259 // Will capture execution time for metrics
260 long startTime = System.currentTimeMillis ();
262 // Build a default rollback object (no actions performed)
263 NetworkRollback networkRollback = new NetworkRollback ();
264 networkRollback.setCloudId (cloudSiteId);
265 networkRollback.setTenantId (tenantId);
266 networkRollback.setMsoRequest (msoRequest);
267 networkRollback.setModelCustomizationUuid(modelCustomizationUuid);
269 // tenant query is not required here.
270 // If the tenant doesn’t exist, the Heat calls will fail anyway (when the HeatUtils try to obtain a token).
271 // So this is just catching that error in a bit more obvious way up front.
273 cloudConfig = cloudConfigFactory.getCloudConfig ();
274 CloudSite cloudSite = cloudConfig.getCloudSite (cloudSiteId);
275 if (cloudSite == null)
277 String error = "Configuration Error. Stack " + networkName + " in "
282 + " CloudSite does not exist in MSO Configuration";
283 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "", "", MsoLogger.ErrorCode.DataError, "Configuration Error");
284 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
285 // Set the detailed error as the Exception 'message'
286 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
289 // Get a handle to the Catalog Database
290 CatalogDatabase db = getCatalogDB ();
292 // Make sure DB connection is always closed
294 NetworkResource networkResource = networkCheck (db,
297 modelCustomizationUuid,
303 String mode = networkResource.getOrchestrationMode ();
304 NetworkType neutronNetworkType = NetworkType.valueOf (networkResource.getNeutronNetworkType ());
306 if (NEUTRON_MODE.equals (mode)) {
308 // Use an MsoNeutronUtils for all neutron commands
309 MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
311 // See if the Network already exists (by name)
312 NetworkInfo netInfo = null;
313 long queryNetworkStarttime = System.currentTimeMillis ();
315 netInfo = neutron.queryNetwork (networkName, tenantId, cloudSiteId);
316 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Response successfully received from OpenStack", "OpenStack", "QueryNetwork", null);
317 } catch (MsoException me) {
318 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while querying network from OpenStack", "OpenStack", "QueryNetwork", null);
319 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception while querying network from OpenStack", me);
320 me.addContext (CREATE_NETWORK_CONTEXT);
321 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while querying network from OpenStack");
322 throw new NetworkException (me);
325 if (netInfo != null) {
326 // Exists. If that's OK, return success with the network ID.
327 // Otherwise, return an exception.
328 if (failIfExists != null && failIfExists) {
329 String error = "Create Nework: Network " + networkName
330 + " already exists in "
334 + " with ID " + netInfo.getId();
335 LOGGER.error (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Network already exists");
336 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
337 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
339 // Populate the outputs from the existing network.
340 networkId.value = netInfo.getId ();
341 neutronNetworkId.value = netInfo.getId ();
342 rollback.value = networkRollback; // Default rollback - no updates performed
343 String msg = "Found Existing network, status=" + netInfo.getStatus () + " for Neutron mode";
344 LOGGER.warn (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "", "", MsoLogger.ErrorCode.DataError, "Found Existing network, status=" + netInfo.getStatus ());
345 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, msg);
350 long createNetworkStarttime = System.currentTimeMillis ();
352 netInfo = neutron.createNetwork (cloudSiteId,
358 LOGGER.recordMetricEvent (createNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Response successfully received from OpenStack", "OpenStack", "CreateNetwork", null);
359 } catch (MsoException me) {
360 me.addContext (CREATE_NETWORK_CONTEXT);
361 LOGGER.recordMetricEvent (createNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while communicate with OpenStack", "OpenStack", "CreateNetwork", null);
362 String error = "Create Network: type " + neutronNetworkType
369 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception while communicate with OpenStack", me);
370 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
372 throw new NetworkException (me);
375 // Note: ignoring MsoNetworkAlreadyExists because we already checked.
377 // If reach this point, network creation is successful.
378 // Since directly created via Neutron, networkId tracked by MSO is the same
379 // as the neutron network ID.
380 networkId.value = netInfo.getId ();
381 neutronNetworkId.value = netInfo.getId ();
383 networkRollback.setNetworkCreated (true);
384 networkRollback.setNetworkId (netInfo.getId ());
385 networkRollback.setNeutronNetworkId (netInfo.getId ());
386 networkRollback.setNetworkType (networkType);
388 LOGGER.debug ("Network " + networkName + " created, id = " + netInfo.getId ());
389 } else if ("HEAT".equals (mode)) {
391 // Use an MsoHeatUtils for all Heat commands
392 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_NETWORK_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
394 //HeatTemplate heatTemplate = db.getHeatTemplate (networkResource.getTemplateId ());
395 HeatTemplate heatTemplate = db.getHeatTemplateByArtifactUuidRegularQuery (networkResource.getHeatTemplateArtifactUUID());
396 if (heatTemplate == null) {
397 String error = "Network error - undefined Heat Template. Network Type = " + networkType;
398 LOGGER.error (MessageEnum.RA_PARAM_NOT_FOUND, "Heat Template", "Network Type", networkType, "Openstack", "", MsoLogger.ErrorCode.DataError, "Network error - undefined Heat Template. Network Type = " + networkType);
399 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error); // Alarm on this
403 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
404 throw new NetworkException (error, MsoExceptionCategory.INTERNAL);
407 LOGGER.debug ("Got HEAT Template from DB: " + heatTemplate.toString ());
409 // "Fix" the template if it has CR/LF (getting this from Oracle)
410 String template = heatTemplate.getHeatTemplate ();
411 template = template.replaceAll ("\r\n", "\n");
413 boolean aic3template=false;
414 String aic3nw = AIC3_NW;
416 aic3nw = msoPropertiesFactory.getMsoJavaProperties(MSO_PROP_NETWORK_ADAPTER).getProperty(AIC3_NW_PROPERTY, AIC3_NW);
417 } catch (MsoPropertiesException e) {
418 String error = "Unable to get properties:" + MSO_PROP_NETWORK_ADAPTER;
419 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "", "", MsoLogger.ErrorCode.DataError, "Exception - Unable to get properties", e);
422 if (template.contains(aic3nw))
425 // First, look up to see if the Network already exists (by name).
426 // For HEAT orchestration of networks, the stack name will always match the network name
427 StackInfo heatStack = null;
428 long queryNetworkStarttime = System.currentTimeMillis ();
430 heatStack = heat.queryStack (cloudSiteId, tenantId, networkName);
431 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Response successfully received from OpenStack", "OpenStack", "QueryNetwork", null);
432 } catch (MsoException me) {
433 me.addContext (CREATE_NETWORK_CONTEXT);
434 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while querying stack from OpenStack", "OpenStack", "QueryNetwork", null);
435 String error = "Create Network (heat): query network " + networkName
442 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception while querying stack from OpenStack", me);
443 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
444 throw new NetworkException (me);
447 if (heatStack != null && !(heatStack.getStatus () == HeatStatus.NOTFOUND)) {
448 // Stack exists. Return success or error depending on input directive
449 if (failIfExists != null && failIfExists) {
450 String error = "CreateNetwork: Stack " + networkName
451 + " already exists in "
455 + " as " + heatStack.getCanonicalName();
456 LOGGER.error (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "", "", MsoLogger.ErrorCode.DataError, "Network already exists");
457 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
458 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
460 // Populate the outputs from the existing stack.
461 networkId.value = heatStack.getCanonicalName ();
462 neutronNetworkId.value = (String) heatStack.getOutputs ().get (NETWORK_ID);
463 rollback.value = networkRollback; // Default rollback - no updates performed
466 networkFqdn.value = (String) heatStack.getOutputs().get(NETWORK_FQDN);
468 Map <String, Object> outputs = heatStack.getOutputs ();
469 Map <String, String> sMap = new HashMap <> ();
470 if (outputs != null) {
471 for (String key : outputs.keySet ()) {
472 if (key != null && key.startsWith ("subnet")) {
473 if (aic3template) //one subnet_id output
475 Map <String, String> map = getSubnetUUId(key, outputs, subnets);
478 else //multiples subnet_%aaid% outputs
480 String subnetUUId = (String) outputs.get(key);
481 sMap.put (key.substring("subnet_id_".length()), subnetUUId);
486 subnetIdMap.value = sMap;
487 LOGGER.warn (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "", "", MsoLogger.ErrorCode.DataError, "Found Existing network stack, status=" + heatStack.getStatus ());
488 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Suc, "Found Existing network stack");
493 // Ready to deploy the new Network
494 // Build the common set of HEAT template parameters
495 Map <String, Object> stackParams = populateNetworkParams (neutronNetworkType,
504 // Validate (and update) the input parameters against the DB definition
505 // Shouldn't happen unless DB config is wrong, since all networks use same inputs
506 // and inputs were already validated.
508 stackParams = heat.validateStackParams (stackParams, heatTemplate);
509 } catch (IllegalArgumentException e) {
510 String error = "Create Network: Configuration Error: " + e.getMessage ();
511 LOGGER.error (MessageEnum.RA_CONFIG_EXC, e.getMessage(), "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception - Create Network, Configuration Error", e);
512 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error); // Alarm on this
516 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
517 // Input parameters were not valid
518 throw new NetworkException (error, MsoExceptionCategory.INTERNAL);
521 if (subnets != null) {
525 template = mergeSubnetsAIC3 (template, subnets, stackParams);
529 template = mergeSubnets (template, subnets);
531 } catch (MsoException me) {
532 me.addContext (CREATE_NETWORK_CONTEXT);
533 String error = "Create Network (heat): type " + neutronNetworkType
540 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception Create Network, merging subnets", me);
541 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
542 throw new NetworkException (me);
546 if (policyFqdns != null && !policyFqdns.isEmpty() && aic3template) {
548 mergePolicyRefs (policyFqdns, stackParams);
549 } catch (MsoException me) {
550 me.addContext (CREATE_NETWORK_CONTEXT);
551 String error = "Create Network (heat) mergePolicyRefs type " + neutronNetworkType
558 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception Create Network, merging policyRefs", me);
559 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
560 throw new NetworkException (me);
564 if (routeTableFqdns != null && !routeTableFqdns.isEmpty() && aic3template) {
566 mergeRouteTableRefs (routeTableFqdns, stackParams);
567 } catch (MsoException me) {
568 me.addContext (CREATE_NETWORK_CONTEXT);
569 String error = "Create Network (heat) mergeRouteTableRefs type " + neutronNetworkType
576 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception Create Network, merging routeTableRefs", me);
577 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
578 throw new NetworkException (me);
582 // Deploy the network stack
583 // Ignore MsoStackAlreadyExists exception because we already checked.
587 heatStack = heat.createStack (cloudSiteId,
593 heatTemplate.getTimeoutMinutes (),
597 backout.booleanValue());
598 } catch (MsoException me) {
599 me.addContext (CREATE_NETWORK_CONTEXT);
600 String error = "Create Network (heat): type " + neutronNetworkType
607 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, networkName, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception creating network", me);
608 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
609 throw new NetworkException (me);
612 // Reach this point if createStack is successful.
614 // For Heat-based orchestration, the MSO-tracked network ID is the heat stack,
615 // and the neutronNetworkId is the network UUID returned in stack outputs.
616 networkId.value = heatStack.getCanonicalName ();
617 neutronNetworkId.value = (String) heatStack.getOutputs ().get (NETWORK_ID);
620 networkFqdn.value = (String) heatStack.getOutputs().get(NETWORK_FQDN);
622 Map <String, Object> outputs = heatStack.getOutputs ();
623 Map <String, String> sMap = new HashMap <> ();
624 if (outputs != null) {
625 for (String key : outputs.keySet ()) {
626 if (key != null && key.startsWith ("subnet")) {
627 if (aic3template) //one subnet output expected
629 Map <String, String> map = getSubnetUUId(key, outputs, subnets);
632 else //multiples subnet_%aaid% outputs allowed
634 String subnetUUId = (String) outputs.get(key);
635 sMap.put (key.substring("subnet_id_".length()), subnetUUId);
640 subnetIdMap.value = sMap;
642 rollback.value = networkRollback;
643 // Populate remaining rollback info and response parameters.
644 networkRollback.setNetworkStackId (heatStack.getCanonicalName ());
645 networkRollback.setNeutronNetworkId ((String) heatStack.getOutputs ().get (NETWORK_ID));
646 networkRollback.setNetworkCreated (true);
647 networkRollback.setNetworkType (networkType);
649 LOGGER.debug ("Network " + networkName + " successfully created via HEAT");
654 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Suc, "Successfully created network");
659 public void updateNetwork (String cloudSiteId,
662 String modelCustomizationUuid,
665 String physicalNetworkName,
666 List <Integer> vlans,
667 List <Subnet> subnets,
668 MsoRequest msoRequest,
669 Holder <Map <String, String>> subnetIdMap,
670 Holder <NetworkRollback> rollback) throws NetworkException {
671 updateNetwork (cloudSiteId,
674 modelCustomizationUuid,
692 public void updateNetworkContrail (String cloudSiteId,
695 String modelCustomizationUuid,
698 List <String> routeTargets,
701 List <Subnet> subnets,
702 List <String> policyFqdns,
703 List<String> routeTableFqdns,
704 MsoRequest msoRequest,
705 Holder <Map <String, String>> subnetIdMap,
706 Holder <NetworkRollback> rollback) throws NetworkException {
707 updateNetwork (cloudSiteId,
710 modelCustomizationUuid,
727 * This is the "Update Network" web service implementation.
728 * It will update an existing Network of the requested type in the specified cloud
729 * and tenant. The typical use will be to replace the VLANs with the supplied
730 * list (to add or remove a VLAN), but other properties may be updated as well.
732 * There will be a pre-defined set of network types defined in the MSO Catalog.
733 * All such networks will have a similar configuration, based on the allowable
734 * Openstack networking definitions. This includes basic networks, provider
735 * networks (with a single VLAN), and multi-provider networks (one or more VLANs).
737 * Initially, all provider networks must currently be "vlan" type, and multi-provider
738 * networks must be multiple VLANs on the same physical network.
740 * This service supports two modes of Network update:
741 * - via Heat Templates
743 * The network orchestration mode for each network type is declared in its
744 * catalog definition. All Heat-based templates must support some subset of
745 * the same input parameters: network_name, physical_network, vlan, segments.
747 * The method returns a NetworkRollback object. This object can be passed
748 * as-is to the rollbackNetwork operation to undo everything that was updated.
749 * This is useful if a network is successfully updated but orchestration
750 * fails on a subsequent operation.
752 private void updateNetwork (String cloudSiteId,
755 String modelCustomizationUuid,
758 String physicalNetworkName,
759 List <Integer> vlans,
760 List <String> routeTargets,
763 List <Subnet> subnets,
764 List <String> policyFqdns,
765 List<String> routeTableFqdns,
766 MsoRequest msoRequest,
767 Holder <Map <String, String>> subnetIdMap,
768 Holder <NetworkRollback> rollback) throws NetworkException {
769 MsoLogger.setLogContext (msoRequest);
770 MsoLogger.setServiceName ("UpdateNetwork");
771 LOGGER.debug ("***UPDATE Network adapter with Network: " + networkName
780 // Will capture execution time for metrics
781 long startTime = System.currentTimeMillis ();
783 // Build a default rollback object (no actions performed)
784 NetworkRollback networkRollback = new NetworkRollback ();
785 networkRollback.setCloudId (cloudSiteId);
786 networkRollback.setTenantId (tenantId);
787 networkRollback.setMsoRequest (msoRequest);
789 cloudConfig = cloudConfigFactory.getCloudConfig ();
790 CloudSite cloudSite = cloudConfig.getCloudSite (cloudSiteId);
791 if (cloudSite == null) {
792 String error = "UpdateNetwork: Configuration Error. Stack " + networkName + " in "
797 + " CloudSite does not exist in MSO Configuration";
798 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "CloudSite does not exist in MSO Configuration");
799 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
800 // Set the detailed error as the Exception 'message'
801 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
804 // Get a handle to the Catalog Database
805 CatalogDatabase db = getCatalogDB ();
807 // Make sure DB connection is always closed
809 NetworkResource networkResource = networkCheck(db,
812 modelCustomizationUuid,
818 String mode = networkResource.getOrchestrationMode();
819 NetworkType neutronNetworkType = NetworkType.valueOf(networkResource.getNeutronNetworkType());
821 // Use an MsoNeutronUtils for all Neutron commands
822 MsoNeutronUtils neutron = new MsoNeutronUtils(MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
824 if (NEUTRON_MODE.equals(mode)) {
826 // Verify that the Network exists
827 // For Neutron-based orchestration, the networkId is the Neutron Network UUID.
828 NetworkInfo netInfo = null;
829 long queryNetworkStarttime = System.currentTimeMillis();
831 netInfo = neutron.queryNetwork(networkId, tenantId, cloudSiteId);
832 LOGGER.recordMetricEvent(queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryNetwork", null);
833 } catch (MsoException me) {
834 me.addContext(UPDATE_NETWORK_CONTEXT);
835 String error = "Update Network (neutron): query " + networkId
842 LOGGER.recordMetricEvent(queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryNetwork", null);
843 LOGGER.error(MessageEnum.RA_QUERY_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "QueryNetwork", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - queryNetwork", me);
844 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
845 throw new NetworkException(me);
848 if (netInfo == null) {
849 String error = "Update Nework: Network " + networkId
850 + " does not exist in "
854 LOGGER.error(MessageEnum.RA_NETWORK_NOT_FOUND, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Network not found");
855 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
856 // Does not exist. Throw an exception (can't update a non-existent network)
857 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
859 long updateNetworkStarttime = System.currentTimeMillis();
861 netInfo = neutron.updateNetwork(cloudSiteId,
867 LOGGER.recordMetricEvent(updateNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "UpdateNetwork", null);
868 } catch (MsoException me) {
869 me.addContext(UPDATE_NETWORK_CONTEXT);
870 String error = "Update Network (neutron): " + networkId
877 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, networkId, cloudSiteId, tenantId, "Openstack", "updateNetwork", MsoLogger.ErrorCode.DataError, "Exception - updateNetwork", me);
878 LOGGER.recordMetricEvent(updateNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "UpdateNetwork", null);
879 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
880 throw new NetworkException(me);
883 // Add the network ID and previously queried vlans to the rollback object
884 networkRollback.setNetworkId(netInfo.getId());
885 networkRollback.setNeutronNetworkId(netInfo.getId());
886 networkRollback.setNetworkType(networkType);
887 // Save previous parameters
888 networkRollback.setNetworkName(netInfo.getName());
889 networkRollback.setPhysicalNetwork(netInfo.getProvider());
890 networkRollback.setVlans(netInfo.getVlans());
892 LOGGER.debug("Network " + networkId + " updated, id = " + netInfo.getId());
893 } else if ("HEAT".equals(mode)) {
895 // Use an MsoHeatUtils for all Heat commands
896 MsoHeatUtilsWithUpdate heat = new MsoHeatUtilsWithUpdate(MSO_PROP_NETWORK_ADAPTER, msoPropertiesFactory, cloudConfigFactory);
898 // First, look up to see that the Network already exists.
899 // For Heat-based orchestration, the networkId is the network Stack ID.
900 StackInfo heatStack = null;
901 long queryStackStarttime = System.currentTimeMillis();
903 heatStack = heat.queryStack(cloudSiteId, tenantId, networkName);
904 LOGGER.recordMetricEvent(queryStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", null);
905 } catch (MsoException me) {
906 me.addContext(UPDATE_NETWORK_CONTEXT);
907 String error = "UpdateNetwork (heat): query " + networkName
914 LOGGER.recordMetricEvent(queryStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryStack", null);
915 LOGGER.error(MessageEnum.RA_QUERY_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Exception - QueryStack", me);
916 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
917 throw new NetworkException(me);
920 if (heatStack == null || (heatStack.getStatus() == HeatStatus.NOTFOUND)) {
921 String error = "UpdateNetwork: Stack " + networkName
922 + " does not exist in "
926 LOGGER.error(MessageEnum.RA_NETWORK_NOT_FOUND, networkId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Network not found");
927 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
928 // Network stack does not exist. Return an error
929 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
932 // Get the previous parameters for rollback
933 Map<String, Object> heatParams = heatStack.getParameters();
935 String previousNetworkName = (String) heatParams.get("network_name");
936 String previousPhysicalNetwork = (String) heatParams.get(PHYSICAL_NETWORK);
938 List<Integer> previousVlans = new ArrayList<>();
939 String vlansParam = (String) heatParams.get(VLANS);
940 if (vlansParam != null) {
941 for (String vlan : vlansParam.split(",")) {
943 previousVlans.add(Integer.parseInt(vlan));
944 } catch (NumberFormatException e) {
945 LOGGER.warn(MessageEnum.RA_VLAN_PARSE, networkId, vlansParam, "", "", MsoLogger.ErrorCode.DataError, "Exception - VLAN parse", e);
949 LOGGER.debug("Update Stack: Previous VLANS: " + previousVlans);
951 // Ready to deploy the updated Network via Heat
953 //HeatTemplate heatTemplate = db.getHeatTemplate (networkResource.getTemplateId ());
954 HeatTemplate heatTemplate = db.getHeatTemplateByArtifactUuidRegularQuery (networkResource.getHeatTemplateArtifactUUID());
955 if (heatTemplate == null) {
956 String error = "Network error - undefined Heat Template. Network Type=" + networkType;
957 LOGGER.error(MessageEnum.RA_PARAM_NOT_FOUND, "Heat Template", "Network Type", networkType, "OpenStack", "getHeatTemplate", MsoLogger.ErrorCode.DataError, "Network error - undefined Heat Template. Network Type=" + networkType);
958 alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
959 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
960 throw new NetworkException(error, MsoExceptionCategory.INTERNAL);
963 LOGGER.debug("Got HEAT Template from DB: " + heatTemplate.toString());
965 // "Fix" the template if it has CR/LF (getting this from Oracle)
966 String template = heatTemplate.getHeatTemplate();
967 template = template.replaceAll("\r\n", "\n");
969 boolean aic3template = false;
970 String aic3nw = AIC3_NW;
972 aic3nw = msoPropertiesFactory.getMsoJavaProperties(MSO_PROP_NETWORK_ADAPTER).getProperty(AIC3_NW_PROPERTY, AIC3_NW);
973 } catch (MsoPropertiesException e) {
974 String error = "Unable to get properties:" + MSO_PROP_NETWORK_ADAPTER;
975 LOGGER.error(MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - Unable to get properties", e);
977 if (template.contains(aic3nw))
980 // Build the common set of HEAT template parameters
981 Map<String, Object> stackParams = populateNetworkParams(neutronNetworkType,
990 // Validate (and update) the input parameters against the DB definition
991 // Shouldn't happen unless DB config is wrong, since all networks use same inputs
993 stackParams = heat.validateStackParams(stackParams, heatTemplate);
994 } catch (IllegalArgumentException e) {
995 String error = "UpdateNetwork: Configuration Error: Network Type=" + networkType;
996 LOGGER.error(MessageEnum.RA_CONFIG_EXC, "Network Type=" + networkType, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork: Configuration Error");
997 alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
998 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.SchemaError, error);
999 throw new NetworkException(error, MsoExceptionCategory.INTERNAL, e);
1002 if (subnets != null) {
1005 template = mergeSubnetsAIC3(template, subnets, stackParams);
1007 template = mergeSubnets(template, subnets);
1009 } catch (MsoException me) {
1010 me.addContext(UPDATE_NETWORK_CONTEXT);
1011 String error = "Update Network (heat): type " + neutronNetworkType
1018 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergeSubnets ", me);
1019 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
1020 throw new NetworkException(me);
1024 if (policyFqdns != null && aic3template) {
1026 mergePolicyRefs(policyFqdns, stackParams);
1027 } catch (MsoException me) {
1028 me.addContext(UPDATE_NETWORK_CONTEXT);
1029 String error = "UpdateNetwork (heat) mergePolicyRefs type " + neutronNetworkType
1036 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergePolicyRefs", me);
1037 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
1038 throw new NetworkException(me);
1042 if (routeTableFqdns != null && !routeTableFqdns.isEmpty() && aic3template) {
1044 mergeRouteTableRefs(routeTableFqdns, stackParams);
1045 } catch (MsoException me) {
1046 me.addContext(UPDATE_NETWORK_CONTEXT);
1047 String error = "UpdateNetwork (heat) mergeRouteTableRefs type " + neutronNetworkType
1054 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergeRouteTableRefs", me);
1055 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
1056 throw new NetworkException(me);
1060 // Update the network stack
1061 // Ignore MsoStackNotFound exception because we already checked.
1062 long updateStackStarttime = System.currentTimeMillis();
1064 heatStack = heat.updateStack(cloudSiteId,
1070 heatTemplate.getTimeoutMinutes());
1071 LOGGER.recordMetricEvent(updateStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "UpdateStack", null);
1072 } catch (MsoException me) {
1073 me.addContext(UPDATE_NETWORK_CONTEXT);
1074 String error = "Update Network: " + networkId + " in " + cloudSiteId + "/" + tenantId + ": " + me;
1075 LOGGER.recordMetricEvent(updateStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "UpdateStack", null);
1076 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - update network", me);
1077 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1078 throw new NetworkException(me);
1081 Map<String, Object> outputs = heatStack.getOutputs();
1082 Map<String, String> sMap = new HashMap<>();
1083 if (outputs != null) {
1084 for (String key : outputs.keySet()) {
1085 if (key != null && key.startsWith("subnet")) {
1086 if (aic3template) //one subnet output expected
1088 Map<String, String> map = getSubnetUUId(key, outputs, subnets);
1090 } else //multiples subnet_%aaid% outputs allowed
1092 String subnetUUId = (String) outputs.get(key);
1093 sMap.put(key.substring("subnet_id_".length()), subnetUUId);
1098 subnetIdMap.value = sMap;
1100 // Reach this point if createStack is successful.
1101 // Populate remaining rollback info and response parameters.
1102 networkRollback.setNetworkStackId(heatStack.getCanonicalName());
1103 if(null != outputs) {
1104 networkRollback.setNeutronNetworkId((String) outputs.get(NETWORK_ID));
1107 LOGGER.debug("outputs is NULL");
1109 networkRollback.setNetworkType(networkType);
1110 // Save previous parameters
1111 networkRollback.setNetworkName(previousNetworkName);
1112 networkRollback.setPhysicalNetwork(previousPhysicalNetwork);
1113 networkRollback.setVlans(previousVlans);
1115 rollback.value = networkRollback;
1117 LOGGER.debug("Network " + networkId + " successfully updated via HEAT");
1122 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully updated network");
1126 private NetworkResource networkCheck (CatalogDatabase db,
1129 String modelCustomizationUuid,
1131 String physicalNetworkName,
1132 List <Integer> vlans,
1133 List <String> routeTargets,
1134 CloudSite cloudSite) throws NetworkException {
1135 // Retrieve the Network Resource definition
1136 NetworkResource networkResource = null;
1138 if (isNullOrEmpty(modelCustomizationUuid)) {
1139 networkResource = db.getNetworkResource(networkType);
1141 networkResource = db
1142 .getNetworkResourceByModelCustUuid(modelCustomizationUuid);
1144 if (networkResource == null) {
1145 String error = "Create/UpdateNetwork: Unable to get network resource with NetworkType:"
1147 + " or ModelCustomizationUUID:"
1148 + modelCustomizationUuid;
1149 LOGGER.error(MessageEnum.RA_UNKOWN_PARAM,
1150 "NetworkType/ModelCustomizationUUID", networkType + "/"
1151 + modelCustomizationUuid, "OpenStack", "",
1152 MsoLogger.ErrorCode.DataError,
1153 "Create/UpdateNetwork: Unknown NetworkType/ModelCustomizationUUID");
1155 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
1157 LOGGER.debug("Got Network definition from Catalog: "
1158 + networkResource.toString());
1160 String mode = networkResource.getOrchestrationMode();
1161 NetworkType neutronNetworkType = NetworkType
1162 .valueOf(networkResource.getNeutronNetworkType());
1164 // All Networks are orchestrated via HEAT or Neutron
1165 if (!("HEAT".equals(mode) || NEUTRON_MODE.equals(mode))) {
1166 String error = "CreateNetwork: Configuration Error: Network Type = "
1168 LOGGER.error(MessageEnum.RA_NETWORK_ORCHE_MODE_NOT_SUPPORT,
1169 mode, "OpenStack", "", MsoLogger.ErrorCode.DataError,
1170 "CreateNetwork: Configuration Error");
1171 // Alarm on this error, configuration must be fixed
1172 alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR,
1173 MsoAlarmLogger.CRITICAL, error);
1175 throw new NetworkException(error, MsoExceptionCategory.INTERNAL);
1178 MavenLikeVersioning aicV = new MavenLikeVersioning();
1179 aicV.setVersion(cloudSite.getAic_version());
1180 if ((aicV.isMoreRecentThan(networkResource.getAicVersionMin()) || aicV
1181 .isTheSameVersion(networkResource.getAicVersionMin())) // aic
1184 && (aicV.isTheSameVersion(networkResource
1185 .getAicVersionMax()) || !(aicV
1186 .isMoreRecentThan(networkResource
1187 .getAicVersionMax())))) // aic <= max
1189 LOGGER.debug("Network Type:" + networkType + " VersionMin:"
1190 + networkResource.getAicVersionMin() + " VersionMax:"
1191 + networkResource.getAicVersionMax()
1192 + " supported on Cloud:" + cloudSite.getId()
1193 + " with AIC_Version:" + cloudSite.getAic_version());
1195 String error = "Network Type:" + networkType + " Version_Min:"
1196 + networkResource.getAicVersionMin() + " Version_Max:"
1197 + networkResource.getAicVersionMax()
1198 + " not supported on Cloud:" + cloudSite.getId()
1199 + " with AIC_Version:" + cloudSite.getAic_version();
1200 LOGGER.error(MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "",
1201 MsoLogger.ErrorCode.DataError,
1202 "Network Type not supported on Cloud");
1203 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR,
1204 MsoLogger.ResponseCode.DataError, error);
1205 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
1208 // Validate the Network parameters.
1209 String missing = validateNetworkParams(neutronNetworkType,
1210 networkName, physicalNetworkName, vlans, routeTargets);
1211 if (!missing.isEmpty()) {
1212 String error = "Create Network: Missing parameters: " + missing;
1213 LOGGER.error(MessageEnum.RA_MISSING_PARAM, missing,
1214 "OpenStack", "", MsoLogger.ErrorCode.DataError,
1215 "Create Network: Missing parameters");
1217 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
1222 return networkResource;
1226 public void queryNetwork (String cloudSiteId,
1228 String networkNameOrId,
1229 MsoRequest msoRequest,
1230 Holder <Boolean> networkExists,
1231 Holder <String> networkId,
1232 Holder <String> neutronNetworkId,
1233 Holder <NetworkStatus> status,
1234 Holder <List <Integer>> vlans,
1235 Holder <Map <String, String>> subnetIdMap) throws NetworkException {
1236 queryNetwork (cloudSiteId,
1250 public void queryNetworkContrail (String cloudSiteId,
1252 String networkNameOrId,
1253 MsoRequest msoRequest,
1254 Holder <Boolean> networkExists,
1255 Holder <String> networkId,
1256 Holder <String> neutronNetworkId,
1257 Holder <NetworkStatus> status,
1258 Holder <List <String>> routeTargets,
1259 Holder <Map <String, String>> subnetIdMap) throws NetworkException {
1260 queryNetwork (cloudSiteId,
1274 * This is the queryNetwork method. It returns the existence and status of
1275 * the specified network, along with its Neutron UUID and list of VLANs.
1276 * This method attempts to find the network using both Heat and Neutron.
1277 * Heat stacks are first searched based on the provided network name/id.
1278 * If none is found, the Neutron is directly queried.
1280 private void queryNetwork (String cloudSiteId,
1282 String networkNameOrId,
1283 MsoRequest msoRequest,
1284 Holder <Boolean> networkExists,
1285 Holder <String> networkId,
1286 Holder <String> neutronNetworkId,
1287 Holder <NetworkStatus> status,
1288 Holder <List <Integer>> vlans,
1289 Holder <List <String>> routeTargets,
1290 Holder <Map <String, String>> subnetIdMap) throws NetworkException {
1291 MsoLogger.setLogContext (msoRequest);
1292 MsoLogger.setServiceName ("QueryNetwork");
1293 LOGGER.debug ("*** QUERY Network with Network: " + networkNameOrId
1299 // Will capture execution time for metrics
1300 long startTime = System.currentTimeMillis ();
1302 if (isNullOrEmpty (cloudSiteId)
1303 || isNullOrEmpty(tenantId)
1304 || isNullOrEmpty(networkNameOrId)) {
1306 String error = "Missing mandatory parameter cloudSiteId, tenantId or networkId";
1307 LOGGER.error (MessageEnum.RA_MISSING_PARAM, "cloudSiteId or tenantId or networkNameOrId", "OpenStack", "", MsoLogger.ErrorCode.DataError, "Missing mandatory parameter cloudSiteId, tenantId or networkId");
1308 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
1309 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1312 cloudConfig = cloudConfigFactory.getCloudConfig ();
1313 CloudSite cloudSite = cloudConfig.getCloudSite (cloudSiteId);
1314 if (cloudSite == null)
1316 String error = "Configuration Error. Stack " + networkNameOrId + " in "
1321 + " CloudSite does not exist in MSO Configuration";
1322 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Configuration Error");
1323 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
1324 // Set the detailed error as the Exception 'message'
1325 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1328 // Use MsoNeutronUtils for all NEUTRON commands
1329 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_NETWORK_ADAPTER,msoPropertiesFactory,cloudConfigFactory);
1330 MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
1334 // Try Heat first, since networks may be named the same as the Heat stack
1335 StackInfo heatStack = null;
1336 long queryStackStarttime = System.currentTimeMillis ();
1338 heatStack = heat.queryStack (cloudSiteId, tenantId, networkNameOrId);
1339 LOGGER.recordMetricEvent (queryStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", null);
1340 } catch (MsoException me) {
1341 me.addContext ("QueryNetwork");
1342 String error = "Query Network (heat): " + networkNameOrId
1349 LOGGER.recordMetricEvent (queryStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "BPMN", "QueryStack", null);
1350 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkNameOrId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Exception - Query Network (heat)", me);
1351 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1352 throw new NetworkException (me);
1355 // Populate the outputs based on the returned Stack information
1356 if (heatStack != null && heatStack.getStatus () != HeatStatus.NOTFOUND) {
1357 // Found it. Get the neutronNetworkId for further query
1358 Map <String, Object> outputs = heatStack.getOutputs ();
1359 neutronId = (String) outputs.get (NETWORK_ID);
1362 Map <String, String> sMap = new HashMap <> ();
1363 if (outputs != null) {
1364 for (String key : outputs.keySet ()) {
1365 if (key != null && key.startsWith ("subnet_id_")) //multiples subnet_%aaid% outputs
1367 String subnetUUId = (String) outputs.get(key);
1368 sMap.put (key.substring("subnet_id_".length()), subnetUUId);
1370 else if (key != null && key.startsWith ("subnet")) //one subnet output expected
1372 Map <String, String> map = getSubnetUUId(key, outputs, null);
1378 subnetIdMap.value = sMap;
1380 // Input ID was not a Heat stack ID. Try it directly in Neutron
1381 neutronId = networkNameOrId;
1382 mode = NEUTRON_MODE;
1385 // Query directly against the Neutron Network for the details
1386 // no RouteTargets available for ContrailV2 in neutron net-show
1387 // networkId is heatStackId
1388 long queryNetworkStarttime = System.currentTimeMillis ();
1390 NetworkInfo netInfo = neutron.queryNetwork (neutronId, tenantId, cloudSiteId);
1391 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryNetwork", null);
1392 if (netInfo != null) {
1393 // Found. Populate the output elements
1394 networkExists.value = Boolean.TRUE;
1395 if ("HEAT".equals (mode)) {
1396 networkId.value = heatStack.getCanonicalName ();
1398 networkId.value = netInfo.getId ();
1400 neutronNetworkId.value = netInfo.getId ();
1401 status.value = netInfo.getStatus ();
1403 vlans.value = netInfo.getVlans ();
1405 LOGGER.debug ("Network " + networkNameOrId
1410 + ("HEAT".equals (mode) ? ",NeutronId = " + neutronNetworkId.value : ""));
1412 // Not found. Populate the status fields, leave the rest null
1413 networkExists.value = Boolean.FALSE;
1414 status.value = NetworkStatus.NOTFOUND;
1415 neutronNetworkId.value = null;
1417 vlans.value = new ArrayList <Integer> ();
1419 LOGGER.debug ("Network " + networkNameOrId + " not found");
1421 } catch (MsoException me) {
1422 me.addContext ("QueryNetwork");
1423 String error = "Query Network (neutron): " + networkNameOrId
1430 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryNetwork", null);
1431 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkNameOrId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - Query Network (neutron)", me);
1432 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1433 throw new NetworkException (me);
1435 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully queried network");
1440 * This is the "Delete Network" web service implementation.
1441 * It will delete a Network in the specified cloud and tenant.
1443 * If the network is not found, it is treated as a success.
1445 * This service supports two modes of Network creation/update/delete:
1446 * - via Heat Templates
1448 * The network orchestration mode for each network type is declared in its
1449 * catalog definition.
1451 * For Heat-based orchestration, the networkId should be the stack ID.
1452 * For Neutron-based orchestration, the networkId should be the Neutron network UUID.
1454 * The method returns nothing on success. Rollback is not possible for delete
1455 * commands, so any failure on delete will require manual fallout in the client.
1458 public void deleteNetwork (String cloudSiteId,
1461 String modelCustomizationUuid,
1463 MsoRequest msoRequest,
1464 Holder <Boolean> networkDeleted) throws NetworkException {
1465 MsoLogger.setLogContext (msoRequest);
1466 MsoLogger.setServiceName ("DeleteNetwork");
1467 LOGGER.debug ("*** DELETE Network adapter with Network: " + networkId
1473 // Will capture execution time for metrics
1474 long startTime = System.currentTimeMillis ();
1476 // Get a handle to the Catalog Database
1477 CatalogDatabase db = getCatalogDB ();
1479 // Make sure DB connection is always closed
1481 if (isNullOrEmpty (cloudSiteId)
1482 || isNullOrEmpty(tenantId)
1483 || isNullOrEmpty(networkId)) {
1484 String error = "Missing mandatory parameter cloudSiteId, tenantId or networkId";
1485 LOGGER.error (MessageEnum.RA_MISSING_PARAM, "cloudSiteId or tenantId or networkId", "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing mandatory parameter cloudSiteId, tenantId or networkId");
1486 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
1487 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1490 // Retrieve the Network Resource definition
1491 NetworkResource networkResource = null;
1492 if (isNullOrEmpty(modelCustomizationUuid)) {
1493 networkResource = db.getNetworkResource (networkType);
1495 else if (!isNullOrEmpty(networkType))
1497 networkResource = db.getNetworkResourceByModelCustUuid(modelCustomizationUuid);
1500 if (networkResource != null) {
1501 LOGGER.debug ("Got Network definition from Catalog: " + networkResource.toString ());
1503 mode = networkResource.getOrchestrationMode ();
1506 if (NEUTRON_MODE.equals (mode)) {
1508 // Use MsoNeutronUtils for all NEUTRON commands
1509 MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
1510 long deleteNetworkStarttime = System.currentTimeMillis ();
1512 // The deleteNetwork function in MsoNeutronUtils returns success if the network
1513 // was not found. So don't bother to query first.
1514 boolean deleted = neutron.deleteNetwork (networkId, tenantId, cloudSiteId);
1515 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteNetwork", null);
1516 networkDeleted.value = deleted;
1517 } catch (MsoException me) {
1518 me.addContext ("DeleteNetwork");
1519 String error = "Delete Network (neutron): " + networkId
1526 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteNetwork", null);
1527 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Delete Network (neutron)", me);
1528 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1529 throw new NetworkException (me);
1531 } else { // DEFAULT to ("HEAT".equals (mode))
1532 long deleteStackStarttime = System.currentTimeMillis ();
1533 // Use MsoHeatUtils for all HEAT commands
1534 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_NETWORK_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
1537 // The deleteStack function in MsoHeatUtils returns NOTFOUND if the stack was not found or if the stack was deleted.
1538 // So query first to report back if stack WAS deleted or just NOTOFUND
1539 StackInfo heatStack = null;
1540 heatStack = heat.queryStack(cloudSiteId, tenantId, networkId);
1541 if (heatStack != null && heatStack.getStatus() != HeatStatus.NOTFOUND)
1543 heat.deleteStack (tenantId, cloudSiteId, networkId, true);
1544 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteStack", null);
1545 networkDeleted.value = true;
1549 networkDeleted.value = false;
1551 } catch (MsoException me) {
1552 me.addContext ("DeleteNetwork");
1553 String error = "Delete Network (heat): " + networkId
1560 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteStack", null);
1561 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Delete Network (heat)", me);
1562 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1563 throw new NetworkException (me);
1570 // On success, nothing is returned.
1571 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully deleted network");
1575 public CatalogDatabase getCatalogDB() {
1576 return CatalogDatabase.getInstance();
1580 * This web service endpoint will rollback a previous Create VNF operation.
1581 * A rollback object is returned to the client in a successful creation
1582 * response. The client can pass that object as-is back to the rollbackVnf
1583 * operation to undo the creation.
1585 * The rollback includes removing the VNF and deleting the tenant if the
1586 * tenant did not exist prior to the VNF creation.
1589 public void rollbackNetwork (NetworkRollback rollback) throws NetworkException {
1590 MsoLogger.setServiceName ("RollbackNetwork");
1591 // Will capture execution time for metrics
1592 long startTime = System.currentTimeMillis ();
1594 if (rollback == null) {
1595 LOGGER.error (MessageEnum.RA_ROLLBACK_NULL, "Openstack", "", MsoLogger.ErrorCode.DataError, "rollback is null");
1596 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, "No action to perform");
1600 MsoLogger.setLogContext (rollback.getMsoRequest());
1602 // Get the elements of the VnfRollback object for easier access
1603 String cloudSiteId = rollback.getCloudId ();
1604 String tenantId = rollback.getTenantId ();
1605 String networkId = rollback.getNetworkStackId ();
1606 String networkType = rollback.getNetworkType ();
1607 String modelCustomizationUuid = rollback.getModelCustomizationUuid();
1609 LOGGER.debug ("*** ROLLBACK Network " + networkId + " in " + cloudSiteId + "/" + tenantId);
1611 // rollback may be null (e.g. if network already existed when Create was called)
1612 // Get a handle to the Catalog Database
1613 CatalogDatabase db = getCatalogDB ();
1615 // Make sure DB connection is always closed
1618 // Retrieve the Network Resource definition
1619 NetworkResource networkResource = null;
1620 if (isNullOrEmpty(modelCustomizationUuid)) {
1621 networkResource = db.getNetworkResource (networkType);
1625 networkResource = db.getNetworkResourceByModelCustUuid(modelCustomizationUuid);
1628 if (networkResource != null) {
1630 LOGGER.debug ("Got Network definition from Catalog: " + networkResource.toString ());
1632 mode = networkResource.getOrchestrationMode ();
1635 if (rollback.getNetworkCreated ()) {
1636 // Rolling back a newly created network, so delete it.
1637 if (NEUTRON_MODE.equals (mode)) {
1638 // Use MsoNeutronUtils for all NEUTRON commands
1639 MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
1640 long deleteNetworkStarttime = System.currentTimeMillis ();
1642 // The deleteNetwork function in MsoNeutronUtils returns success if the network
1643 // was not found. So don't bother to query first.
1644 neutron.deleteNetwork (networkId, tenantId, cloudSiteId);
1645 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteNetwork", null);
1646 } catch (MsoException me) {
1647 me.addContext ("RollbackNetwork");
1648 String error = "Rollback Network (neutron): " + networkId
1655 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteNetwork", null);
1656 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - Rollback Network (neutron)", me);
1657 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1658 throw new NetworkException (me);
1660 } else { // DEFAULT to if ("HEAT".equals (mode))
1661 // Use MsoHeatUtils for all HEAT commands
1662 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_NETWORK_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
1663 long deleteStackStarttime = System.currentTimeMillis ();
1665 // The deleteStack function in MsoHeatUtils returns success if the stack
1666 // was not found. So don't bother to query first.
1667 heat.deleteStack (tenantId, cloudSiteId, networkId, true);
1668 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteStack", null);
1669 } catch (MsoException me) {
1670 me.addContext ("RollbackNetwork");
1671 String error = "Rollback Network (heat): " + networkId
1678 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteStack", null);
1679 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - Rollback Network (heat)", me);
1680 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1681 throw new NetworkException (me);
1688 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully rolled back network");
1692 private String validateNetworkParams (NetworkType neutronNetworkType,
1694 String physicalNetwork,
1695 List <Integer> vlans,
1696 List <String> routeTargets) {
1698 StringBuilder missing = new StringBuilder ();
1699 if (isNullOrEmpty(networkName)) {
1700 missing.append ("networkName");
1704 if (neutronNetworkType == NetworkType.PROVIDER || neutronNetworkType == NetworkType.MULTI_PROVIDER) {
1705 if (isNullOrEmpty(physicalNetwork)) {
1706 missing.append (sep).append ("physicalNetworkName");
1709 if (vlans == null || vlans.isEmpty ()) {
1710 missing.append (sep).append (VLANS);
1714 return missing.toString ();
1717 private Map <String, Object> populateNetworkParams (NetworkType neutronNetworkType,
1719 String physicalNetwork,
1720 List <Integer> vlans,
1721 List <String> routeTargets,
1724 boolean aic3template) {
1725 // Build the common set of HEAT template parameters
1726 Map <String, Object> stackParams = new HashMap <> ();
1727 stackParams.put ("network_name", networkName);
1729 if (neutronNetworkType == NetworkType.PROVIDER) {
1730 // For Provider type
1731 stackParams.put (PHYSICAL_NETWORK, physicalNetwork);
1732 stackParams.put ("vlan", vlans.get (0).toString ());
1733 } else if (neutronNetworkType == NetworkType.MULTI_PROVIDER) {
1734 // For Multi-provider, PO supports a custom resource extension of ProviderNet.
1735 // It supports all ProviderNet properties except segmentation_id, and adds a
1736 // comma-separated-list of VLANs as a "segments" property.
1737 // Note that this does not match the Neutron definition of Multi-Provider network,
1738 // which contains a list of 'segments', each having physical_network, network_type,
1739 // and segmentation_id.
1740 StringBuilder buf = new StringBuilder ();
1742 for (Integer vlan : vlans) {
1743 buf.append (sep).append (vlan.toString ());
1746 String csl = buf.toString ();
1748 stackParams.put (PHYSICAL_NETWORK, physicalNetwork);
1749 stackParams.put (VLANS, csl);
1751 if (routeTargets != null && !routeTargets.isEmpty()) {
1752 StringBuilder buf = new StringBuilder ();
1754 for (String rt : routeTargets) {
1755 if (!isNullOrEmpty(rt))
1758 buf.append (sep).append ("target:" + rt);
1760 buf.append (sep).append (rt);
1765 String csl = buf.toString ();
1767 stackParams.put ("route_targets", csl);
1769 if (isNullOrEmpty(shared)) {
1770 stackParams.put ("shared", "False");
1772 stackParams.put ("shared", shared);
1774 if (isNullOrEmpty(external)) {
1775 stackParams.put ("external", "False");
1777 stackParams.put ("external", external);
1784 /** policyRef_list structure in stackParams
1787 "network_policy_refs_data_sequence": {
1788 "network_policy_refs_data_sequence_major": "1",
1789 "network_policy_refs_data_sequence_minor": "0"
1793 "network_policy_refs_data_sequence": {
1794 "network_policy_refs_data_sequence_major": "2",
1795 "network_policy_refs_data_sequence_minor": "0"
1800 private void mergePolicyRefs(List <String> pFqdns, Map <String, Object> stackParams) throws MsoException {
1802 List<ContrailPolicyRef> prlist = new ArrayList <> ();
1804 for (String pf : pFqdns) {
1805 if (!isNullOrEmpty(pf))
1807 ContrailPolicyRef pr = new ContrailPolicyRef();
1808 pr.populate(String.valueOf(index), "0");
1810 LOGGER.debug("Contrail PolicyRefs Data:" + pr.toString());
1815 JsonNode node = null;
1818 ObjectMapper mapper = new ObjectMapper();
1819 node = mapper.convertValue(prlist, JsonNode.class);
1820 String jsonString = mapper.writeValueAsString(prlist);
1821 LOGGER.debug("Json PolicyRefs Data:" + jsonString);
1825 String error = "Error creating JsonNode for policyRefs Data";
1826 LOGGER.error (MessageEnum.RA_MARSHING_ERROR, error, "Openstack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception creating JsonNode for policyRefs Data", e);
1827 throw new MsoAdapterException (error);
1830 if (pFqdns != null && node != null)
1832 StringBuilder buf = new StringBuilder ();
1834 for (String pf : pFqdns) {
1835 if (!isNullOrEmpty(pf))
1837 buf.append (sep).append (pf);
1841 String csl = buf.toString ();
1842 stackParams.put ("policy_refs", csl);
1843 stackParams.put ("policy_refsdata", node);
1846 LOGGER.debug ("StackParams updated with policy refs");
1850 private void mergeRouteTableRefs(List <String> rtFqdns, Map <String, Object> stackParams) throws MsoException {
1853 if (rtFqdns != null)
1855 StringBuilder buf = new StringBuilder ();
1857 for (String rtf : rtFqdns) {
1858 if (!isNullOrEmpty(rtf))
1860 buf.append (sep).append (rtf);
1864 String csl = buf.toString ();
1865 stackParams.put ("route_table_refs", csl);
1868 LOGGER.debug ("StackParams updated with route_table refs");
1873 /*** Subnet Output structure from Juniper
1878 "ip_prefix": "10.100.1.0",
1881 "addr_from_start": null,
1882 "enable_dhcp": false,
1883 "default_gateway": "10.100.1.1",
1884 "dns_nameservers": [],
1885 "dhcp_option_list": null,
1886 "subnet_uuid": "10391fbf-6b9c-4160-825d-2d018b7649cf",
1887 "allocation_pools": [
1889 "start": "10.100.1.3",
1893 "start": "10.100.1.6",
1897 "host_routes": null,
1898 "dns_server_address": "10.100.1.13",
1899 "subnet_name": "subnet_MsoNW1_692c9032-e1a2-4d64-828c-7b9a4fcc05b0"
1903 "ip_prefix": "10.100.2.16",
1906 "addr_from_start": null,
1907 "enable_dhcp": true,
1908 "default_gateway": "10.100.2.17",
1909 "dns_nameservers": [],
1910 "dhcp_option_list": null,
1911 "subnet_uuid": "c7aac5ea-66fe-443a-85f9-9c38a608c0f6",
1912 "allocation_pools": [
1914 "start": "10.100.2.18",
1915 "end": "10.100.2.20"
1918 "host_routes": null,
1919 "dns_server_address": "10.100.2.29",
1920 "subnet_name": "subnet_MsoNW1_692c9032-e1a2-4d64-828c-7b9a4fcc05b1"
1926 private String mergeSubnetsAIC3 (String heatTemplate, List <Subnet> subnets, Map <String, Object> stackParams) throws MsoException {
1929 List<ContrailSubnet> cslist = new ArrayList <> ();
1930 for (Subnet subnet : subnets) {
1931 ContrailSubnet cs = new ContrailSubnet();
1932 LOGGER.debug("Input Subnet:" + subnet.toString());
1933 cs.populateWith(subnet);
1934 LOGGER.debug("Contrail Subnet:" + cs.toString());
1938 JsonNode node = null;
1941 ObjectMapper mapper = new ObjectMapper();
1942 node = mapper.convertValue(cslist, JsonNode.class);
1943 String jsonString = mapper.writeValueAsString(cslist);
1944 LOGGER.debug("Json Subnet List:" + jsonString);
1948 String error = "Error creating JsonNode from input subnets";
1949 LOGGER.error (MessageEnum.RA_MARSHING_ERROR, error, "", "", MsoLogger.ErrorCode.DataError, "Exception creating JsonNode from input subnets", e);
1950 throw new MsoAdapterException (error);
1955 stackParams.put ("subnet_list", node);
1957 //Outputs - All subnets are in one ipam_subnets structure
1958 String outputTempl = " subnet:\n" + " description: Openstack subnet identifier\n"
1959 + " value: { get_attr: [network, network_ipam_refs, 0, attr]}\n";
1961 // append outputs in heatTemplate
1962 int outputsIdx = heatTemplate.indexOf ("outputs:");
1963 heatTemplate = insertStr (heatTemplate, outputTempl, outputsIdx + 8);
1964 LOGGER.debug ("Template updated with all AIC3.0 subnets:" + heatTemplate);
1965 return heatTemplate;
1969 private String mergeSubnets (String heatTemplate, List <Subnet> subnets) throws MsoException {
1971 String resourceTempl = " subnet_%subnetId%:\n" + " type: OS::Neutron::Subnet\n"
1974 + " network_id: { get_resource: network }\n"
1975 + " cidr: %cidr%\n";
1977 /* make these optional
1978 + " ip_version: %ipversion%\n"
1979 + " enable_dhcp: %enabledhcp%\n"
1980 + " gateway_ip: %gatewayip%\n"
1981 + " allocation_pools:\n"
1982 + " - start: %poolstart%\n"
1983 + " end: %poolend%\n";
1987 String outputTempl = " subnet_id_%subnetId%:\n" + " description: Openstack subnet identifier\n"
1988 + " value: {get_resource: subnet_%subnetId%}\n";
1992 StringBuilder resourcesBuf = new StringBuilder ();
1993 StringBuilder outputsBuf = new StringBuilder ();
1994 for (Subnet subnet : subnets) {
1996 // build template for each subnet
1997 curR = resourceTempl;
1998 if (subnet.getSubnetId () != null) {
1999 curR = curR.replace ("%subnetId%", subnet.getSubnetId ());
2001 String error = "Missing Required AAI SubnetId for subnet in HEAT Template";
2002 LOGGER.error (MessageEnum.RA_MISSING_PARAM, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing Required AAI ID for subnet in HEAT Template");
2003 throw new MsoAdapterException (error);
2006 if (subnet.getSubnetName () != null) {
2007 curR = curR.replace ("%name%", subnet.getSubnetName ());
2009 curR = curR.replace ("%name%", subnet.getSubnetId ());
2012 if (subnet.getCidr () != null) {
2013 curR = curR.replace ("%cidr%", subnet.getCidr ());
2015 String error = "Missing Required cidr for subnet in HEAT Template";
2016 LOGGER.error (MessageEnum.RA_MISSING_PARAM, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing Required cidr for subnet in HEAT Template");
2017 throw new MsoAdapterException (error);
2020 if (subnet.getIpVersion () != null) {
2021 curR = curR + " ip_version: " + subnet.getIpVersion () + "\n";
2023 if (subnet.getEnableDHCP () != null) {
2024 curR = curR + " enable_dhcp: " + Boolean.toString (subnet.getEnableDHCP ()) + "\n";
2026 if (subnet.getGatewayIp () != null && !subnet.getGatewayIp ().isEmpty() ) {
2027 curR = curR + " gateway_ip: " + subnet.getGatewayIp () + "\n";
2030 if (subnet.getAllocationPools() != null) {
2031 curR = curR + " allocation_pools:\n";
2032 for (Pool pool : subnet.getAllocationPools())
2034 if (!isNullOrEmpty(pool.getStart()) && !isNullOrEmpty(pool.getEnd()))
2036 curR = curR + " - start: " + pool.getStart () + "\n";
2037 curR = curR + " end: " + pool.getEnd () + "\n";
2042 resourcesBuf.append (curR);
2045 curO = curO.replace ("%subnetId%", subnet.getSubnetId ());
2047 outputsBuf.append (curO);
2050 // append resources and outputs in heatTemplate
2051 LOGGER.debug ("Tempate initial:" + heatTemplate);
2052 int outputsIdx = heatTemplate.indexOf ("outputs:");
2053 heatTemplate = insertStr (heatTemplate, outputsBuf.toString (), outputsIdx + 8);
2054 int resourcesIdx = heatTemplate.indexOf ("resources:");
2055 heatTemplate = insertStr (heatTemplate, resourcesBuf.toString (), resourcesIdx + 10);
2057 LOGGER.debug ("Template updated with all subnets:" + heatTemplate);
2058 return heatTemplate;
2061 private Map <String, String> getSubnetUUId(String key, Map <String, Object> outputs, List <Subnet> subnets) {
2063 Map <String, String> sMap = new HashMap <> ();
2066 Object obj = outputs.get(key);
2067 ObjectMapper mapper = new ObjectMapper();
2068 String jStr = mapper.writeValueAsString(obj);
2069 LOGGER.debug ("Subnet_Ipam Output JSON String:" + obj.getClass() + " " + jStr);
2071 JsonNode rootNode = mapper.readTree(jStr);
2072 for (JsonNode sNode : rootNode.path("ipam_subnets"))
2074 LOGGER.debug("Output Subnet Node" + sNode.toString());
2075 String name = sNode.path("subnet_name").getTextValue();
2076 String uuid = sNode.path("subnet_uuid").getTextValue();
2077 String aaiId = name; // default
2078 // try to find aaiId for name in input subnetList
2079 if (subnets != null)
2081 for (Subnet subnet : subnets)
2083 if ( subnet != null && !isNullOrEmpty(subnet.getSubnetName()))
2085 if (subnet.getSubnetName().equals(name))
2087 aaiId = subnet.getSubnetId();
2093 sMap.put(aaiId, uuid); //bpmn needs aaid to uuid map
2098 LOGGER.error (MessageEnum.RA_MARSHING_ERROR, "error getting subnet-uuids", "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception getting subnet-uuids", e);
2101 LOGGER.debug ("Return sMap" + sMap.toString());
2105 private static String insertStr (String template, String snippet, int index) {
2107 String updatedTemplate;
2109 LOGGER.debug ("Index:" + index + " Snippet:" + snippet);
2111 String templateBeg = template.substring (0, index);
2112 String templateEnd = template.substring (index);
2114 updatedTemplate = templateBeg + "\n" + snippet + templateEnd;
2116 LOGGER.debug ("Template updated with a subnet:" + updatedTemplate);
2117 return updatedTemplate;