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 java.util.Optional;
30 import javax.jws.WebService;
31 import javax.xml.ws.Holder;
33 import org.codehaus.jackson.JsonNode;
34 import org.codehaus.jackson.map.ObjectMapper;
36 import org.openecomp.mso.adapters.network.exceptions.NetworkException;
37 import org.openecomp.mso.cloud.CloudConfig;
38 import org.openecomp.mso.cloud.CloudConfigFactory;
39 import org.openecomp.mso.cloud.CloudSite;
40 import org.openecomp.mso.db.catalog.CatalogDatabase;
41 import org.openecomp.mso.db.catalog.beans.HeatTemplate;
42 import org.openecomp.mso.db.catalog.beans.NetworkResource;
43 import org.openecomp.mso.db.catalog.utils.MavenLikeVersioning;
44 import org.openecomp.mso.entity.MsoRequest;
45 import org.openecomp.mso.logger.MessageEnum;
46 import org.openecomp.mso.logger.MsoAlarmLogger;
47 import org.openecomp.mso.logger.MsoLogger;
48 import org.openecomp.mso.openstack.beans.HeatStatus;
49 import org.openecomp.mso.openstack.beans.NetworkInfo;
50 import org.openecomp.mso.openstack.beans.NetworkRollback;
51 import org.openecomp.mso.openstack.beans.NetworkStatus;
52 import org.openecomp.mso.openstack.beans.Pool;
53 import org.openecomp.mso.openstack.beans.StackInfo;
54 import org.openecomp.mso.openstack.beans.Subnet;
55 import org.openecomp.mso.openstack.exceptions.MsoAdapterException;
56 import org.openecomp.mso.openstack.exceptions.MsoException;
57 import org.openecomp.mso.openstack.exceptions.MsoExceptionCategory;
58 import org.openecomp.mso.openstack.utils.MsoHeatUtils;
59 import org.openecomp.mso.openstack.utils.MsoHeatUtilsWithUpdate;
60 import org.openecomp.mso.openstack.utils.MsoNeutronUtils;
61 import org.openecomp.mso.openstack.utils.MsoNeutronUtils.NetworkType;
62 import org.openecomp.mso.properties.MsoPropertiesException;
63 import org.openecomp.mso.properties.MsoPropertiesFactory;
65 import static org.openecomp.mso.openstack.utils.MsoCommonUtils.isNullOrEmpty;
67 @WebService(serviceName = "NetworkAdapter", endpointInterface = "org.openecomp.mso.adapters.network.MsoNetworkAdapter", targetNamespace = "http://org.openecomp.mso/network")
68 public class MsoNetworkAdapterImpl implements MsoNetworkAdapter {
70 MsoPropertiesFactory msoPropertiesFactory=new MsoPropertiesFactory();
72 CloudConfigFactory cloudConfigFactory=new CloudConfigFactory();
74 private static final String AIC3_NW_PROPERTY= "org.openecomp.mso.adapters.network.aic3nw";
75 private static final String AIC3_NW="OS::ContrailV2::VirtualNetwork";
76 public static final String MSO_PROP_NETWORK_ADAPTER="MSO_PROP_NETWORK_ADAPTER";
77 private static final String VLANS = "vlans";
78 private static final String PHYSICAL_NETWORK = "physical_network";
79 private static final String UPDATE_NETWORK_CONTEXT = "UpdateNetwork";
80 private static final String NETWORK_ID = "network_id";
81 private static final String NETWORK_FQDN = "network_fqdn";
82 private static final String CREATE_NETWORK_CONTEXT = "CreateNetwork";
83 private static final String MSO_CONFIGURATION_ERROR = "MsoConfigurationError";
84 private static final String NEUTRON_MODE = "NEUTRON";
85 private static MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.RA);
86 private static MsoAlarmLogger alarmLogger = new MsoAlarmLogger ();
87 protected CloudConfig cloudConfig;
90 * Health Check web method. Does nothing but return to show the adapter is deployed.
93 public void healthCheck () {
94 LOGGER.debug ("Health check call in Network Adapter");
98 * Do not use this constructor or the msoPropertiesFactory will be NULL.
100 * @see MsoNetworkAdapterImpl#MsoNetworkAdapterImpl(MsoPropertiesFactory)
102 public MsoNetworkAdapterImpl() {
106 * This constructor MUST be used if this class if called with the new operator.
107 * @param msoPropFactory
110 public MsoNetworkAdapterImpl(MsoPropertiesFactory msoPropFactory,CloudConfigFactory cloudConfigFact) {
111 this.msoPropertiesFactory = msoPropFactory;
112 this.cloudConfigFactory=cloudConfigFact;
113 cloudConfig = cloudConfigFactory.getCloudConfig ();
117 public void createNetwork (String cloudSiteId,
120 String modelCustomizationUuid,
122 String physicalNetworkName,
123 List <Integer> vlans,
124 Boolean failIfExists,
126 List <Subnet> subnets,
127 MsoRequest msoRequest,
128 Holder <String> networkId,
129 Holder <String> neutronNetworkId,
130 Holder <Map <String, String>> subnetIdMap,
131 Holder <NetworkRollback> rollback) throws NetworkException {
132 Holder <String> networkFqdn = new Holder <> ();
133 createNetwork (cloudSiteId,
136 modelCustomizationUuid,
157 public void createNetworkContrail (String cloudSiteId,
160 String modelCustomizationUuid,
162 List <String> routeTargets,
165 Boolean failIfExists,
167 List <Subnet> subnets,
168 List <String> policyFqdns,
169 List<String> routeTableFqdns,
170 MsoRequest msoRequest,
171 Holder <String> networkId,
172 Holder <String> neutronNetworkId,
173 Holder <String> networkFqdn,
174 Holder <Map <String, String>> subnetIdMap,
175 Holder <NetworkRollback> rollback) throws NetworkException {
176 createNetwork (cloudSiteId,
179 modelCustomizationUuid,
200 * This is the "Create Network" web service implementation.
201 * It will create a new Network of the requested type in the specified cloud
202 * and tenant. The tenant must exist at the time this service is called.
204 * If a network with the same name already exists, this can be considered a
205 * success or failure, depending on the value of the 'failIfExists' parameter.
207 * There will be a pre-defined set of network types defined in the MSO Catalog.
208 * All such networks will have a similar configuration, based on the allowable
209 * Openstack networking definitions. This includes basic networks, provider
210 * networks (with a single VLAN), and multi-provider networks (one or more VLANs)
212 * Initially, all provider networks must be "vlan" type, and multiple segments in
213 * a multi-provider network must be multiple VLANs on the same physical network.
215 * This service supports two modes of Network creation/update:
216 * - via Heat Templates
218 * The network orchestration mode for each network type is declared in its
219 * catalog definition. All Heat-based templates must support some subset of
220 * the same input parameters: network_name, physical_network, vlan(s).
222 * The method returns the network ID and a NetworkRollback object. This latter
223 * object can be passed as-is to the rollbackNetwork operation to undo everything
224 * that was created. This is useful if a network is successfully created but
225 * the orchestration fails on a subsequent operation.
228 private void createNetwork (String cloudSiteId,
231 String modelCustomizationUuid,
233 String physicalNetworkName,
234 List <Integer> vlans,
235 List <String> routeTargets,
238 Boolean failIfExists,
240 List <Subnet> subnets,
241 List <String> policyFqdns,
242 List <String> routeTableFqdns,
243 MsoRequest msoRequest,
244 Holder <String> networkId,
245 Holder <String> neutronNetworkId,
246 Holder <String> networkFqdn,
247 Holder <Map <String, String>> subnetIdMap,
248 Holder <NetworkRollback> rollback) throws NetworkException {
249 MsoLogger.setLogContext (msoRequest);
250 MsoLogger.setServiceName ("CreateNetwork");
252 LOGGER.debug ("*** CREATE Network: " + networkName
260 // Will capture execution time for metrics
261 long startTime = System.currentTimeMillis ();
263 // Build a default rollback object (no actions performed)
264 NetworkRollback networkRollback = new NetworkRollback ();
265 networkRollback.setCloudId (cloudSiteId);
266 networkRollback.setTenantId (tenantId);
267 networkRollback.setMsoRequest (msoRequest);
268 networkRollback.setModelCustomizationUuid(modelCustomizationUuid);
270 // tenant query is not required here.
271 // If the tenant doesn’t exist, the Heat calls will fail anyway (when the HeatUtils try to obtain a token).
272 // So this is just catching that error in a bit more obvious way up front.
274 cloudConfig = cloudConfigFactory.getCloudConfig ();
275 Optional<CloudSite> cloudSiteOpt = cloudConfig.getCloudSite(cloudSiteId);
276 if (!cloudSiteOpt.isPresent())
278 String error = "Configuration Error. Stack " + networkName + " in "
283 + " CloudSite does not exist in MSO Configuration";
284 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "", "", MsoLogger.ErrorCode.DataError, "Configuration Error");
285 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
286 // Set the detailed error as the Exception 'message'
287 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
290 // Get a handle to the Catalog Database
291 CatalogDatabase db = getCatalogDB ();
293 // Make sure DB connection is always closed
295 NetworkResource networkResource = networkCheck (db,
298 modelCustomizationUuid,
304 String mode = networkResource.getOrchestrationMode ();
305 NetworkType neutronNetworkType = NetworkType.valueOf (networkResource.getNeutronNetworkType ());
307 if (NEUTRON_MODE.equals (mode)) {
309 // Use an MsoNeutronUtils for all neutron commands
310 MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
312 // See if the Network already exists (by name)
313 NetworkInfo netInfo = null;
314 long queryNetworkStarttime = System.currentTimeMillis ();
316 netInfo = neutron.queryNetwork (networkName, tenantId, cloudSiteId);
317 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Response successfully received from OpenStack", "OpenStack", "QueryNetwork", null);
318 } catch (MsoException me) {
319 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while querying network from OpenStack", "OpenStack", "QueryNetwork", null);
320 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception while querying network from OpenStack", me);
321 me.addContext (CREATE_NETWORK_CONTEXT);
322 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while querying network from OpenStack");
323 throw new NetworkException (me);
326 if (netInfo != null) {
327 // Exists. If that's OK, return success with the network ID.
328 // Otherwise, return an exception.
329 if (failIfExists != null && failIfExists) {
330 String error = "Create Nework: Network " + networkName
331 + " already exists in "
335 + " with ID " + netInfo.getId();
336 LOGGER.error (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Network already exists");
337 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
338 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
340 // Populate the outputs from the existing network.
341 networkId.value = netInfo.getId ();
342 neutronNetworkId.value = netInfo.getId ();
343 rollback.value = networkRollback; // Default rollback - no updates performed
344 String msg = "Found Existing network, status=" + netInfo.getStatus () + " for Neutron mode";
345 LOGGER.warn (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "", "", MsoLogger.ErrorCode.DataError, "Found Existing network, status=" + netInfo.getStatus ());
346 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, msg);
351 long createNetworkStarttime = System.currentTimeMillis ();
353 netInfo = neutron.createNetwork (cloudSiteId,
359 LOGGER.recordMetricEvent (createNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Response successfully received from OpenStack", "OpenStack", "CreateNetwork", null);
360 } catch (MsoException me) {
361 me.addContext (CREATE_NETWORK_CONTEXT);
362 LOGGER.recordMetricEvent (createNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while communicate with OpenStack", "OpenStack", "CreateNetwork", null);
363 String error = "Create Network: type " + neutronNetworkType
370 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception while communicate with OpenStack", me);
371 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
373 throw new NetworkException (me);
376 // Note: ignoring MsoNetworkAlreadyExists because we already checked.
378 // If reach this point, network creation is successful.
379 // Since directly created via Neutron, networkId tracked by MSO is the same
380 // as the neutron network ID.
381 networkId.value = netInfo.getId ();
382 neutronNetworkId.value = netInfo.getId ();
384 networkRollback.setNetworkCreated (true);
385 networkRollback.setNetworkId (netInfo.getId ());
386 networkRollback.setNeutronNetworkId (netInfo.getId ());
387 networkRollback.setNetworkType (networkType);
389 LOGGER.debug ("Network " + networkName + " created, id = " + netInfo.getId ());
390 } else if ("HEAT".equals (mode)) {
392 // Use an MsoHeatUtils for all Heat commands
393 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_NETWORK_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
395 //HeatTemplate heatTemplate = db.getHeatTemplate (networkResource.getTemplateId ());
396 HeatTemplate heatTemplate = db.getHeatTemplateByArtifactUuidRegularQuery (networkResource.getHeatTemplateArtifactUUID());
397 if (heatTemplate == null) {
398 String error = "Network error - undefined Heat Template. Network Type = " + networkType;
399 LOGGER.error (MessageEnum.RA_PARAM_NOT_FOUND, "Heat Template", "Network Type", networkType, "Openstack", "", MsoLogger.ErrorCode.DataError, "Network error - undefined Heat Template. Network Type = " + networkType);
400 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error); // Alarm on this
404 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
405 throw new NetworkException (error, MsoExceptionCategory.INTERNAL);
408 LOGGER.debug ("Got HEAT Template from DB: " + heatTemplate.toString ());
410 // "Fix" the template if it has CR/LF (getting this from Oracle)
411 String template = heatTemplate.getHeatTemplate ();
412 template = template.replaceAll ("\r\n", "\n");
414 boolean aic3template=false;
415 String aic3nw = AIC3_NW;
417 aic3nw = msoPropertiesFactory.getMsoJavaProperties(MSO_PROP_NETWORK_ADAPTER).getProperty(AIC3_NW_PROPERTY, AIC3_NW);
418 } catch (MsoPropertiesException e) {
419 String error = "Unable to get properties:" + MSO_PROP_NETWORK_ADAPTER;
420 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "", "", MsoLogger.ErrorCode.DataError, "Exception - Unable to get properties", e);
423 if (template.contains(aic3nw))
426 // First, look up to see if the Network already exists (by name).
427 // For HEAT orchestration of networks, the stack name will always match the network name
428 StackInfo heatStack = null;
429 long queryNetworkStarttime = System.currentTimeMillis ();
431 heatStack = heat.queryStack (cloudSiteId, tenantId, networkName);
432 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Response successfully received from OpenStack", "OpenStack", "QueryNetwork", null);
433 } catch (MsoException me) {
434 me.addContext (CREATE_NETWORK_CONTEXT);
435 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while querying stack from OpenStack", "OpenStack", "QueryNetwork", null);
436 String error = "Create Network (heat): query network " + networkName
443 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception while querying stack from OpenStack", me);
444 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
445 throw new NetworkException (me);
448 if (heatStack != null && (heatStack.getStatus () != HeatStatus.NOTFOUND)) {
449 // Stack exists. Return success or error depending on input directive
450 if (failIfExists != null && failIfExists) {
451 String error = "CreateNetwork: Stack " + networkName
452 + " already exists in "
456 + " as " + heatStack.getCanonicalName();
457 LOGGER.error (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "", "", MsoLogger.ErrorCode.DataError, "Network already exists");
458 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
459 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
461 // Populate the outputs from the existing stack.
462 networkId.value = heatStack.getCanonicalName ();
463 neutronNetworkId.value = (String) heatStack.getOutputs ().get (NETWORK_ID);
464 rollback.value = networkRollback; // Default rollback - no updates performed
467 networkFqdn.value = (String) heatStack.getOutputs().get(NETWORK_FQDN);
469 Map <String, Object> outputs = heatStack.getOutputs ();
470 Map <String, String> sMap = new HashMap <> ();
471 if (outputs != null) {
472 for (String key : outputs.keySet ()) {
473 if (key != null && key.startsWith ("subnet")) {
474 if (aic3template) //one subnet_id output
476 Map <String, String> map = getSubnetUUId(key, outputs, subnets);
479 else //multiples subnet_%aaid% outputs
481 String subnetUUId = (String) outputs.get(key);
482 sMap.put (key.substring("subnet_id_".length()), subnetUUId);
487 subnetIdMap.value = sMap;
488 LOGGER.warn (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "", "", MsoLogger.ErrorCode.DataError, "Found Existing network stack, status=" + heatStack.getStatus ());
489 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Suc, "Found Existing network stack");
494 // Ready to deploy the new Network
495 // Build the common set of HEAT template parameters
496 Map <String, Object> stackParams = populateNetworkParams (neutronNetworkType,
505 // Validate (and update) the input parameters against the DB definition
506 // Shouldn't happen unless DB config is wrong, since all networks use same inputs
507 // and inputs were already validated.
509 stackParams = heat.validateStackParams (stackParams, heatTemplate);
510 } catch (IllegalArgumentException e) {
511 String error = "Create Network: Configuration Error: " + e.getMessage ();
512 LOGGER.error (MessageEnum.RA_CONFIG_EXC, e.getMessage(), "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception - Create Network, Configuration Error", e);
513 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error); // Alarm on this
517 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
518 // Input parameters were not valid
519 throw new NetworkException (error, MsoExceptionCategory.INTERNAL);
522 if (subnets != null) {
526 template = mergeSubnetsAIC3 (template, subnets, stackParams);
530 template = mergeSubnets (template, subnets);
532 } catch (MsoException me) {
533 me.addContext (CREATE_NETWORK_CONTEXT);
534 String error = "Create Network (heat): type " + neutronNetworkType
541 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception Create Network, merging subnets", me);
542 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
543 throw new NetworkException (me);
547 if (policyFqdns != null && !policyFqdns.isEmpty() && aic3template) {
549 mergePolicyRefs (policyFqdns, stackParams);
550 } catch (MsoException me) {
551 me.addContext (CREATE_NETWORK_CONTEXT);
552 String error = "Create Network (heat) mergePolicyRefs type " + neutronNetworkType
559 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception Create Network, merging policyRefs", me);
560 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
561 throw new NetworkException (me);
565 if (routeTableFqdns != null && !routeTableFqdns.isEmpty() && aic3template) {
567 mergeRouteTableRefs (routeTableFqdns, stackParams);
568 } catch (MsoException me) {
569 me.addContext (CREATE_NETWORK_CONTEXT);
570 String error = "Create Network (heat) mergeRouteTableRefs type " + neutronNetworkType
577 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception Create Network, merging routeTableRefs", me);
578 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
579 throw new NetworkException (me);
583 // Deploy the network stack
584 // Ignore MsoStackAlreadyExists exception because we already checked.
588 heatStack = heat.createStack (cloudSiteId,
594 heatTemplate.getTimeoutMinutes (),
598 backout.booleanValue());
599 } catch (MsoException me) {
600 me.addContext (CREATE_NETWORK_CONTEXT);
601 String error = "Create Network (heat): type " + neutronNetworkType
608 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, networkName, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception creating network", me);
609 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
610 throw new NetworkException (me);
613 // Reach this point if createStack is successful.
615 // For Heat-based orchestration, the MSO-tracked network ID is the heat stack,
616 // and the neutronNetworkId is the network UUID returned in stack outputs.
617 networkId.value = heatStack.getCanonicalName ();
618 neutronNetworkId.value = (String) heatStack.getOutputs ().get (NETWORK_ID);
621 networkFqdn.value = (String) heatStack.getOutputs().get(NETWORK_FQDN);
623 Map <String, Object> outputs = heatStack.getOutputs ();
624 Map <String, String> sMap = new HashMap <> ();
625 if (outputs != null) {
626 for (String key : outputs.keySet ()) {
627 if (key != null && key.startsWith ("subnet")) {
628 if (aic3template) //one subnet output expected
630 Map <String, String> map = getSubnetUUId(key, outputs, subnets);
633 else //multiples subnet_%aaid% outputs allowed
635 String subnetUUId = (String) outputs.get(key);
636 sMap.put (key.substring("subnet_id_".length()), subnetUUId);
641 subnetIdMap.value = sMap;
643 rollback.value = networkRollback;
644 // Populate remaining rollback info and response parameters.
645 networkRollback.setNetworkStackId (heatStack.getCanonicalName ());
646 networkRollback.setNeutronNetworkId ((String) heatStack.getOutputs ().get (NETWORK_ID));
647 networkRollback.setNetworkCreated (true);
648 networkRollback.setNetworkType (networkType);
650 LOGGER.debug ("Network " + networkName + " successfully created via HEAT");
655 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Suc, "Successfully created network");
660 public void updateNetwork (String cloudSiteId,
663 String modelCustomizationUuid,
666 String physicalNetworkName,
667 List <Integer> vlans,
668 List <Subnet> subnets,
669 MsoRequest msoRequest,
670 Holder <Map <String, String>> subnetIdMap,
671 Holder <NetworkRollback> rollback) throws NetworkException {
672 updateNetwork (cloudSiteId,
675 modelCustomizationUuid,
693 public void updateNetworkContrail (String cloudSiteId,
696 String modelCustomizationUuid,
699 List <String> routeTargets,
702 List <Subnet> subnets,
703 List <String> policyFqdns,
704 List<String> routeTableFqdns,
705 MsoRequest msoRequest,
706 Holder <Map <String, String>> subnetIdMap,
707 Holder <NetworkRollback> rollback) throws NetworkException {
708 updateNetwork (cloudSiteId,
711 modelCustomizationUuid,
728 * This is the "Update Network" web service implementation.
729 * It will update an existing Network of the requested type in the specified cloud
730 * and tenant. The typical use will be to replace the VLANs with the supplied
731 * list (to add or remove a VLAN), but other properties may be updated as well.
733 * There will be a pre-defined set of network types defined in the MSO Catalog.
734 * All such networks will have a similar configuration, based on the allowable
735 * Openstack networking definitions. This includes basic networks, provider
736 * networks (with a single VLAN), and multi-provider networks (one or more VLANs).
738 * Initially, all provider networks must currently be "vlan" type, and multi-provider
739 * networks must be multiple VLANs on the same physical network.
741 * This service supports two modes of Network update:
742 * - via Heat Templates
744 * The network orchestration mode for each network type is declared in its
745 * catalog definition. All Heat-based templates must support some subset of
746 * the same input parameters: network_name, physical_network, vlan, segments.
748 * The method returns a NetworkRollback object. This object can be passed
749 * as-is to the rollbackNetwork operation to undo everything that was updated.
750 * This is useful if a network is successfully updated but orchestration
751 * fails on a subsequent operation.
753 private void updateNetwork (String cloudSiteId,
756 String modelCustomizationUuid,
759 String physicalNetworkName,
760 List <Integer> vlans,
761 List <String> routeTargets,
764 List <Subnet> subnets,
765 List <String> policyFqdns,
766 List<String> routeTableFqdns,
767 MsoRequest msoRequest,
768 Holder <Map <String, String>> subnetIdMap,
769 Holder <NetworkRollback> rollback) throws NetworkException {
770 MsoLogger.setLogContext (msoRequest);
771 MsoLogger.setServiceName ("UpdateNetwork");
772 LOGGER.debug ("***UPDATE Network adapter with Network: " + networkName
781 // Will capture execution time for metrics
782 long startTime = System.currentTimeMillis ();
784 // Build a default rollback object (no actions performed)
785 NetworkRollback networkRollback = new NetworkRollback ();
786 networkRollback.setCloudId (cloudSiteId);
787 networkRollback.setTenantId (tenantId);
788 networkRollback.setMsoRequest (msoRequest);
790 cloudConfig = cloudConfigFactory.getCloudConfig ();
791 Optional<CloudSite> cloudSiteOpt = cloudConfig.getCloudSite (cloudSiteId);
792 if (!cloudSiteOpt.isPresent()) {
793 String error = "UpdateNetwork: Configuration Error. Stack " + networkName + " in "
798 + " CloudSite does not exist in MSO Configuration";
799 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "CloudSite does not exist in MSO Configuration");
800 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
801 // Set the detailed error as the Exception 'message'
802 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
805 // Get a handle to the Catalog Database
806 CatalogDatabase db = getCatalogDB ();
808 // Make sure DB connection is always closed
810 NetworkResource networkResource = networkCheck(db,
813 modelCustomizationUuid,
819 String mode = networkResource.getOrchestrationMode();
820 NetworkType neutronNetworkType = NetworkType.valueOf(networkResource.getNeutronNetworkType());
822 // Use an MsoNeutronUtils for all Neutron commands
823 MsoNeutronUtils neutron = new MsoNeutronUtils(MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
825 if (NEUTRON_MODE.equals(mode)) {
827 // Verify that the Network exists
828 // For Neutron-based orchestration, the networkId is the Neutron Network UUID.
829 NetworkInfo netInfo = null;
830 long queryNetworkStarttime = System.currentTimeMillis();
832 netInfo = neutron.queryNetwork(networkId, tenantId, cloudSiteId);
833 LOGGER.recordMetricEvent(queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryNetwork", null);
834 } catch (MsoException me) {
835 me.addContext(UPDATE_NETWORK_CONTEXT);
836 String error = "Update Network (neutron): query " + networkId
843 LOGGER.recordMetricEvent(queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryNetwork", null);
844 LOGGER.error(MessageEnum.RA_QUERY_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "QueryNetwork", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - queryNetwork", me);
845 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
846 throw new NetworkException(me);
849 if (netInfo == null) {
850 String error = "Update Nework: Network " + networkId
851 + " does not exist in "
855 LOGGER.error(MessageEnum.RA_NETWORK_NOT_FOUND, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Network not found");
856 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
857 // Does not exist. Throw an exception (can't update a non-existent network)
858 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
860 long updateNetworkStarttime = System.currentTimeMillis();
862 netInfo = neutron.updateNetwork(cloudSiteId,
868 LOGGER.recordMetricEvent(updateNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "UpdateNetwork", null);
869 } catch (MsoException me) {
870 me.addContext(UPDATE_NETWORK_CONTEXT);
871 String error = "Update Network (neutron): " + networkId
878 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, networkId, cloudSiteId, tenantId, "Openstack", "updateNetwork", MsoLogger.ErrorCode.DataError, "Exception - updateNetwork", me);
879 LOGGER.recordMetricEvent(updateNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "UpdateNetwork", null);
880 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
881 throw new NetworkException(me);
884 // Add the network ID and previously queried vlans to the rollback object
885 networkRollback.setNetworkId(netInfo.getId());
886 networkRollback.setNeutronNetworkId(netInfo.getId());
887 networkRollback.setNetworkType(networkType);
888 // Save previous parameters
889 networkRollback.setNetworkName(netInfo.getName());
890 networkRollback.setPhysicalNetwork(netInfo.getProvider());
891 networkRollback.setVlans(netInfo.getVlans());
893 LOGGER.debug("Network " + networkId + " updated, id = " + netInfo.getId());
894 } else if ("HEAT".equals(mode)) {
896 // Use an MsoHeatUtils for all Heat commands
897 MsoHeatUtilsWithUpdate heat = new MsoHeatUtilsWithUpdate(MSO_PROP_NETWORK_ADAPTER, msoPropertiesFactory, cloudConfigFactory);
899 // First, look up to see that the Network already exists.
900 // For Heat-based orchestration, the networkId is the network Stack ID.
901 StackInfo heatStack = null;
902 long queryStackStarttime = System.currentTimeMillis();
904 heatStack = heat.queryStack(cloudSiteId, tenantId, networkName);
905 LOGGER.recordMetricEvent(queryStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", null);
906 } catch (MsoException me) {
907 me.addContext(UPDATE_NETWORK_CONTEXT);
908 String error = "UpdateNetwork (heat): query " + networkName
915 LOGGER.recordMetricEvent(queryStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryStack", null);
916 LOGGER.error(MessageEnum.RA_QUERY_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Exception - QueryStack", me);
917 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
918 throw new NetworkException(me);
921 if (heatStack == null || (heatStack.getStatus() == HeatStatus.NOTFOUND)) {
922 String error = "UpdateNetwork: Stack " + networkName
923 + " does not exist in "
927 LOGGER.error(MessageEnum.RA_NETWORK_NOT_FOUND, networkId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Network not found");
928 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
929 // Network stack does not exist. Return an error
930 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
933 // Get the previous parameters for rollback
934 Map<String, Object> heatParams = heatStack.getParameters();
936 String previousNetworkName = (String) heatParams.get("network_name");
937 String previousPhysicalNetwork = (String) heatParams.get(PHYSICAL_NETWORK);
939 List<Integer> previousVlans = new ArrayList<>();
940 String vlansParam = (String) heatParams.get(VLANS);
941 if (vlansParam != null) {
942 for (String vlan : vlansParam.split(",")) {
944 previousVlans.add(Integer.parseInt(vlan));
945 } catch (NumberFormatException e) {
946 LOGGER.warn(MessageEnum.RA_VLAN_PARSE, networkId, vlansParam, "", "", MsoLogger.ErrorCode.DataError, "Exception - VLAN parse", e);
950 LOGGER.debug("Update Stack: Previous VLANS: " + previousVlans);
952 // Ready to deploy the updated Network via Heat
954 //HeatTemplate heatTemplate = db.getHeatTemplate (networkResource.getTemplateId ());
955 HeatTemplate heatTemplate = db.getHeatTemplateByArtifactUuidRegularQuery (networkResource.getHeatTemplateArtifactUUID());
956 if (heatTemplate == null) {
957 String error = "Network error - undefined Heat Template. Network Type=" + networkType;
958 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);
959 alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
960 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
961 throw new NetworkException(error, MsoExceptionCategory.INTERNAL);
964 LOGGER.debug("Got HEAT Template from DB: " + heatTemplate.toString());
966 // "Fix" the template if it has CR/LF (getting this from Oracle)
967 String template = heatTemplate.getHeatTemplate();
968 template = template.replaceAll("\r\n", "\n");
970 boolean aic3template = false;
971 String aic3nw = AIC3_NW;
973 aic3nw = msoPropertiesFactory.getMsoJavaProperties(MSO_PROP_NETWORK_ADAPTER).getProperty(AIC3_NW_PROPERTY, AIC3_NW);
974 } catch (MsoPropertiesException e) {
975 String error = "Unable to get properties:" + MSO_PROP_NETWORK_ADAPTER;
976 LOGGER.error(MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - Unable to get properties", e);
978 if (template.contains(aic3nw))
981 // Build the common set of HEAT template parameters
982 Map<String, Object> stackParams = populateNetworkParams(neutronNetworkType,
991 // Validate (and update) the input parameters against the DB definition
992 // Shouldn't happen unless DB config is wrong, since all networks use same inputs
994 stackParams = heat.validateStackParams(stackParams, heatTemplate);
995 } catch (IllegalArgumentException e) {
996 String error = "UpdateNetwork: Configuration Error: Network Type=" + networkType;
997 LOGGER.error(MessageEnum.RA_CONFIG_EXC, "Network Type=" + networkType, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork: Configuration Error");
998 alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
999 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.SchemaError, error);
1000 throw new NetworkException(error, MsoExceptionCategory.INTERNAL, e);
1003 if (subnets != null) {
1006 template = mergeSubnetsAIC3(template, subnets, stackParams);
1008 template = mergeSubnets(template, subnets);
1010 } catch (MsoException me) {
1011 me.addContext(UPDATE_NETWORK_CONTEXT);
1012 String error = "Update Network (heat): type " + neutronNetworkType
1019 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergeSubnets ", me);
1020 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
1021 throw new NetworkException(me);
1025 if (policyFqdns != null && aic3template) {
1027 mergePolicyRefs(policyFqdns, stackParams);
1028 } catch (MsoException me) {
1029 me.addContext(UPDATE_NETWORK_CONTEXT);
1030 String error = "UpdateNetwork (heat) mergePolicyRefs type " + neutronNetworkType
1037 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergePolicyRefs", me);
1038 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
1039 throw new NetworkException(me);
1043 if (routeTableFqdns != null && !routeTableFqdns.isEmpty() && aic3template) {
1045 mergeRouteTableRefs(routeTableFqdns, stackParams);
1046 } catch (MsoException me) {
1047 me.addContext(UPDATE_NETWORK_CONTEXT);
1048 String error = "UpdateNetwork (heat) mergeRouteTableRefs type " + neutronNetworkType
1055 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergeRouteTableRefs", me);
1056 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
1057 throw new NetworkException(me);
1061 // Update the network stack
1062 // Ignore MsoStackNotFound exception because we already checked.
1063 long updateStackStarttime = System.currentTimeMillis();
1065 heatStack = heat.updateStack(cloudSiteId,
1071 heatTemplate.getTimeoutMinutes());
1072 LOGGER.recordMetricEvent(updateStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "UpdateStack", null);
1073 } catch (MsoException me) {
1074 me.addContext(UPDATE_NETWORK_CONTEXT);
1075 String error = "Update Network: " + networkId + " in " + cloudSiteId + "/" + tenantId + ": " + me;
1076 LOGGER.recordMetricEvent(updateStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "UpdateStack", null);
1077 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - update network", me);
1078 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1079 throw new NetworkException(me);
1082 Map<String, Object> outputs = heatStack.getOutputs();
1083 Map<String, String> sMap = new HashMap<>();
1084 if (outputs != null) {
1085 for (String key : outputs.keySet()) {
1086 if (key != null && key.startsWith("subnet")) {
1087 if (aic3template) //one subnet output expected
1089 Map<String, String> map = getSubnetUUId(key, outputs, subnets);
1091 } else //multiples subnet_%aaid% outputs allowed
1093 String subnetUUId = (String) outputs.get(key);
1094 sMap.put(key.substring("subnet_id_".length()), subnetUUId);
1099 subnetIdMap.value = sMap;
1101 // Reach this point if createStack is successful.
1102 // Populate remaining rollback info and response parameters.
1103 networkRollback.setNetworkStackId(heatStack.getCanonicalName());
1104 if(null != outputs) {
1105 networkRollback.setNeutronNetworkId((String) outputs.get(NETWORK_ID));
1108 LOGGER.debug("outputs is NULL");
1110 networkRollback.setNetworkType(networkType);
1111 // Save previous parameters
1112 networkRollback.setNetworkName(previousNetworkName);
1113 networkRollback.setPhysicalNetwork(previousPhysicalNetwork);
1114 networkRollback.setVlans(previousVlans);
1116 rollback.value = networkRollback;
1118 LOGGER.debug("Network " + networkId + " successfully updated via HEAT");
1123 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully updated network");
1127 private NetworkResource networkCheck (CatalogDatabase db,
1130 String modelCustomizationUuid,
1132 String physicalNetworkName,
1133 List <Integer> vlans,
1134 List <String> routeTargets,
1135 CloudSite cloudSite) throws NetworkException {
1136 // Retrieve the Network Resource definition
1137 NetworkResource networkResource = null;
1139 if (isNullOrEmpty(modelCustomizationUuid)) {
1140 networkResource = db.getNetworkResource(networkType);
1142 networkResource = db
1143 .getNetworkResourceByModelCustUuid(modelCustomizationUuid);
1145 if (networkResource == null) {
1146 String error = "Create/UpdateNetwork: Unable to get network resource with NetworkType:"
1148 + " or ModelCustomizationUUID:"
1149 + modelCustomizationUuid;
1150 LOGGER.error(MessageEnum.RA_UNKOWN_PARAM,
1151 "NetworkType/ModelCustomizationUUID", networkType + "/"
1152 + modelCustomizationUuid, "OpenStack", "",
1153 MsoLogger.ErrorCode.DataError,
1154 "Create/UpdateNetwork: Unknown NetworkType/ModelCustomizationUUID");
1156 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
1158 LOGGER.debug("Got Network definition from Catalog: "
1159 + networkResource.toString());
1161 String mode = networkResource.getOrchestrationMode();
1162 NetworkType neutronNetworkType = NetworkType
1163 .valueOf(networkResource.getNeutronNetworkType());
1165 // All Networks are orchestrated via HEAT or Neutron
1166 if (!("HEAT".equals(mode) || NEUTRON_MODE.equals(mode))) {
1167 String error = "CreateNetwork: Configuration Error: Network Type = "
1169 LOGGER.error(MessageEnum.RA_NETWORK_ORCHE_MODE_NOT_SUPPORT,
1170 mode, "OpenStack", "", MsoLogger.ErrorCode.DataError,
1171 "CreateNetwork: Configuration Error");
1172 // Alarm on this error, configuration must be fixed
1173 alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR,
1174 MsoAlarmLogger.CRITICAL, error);
1176 throw new NetworkException(error, MsoExceptionCategory.INTERNAL);
1179 MavenLikeVersioning aicV = new MavenLikeVersioning();
1180 aicV.setVersion(cloudSite.getAic_version());
1181 if ((aicV.isMoreRecentThan(networkResource.getAicVersionMin()) || aicV
1182 .isTheSameVersion(networkResource.getAicVersionMin())) // aic
1185 && (aicV.isTheSameVersion(networkResource
1186 .getAicVersionMax()) || !(aicV
1187 .isMoreRecentThan(networkResource
1188 .getAicVersionMax())))) // aic <= max
1190 LOGGER.debug("Network Type:" + networkType + " VersionMin:"
1191 + networkResource.getAicVersionMin() + " VersionMax:"
1192 + networkResource.getAicVersionMax()
1193 + " supported on Cloud:" + cloudSite.getId()
1194 + " with AIC_Version:" + cloudSite.getAic_version());
1196 String error = "Network Type:" + networkType + " Version_Min:"
1197 + networkResource.getAicVersionMin() + " Version_Max:"
1198 + networkResource.getAicVersionMax()
1199 + " not supported on Cloud:" + cloudSite.getId()
1200 + " with AIC_Version:" + cloudSite.getAic_version();
1201 LOGGER.error(MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "",
1202 MsoLogger.ErrorCode.DataError,
1203 "Network Type not supported on Cloud");
1204 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR,
1205 MsoLogger.ResponseCode.DataError, error);
1206 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
1209 // Validate the Network parameters.
1210 String missing = validateNetworkParams(neutronNetworkType,
1211 networkName, physicalNetworkName, vlans, routeTargets);
1212 if (!missing.isEmpty()) {
1213 String error = "Create Network: Missing parameters: " + missing;
1214 LOGGER.error(MessageEnum.RA_MISSING_PARAM, missing,
1215 "OpenStack", "", MsoLogger.ErrorCode.DataError,
1216 "Create Network: Missing parameters");
1218 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
1223 return networkResource;
1227 public void queryNetwork (String cloudSiteId,
1229 String networkNameOrId,
1230 MsoRequest msoRequest,
1231 Holder <Boolean> networkExists,
1232 Holder <String> networkId,
1233 Holder <String> neutronNetworkId,
1234 Holder <NetworkStatus> status,
1235 Holder <List <Integer>> vlans,
1236 Holder <Map <String, String>> subnetIdMap) throws NetworkException {
1237 queryNetworkInfo(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 queryNetworkInfo(cloudSiteId,
1273 * This is the queryNetworkInfo method. It returns the existence and status of
1274 * the specified network, along with its Neutron UUID and list of VLANs.
1275 * This method attempts to find the network using both Heat and Neutron.
1276 * Heat stacks are first searched based on the provided network name/id.
1277 * If none is found, the Neutron is directly queried.
1279 private void queryNetworkInfo(String cloudSiteId,
1281 String networkNameOrId,
1282 MsoRequest msoRequest,
1283 Holder <Boolean> networkExists,
1284 Holder <String> networkId,
1285 Holder <String> neutronNetworkId,
1286 Holder <NetworkStatus> status,
1287 Holder <List <Integer>> vlans,
1288 Holder <Map <String, String>> subnetIdMap) throws NetworkException {
1289 MsoLogger.setLogContext (msoRequest);
1290 MsoLogger.setServiceName ("QueryNetwork");
1291 LOGGER.debug ("*** QUERY Network with Network: " + networkNameOrId
1297 // Will capture execution time for metrics
1298 long startTime = System.currentTimeMillis ();
1300 if (isNullOrEmpty (cloudSiteId)
1301 || isNullOrEmpty(tenantId)
1302 || isNullOrEmpty(networkNameOrId)) {
1304 String error = "Missing mandatory parameter cloudSiteId, tenantId or networkId";
1305 LOGGER.error (MessageEnum.RA_MISSING_PARAM, "cloudSiteId or tenantId or networkNameOrId", "OpenStack", "", MsoLogger.ErrorCode.DataError, "Missing mandatory parameter cloudSiteId, tenantId or networkId");
1306 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
1307 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1310 cloudConfig = cloudConfigFactory.getCloudConfig();
1311 Optional<CloudSite> cloudSiteOpt = cloudConfig.getCloudSite(cloudSiteId);
1312 if (!cloudSiteOpt.isPresent())
1314 String error = "Configuration Error. Stack " + networkNameOrId + " in "
1319 + " CloudSite does not exist in MSO Configuration";
1320 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Configuration Error");
1321 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
1322 // Set the detailed error as the Exception 'message'
1323 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1326 // Use MsoNeutronUtils for all NEUTRON commands
1327 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_NETWORK_ADAPTER,msoPropertiesFactory,cloudConfigFactory);
1328 MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
1332 // Try Heat first, since networks may be named the same as the Heat stack
1333 StackInfo heatStack = null;
1334 long queryStackStarttime = System.currentTimeMillis ();
1336 heatStack = heat.queryStack (cloudSiteId, tenantId, networkNameOrId);
1337 LOGGER.recordMetricEvent (queryStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", null);
1338 } catch (MsoException me) {
1339 me.addContext ("QueryNetwork");
1340 String error = "Query Network (heat): " + networkNameOrId
1347 LOGGER.recordMetricEvent (queryStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "BPMN", "QueryStack", null);
1348 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkNameOrId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Exception - Query Network (heat)", me);
1349 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1350 throw new NetworkException (me);
1353 // Populate the outputs based on the returned Stack information
1354 if (heatStack != null && heatStack.getStatus () != HeatStatus.NOTFOUND) {
1355 // Found it. Get the neutronNetworkId for further query
1356 Map <String, Object> outputs = heatStack.getOutputs ();
1357 neutronId = (String) outputs.get (NETWORK_ID);
1360 Map <String, String> sMap = new HashMap <> ();
1361 if (outputs != null) {
1362 for (String key : outputs.keySet ()) {
1363 if (key != null && key.startsWith ("subnet_id_")) //multiples subnet_%aaid% outputs
1365 String subnetUUId = (String) outputs.get(key);
1366 sMap.put (key.substring("subnet_id_".length()), subnetUUId);
1368 else if (key != null && key.startsWith ("subnet")) //one subnet output expected
1370 Map <String, String> map = getSubnetUUId(key, outputs, null);
1376 subnetIdMap.value = sMap;
1378 // Input ID was not a Heat stack ID. Try it directly in Neutron
1379 neutronId = networkNameOrId;
1380 mode = NEUTRON_MODE;
1383 // Query directly against the Neutron Network for the details
1384 // no RouteTargets available for ContrailV2 in neutron net-show
1385 // networkId is heatStackId
1386 long queryNetworkStarttime = System.currentTimeMillis ();
1388 NetworkInfo netInfo = neutron.queryNetwork (neutronId, tenantId, cloudSiteId);
1389 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryNetwork", null);
1390 if (netInfo != null) {
1391 // Found. Populate the output elements
1392 networkExists.value = Boolean.TRUE;
1393 if ("HEAT".equals (mode)) {
1394 networkId.value = heatStack.getCanonicalName ();
1396 networkId.value = netInfo.getId ();
1398 neutronNetworkId.value = netInfo.getId ();
1399 status.value = netInfo.getStatus ();
1401 vlans.value = netInfo.getVlans ();
1403 LOGGER.debug ("Network " + networkNameOrId
1408 + ("HEAT".equals (mode) ? ",NeutronId = " + neutronNetworkId.value : ""));
1410 // Not found. Populate the status fields, leave the rest null
1411 networkExists.value = Boolean.FALSE;
1412 status.value = NetworkStatus.NOTFOUND;
1413 neutronNetworkId.value = null;
1415 vlans.value = new ArrayList<>();
1417 LOGGER.debug ("Network " + networkNameOrId + " not found");
1419 } catch (MsoException me) {
1420 me.addContext ("QueryNetwork");
1421 String error = "Query Network (neutron): " + networkNameOrId
1428 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryNetwork", null);
1429 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkNameOrId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - Query Network (neutron)", me);
1430 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1431 throw new NetworkException (me);
1433 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully queried network");
1438 * This is the "Delete Network" web service implementation.
1439 * It will delete a Network in the specified cloud and tenant.
1441 * If the network is not found, it is treated as a success.
1443 * This service supports two modes of Network creation/update/delete:
1444 * - via Heat Templates
1446 * The network orchestration mode for each network type is declared in its
1447 * catalog definition.
1449 * For Heat-based orchestration, the networkId should be the stack ID.
1450 * For Neutron-based orchestration, the networkId should be the Neutron network UUID.
1452 * The method returns nothing on success. Rollback is not possible for delete
1453 * commands, so any failure on delete will require manual fallout in the client.
1456 public void deleteNetwork (String cloudSiteId,
1459 String modelCustomizationUuid,
1461 MsoRequest msoRequest,
1462 Holder <Boolean> networkDeleted) throws NetworkException {
1463 MsoLogger.setLogContext (msoRequest);
1464 MsoLogger.setServiceName ("DeleteNetwork");
1465 LOGGER.debug ("*** DELETE Network adapter with Network: " + networkId
1471 // Will capture execution time for metrics
1472 long startTime = System.currentTimeMillis ();
1474 // Get a handle to the Catalog Database
1475 CatalogDatabase db = getCatalogDB ();
1477 // Make sure DB connection is always closed
1479 if (isNullOrEmpty (cloudSiteId)
1480 || isNullOrEmpty(tenantId)
1481 || isNullOrEmpty(networkId)) {
1482 String error = "Missing mandatory parameter cloudSiteId, tenantId or networkId";
1483 LOGGER.error (MessageEnum.RA_MISSING_PARAM, "cloudSiteId or tenantId or networkId", "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing mandatory parameter cloudSiteId, tenantId or networkId");
1484 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
1485 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1488 // Retrieve the Network Resource definition
1489 NetworkResource networkResource = null;
1490 if (isNullOrEmpty(modelCustomizationUuid)) {
1491 networkResource = db.getNetworkResource (networkType);
1493 else if (!isNullOrEmpty(networkType))
1495 networkResource = db.getNetworkResourceByModelCustUuid(modelCustomizationUuid);
1498 if (networkResource != null) {
1499 LOGGER.debug ("Got Network definition from Catalog: " + networkResource.toString ());
1501 mode = networkResource.getOrchestrationMode ();
1504 if (NEUTRON_MODE.equals (mode)) {
1506 // Use MsoNeutronUtils for all NEUTRON commands
1507 MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
1508 long deleteNetworkStarttime = System.currentTimeMillis ();
1510 // The deleteNetwork function in MsoNeutronUtils returns success if the network
1511 // was not found. So don't bother to query first.
1512 boolean deleted = neutron.deleteNetwork (networkId, tenantId, cloudSiteId);
1513 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteNetwork", null);
1514 networkDeleted.value = deleted;
1515 } catch (MsoException me) {
1516 me.addContext ("DeleteNetwork");
1517 String error = "Delete Network (neutron): " + networkId
1524 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteNetwork", null);
1525 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Delete Network (neutron)", me);
1526 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1527 throw new NetworkException (me);
1529 } else { // DEFAULT to ("HEAT".equals (mode))
1530 long deleteStackStarttime = System.currentTimeMillis ();
1531 // Use MsoHeatUtils for all HEAT commands
1532 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_NETWORK_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
1535 // The deleteStack function in MsoHeatUtils returns NOTFOUND if the stack was not found or if the stack was deleted.
1536 // So query first to report back if stack WAS deleted or just NOTOFUND
1537 StackInfo heatStack = null;
1538 heatStack = heat.queryStack(cloudSiteId, tenantId, networkId);
1539 if (heatStack != null && heatStack.getStatus() != HeatStatus.NOTFOUND)
1541 heat.deleteStack (tenantId, cloudSiteId, networkId, true);
1542 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteStack", null);
1543 networkDeleted.value = true;
1547 networkDeleted.value = false;
1549 } catch (MsoException me) {
1550 me.addContext ("DeleteNetwork");
1551 String error = "Delete Network (heat): " + networkId
1558 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteStack", null);
1559 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Delete Network (heat)", me);
1560 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1561 throw new NetworkException (me);
1568 // On success, nothing is returned.
1569 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully deleted network");
1573 public CatalogDatabase getCatalogDB() {
1574 return CatalogDatabase.getInstance();
1578 * This web service endpoint will rollback a previous Create VNF operation.
1579 * A rollback object is returned to the client in a successful creation
1580 * response. The client can pass that object as-is back to the rollbackVnf
1581 * operation to undo the creation.
1583 * The rollback includes removing the VNF and deleting the tenant if the
1584 * tenant did not exist prior to the VNF creation.
1587 public void rollbackNetwork (NetworkRollback rollback) throws NetworkException {
1588 MsoLogger.setServiceName ("RollbackNetwork");
1589 // Will capture execution time for metrics
1590 long startTime = System.currentTimeMillis ();
1592 if (rollback == null) {
1593 LOGGER.error (MessageEnum.RA_ROLLBACK_NULL, "Openstack", "", MsoLogger.ErrorCode.DataError, "rollback is null");
1594 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, "No action to perform");
1598 MsoLogger.setLogContext (rollback.getMsoRequest());
1600 // Get the elements of the VnfRollback object for easier access
1601 String cloudSiteId = rollback.getCloudId ();
1602 String tenantId = rollback.getTenantId ();
1603 String networkId = rollback.getNetworkStackId ();
1604 String networkType = rollback.getNetworkType ();
1605 String modelCustomizationUuid = rollback.getModelCustomizationUuid();
1607 LOGGER.debug ("*** ROLLBACK Network " + networkId + " in " + cloudSiteId + "/" + tenantId);
1609 // rollback may be null (e.g. if network already existed when Create was called)
1610 // Get a handle to the Catalog Database
1611 CatalogDatabase db = getCatalogDB ();
1613 // Make sure DB connection is always closed
1616 // Retrieve the Network Resource definition
1617 NetworkResource networkResource = null;
1618 if (isNullOrEmpty(modelCustomizationUuid)) {
1619 networkResource = db.getNetworkResource (networkType);
1623 networkResource = db.getNetworkResourceByModelCustUuid(modelCustomizationUuid);
1626 if (networkResource != null) {
1628 LOGGER.debug ("Got Network definition from Catalog: " + networkResource.toString ());
1630 mode = networkResource.getOrchestrationMode ();
1633 if (rollback.getNetworkCreated ()) {
1634 // Rolling back a newly created network, so delete it.
1635 if (NEUTRON_MODE.equals (mode)) {
1636 // Use MsoNeutronUtils for all NEUTRON commands
1637 MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
1638 long deleteNetworkStarttime = System.currentTimeMillis ();
1640 // The deleteNetwork function in MsoNeutronUtils returns success if the network
1641 // was not found. So don't bother to query first.
1642 neutron.deleteNetwork (networkId, tenantId, cloudSiteId);
1643 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteNetwork", null);
1644 } catch (MsoException me) {
1645 me.addContext ("RollbackNetwork");
1646 String error = "Rollback Network (neutron): " + networkId
1653 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteNetwork", null);
1654 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - Rollback Network (neutron)", me);
1655 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1656 throw new NetworkException (me);
1658 } else { // DEFAULT to if ("HEAT".equals (mode))
1659 // Use MsoHeatUtils for all HEAT commands
1660 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_NETWORK_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
1661 long deleteStackStarttime = System.currentTimeMillis ();
1663 // The deleteStack function in MsoHeatUtils returns success if the stack
1664 // was not found. So don't bother to query first.
1665 heat.deleteStack (tenantId, cloudSiteId, networkId, true);
1666 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteStack", null);
1667 } catch (MsoException me) {
1668 me.addContext ("RollbackNetwork");
1669 String error = "Rollback Network (heat): " + networkId
1676 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteStack", null);
1677 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - Rollback Network (heat)", me);
1678 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1679 throw new NetworkException (me);
1686 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully rolled back network");
1690 private String validateNetworkParams (NetworkType neutronNetworkType,
1692 String physicalNetwork,
1693 List <Integer> vlans,
1694 List <String> routeTargets) {
1696 StringBuilder missing = new StringBuilder ();
1697 if (isNullOrEmpty(networkName)) {
1698 missing.append ("networkName");
1702 if (neutronNetworkType == NetworkType.PROVIDER || neutronNetworkType == NetworkType.MULTI_PROVIDER) {
1703 if (isNullOrEmpty(physicalNetwork)) {
1704 missing.append (sep).append ("physicalNetworkName");
1707 if (vlans == null || vlans.isEmpty ()) {
1708 missing.append (sep).append (VLANS);
1712 return missing.toString ();
1715 private Map <String, Object> populateNetworkParams (NetworkType neutronNetworkType,
1717 String physicalNetwork,
1718 List <Integer> vlans,
1719 List <String> routeTargets,
1722 boolean aic3template) {
1723 // Build the common set of HEAT template parameters
1724 Map <String, Object> stackParams = new HashMap <> ();
1725 stackParams.put ("network_name", networkName);
1727 if (neutronNetworkType == NetworkType.PROVIDER) {
1728 // For Provider type
1729 stackParams.put (PHYSICAL_NETWORK, physicalNetwork);
1730 stackParams.put ("vlan", vlans.get (0).toString ());
1731 } else if (neutronNetworkType == NetworkType.MULTI_PROVIDER) {
1732 // For Multi-provider, PO supports a custom resource extension of ProviderNet.
1733 // It supports all ProviderNet properties except segmentation_id, and adds a
1734 // comma-separated-list of VLANs as a "segments" property.
1735 // Note that this does not match the Neutron definition of Multi-Provider network,
1736 // which contains a list of 'segments', each having physical_network, network_type,
1737 // and segmentation_id.
1738 StringBuilder buf = new StringBuilder ();
1740 for (Integer vlan : vlans) {
1741 buf.append (sep).append (vlan.toString ());
1744 String csl = buf.toString ();
1746 stackParams.put (PHYSICAL_NETWORK, physicalNetwork);
1747 stackParams.put (VLANS, csl);
1749 if (routeTargets != null && !routeTargets.isEmpty()) {
1750 StringBuilder sb = new StringBuilder ();
1752 for (String rt : routeTargets) {
1753 if (!isNullOrEmpty(rt))
1756 sb.append(sep).append("target:").append(rt);
1758 sb.append (sep).append (rt);
1763 String csl = sb.toString ();
1765 stackParams.put ("route_targets", csl);
1767 if (isNullOrEmpty(shared)) {
1768 stackParams.put ("shared", "False");
1770 stackParams.put ("shared", shared);
1772 if (isNullOrEmpty(external)) {
1773 stackParams.put ("external", "False");
1775 stackParams.put ("external", external);
1782 /** policyRef_list structure in stackParams
1785 "network_policy_refs_data_sequence": {
1786 "network_policy_refs_data_sequence_major": "1",
1787 "network_policy_refs_data_sequence_minor": "0"
1791 "network_policy_refs_data_sequence": {
1792 "network_policy_refs_data_sequence_major": "2",
1793 "network_policy_refs_data_sequence_minor": "0"
1798 private void mergePolicyRefs(List <String> pFqdns, Map <String, Object> stackParams) throws MsoException {
1800 List<ContrailPolicyRef> prlist = new ArrayList <> ();
1802 for (String pf : pFqdns) {
1803 if (!isNullOrEmpty(pf))
1805 ContrailPolicyRef pr = new ContrailPolicyRef();
1806 pr.populate(String.valueOf(index), "0");
1808 LOGGER.debug("Contrail PolicyRefs Data:" + pr.toString());
1813 JsonNode node = null;
1816 ObjectMapper mapper = new ObjectMapper();
1817 node = mapper.convertValue(prlist, JsonNode.class);
1818 String jsonString = mapper.writeValueAsString(prlist);
1819 LOGGER.debug("Json PolicyRefs Data:" + jsonString);
1823 String error = "Error creating JsonNode for policyRefs Data";
1824 LOGGER.error (MessageEnum.RA_MARSHING_ERROR, error, "Openstack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception creating JsonNode for policyRefs Data", e);
1825 throw new MsoAdapterException (error);
1828 if (pFqdns != null && node != null)
1830 StringBuilder buf = new StringBuilder ();
1832 for (String pf : pFqdns) {
1833 if (!isNullOrEmpty(pf))
1835 buf.append (sep).append (pf);
1839 String csl = buf.toString ();
1840 stackParams.put ("policy_refs", csl);
1841 stackParams.put ("policy_refsdata", node);
1844 LOGGER.debug ("StackParams updated with policy refs");
1848 private void mergeRouteTableRefs(List <String> rtFqdns, Map <String, Object> stackParams) throws MsoException {
1851 if (rtFqdns != null)
1853 StringBuilder buf = new StringBuilder ();
1855 for (String rtf : rtFqdns) {
1856 if (!isNullOrEmpty(rtf))
1858 buf.append (sep).append (rtf);
1862 String csl = buf.toString ();
1863 stackParams.put ("route_table_refs", csl);
1866 LOGGER.debug ("StackParams updated with route_table refs");
1871 /*** Subnet Output structure from Juniper
1876 "ip_prefix": "10.100.1.0",
1879 "addr_from_start": null,
1880 "enable_dhcp": false,
1881 "default_gateway": "10.100.1.1",
1882 "dns_nameservers": [],
1883 "dhcp_option_list": null,
1884 "subnet_uuid": "10391fbf-6b9c-4160-825d-2d018b7649cf",
1885 "allocation_pools": [
1887 "start": "10.100.1.3",
1891 "start": "10.100.1.6",
1895 "host_routes": null,
1896 "dns_server_address": "10.100.1.13",
1897 "subnet_name": "subnet_MsoNW1_692c9032-e1a2-4d64-828c-7b9a4fcc05b0"
1901 "ip_prefix": "10.100.2.16",
1904 "addr_from_start": null,
1905 "enable_dhcp": true,
1906 "default_gateway": "10.100.2.17",
1907 "dns_nameservers": [],
1908 "dhcp_option_list": null,
1909 "subnet_uuid": "c7aac5ea-66fe-443a-85f9-9c38a608c0f6",
1910 "allocation_pools": [
1912 "start": "10.100.2.18",
1913 "end": "10.100.2.20"
1916 "host_routes": null,
1917 "dns_server_address": "10.100.2.29",
1918 "subnet_name": "subnet_MsoNW1_692c9032-e1a2-4d64-828c-7b9a4fcc05b1"
1924 private String mergeSubnetsAIC3 (String heatTemplate, List <Subnet> subnets, Map <String, Object> stackParams) throws MsoException {
1927 List<ContrailSubnet> cslist = new ArrayList <> ();
1928 for (Subnet subnet : subnets) {
1929 ContrailSubnet cs = new ContrailSubnet();
1930 LOGGER.debug("Input Subnet:" + subnet.toString());
1931 cs.populateWith(subnet);
1932 LOGGER.debug("Contrail Subnet:" + cs.toString());
1936 JsonNode node = null;
1939 ObjectMapper mapper = new ObjectMapper();
1940 node = mapper.convertValue(cslist, JsonNode.class);
1941 String jsonString = mapper.writeValueAsString(cslist);
1942 LOGGER.debug("Json Subnet List:" + jsonString);
1946 String error = "Error creating JsonNode from input subnets";
1947 LOGGER.error (MessageEnum.RA_MARSHING_ERROR, error, "", "", MsoLogger.ErrorCode.DataError, "Exception creating JsonNode from input subnets", e);
1948 throw new MsoAdapterException (error);
1953 stackParams.put ("subnet_list", node);
1955 //Outputs - All subnets are in one ipam_subnets structure
1956 String outputTempl = " subnet:\n" + " description: Openstack subnet identifier\n"
1957 + " value: { get_attr: [network, network_ipam_refs, 0, attr]}\n";
1959 // append outputs in heatTemplate
1960 int outputsIdx = heatTemplate.indexOf ("outputs:");
1961 heatTemplate = insertStr (heatTemplate, outputTempl, outputsIdx + 8);
1962 LOGGER.debug ("Template updated with all AIC3.0 subnets:" + heatTemplate);
1963 return heatTemplate;
1967 private String mergeSubnets (String heatTemplate, List <Subnet> subnets) throws MsoException {
1969 String resourceTempl = " subnet_%subnetId%:\n" + " type: OS::Neutron::Subnet\n"
1972 + " network_id: { get_resource: network }\n"
1973 + " cidr: %cidr%\n";
1975 /* make these optional
1976 + " ip_version: %ipversion%\n"
1977 + " enable_dhcp: %enabledhcp%\n"
1978 + " gateway_ip: %gatewayip%\n"
1979 + " allocation_pools:\n"
1980 + " - start: %poolstart%\n"
1981 + " end: %poolend%\n";
1985 String outputTempl = " subnet_id_%subnetId%:\n" + " description: Openstack subnet identifier\n"
1986 + " value: {get_resource: subnet_%subnetId%}\n";
1990 StringBuilder resourcesBuf = new StringBuilder ();
1991 StringBuilder outputsBuf = new StringBuilder ();
1992 for (Subnet subnet : subnets) {
1994 // build template for each subnet
1995 curR = new StringBuilder(resourceTempl);
1996 if (subnet.getSubnetId () != null) {
1997 curR = new StringBuilder(curR.toString().replace("%subnetId%", subnet.getSubnetId()));
1999 String error = "Missing Required AAI SubnetId for subnet in HEAT Template";
2000 LOGGER.error (MessageEnum.RA_MISSING_PARAM, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing Required AAI ID for subnet in HEAT Template");
2001 throw new MsoAdapterException (error);
2004 if (subnet.getSubnetName () != null) {
2005 curR = new StringBuilder(curR.toString().replace("%name%", subnet.getSubnetName()));
2007 curR = new StringBuilder(curR.toString().replace("%name%", subnet.getSubnetId()));
2010 if (subnet.getCidr () != null) {
2011 curR = new StringBuilder(curR.toString().replace("%cidr%", subnet.getCidr()));
2013 String error = "Missing Required cidr for subnet in HEAT Template";
2014 LOGGER.error (MessageEnum.RA_MISSING_PARAM, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing Required cidr for subnet in HEAT Template");
2015 throw new MsoAdapterException (error);
2018 if (subnet.getIpVersion () != null) {
2019 curR.append(" ip_version: " + subnet.getIpVersion() + "\n");
2021 if (subnet.getEnableDHCP () != null) {
2022 curR.append(" enable_dhcp: ").append(Boolean.toString(subnet.getEnableDHCP())).append("\n");
2024 if (subnet.getGatewayIp () != null && !subnet.getGatewayIp ().isEmpty() ) {
2025 curR.append(" gateway_ip: " + subnet.getGatewayIp() + "\n");
2028 if (subnet.getAllocationPools() != null) {
2029 curR.append(" allocation_pools:\n");
2030 for (Pool pool : subnet.getAllocationPools())
2032 if (!isNullOrEmpty(pool.getStart()) && !isNullOrEmpty(pool.getEnd()))
2034 curR.append(" - start: " + pool.getStart() + "\n");
2035 curR.append(" end: " + pool.getEnd() + "\n");
2040 resourcesBuf.append (curR);
2043 curO = curO.replace ("%subnetId%", subnet.getSubnetId ());
2045 outputsBuf.append (curO);
2048 // append resources and outputs in heatTemplate
2049 LOGGER.debug ("Tempate initial:" + heatTemplate);
2050 int outputsIdx = heatTemplate.indexOf ("outputs:");
2051 heatTemplate = insertStr (heatTemplate, outputsBuf.toString (), outputsIdx + 8);
2052 int resourcesIdx = heatTemplate.indexOf ("resources:");
2053 heatTemplate = insertStr (heatTemplate, resourcesBuf.toString (), resourcesIdx + 10);
2055 LOGGER.debug ("Template updated with all subnets:" + heatTemplate);
2056 return heatTemplate;
2059 private Map <String, String> getSubnetUUId(String key, Map <String, Object> outputs, List <Subnet> subnets) {
2061 Map <String, String> sMap = new HashMap <> ();
2064 Object obj = outputs.get(key);
2065 ObjectMapper mapper = new ObjectMapper();
2066 String jStr = mapper.writeValueAsString(obj);
2067 LOGGER.debug ("Subnet_Ipam Output JSON String:" + obj.getClass() + " " + jStr);
2069 JsonNode rootNode = mapper.readTree(jStr);
2070 for (JsonNode sNode : rootNode.path("ipam_subnets"))
2072 LOGGER.debug("Output Subnet Node" + sNode.toString());
2073 String name = sNode.path("subnet_name").getTextValue();
2074 String uuid = sNode.path("subnet_uuid").getTextValue();
2075 String aaiId = name; // default
2076 // try to find aaiId for name in input subnetList
2077 if (subnets != null)
2079 for (Subnet subnet : subnets)
2081 if ( subnet != null && !isNullOrEmpty(subnet.getSubnetName()))
2083 if (subnet.getSubnetName().equals(name))
2085 aaiId = subnet.getSubnetId();
2091 sMap.put(aaiId, uuid); //bpmn needs aaid to uuid map
2096 LOGGER.error (MessageEnum.RA_MARSHING_ERROR, "error getting subnet-uuids", "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception getting subnet-uuids", e);
2099 LOGGER.debug ("Return sMap" + sMap.toString());
2103 private static String insertStr (String template, String snippet, int index) {
2105 String updatedTemplate;
2107 LOGGER.debug ("Index:" + index + " Snippet:" + snippet);
2109 String templateBeg = template.substring (0, index);
2110 String templateEnd = template.substring (index);
2112 updatedTemplate = templateBeg + "\n" + snippet + templateEnd;
2114 LOGGER.debug ("Template updated with a subnet:" + updatedTemplate);
2115 return updatedTemplate;