2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.mso.adapters.network;
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.List;
28 import javax.jws.WebParam;
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.MsoCommonUtils;
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 <String> ();
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 CloudSite cloudSite = cloudConfig.getCloudSite (cloudSiteId);
276 if (cloudSite == null)
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 String error = "Create Network (neutron): query network " + networkName
327 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception while querying network from OpenStack", me);
328 me.addContext (CREATE_NETWORK_CONTEXT);
329 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while querying network from OpenStack");
330 throw new NetworkException (me);
333 if (netInfo != null) {
334 // Exists. If that's OK, return success with the network ID.
335 // Otherwise, return an exception.
336 if (failIfExists != null && failIfExists) {
337 String error = "Create Nework: Network " + networkName
338 + " already exists in "
342 + " with ID " + netInfo.getId();
343 LOGGER.error (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Network already exists");
344 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
345 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
347 // Populate the outputs from the existing network.
348 networkId.value = netInfo.getId ();
349 neutronNetworkId.value = netInfo.getId ();
350 rollback.value = networkRollback; // Default rollback - no updates performed
351 String msg = "Found Existing network, status=" + netInfo.getStatus () + " for Neutron mode";
352 LOGGER.warn (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "", "", MsoLogger.ErrorCode.DataError, "Found Existing network, status=" + netInfo.getStatus ());
353 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, msg);
358 long createNetworkStarttime = System.currentTimeMillis ();
360 netInfo = neutron.createNetwork (cloudSiteId,
366 LOGGER.recordMetricEvent (createNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Response successfully received from OpenStack", "OpenStack", "CreateNetwork", null);
367 } catch (MsoException me) {
368 me.addContext (CREATE_NETWORK_CONTEXT);
369 LOGGER.recordMetricEvent (createNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while communicate with OpenStack", "OpenStack", "CreateNetwork", null);
370 String error = "Create Network: type " + neutronNetworkType
377 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception while communicate with OpenStack", me);
378 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
380 throw new NetworkException (me);
383 // Note: ignoring MsoNetworkAlreadyExists because we already checked.
385 // If reach this point, network creation is successful.
386 // Since directly created via Neutron, networkId tracked by MSO is the same
387 // as the neutron network ID.
388 networkId.value = netInfo.getId ();
389 neutronNetworkId.value = netInfo.getId ();
391 networkRollback.setNetworkCreated (true);
392 networkRollback.setNetworkId (netInfo.getId ());
393 networkRollback.setNeutronNetworkId (netInfo.getId ());
394 networkRollback.setNetworkType (networkType);
396 LOGGER.debug ("Network " + networkName + " created, id = " + netInfo.getId ());
397 } else if ("HEAT".equals (mode)) {
399 // Use an MsoHeatUtils for all Heat commands
400 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_NETWORK_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
402 HeatTemplate heatTemplate = db.getHeatTemplate (networkResource.getTemplateId ());
403 if (heatTemplate == null) {
404 String error = "Network error - undefined Heat Template. Network Type = " + networkType;
405 LOGGER.error (MessageEnum.RA_PARAM_NOT_FOUND, "Heat Template", "Network Type", networkType, "Openstack", "", MsoLogger.ErrorCode.DataError, "Network error - undefined Heat Template. Network Type = " + networkType);
406 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error); // Alarm on this
410 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
411 throw new NetworkException (error, MsoExceptionCategory.INTERNAL);
414 LOGGER.debug ("Got HEAT Template from DB: " + heatTemplate.toString ());
416 // "Fix" the template if it has CR/LF (getting this from Oracle)
417 String template = heatTemplate.getHeatTemplate ();
418 template = template.replaceAll ("\r\n", "\n");
420 boolean aic3template=false;
421 String aic3nw = AIC3_NW;
423 aic3nw = msoPropertiesFactory.getMsoJavaProperties(MSO_PROP_NETWORK_ADAPTER).getProperty(AIC3_NW_PROPERTY, AIC3_NW);
424 } catch (MsoPropertiesException e) {
425 String error = "Unable to get properties:" + MSO_PROP_NETWORK_ADAPTER;
426 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "", "", MsoLogger.ErrorCode.DataError, "Exception - Unable to get properties", e);
429 if (template.contains(aic3nw))
432 // First, look up to see if the Network already exists (by name).
433 // For HEAT orchestration of networks, the stack name will always match the network name
434 StackInfo heatStack = null;
435 long queryNetworkStarttime = System.currentTimeMillis ();
437 heatStack = heat.queryStack (cloudSiteId, tenantId, networkName);
438 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Response successfully received from OpenStack", "OpenStack", "QueryNetwork", null);
439 } catch (MsoException me) {
440 me.addContext (CREATE_NETWORK_CONTEXT);
441 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while querying stack from OpenStack", "OpenStack", "QueryNetwork", null);
442 String error = "Create Network (heat): query network " + networkName
449 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception while querying stack from OpenStack", me);
450 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
451 throw new NetworkException (me);
454 if (heatStack != null && !(heatStack.getStatus () == HeatStatus.NOTFOUND)) {
455 // Stack exists. Return success or error depending on input directive
456 if (failIfExists != null && failIfExists) {
457 String error = "CreateNetwork: Stack " + networkName
458 + " already exists in "
462 + " as " + heatStack.getCanonicalName();
463 LOGGER.error (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "", "", MsoLogger.ErrorCode.DataError, "Network already exists");
464 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
465 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
467 // Populate the outputs from the existing stack.
468 networkId.value = heatStack.getCanonicalName ();
469 neutronNetworkId.value = (String) heatStack.getOutputs ().get (NETWORK_ID);
470 rollback.value = networkRollback; // Default rollback - no updates performed
473 networkFqdn.value = (String) heatStack.getOutputs().get(NETWORK_FQDN);
475 Map <String, Object> outputs = heatStack.getOutputs ();
476 Map <String, String> sMap = new HashMap <String, String> ();
477 if (outputs != null) {
478 for (String key : outputs.keySet ()) {
479 if (key != null && key.startsWith ("subnet")) {
480 if (aic3template) //one subnet_id output
482 Map <String, String> map = getSubnetUUId(key, outputs, subnets);
485 else //multiples subnet_%aaid% outputs
487 String subnetUUId = (String) outputs.get(key);
488 sMap.put (key.substring("subnet_id_".length()), subnetUUId);
493 subnetIdMap.value = sMap;
494 String msg = "Found Existing network stack, status=" + heatStack.getStatus () + " for Heat mode";
495 LOGGER.warn (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "", "", MsoLogger.ErrorCode.DataError, "Found Existing network stack, status=" + heatStack.getStatus ());
496 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Suc, "Found Existing network stack");
501 // Ready to deploy the new Network
502 // Build the common set of HEAT template parameters
503 Map <String, Object> stackParams = populateNetworkParams (neutronNetworkType,
512 // Validate (and update) the input parameters against the DB definition
513 // Shouldn't happen unless DB config is wrong, since all networks use same inputs
514 // and inputs were already validated.
516 stackParams = heat.validateStackParams (stackParams, heatTemplate);
517 } catch (IllegalArgumentException e) {
518 String error = "Create Network: Configuration Error: " + e.getMessage ();
519 LOGGER.error (MessageEnum.RA_CONFIG_EXC, e.getMessage(), "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception - Create Network, Configuration Error", e);
520 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error); // Alarm on this
524 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
525 // Input parameters were not valid
526 throw new NetworkException (error, MsoExceptionCategory.INTERNAL);
529 if (subnets != null) {
533 template = mergeSubnetsAIC3 (template, subnets, stackParams);
537 template = mergeSubnets (template, subnets);
539 } catch (MsoException me) {
540 me.addContext (CREATE_NETWORK_CONTEXT);
541 String error = "Create Network (heat): type " + neutronNetworkType
548 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception Create Network, merging subnets", me);
549 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
550 throw new NetworkException (me);
554 if (policyFqdns != null && !policyFqdns.isEmpty() && aic3template) {
556 mergePolicyRefs (policyFqdns, stackParams);
557 } catch (MsoException me) {
558 me.addContext (CREATE_NETWORK_CONTEXT);
559 String error = "Create Network (heat) mergePolicyRefs type " + neutronNetworkType
566 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception Create Network, merging policyRefs", me);
567 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
568 throw new NetworkException (me);
572 if (routeTableFqdns != null && !routeTableFqdns.isEmpty() && aic3template) {
574 mergeRouteTableRefs (routeTableFqdns, stackParams);
575 } catch (MsoException me) {
576 me.addContext (CREATE_NETWORK_CONTEXT);
577 String error = "Create Network (heat) mergeRouteTableRefs type " + neutronNetworkType
584 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception Create Network, merging routeTableRefs", me);
585 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
586 throw new NetworkException (me);
590 // Deploy the network stack
591 // Ignore MsoStackAlreadyExists exception because we already checked.
592 long createStackStartTime = System.currentTimeMillis ();
596 heatStack = heat.createStack (cloudSiteId,
602 heatTemplate.getTimeoutMinutes (),
606 backout.booleanValue());
607 } catch (MsoException me) {
608 me.addContext (CREATE_NETWORK_CONTEXT);
609 String error = "Create Network (heat): type " + neutronNetworkType
616 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, networkName, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception creating network", me);
617 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
618 throw new NetworkException (me);
621 // Reach this point if createStack is successful.
623 // For Heat-based orchestration, the MSO-tracked network ID is the heat stack,
624 // and the neutronNetworkId is the network UUID returned in stack outputs.
625 networkId.value = heatStack.getCanonicalName ();
626 neutronNetworkId.value = (String) heatStack.getOutputs ().get (NETWORK_ID);
629 networkFqdn.value = (String) heatStack.getOutputs().get(NETWORK_FQDN);
631 Map <String, Object> outputs = heatStack.getOutputs ();
632 Map <String, String> sMap = new HashMap <String, String> ();
633 if (outputs != null) {
634 for (String key : outputs.keySet ()) {
635 if (key != null && key.startsWith ("subnet")) {
636 if (aic3template) //one subnet output expected
638 Map <String, String> map = getSubnetUUId(key, outputs, subnets);
641 else //multiples subnet_%aaid% outputs allowed
643 String subnetUUId = (String) outputs.get(key);
644 sMap.put (key.substring("subnet_id_".length()), subnetUUId);
649 subnetIdMap.value = sMap;
651 rollback.value = networkRollback;
652 // Populate remaining rollback info and response parameters.
653 networkRollback.setNetworkStackId (heatStack.getCanonicalName ());
654 networkRollback.setNeutronNetworkId ((String) heatStack.getOutputs ().get (NETWORK_ID));
655 networkRollback.setNetworkCreated (true);
656 networkRollback.setNetworkType (networkType);
658 LOGGER.debug ("Network " + networkName + " successfully created via HEAT");
663 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Suc, "Successfully created network");
668 public void updateNetwork (String cloudSiteId,
671 String modelCustomizationUuid,
674 String physicalNetworkName,
675 List <Integer> vlans,
676 List <Subnet> subnets,
677 MsoRequest msoRequest,
678 Holder <Map <String, String>> subnetIdMap,
679 Holder <NetworkRollback> rollback) throws NetworkException {
680 updateNetwork (cloudSiteId,
683 modelCustomizationUuid,
701 public void updateNetworkContrail (String cloudSiteId,
704 String modelCustomizationUuid,
707 List <String> routeTargets,
710 List <Subnet> subnets,
711 List <String> policyFqdns,
712 List<String> routeTableFqdns,
713 MsoRequest msoRequest,
714 Holder <Map <String, String>> subnetIdMap,
715 Holder <NetworkRollback> rollback) throws NetworkException {
716 updateNetwork (cloudSiteId,
719 modelCustomizationUuid,
736 * This is the "Update Network" web service implementation.
737 * It will update an existing Network of the requested type in the specified cloud
738 * and tenant. The typical use will be to replace the VLANs with the supplied
739 * list (to add or remove a VLAN), but other properties may be updated as well.
741 * There will be a pre-defined set of network types defined in the MSO Catalog.
742 * All such networks will have a similar configuration, based on the allowable
743 * Openstack networking definitions. This includes basic networks, provider
744 * networks (with a single VLAN), and multi-provider networks (one or more VLANs).
746 * Initially, all provider networks must currently be "vlan" type, and multi-provider
747 * networks must be multiple VLANs on the same physical network.
749 * This service supports two modes of Network update:
750 * - via Heat Templates
752 * The network orchestration mode for each network type is declared in its
753 * catalog definition. All Heat-based templates must support some subset of
754 * the same input parameters: network_name, physical_network, vlan, segments.
756 * The method returns a NetworkRollback object. This object can be passed
757 * as-is to the rollbackNetwork operation to undo everything that was updated.
758 * This is useful if a network is successfully updated but orchestration
759 * fails on a subsequent operation.
761 private void updateNetwork (String cloudSiteId,
764 String modelCustomizationUuid,
767 String physicalNetworkName,
768 List <Integer> vlans,
769 List <String> routeTargets,
772 List <Subnet> subnets,
773 List <String> policyFqdns,
774 List<String> routeTableFqdns,
775 MsoRequest msoRequest,
776 Holder <Map <String, String>> subnetIdMap,
777 Holder <NetworkRollback> rollback) throws NetworkException {
778 MsoLogger.setLogContext (msoRequest);
779 MsoLogger.setServiceName ("UpdateNetwork");
780 LOGGER.debug ("***UPDATE Network adapter with Network: " + networkName
789 // Will capture execution time for metrics
790 long startTime = System.currentTimeMillis ();
792 // Build a default rollback object (no actions performed)
793 NetworkRollback networkRollback = new NetworkRollback ();
794 networkRollback.setCloudId (cloudSiteId);
795 networkRollback.setTenantId (tenantId);
796 networkRollback.setMsoRequest (msoRequest);
798 cloudConfig = cloudConfigFactory.getCloudConfig ();
799 CloudSite cloudSite = cloudConfig.getCloudSite (cloudSiteId);
800 if (cloudSite == null) {
801 String error = "UpdateNetwork: Configuration Error. Stack " + networkName + " in "
806 + " CloudSite does not exist in MSO Configuration";
807 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "CloudSite does not exist in MSO Configuration");
808 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
809 // Set the detailed error as the Exception 'message'
810 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
813 // Get a handle to the Catalog Database
814 CatalogDatabase db = getCatalogDB ();
816 // Make sure DB connection is always closed
818 NetworkResource networkResource = networkCheck(db,
821 modelCustomizationUuid,
827 String mode = networkResource.getOrchestrationMode();
828 NetworkType neutronNetworkType = NetworkType.valueOf(networkResource.getNeutronNetworkType());
830 // Use an MsoNeutronUtils for all Neutron commands
831 MsoNeutronUtils neutron = new MsoNeutronUtils(MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
833 if (NEUTRON_MODE.equals(mode)) {
835 // Verify that the Network exists
836 // For Neutron-based orchestration, the networkId is the Neutron Network UUID.
837 NetworkInfo netInfo = null;
838 long queryNetworkStarttime = System.currentTimeMillis();
840 netInfo = neutron.queryNetwork(networkId, tenantId, cloudSiteId);
841 LOGGER.recordMetricEvent(queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryNetwork", null);
842 } catch (MsoException me) {
843 me.addContext(UPDATE_NETWORK_CONTEXT);
844 String error = "Update Network (neutron): query " + networkId
851 LOGGER.recordMetricEvent(queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryNetwork", null);
852 LOGGER.error(MessageEnum.RA_QUERY_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "QueryNetwork", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - queryNetwork", me);
853 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
854 throw new NetworkException(me);
857 if (netInfo == null) {
858 String error = "Update Nework: Network " + networkId
859 + " does not exist in "
863 LOGGER.error(MessageEnum.RA_NETWORK_NOT_FOUND, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Network not found");
864 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
865 // Does not exist. Throw an exception (can't update a non-existent network)
866 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
868 long updateNetworkStarttime = System.currentTimeMillis();
870 netInfo = neutron.updateNetwork(cloudSiteId,
876 LOGGER.recordMetricEvent(updateNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "UpdateNetwork", null);
877 } catch (MsoException me) {
878 me.addContext(UPDATE_NETWORK_CONTEXT);
879 String error = "Update Network (neutron): " + networkId
886 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, networkId, cloudSiteId, tenantId, "Openstack", "updateNetwork", MsoLogger.ErrorCode.DataError, "Exception - updateNetwork", me);
887 LOGGER.recordMetricEvent(updateNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "UpdateNetwork", null);
888 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
889 throw new NetworkException(me);
892 // Add the network ID and previously queried vlans to the rollback object
893 networkRollback.setNetworkId(netInfo.getId());
894 networkRollback.setNeutronNetworkId(netInfo.getId());
895 networkRollback.setNetworkType(networkType);
896 // Save previous parameters
897 networkRollback.setNetworkName(netInfo.getName());
898 networkRollback.setPhysicalNetwork(netInfo.getProvider());
899 networkRollback.setVlans(netInfo.getVlans());
901 LOGGER.debug("Network " + networkId + " updated, id = " + netInfo.getId());
902 } else if ("HEAT".equals(mode)) {
904 // Use an MsoHeatUtils for all Heat commands
905 MsoHeatUtilsWithUpdate heat = new MsoHeatUtilsWithUpdate(MSO_PROP_NETWORK_ADAPTER, msoPropertiesFactory, cloudConfigFactory);
907 // First, look up to see that the Network already exists.
908 // For Heat-based orchestration, the networkId is the network Stack ID.
909 StackInfo heatStack = null;
910 long queryStackStarttime = System.currentTimeMillis();
912 heatStack = heat.queryStack(cloudSiteId, tenantId, networkName);
913 LOGGER.recordMetricEvent(queryStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", null);
914 } catch (MsoException me) {
915 me.addContext(UPDATE_NETWORK_CONTEXT);
916 String error = "UpdateNetwork (heat): query " + networkName
923 LOGGER.recordMetricEvent(queryStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryStack", null);
924 LOGGER.error(MessageEnum.RA_QUERY_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Exception - QueryStack", me);
925 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
926 throw new NetworkException(me);
929 if (heatStack == null || (heatStack.getStatus() == HeatStatus.NOTFOUND)) {
930 String error = "UpdateNetwork: Stack " + networkName
931 + " does not exist in "
935 LOGGER.error(MessageEnum.RA_NETWORK_NOT_FOUND, networkId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Network not found");
936 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
937 // Network stack does not exist. Return an error
938 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
941 // Get the previous parameters for rollback
942 Map<String, Object> heatParams = heatStack.getParameters();
944 String previousNetworkName = (String) heatParams.get("network_name");
945 String previousPhysicalNetwork = (String) heatParams.get(PHYSICAL_NETWORK);
947 List<Integer> previousVlans = new ArrayList<Integer>();
948 String vlansParam = (String) heatParams.get(VLANS);
949 if (vlansParam != null) {
950 for (String vlan : vlansParam.split(",")) {
952 previousVlans.add(Integer.parseInt(vlan));
953 } catch (NumberFormatException e) {
954 LOGGER.warn(MessageEnum.RA_VLAN_PARSE, networkId, vlansParam, "", "", MsoLogger.ErrorCode.DataError, "Exception - VLAN parse", e);
958 LOGGER.debug("Update Stack: Previous VLANS: " + previousVlans);
960 // Ready to deploy the updated Network via Heat
962 HeatTemplate heatTemplate = db.getHeatTemplate(networkResource.getTemplateId());
963 if (heatTemplate == null) {
964 String error = "Network error - undefined Heat Template. Network Type=" + networkType;
965 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);
966 alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
967 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
968 throw new NetworkException(error, MsoExceptionCategory.INTERNAL);
971 LOGGER.debug("Got HEAT Template from DB: " + heatTemplate.toString());
973 // "Fix" the template if it has CR/LF (getting this from Oracle)
974 String template = heatTemplate.getHeatTemplate();
975 template = template.replaceAll("\r\n", "\n");
977 boolean aic3template = false;
978 String aic3nw = AIC3_NW;
980 aic3nw = msoPropertiesFactory.getMsoJavaProperties(MSO_PROP_NETWORK_ADAPTER).getProperty(AIC3_NW_PROPERTY, AIC3_NW);
981 } catch (MsoPropertiesException e) {
982 String error = "Unable to get properties:" + MSO_PROP_NETWORK_ADAPTER;
983 LOGGER.error(MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - Unable to get properties", e);
985 if (template.contains(aic3nw))
988 // Build the common set of HEAT template parameters
989 Map<String, Object> stackParams = populateNetworkParams(neutronNetworkType,
998 // Validate (and update) the input parameters against the DB definition
999 // Shouldn't happen unless DB config is wrong, since all networks use same inputs
1001 stackParams = heat.validateStackParams(stackParams, heatTemplate);
1002 } catch (IllegalArgumentException e) {
1003 String error = "UpdateNetwork: Configuration Error: Network Type=" + networkType;
1004 LOGGER.error(MessageEnum.RA_CONFIG_EXC, "Network Type=" + networkType, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork: Configuration Error");
1005 alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
1006 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.SchemaError, error);
1007 throw new NetworkException(error, MsoExceptionCategory.INTERNAL, e);
1010 if (subnets != null) {
1013 template = mergeSubnetsAIC3(template, subnets, stackParams);
1015 template = mergeSubnets(template, subnets);
1017 } catch (MsoException me) {
1018 me.addContext(UPDATE_NETWORK_CONTEXT);
1019 String error = "Update Network (heat): type " + neutronNetworkType
1026 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergeSubnets ", me);
1027 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
1028 throw new NetworkException(me);
1032 if (policyFqdns != null && aic3template) {
1034 mergePolicyRefs(policyFqdns, stackParams);
1035 } catch (MsoException me) {
1036 me.addContext(UPDATE_NETWORK_CONTEXT);
1037 String error = "UpdateNetwork (heat) mergePolicyRefs type " + neutronNetworkType
1044 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergePolicyRefs", me);
1045 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
1046 throw new NetworkException(me);
1050 if (routeTableFqdns != null && !routeTableFqdns.isEmpty() && aic3template) {
1052 mergeRouteTableRefs(routeTableFqdns, stackParams);
1053 } catch (MsoException me) {
1054 me.addContext(UPDATE_NETWORK_CONTEXT);
1055 String error = "UpdateNetwork (heat) mergeRouteTableRefs type " + neutronNetworkType
1062 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergeRouteTableRefs", me);
1063 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
1064 throw new NetworkException(me);
1068 // Update the network stack
1069 // Ignore MsoStackNotFound exception because we already checked.
1070 long updateStackStarttime = System.currentTimeMillis();
1072 heatStack = heat.updateStack(cloudSiteId,
1078 heatTemplate.getTimeoutMinutes());
1079 LOGGER.recordMetricEvent(updateStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "UpdateStack", null);
1080 } catch (MsoException me) {
1081 me.addContext(UPDATE_NETWORK_CONTEXT);
1082 String error = "Update Network: " + networkId + " in " + cloudSiteId + "/" + tenantId + ": " + me;
1083 LOGGER.recordMetricEvent(updateStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "UpdateStack", null);
1084 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - update network", me);
1085 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1086 throw new NetworkException(me);
1089 Map<String, Object> outputs = heatStack.getOutputs();
1090 Map<String, String> sMap = new HashMap<String, String>();
1091 if (outputs != null) {
1092 for (String key : outputs.keySet()) {
1093 if (key != null && key.startsWith("subnet")) {
1094 if (aic3template) //one subnet output expected
1096 Map<String, String> map = getSubnetUUId(key, outputs, subnets);
1098 } else //multiples subnet_%aaid% outputs allowed
1100 String subnetUUId = (String) outputs.get(key);
1101 sMap.put(key.substring("subnet_id_".length()), subnetUUId);
1106 subnetIdMap.value = sMap;
1108 // Reach this point if createStack is successful.
1109 // Populate remaining rollback info and response parameters.
1110 networkRollback.setNetworkStackId(heatStack.getCanonicalName());
1111 networkRollback.setNeutronNetworkId((String) outputs.get(NETWORK_ID));
1112 networkRollback.setNetworkType(networkType);
1113 // Save previous parameters
1114 networkRollback.setNetworkName(previousNetworkName);
1115 networkRollback.setPhysicalNetwork(previousPhysicalNetwork);
1116 networkRollback.setVlans(previousVlans);
1118 rollback.value = networkRollback;
1120 LOGGER.debug("Network " + networkId + " successfully updated via HEAT");
1125 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully updated network");
1129 private NetworkResource networkCheck (CatalogDatabase db,
1132 String modelCustomizationUuid,
1134 String physicalNetworkName,
1135 List <Integer> vlans,
1136 List <String> routeTargets,
1137 CloudSite cloudSite) throws NetworkException {
1138 // Retrieve the Network Resource definition
1139 NetworkResource networkResource = null;
1140 if (isNullOrEmpty(modelCustomizationUuid)) {
1141 networkResource = db.getNetworkResource (networkType);
1145 networkResource = db.getNetworkResourceByModelCustUuid(modelCustomizationUuid);
1147 if (networkResource == null) {
1148 String error = "Create/UpdateNetwork: Unable to get network resource with NetworkType:" + networkType + " or ModelCustomizationUUID:" + modelCustomizationUuid ;
1149 LOGGER.error (MessageEnum.RA_UNKOWN_PARAM, "NetworkType/ModelCustomizationUUID", networkType + "/" + modelCustomizationUuid, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Create/UpdateNetwork: Unknown NetworkType/ModelCustomizationUUID");
1151 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1153 LOGGER.debug ("Got Network definition from Catalog: " + networkResource.toString ());
1155 String mode = networkResource.getOrchestrationMode ();
1156 NetworkType neutronNetworkType = NetworkType.valueOf (networkResource.getNeutronNetworkType ());
1158 // All Networks are orchestrated via HEAT or Neutron
1159 if (!("HEAT".equals (mode) || NEUTRON_MODE.equals (mode))) {
1160 String error = "CreateNetwork: Configuration Error: Network Type = " + networkType;
1161 LOGGER.error (MessageEnum.RA_NETWORK_ORCHE_MODE_NOT_SUPPORT, mode, "OpenStack", "", MsoLogger.ErrorCode.DataError, "CreateNetwork: Configuration Error");
1162 // Alarm on this error, configuration must be fixed
1163 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
1165 throw new NetworkException (error, MsoExceptionCategory.INTERNAL);
1168 MavenLikeVersioning aicV = new MavenLikeVersioning();
1169 aicV.setVersion(cloudSite.getAic_version());
1171 if ((aicV.isMoreRecentThan(networkResource.getAicVersionMin()) || aicV.isTheSameVersion(networkResource.getAicVersionMin())) // aic >= min
1172 && (aicV.isTheSameVersion(networkResource.getAicVersionMax()) || !(aicV.isMoreRecentThan(networkResource.getAicVersionMax())))) //aic <= max
1174 LOGGER.debug("Network Type:" + networkType
1175 + " VersionMin:" + networkResource.getAicVersionMin()
1176 + " VersionMax:" + networkResource.getAicVersionMax()
1177 + " supported on Cloud:" + cloudSite.getId()
1178 + " with AIC_Version:" + cloudSite.getAic_version());
1180 String error = "Network Type:" + networkType
1181 + " Version_Min:" + networkResource.getAicVersionMin()
1182 + " Version_Max:" + networkResource.getAicVersionMax()
1183 + " not supported on Cloud:" + cloudSite.getId()
1184 + " with AIC_Version:" + cloudSite.getAic_version();
1185 LOGGER.error(MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Network Type not supported on Cloud");
1186 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
1187 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
1189 } catch (Exception e) {
1190 String error = "Exception during Network version check";
1191 LOGGER.error (MessageEnum.RA_GENERAL_EXCEPTION_ARG, e.getMessage(), "", "", MsoLogger.ErrorCode.DataError, error);
1193 throw new NetworkException (error, MsoExceptionCategory.INTERNAL);
1197 // Validate the Network parameters.
1198 String missing = validateNetworkParams (neutronNetworkType,
1200 physicalNetworkName,
1203 if (!missing.isEmpty ()) {
1204 String error = "Create Network: Missing parameters: " + missing;
1205 LOGGER.error (MessageEnum.RA_MISSING_PARAM, missing, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Create Network: Missing parameters");
1207 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1209 return networkResource;
1213 public void queryNetwork (String cloudSiteId,
1215 String networkNameOrId,
1216 MsoRequest msoRequest,
1217 Holder <Boolean> networkExists,
1218 Holder <String> networkId,
1219 Holder <String> neutronNetworkId,
1220 Holder <NetworkStatus> status,
1221 Holder <List <Integer>> vlans,
1222 Holder <Map <String, String>> subnetIdMap) throws NetworkException {
1223 queryNetwork (cloudSiteId,
1237 public void queryNetworkContrail (String cloudSiteId,
1239 String networkNameOrId,
1240 MsoRequest msoRequest,
1241 Holder <Boolean> networkExists,
1242 Holder <String> networkId,
1243 Holder <String> neutronNetworkId,
1244 Holder <NetworkStatus> status,
1245 Holder <List <String>> routeTargets,
1246 Holder <Map <String, String>> subnetIdMap) throws NetworkException {
1247 queryNetwork (cloudSiteId,
1261 * This is the queryNetwork method. It returns the existence and status of
1262 * the specified network, along with its Neutron UUID and list of VLANs.
1263 * This method attempts to find the network using both Heat and Neutron.
1264 * Heat stacks are first searched based on the provided network name/id.
1265 * If none is found, the Neutron is directly queried.
1267 private void queryNetwork (String cloudSiteId,
1269 String networkNameOrId,
1270 MsoRequest msoRequest,
1271 Holder <Boolean> networkExists,
1272 Holder <String> networkId,
1273 Holder <String> neutronNetworkId,
1274 Holder <NetworkStatus> status,
1275 Holder <List <Integer>> vlans,
1276 Holder <List <String>> routeTargets,
1277 Holder <Map <String, String>> subnetIdMap) throws NetworkException {
1278 MsoLogger.setLogContext (msoRequest);
1279 MsoLogger.setServiceName ("QueryNetwork");
1280 LOGGER.debug ("*** QUERY Network with Network: " + networkNameOrId
1286 // Will capture execution time for metrics
1287 long startTime = System.currentTimeMillis ();
1289 if (isNullOrEmpty (cloudSiteId)
1290 || isNullOrEmpty(tenantId)
1291 || isNullOrEmpty(networkNameOrId)) {
1293 String error = "Missing mandatory parameter cloudSiteId, tenantId or networkId";
1294 LOGGER.error (MessageEnum.RA_MISSING_PARAM, "cloudSiteId or tenantId or networkNameOrId", "OpenStack", "", MsoLogger.ErrorCode.DataError, "Missing mandatory parameter cloudSiteId, tenantId or networkId");
1295 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
1296 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1299 cloudConfig = cloudConfigFactory.getCloudConfig ();
1300 CloudSite cloudSite = cloudConfig.getCloudSite (cloudSiteId);
1301 if (cloudSite == null)
1303 String error = "Configuration Error. Stack " + networkNameOrId + " in "
1308 + " CloudSite does not exist in MSO Configuration";
1309 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Configuration Error");
1310 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
1311 // Set the detailed error as the Exception 'message'
1312 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1315 // Use MsoNeutronUtils for all NEUTRON commands
1316 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_NETWORK_ADAPTER,msoPropertiesFactory,cloudConfigFactory);
1317 MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
1320 String neutronId = null;
1321 // Try Heat first, since networks may be named the same as the Heat stack
1322 StackInfo heatStack = null;
1323 long queryStackStarttime = System.currentTimeMillis ();
1325 heatStack = heat.queryStack (cloudSiteId, tenantId, networkNameOrId);
1326 LOGGER.recordMetricEvent (queryStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", null);
1327 } catch (MsoException me) {
1328 me.addContext ("QueryNetwork");
1329 String error = "Query Network (heat): " + networkNameOrId
1336 LOGGER.recordMetricEvent (queryStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "BPMN", "QueryStack", null);
1337 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkNameOrId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Exception - Query Network (heat)", me);
1338 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1339 throw new NetworkException (me);
1342 // Populate the outputs based on the returned Stack information
1343 if (heatStack != null && heatStack.getStatus () != HeatStatus.NOTFOUND) {
1344 // Found it. Get the neutronNetworkId for further query
1345 Map <String, Object> outputs = heatStack.getOutputs ();
1346 neutronId = (String) outputs.get (NETWORK_ID);
1349 Map <String, String> sMap = new HashMap <String, String> ();
1350 if (outputs != null) {
1351 for (String key : outputs.keySet ()) {
1352 if (key != null && key.startsWith ("subnet_id_")) //multiples subnet_%aaid% outputs
1354 String subnetUUId = (String) outputs.get(key);
1355 sMap.put (key.substring("subnet_id_".length()), subnetUUId);
1357 else if (key != null && key.startsWith ("subnet")) //one subnet output expected
1359 Map <String, String> map = getSubnetUUId(key, outputs, null);
1365 subnetIdMap.value = sMap;
1367 // Input ID was not a Heat stack ID. Try it directly in Neutron
1368 neutronId = networkNameOrId;
1369 mode = NEUTRON_MODE;
1372 // Query directly against the Neutron Network for the details
1373 // no RouteTargets available for ContrailV2 in neutron net-show
1374 // networkId is heatStackId
1375 long queryNetworkStarttime = System.currentTimeMillis ();
1377 NetworkInfo netInfo = neutron.queryNetwork (neutronId, tenantId, cloudSiteId);
1378 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryNetwork", null);
1379 if (netInfo != null) {
1380 // Found. Populate the output elements
1381 networkExists.value = Boolean.TRUE;
1382 if ("HEAT".equals (mode)) {
1383 networkId.value = heatStack.getCanonicalName ();
1385 networkId.value = netInfo.getId ();
1387 neutronNetworkId.value = netInfo.getId ();
1388 status.value = netInfo.getStatus ();
1390 vlans.value = netInfo.getVlans ();
1392 LOGGER.debug ("Network " + networkNameOrId
1397 + ("HEAT".equals (mode) ? ",NeutronId = " + neutronNetworkId.value : ""));
1399 // Not found. Populate the status fields, leave the rest null
1400 networkExists.value = Boolean.FALSE;
1401 status.value = NetworkStatus.NOTFOUND;
1402 neutronNetworkId.value = null;
1404 vlans.value = new ArrayList <Integer> ();
1406 LOGGER.debug ("Network " + networkNameOrId + " not found");
1408 } catch (MsoException me) {
1409 me.addContext ("QueryNetwork");
1410 String error = "Query Network (neutron): " + networkNameOrId
1417 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryNetwork", null);
1418 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkNameOrId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - Query Network (neutron)", me);
1419 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1420 throw new NetworkException (me);
1422 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully queried network");
1427 * This is the "Delete Network" web service implementation.
1428 * It will delete a Network in the specified cloud and tenant.
1430 * If the network is not found, it is treated as a success.
1432 * This service supports two modes of Network creation/update/delete:
1433 * - via Heat Templates
1435 * The network orchestration mode for each network type is declared in its
1436 * catalog definition.
1438 * For Heat-based orchestration, the networkId should be the stack ID.
1439 * For Neutron-based orchestration, the networkId should be the Neutron network UUID.
1441 * The method returns nothing on success. Rollback is not possible for delete
1442 * commands, so any failure on delete will require manual fallout in the client.
1445 public void deleteNetwork (String cloudSiteId,
1448 String modelCustomizationUuid,
1450 MsoRequest msoRequest,
1451 Holder <Boolean> networkDeleted) throws NetworkException {
1452 MsoLogger.setLogContext (msoRequest);
1453 MsoLogger.setServiceName ("DeleteNetwork");
1454 LOGGER.debug ("*** DELETE Network adapter with Network: " + networkId
1460 // Will capture execution time for metrics
1461 long startTime = System.currentTimeMillis ();
1463 // Get a handle to the Catalog Database
1464 CatalogDatabase db = getCatalogDB ();
1466 // Make sure DB connection is always closed
1468 if (isNullOrEmpty (cloudSiteId)
1469 || isNullOrEmpty(tenantId)
1470 || isNullOrEmpty(networkId)) {
1471 String error = "Missing mandatory parameter cloudSiteId, tenantId or networkId";
1472 LOGGER.error (MessageEnum.RA_MISSING_PARAM, "cloudSiteId or tenantId or networkId", "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing mandatory parameter cloudSiteId, tenantId or networkId");
1473 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
1474 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1477 // Retrieve the Network Resource definition
1478 NetworkResource networkResource = null;
1479 if (isNullOrEmpty(modelCustomizationUuid)) {
1480 networkResource = db.getNetworkResource (networkType);
1482 else if (!isNullOrEmpty(networkType))
1484 networkResource = db.getNetworkResourceByModelCustUuid(modelCustomizationUuid);
1487 if (networkResource != null) {
1488 LOGGER.debug ("Got Network definition from Catalog: " + networkResource.toString ());
1490 mode = networkResource.getOrchestrationMode ();
1493 if (NEUTRON_MODE.equals (mode)) {
1495 // Use MsoNeutronUtils for all NEUTRON commands
1496 MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
1497 long deleteNetworkStarttime = System.currentTimeMillis ();
1499 // The deleteNetwork function in MsoNeutronUtils returns success if the network
1500 // was not found. So don't bother to query first.
1501 boolean deleted = neutron.deleteNetwork (networkId, tenantId, cloudSiteId);
1502 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteNetwork", null);
1503 networkDeleted.value = deleted;
1504 } catch (MsoException me) {
1505 me.addContext ("DeleteNetwork");
1506 String error = "Delete Network (neutron): " + networkId
1513 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteNetwork", null);
1514 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Delete Network (neutron)", me);
1515 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1516 throw new NetworkException (me);
1518 } else { // DEFAULT to ("HEAT".equals (mode))
1519 long deleteStackStarttime = System.currentTimeMillis ();
1520 // Use MsoHeatUtils for all HEAT commands
1521 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_NETWORK_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
1524 // The deleteStack function in MsoHeatUtils returns NOTFOUND if the stack was not found or if the stack was deleted.
1525 // So query first to report back if stack WAS deleted or just NOTOFUND
1526 StackInfo heatStack = null;
1527 heatStack = heat.queryStack(cloudSiteId, tenantId, networkId);
1528 if (heatStack != null && heatStack.getStatus() != HeatStatus.NOTFOUND)
1530 heat.deleteStack (tenantId, cloudSiteId, networkId, true);
1531 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteStack", null);
1532 networkDeleted.value = true;
1536 networkDeleted.value = false;
1538 } catch (MsoException me) {
1539 me.addContext ("DeleteNetwork");
1540 String error = "Delete Network (heat): " + networkId
1547 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteStack", null);
1548 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Delete Network (heat)", me);
1549 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1550 throw new NetworkException (me);
1557 // On success, nothing is returned.
1558 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully deleted network");
1562 public CatalogDatabase getCatalogDB() {
1563 return new CatalogDatabase();
1567 * This web service endpoint will rollback a previous Create VNF operation.
1568 * A rollback object is returned to the client in a successful creation
1569 * response. The client can pass that object as-is back to the rollbackVnf
1570 * operation to undo the creation.
1572 * The rollback includes removing the VNF and deleting the tenant if the
1573 * tenant did not exist prior to the VNF creation.
1576 public void rollbackNetwork (NetworkRollback rollback) throws NetworkException {
1577 MsoLogger.setServiceName ("RollbackNetwork");
1578 // Will capture execution time for metrics
1579 long startTime = System.currentTimeMillis ();
1581 if (rollback == null) {
1582 LOGGER.error (MessageEnum.RA_ROLLBACK_NULL, "Openstack", "", MsoLogger.ErrorCode.DataError, "rollback is null");
1583 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, "No action to perform");
1587 MsoLogger.setLogContext (rollback.getMsoRequest());
1589 // Get the elements of the VnfRollback object for easier access
1590 String cloudSiteId = rollback.getCloudId ();
1591 String tenantId = rollback.getTenantId ();
1592 String networkId = rollback.getNetworkStackId ();
1593 String networkType = rollback.getNetworkType ();
1594 String modelCustomizationUuid = rollback.getModelCustomizationUuid();
1596 LOGGER.debug ("*** ROLLBACK Network " + networkId + " in " + cloudSiteId + "/" + tenantId);
1598 // rollback may be null (e.g. if network already existed when Create was called)
1599 // Get a handle to the Catalog Database
1600 CatalogDatabase db = getCatalogDB ();
1602 // Make sure DB connection is always closed
1605 // Retrieve the Network Resource definition
1606 NetworkResource networkResource = null;
1607 if (isNullOrEmpty(modelCustomizationUuid)) {
1608 networkResource = db.getNetworkResource (networkType);
1612 networkResource = db.getNetworkResourceByModelCustUuid(modelCustomizationUuid);
1615 if (networkResource != null) {
1617 LOGGER.debug ("Got Network definition from Catalog: " + networkResource.toString ());
1619 mode = networkResource.getOrchestrationMode ();
1622 if (rollback.getNetworkCreated ()) {
1623 // Rolling back a newly created network, so delete it.
1624 if (NEUTRON_MODE.equals (mode)) {
1625 // Use MsoNeutronUtils for all NEUTRON commands
1626 MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
1627 long deleteNetworkStarttime = System.currentTimeMillis ();
1629 // The deleteNetwork function in MsoNeutronUtils returns success if the network
1630 // was not found. So don't bother to query first.
1631 neutron.deleteNetwork (networkId, tenantId, cloudSiteId);
1632 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteNetwork", null);
1633 } catch (MsoException me) {
1634 me.addContext ("RollbackNetwork");
1635 String error = "Rollback Network (neutron): " + networkId
1642 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteNetwork", null);
1643 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - Rollback Network (neutron)", me);
1644 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1645 throw new NetworkException (me);
1647 } else { // DEFAULT to if ("HEAT".equals (mode))
1648 // Use MsoHeatUtils for all HEAT commands
1649 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_NETWORK_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
1650 long deleteStackStarttime = System.currentTimeMillis ();
1652 // The deleteStack function in MsoHeatUtils returns success if the stack
1653 // was not found. So don't bother to query first.
1654 heat.deleteStack (tenantId, cloudSiteId, networkId, true);
1655 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteStack", null);
1656 } catch (MsoException me) {
1657 me.addContext ("RollbackNetwork");
1658 String error = "Rollback Network (heat): " + networkId
1665 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteStack", null);
1666 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - Rollback Network (heat)", me);
1667 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1668 throw new NetworkException (me);
1675 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully rolled back network");
1679 private String validateNetworkParams (NetworkType neutronNetworkType,
1681 String physicalNetwork,
1682 List <Integer> vlans,
1683 List <String> routeTargets) {
1685 StringBuilder missing = new StringBuilder ();
1686 if (isNullOrEmpty(networkName)) {
1687 missing.append ("networkName");
1691 if (neutronNetworkType == NetworkType.PROVIDER || neutronNetworkType == NetworkType.MULTI_PROVIDER) {
1692 if (isNullOrEmpty(physicalNetwork)) {
1693 missing.append (sep).append ("physicalNetworkName");
1696 if (vlans == null || vlans.isEmpty ()) {
1697 missing.append (sep).append (VLANS);
1701 return missing.toString ();
1704 private Map <String, Object> populateNetworkParams (NetworkType neutronNetworkType,
1706 String physicalNetwork,
1707 List <Integer> vlans,
1708 List <String> routeTargets,
1711 boolean aic3template) {
1712 // Build the common set of HEAT template parameters
1713 Map <String, Object> stackParams = new HashMap <String, Object> ();
1714 stackParams.put ("network_name", networkName);
1716 if (neutronNetworkType == NetworkType.PROVIDER) {
1717 // For Provider type
1718 stackParams.put (PHYSICAL_NETWORK, physicalNetwork);
1719 stackParams.put ("vlan", vlans.get (0).toString ());
1720 } else if (neutronNetworkType == NetworkType.MULTI_PROVIDER) {
1721 // For Multi-provider, PO supports a custom resource extension of ProviderNet.
1722 // It supports all ProviderNet properties except segmentation_id, and adds a
1723 // comma-separated-list of VLANs as a "segments" property.
1724 // Note that this does not match the Neutron definition of Multi-Provider network,
1725 // which contains a list of 'segments', each having physical_network, network_type,
1726 // and segmentation_id.
1727 StringBuilder buf = new StringBuilder ();
1729 for (Integer vlan : vlans) {
1730 buf.append (sep).append (vlan.toString ());
1733 String csl = buf.toString ();
1735 stackParams.put (PHYSICAL_NETWORK, physicalNetwork);
1736 stackParams.put (VLANS, csl);
1738 if (routeTargets != null && !routeTargets.isEmpty()) {
1739 StringBuilder buf = new StringBuilder ();
1741 for (String rt : routeTargets) {
1742 if (!isNullOrEmpty(rt))
1745 buf.append (sep).append ("target:" + rt.toString ());
1747 buf.append (sep).append (rt.toString ());
1752 String csl = buf.toString ();
1754 stackParams.put ("route_targets", csl);
1756 if (isNullOrEmpty(shared)) {
1757 stackParams.put ("shared", "False");
1759 stackParams.put ("shared", shared);
1761 if (isNullOrEmpty(external)) {
1762 stackParams.put ("external", "False");
1764 stackParams.put ("external", external);
1771 /** policyRef_list structure in stackParams
1774 "network_policy_refs_data_sequence": {
1775 "network_policy_refs_data_sequence_major": "1",
1776 "network_policy_refs_data_sequence_minor": "0"
1780 "network_policy_refs_data_sequence": {
1781 "network_policy_refs_data_sequence_major": "2",
1782 "network_policy_refs_data_sequence_minor": "0"
1787 private void mergePolicyRefs(List <String> pFqdns, Map <String, Object> stackParams) throws MsoException {
1789 List<ContrailPolicyRef> prlist = new ArrayList <ContrailPolicyRef> ();
1791 for (String pf : pFqdns) {
1792 if (!isNullOrEmpty(pf))
1794 ContrailPolicyRef pr = new ContrailPolicyRef();
1795 pr.populate(String.valueOf(index), "0");
1797 LOGGER.debug("Contrail PolicyRefs Data:" + pr.toString());
1802 JsonNode node = null;
1805 ObjectMapper mapper = new ObjectMapper();
1806 node = mapper.convertValue(prlist, JsonNode.class);
1807 String jsonString = mapper.writeValueAsString(prlist);
1808 LOGGER.debug("Json PolicyRefs Data:" + jsonString);
1812 String error = "Error creating JsonNode for policyRefs Data";
1813 LOGGER.error (MessageEnum.RA_MARSHING_ERROR, error, "Openstack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception creating JsonNode for policyRefs Data", e);
1814 throw new MsoAdapterException (error);
1817 if (pFqdns != null && node != null)
1819 StringBuilder buf = new StringBuilder ();
1821 for (String pf : pFqdns) {
1822 if (!isNullOrEmpty(pf))
1824 buf.append (sep).append (pf.toString ());
1828 String csl = buf.toString ();
1829 stackParams.put ("policy_refs", csl);
1830 stackParams.put ("policy_refsdata", node);
1833 LOGGER.debug ("StackParams updated with policy refs");
1837 private void mergeRouteTableRefs(List <String> rtFqdns, Map <String, Object> stackParams) throws MsoException {
1840 if (rtFqdns != null)
1842 StringBuilder buf = new StringBuilder ();
1844 for (String rtf : rtFqdns) {
1845 if (!isNullOrEmpty(rtf))
1847 buf.append (sep).append (rtf.toString ());
1851 String csl = buf.toString ();
1852 stackParams.put ("route_table_refs", csl);
1855 LOGGER.debug ("StackParams updated with route_table refs");
1860 /*** Subnet Output structure from Juniper
1865 "ip_prefix": "10.100.1.0",
1868 "addr_from_start": null,
1869 "enable_dhcp": false,
1870 "default_gateway": "10.100.1.1",
1871 "dns_nameservers": [],
1872 "dhcp_option_list": null,
1873 "subnet_uuid": "10391fbf-6b9c-4160-825d-2d018b7649cf",
1874 "allocation_pools": [
1876 "start": "10.100.1.3",
1880 "start": "10.100.1.6",
1884 "host_routes": null,
1885 "dns_server_address": "10.100.1.13",
1886 "subnet_name": "subnet_MsoNW1_692c9032-e1a2-4d64-828c-7b9a4fcc05b0"
1890 "ip_prefix": "10.100.2.16",
1893 "addr_from_start": null,
1894 "enable_dhcp": true,
1895 "default_gateway": "10.100.2.17",
1896 "dns_nameservers": [],
1897 "dhcp_option_list": null,
1898 "subnet_uuid": "c7aac5ea-66fe-443a-85f9-9c38a608c0f6",
1899 "allocation_pools": [
1901 "start": "10.100.2.18",
1902 "end": "10.100.2.20"
1905 "host_routes": null,
1906 "dns_server_address": "10.100.2.29",
1907 "subnet_name": "subnet_MsoNW1_692c9032-e1a2-4d64-828c-7b9a4fcc05b1"
1913 private String mergeSubnetsAIC3 (String heatTemplate, List <Subnet> subnets, Map <String, Object> stackParams) throws MsoException {
1916 List<ContrailSubnet> cslist = new ArrayList <ContrailSubnet> ();
1917 for (Subnet subnet : subnets) {
1918 ContrailSubnet cs = new ContrailSubnet();
1919 LOGGER.debug("Input Subnet:" + subnet.toString());
1920 cs.populateWith(subnet);
1921 LOGGER.debug("Contrail Subnet:" + cs.toString());
1925 JsonNode node = null;
1928 ObjectMapper mapper = new ObjectMapper();
1929 node = mapper.convertValue(cslist, JsonNode.class);
1930 String jsonString = mapper.writeValueAsString(cslist);
1931 LOGGER.debug("Json Subnet List:" + jsonString);
1935 String error = "Error creating JsonNode from input subnets";
1936 LOGGER.error (MessageEnum.RA_MARSHING_ERROR, error, "", "", MsoLogger.ErrorCode.DataError, "Exception creating JsonNode from input subnets", e);
1937 throw new MsoAdapterException (error);
1942 stackParams.put ("subnet_list", node);
1944 //Outputs - All subnets are in one ipam_subnets structure
1945 String outputTempl = " subnet:\n" + " description: Openstack subnet identifier\n"
1946 + " value: { get_attr: [network, network_ipam_refs, 0, attr]}\n";
1948 // append outputs in heatTemplate
1949 int outputsIdx = heatTemplate.indexOf ("outputs:");
1950 heatTemplate = insertStr (heatTemplate, outputTempl, outputsIdx + 8);
1951 LOGGER.debug ("Template updated with all AIC3.0 subnets:" + heatTemplate);
1952 return heatTemplate;
1956 private String mergeSubnets (String heatTemplate, List <Subnet> subnets) throws MsoException {
1958 String resourceTempl = " subnet_%subnetId%:\n" + " type: OS::Neutron::Subnet\n"
1961 + " network_id: { get_resource: network }\n"
1962 + " cidr: %cidr%\n";
1964 /* make these optional
1965 + " ip_version: %ipversion%\n"
1966 + " enable_dhcp: %enabledhcp%\n"
1967 + " gateway_ip: %gatewayip%\n"
1968 + " allocation_pools:\n"
1969 + " - start: %poolstart%\n"
1970 + " end: %poolend%\n";
1974 String outputTempl = " subnet_id_%subnetId%:\n" + " description: Openstack subnet identifier\n"
1975 + " value: {get_resource: subnet_%subnetId%}\n";
1979 StringBuilder resourcesBuf = new StringBuilder ();
1980 StringBuilder outputsBuf = new StringBuilder ();
1981 for (Subnet subnet : subnets) {
1983 // build template for each subnet
1984 curR = resourceTempl;
1985 if (subnet.getSubnetId () != null) {
1986 curR = curR.replace ("%subnetId%", subnet.getSubnetId ());
1988 String error = "Missing Required AAI SubnetId for subnet in HEAT Template";
1989 LOGGER.error (MessageEnum.RA_MISSING_PARAM, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing Required AAI ID for subnet in HEAT Template");
1990 throw new MsoAdapterException (error);
1993 if (subnet.getSubnetName () != null) {
1994 curR = curR.replace ("%name%", subnet.getSubnetName ());
1996 curR = curR.replace ("%name%", subnet.getSubnetId ());
1999 if (subnet.getCidr () != null) {
2000 curR = curR.replace ("%cidr%", subnet.getCidr ());
2002 String error = "Missing Required cidr for subnet in HEAT Template";
2003 LOGGER.error (MessageEnum.RA_MISSING_PARAM, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing Required cidr for subnet in HEAT Template");
2004 throw new MsoAdapterException (error);
2007 if (subnet.getIpVersion () != null) {
2008 curR = curR + " ip_version: " + subnet.getIpVersion () + "\n";
2010 if (subnet.getEnableDHCP () != null) {
2011 curR = curR + " enable_dhcp: " + Boolean.toString (subnet.getEnableDHCP ()) + "\n";
2013 if (subnet.getGatewayIp () != null && !subnet.getGatewayIp ().isEmpty() ) {
2014 curR = curR + " gateway_ip: " + subnet.getGatewayIp () + "\n";
2017 if (subnet.getAllocationPools() != null) {
2018 curR = curR + " allocation_pools:\n";
2019 for (Pool pool : subnet.getAllocationPools())
2021 if (!isNullOrEmpty(pool.getStart()) && !isNullOrEmpty(pool.getEnd()))
2023 curR = curR + " - start: " + pool.getStart () + "\n";
2024 curR = curR + " end: " + pool.getEnd () + "\n";
2029 resourcesBuf.append (curR);
2032 curO = curO.replace ("%subnetId%", subnet.getSubnetId ());
2034 outputsBuf.append (curO);
2037 // append resources and outputs in heatTemplate
2038 LOGGER.debug ("Tempate initial:" + heatTemplate);
2039 int outputsIdx = heatTemplate.indexOf ("outputs:");
2040 heatTemplate = insertStr (heatTemplate, outputsBuf.toString (), outputsIdx + 8);
2041 int resourcesIdx = heatTemplate.indexOf ("resources:");
2042 heatTemplate = insertStr (heatTemplate, resourcesBuf.toString (), resourcesIdx + 10);
2044 LOGGER.debug ("Template updated with all subnets:" + heatTemplate);
2045 return heatTemplate;
2048 private Map <String, String> getSubnetUUId(String key, Map <String, Object> outputs, List <Subnet> subnets) {
2050 Map <String, String> sMap = new HashMap <String, String> ();
2053 Object obj = outputs.get(key);
2054 ObjectMapper mapper = new ObjectMapper();
2055 String jStr = mapper.writeValueAsString(obj);
2056 LOGGER.debug ("Subnet_Ipam Output JSON String:" + obj.getClass() + " " + jStr);
2058 JsonNode rootNode = mapper.readTree(jStr);
2059 for (JsonNode sNode : rootNode.path("ipam_subnets"))
2061 LOGGER.debug("Output Subnet Node" + sNode.toString());
2062 String name = sNode.path("subnet_name").getTextValue();
2063 String uuid = sNode.path("subnet_uuid").getTextValue();
2064 String aaiId = name; // default
2065 // try to find aaiId for name in input subnetList
2066 if (subnets != null)
2068 for (Subnet subnet : subnets)
2070 if ( subnet != null && !isNullOrEmpty(subnet.getSubnetName()))
2072 if (subnet.getSubnetName().equals(name))
2074 aaiId = subnet.getSubnetId();
2080 sMap.put(aaiId, uuid); //bpmn needs aaid to uuid map
2085 LOGGER.error (MessageEnum.RA_MARSHING_ERROR, "error getting subnet-uuids", "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception getting subnet-uuids", e);
2088 LOGGER.debug ("Return sMap" + sMap.toString());
2092 private static String insertStr (String template, String snippet, int index) {
2094 String updatedTemplate = "";
2096 LOGGER.debug ("Index:" + index + " Snippet:" + snippet);
2098 String templateBeg = template.substring (0, index);
2099 String templateEnd = template.substring (index);
2101 updatedTemplate = templateBeg + "\n" + snippet + templateEnd;
2103 LOGGER.debug ("Template updated with a subnet:" + updatedTemplate);
2104 return updatedTemplate;