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,
121 String physicalNetworkName,
122 List <Integer> vlans,
123 Boolean failIfExists,
125 List <Subnet> subnets,
126 MsoRequest msoRequest,
127 Holder <String> networkId,
128 Holder <String> neutronNetworkId,
129 Holder <Map <String, String>> subnetIdMap,
130 Holder <NetworkRollback> rollback) throws NetworkException {
131 Holder <String> networkFqdn = new Holder <String> ();
132 createNetwork (cloudSiteId,
155 public void createNetworkContrail (String cloudSiteId,
159 List <String> routeTargets,
162 Boolean failIfExists,
164 List <Subnet> subnets,
165 List <String> policyFqdns,
166 List<String> routeTableFqdns,
167 MsoRequest msoRequest,
168 Holder <String> networkId,
169 Holder <String> neutronNetworkId,
170 Holder <String> networkFqdn,
171 Holder <Map <String, String>> subnetIdMap,
172 Holder <NetworkRollback> rollback) throws NetworkException {
173 createNetwork (cloudSiteId,
196 * This is the "Create Network" web service implementation.
197 * It will create a new Network of the requested type in the specified cloud
198 * and tenant. The tenant must exist at the time this service is called.
200 * If a network with the same name already exists, this can be considered a
201 * success or failure, depending on the value of the 'failIfExists' parameter.
203 * There will be a pre-defined set of network types defined in the MSO Catalog.
204 * All such networks will have a similar configuration, based on the allowable
205 * Openstack networking definitions. This includes basic networks, provider
206 * networks (with a single VLAN), and multi-provider networks (one or more VLANs)
208 * Initially, all provider networks must be "vlan" type, and multiple segments in
209 * a multi-provider network must be multiple VLANs on the same physical network.
211 * This service supports two modes of Network creation/update:
212 * - via Heat Templates
214 * The network orchestration mode for each network type is declared in its
215 * catalog definition. All Heat-based templates must support some subset of
216 * the same input parameters: network_name, physical_network, vlan(s).
218 * The method returns the network ID and a NetworkRollback object. This latter
219 * object can be passed as-is to the rollbackNetwork operation to undo everything
220 * that was created. This is useful if a network is successfully created but
221 * the orchestration fails on a subsequent operation.
224 private void createNetwork (String cloudSiteId,
228 String physicalNetworkName,
229 List <Integer> vlans,
230 List <String> routeTargets,
233 Boolean failIfExists,
235 List <Subnet> subnets,
236 List <String> policyFqdns,
237 List <String> routeTableFqdns,
238 MsoRequest msoRequest,
239 Holder <String> networkId,
240 Holder <String> neutronNetworkId,
241 Holder <String> networkFqdn,
242 Holder <Map <String, String>> subnetIdMap,
243 Holder <NetworkRollback> rollback) throws NetworkException {
244 MsoLogger.setLogContext (msoRequest);
245 MsoLogger.setServiceName ("CreateNetwork");
247 LOGGER.debug ("*** CREATE Network: " + networkName
255 // Will capture execution time for metrics
256 long startTime = System.currentTimeMillis ();
258 // Build a default rollback object (no actions performed)
259 NetworkRollback networkRollback = new NetworkRollback ();
260 networkRollback.setCloudId (cloudSiteId);
261 networkRollback.setTenantId (tenantId);
262 networkRollback.setMsoRequest (msoRequest);
264 // tenant query is not required here.
265 // If the tenant doesn’t exist, the Heat calls will fail anyway (when the HeatUtils try to obtain a token).
266 // So this is just catching that error in a bit more obvious way up front.
268 cloudConfig = cloudConfigFactory.getCloudConfig ();
269 CloudSite cloudSite = cloudConfig.getCloudSite (cloudSiteId);
270 if (cloudSite == null)
272 String error = "Configuration Error. Stack " + networkName + " in "
277 + " CloudSite does not exist in MSO Configuration";
278 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "", "", MsoLogger.ErrorCode.DataError, "Configuration Error");
279 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
280 // Set the detailed error as the Exception 'message'
281 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
284 // Get a handle to the Catalog Database
285 CatalogDatabase db = getCatalogDB ();
287 // Make sure DB connection is always closed
289 NetworkResource networkResource = networkCheck (db,
297 String mode = networkResource.getOrchestrationMode ();
298 NetworkType neutronNetworkType = NetworkType.valueOf (networkResource.getNeutronNetworkType ());
300 if (NEUTRON_MODE.equals (mode)) {
302 // Use an MsoNeutronUtils for all neutron commands
303 MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
305 // See if the Network already exists (by name)
306 NetworkInfo netInfo = null;
307 long queryNetworkStarttime = System.currentTimeMillis ();
309 netInfo = neutron.queryNetwork (networkName, tenantId, cloudSiteId);
310 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Response successfully received from OpenStack", "OpenStack", "QueryNetwork", null);
311 } catch (MsoException me) {
312 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while querying network from OpenStack", "OpenStack", "QueryNetwork", null);
313 String error = "Create Network (neutron): query network " + networkName
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 if (heatTemplate == null) {
397 String error = "Network error - undefined Heat Template. Network Type = " + networkType;
398 LOGGER.error (MessageEnum.RA_PARAM_NOT_FOUND, "Heat Template", "Network Type", networkType, "Openstack", "", MsoLogger.ErrorCode.DataError, "Network error - undefined Heat Template. Network Type = " + networkType);
399 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error); // Alarm on this
403 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
404 throw new NetworkException (error, MsoExceptionCategory.INTERNAL);
407 LOGGER.debug ("Got HEAT Template from DB: " + heatTemplate.toString ());
409 // "Fix" the template if it has CR/LF (getting this from Oracle)
410 String template = heatTemplate.getHeatTemplate ();
411 template = template.replaceAll ("\r\n", "\n");
413 boolean aic3template=false;
414 String aic3nw = AIC3_NW;
416 aic3nw = msoPropertiesFactory.getMsoJavaProperties(MSO_PROP_NETWORK_ADAPTER).getProperty(AIC3_NW_PROPERTY, AIC3_NW);
417 } catch (MsoPropertiesException e) {
418 String error = "Unable to get properties:" + MSO_PROP_NETWORK_ADAPTER;
419 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "", "", MsoLogger.ErrorCode.DataError, "Exception - Unable to get properties", e);
422 if (template.contains(aic3nw))
425 // First, look up to see if the Network already exists (by name).
426 // For HEAT orchestration of networks, the stack name will always match the network name
427 StackInfo heatStack = null;
428 long queryNetworkStarttime = System.currentTimeMillis ();
430 heatStack = heat.queryStack (cloudSiteId, tenantId, networkName);
431 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Response successfully received from OpenStack", "OpenStack", "QueryNetwork", null);
432 } catch (MsoException me) {
433 me.addContext (CREATE_NETWORK_CONTEXT);
434 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while querying stack from OpenStack", "OpenStack", "QueryNetwork", null);
435 String error = "Create Network (heat): query network " + networkName
442 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception while querying stack from OpenStack", me);
443 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
444 throw new NetworkException (me);
447 if (heatStack != null && !(heatStack.getStatus () == HeatStatus.NOTFOUND)) {
448 // Stack exists. Return success or error depending on input directive
449 if (failIfExists != null && failIfExists) {
450 String error = "CreateNetwork: Stack " + networkName
451 + " already exists in "
455 + " as " + heatStack.getCanonicalName();
456 LOGGER.error (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "", "", MsoLogger.ErrorCode.DataError, "Network already exists");
457 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
458 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
460 // Populate the outputs from the existing stack.
461 networkId.value = heatStack.getCanonicalName ();
462 neutronNetworkId.value = (String) heatStack.getOutputs ().get (NETWORK_ID);
463 rollback.value = networkRollback; // Default rollback - no updates performed
466 networkFqdn.value = (String) heatStack.getOutputs().get(NETWORK_FQDN);
468 Map <String, Object> outputs = heatStack.getOutputs ();
469 Map <String, String> sMap = new HashMap <String, String> ();
470 if (outputs != null) {
471 for (String key : outputs.keySet ()) {
472 if (key != null && key.startsWith ("subnet")) {
473 if (aic3template) //one subnet_id output
475 Map <String, String> map = getSubnetUUId(key, outputs, subnets);
478 else //multiples subnet_%aaid% outputs
480 String subnetUUId = (String) outputs.get(key);
481 sMap.put (key.substring("subnet_id_".length()), subnetUUId);
486 subnetIdMap.value = sMap;
487 String msg = "Found Existing network stack, status=" + heatStack.getStatus () + " for Heat mode";
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.
585 long createStackStartTime = System.currentTimeMillis ();
589 heatStack = heat.createStack (cloudSiteId,
595 heatTemplate.getTimeoutMinutes (),
599 backout.booleanValue());
600 } catch (MsoException me) {
601 me.addContext (CREATE_NETWORK_CONTEXT);
602 String error = "Create Network (heat): type " + neutronNetworkType
609 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, networkName, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception creating network", me);
610 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
611 throw new NetworkException (me);
614 // Reach this point if createStack is successful.
616 // For Heat-based orchestration, the MSO-tracked network ID is the heat stack,
617 // and the neutronNetworkId is the network UUID returned in stack outputs.
618 networkId.value = heatStack.getCanonicalName ();
619 neutronNetworkId.value = (String) heatStack.getOutputs ().get (NETWORK_ID);
622 networkFqdn.value = (String) heatStack.getOutputs().get(NETWORK_FQDN);
624 Map <String, Object> outputs = heatStack.getOutputs ();
625 Map <String, String> sMap = new HashMap <String, String> ();
626 if (outputs != null) {
627 for (String key : outputs.keySet ()) {
628 if (key != null && key.startsWith ("subnet")) {
629 if (aic3template) //one subnet output expected
631 Map <String, String> map = getSubnetUUId(key, outputs, subnets);
634 else //multiples subnet_%aaid% outputs allowed
636 String subnetUUId = (String) outputs.get(key);
637 sMap.put (key.substring("subnet_id_".length()), subnetUUId);
642 subnetIdMap.value = sMap;
644 rollback.value = networkRollback;
645 // Populate remaining rollback info and response parameters.
646 networkRollback.setNetworkStackId (heatStack.getCanonicalName ());
647 networkRollback.setNeutronNetworkId ((String) heatStack.getOutputs ().get (NETWORK_ID));
648 networkRollback.setNetworkCreated (true);
649 networkRollback.setNetworkType (networkType);
651 LOGGER.debug ("Network " + networkName + " successfully created via HEAT");
656 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Suc, "Successfully created network");
661 public void updateNetwork (String cloudSiteId,
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,
692 public void updateNetworkContrail (String cloudSiteId,
697 List <String> routeTargets,
700 List <Subnet> subnets,
701 List <String> policyFqdns,
702 List<String> routeTableFqdns,
703 MsoRequest msoRequest,
704 Holder <Map <String, String>> subnetIdMap,
705 Holder <NetworkRollback> rollback) throws NetworkException {
706 updateNetwork (cloudSiteId,
725 * This is the "Update Network" web service implementation.
726 * It will update an existing Network of the requested type in the specified cloud
727 * and tenant. The typical use will be to replace the VLANs with the supplied
728 * list (to add or remove a VLAN), but other properties may be updated as well.
730 * There will be a pre-defined set of network types defined in the MSO Catalog.
731 * All such networks will have a similar configuration, based on the allowable
732 * Openstack networking definitions. This includes basic networks, provider
733 * networks (with a single VLAN), and multi-provider networks (one or more VLANs).
735 * Initially, all provider networks must currently be "vlan" type, and multi-provider
736 * networks must be multiple VLANs on the same physical network.
738 * This service supports two modes of Network update:
739 * - via Heat Templates
741 * The network orchestration mode for each network type is declared in its
742 * catalog definition. All Heat-based templates must support some subset of
743 * the same input parameters: network_name, physical_network, vlan, segments.
745 * The method returns a NetworkRollback object. This object can be passed
746 * as-is to the rollbackNetwork operation to undo everything that was updated.
747 * This is useful if a network is successfully updated but orchestration
748 * fails on a subsequent operation.
750 private void updateNetwork (String cloudSiteId,
755 String physicalNetworkName,
756 List <Integer> vlans,
757 List <String> routeTargets,
760 List <Subnet> subnets,
761 List <String> policyFqdns,
762 List<String> routeTableFqdns,
763 MsoRequest msoRequest,
764 Holder <Map <String, String>> subnetIdMap,
765 Holder <NetworkRollback> rollback) throws NetworkException {
766 MsoLogger.setLogContext (msoRequest);
767 MsoLogger.setServiceName ("UpdateNetwork");
768 LOGGER.debug ("***UPDATE Network adapter with Network: " + networkName
777 // Will capture execution time for metrics
778 long startTime = System.currentTimeMillis ();
780 // Build a default rollback object (no actions performed)
781 NetworkRollback networkRollback = new NetworkRollback ();
782 networkRollback.setCloudId (cloudSiteId);
783 networkRollback.setTenantId (tenantId);
784 networkRollback.setMsoRequest (msoRequest);
786 cloudConfig = cloudConfigFactory.getCloudConfig ();
787 CloudSite cloudSite = cloudConfig.getCloudSite (cloudSiteId);
788 if (cloudSite == null) {
789 String error = "UpdateNetwork: Configuration Error. Stack " + networkName + " in "
794 + " CloudSite does not exist in MSO Configuration";
795 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "CloudSite does not exist in MSO Configuration");
796 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
797 // Set the detailed error as the Exception 'message'
798 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
801 // Get a handle to the Catalog Database
802 CatalogDatabase db = getCatalogDB ();
804 // Make sure DB connection is always closed
806 NetworkResource networkResource = networkCheck(db,
814 String mode = networkResource.getOrchestrationMode();
815 NetworkType neutronNetworkType = NetworkType.valueOf(networkResource.getNeutronNetworkType());
817 // Use an MsoNeutronUtils for all Neutron commands
818 MsoNeutronUtils neutron = new MsoNeutronUtils(MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
820 if (NEUTRON_MODE.equals(mode)) {
822 // Verify that the Network exists
823 // For Neutron-based orchestration, the networkId is the Neutron Network UUID.
824 NetworkInfo netInfo = null;
825 long queryNetworkStarttime = System.currentTimeMillis();
827 netInfo = neutron.queryNetwork(networkId, tenantId, cloudSiteId);
828 LOGGER.recordMetricEvent(queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryNetwork", null);
829 } catch (MsoException me) {
830 me.addContext(UPDATE_NETWORK_CONTEXT);
831 String error = "Update Network (neutron): query " + networkId
838 LOGGER.recordMetricEvent(queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryNetwork", null);
839 LOGGER.error(MessageEnum.RA_QUERY_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "QueryNetwork", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - queryNetwork", me);
840 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
841 throw new NetworkException(me);
844 if (netInfo == null) {
845 String error = "Update Nework: Network " + networkId
846 + " does not exist in "
850 LOGGER.error(MessageEnum.RA_NETWORK_NOT_FOUND, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Network not found");
851 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
852 // Does not exist. Throw an exception (can't update a non-existent network)
853 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
855 long updateNetworkStarttime = System.currentTimeMillis();
857 netInfo = neutron.updateNetwork(cloudSiteId,
863 LOGGER.recordMetricEvent(updateNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "UpdateNetwork", null);
864 } catch (MsoException me) {
865 me.addContext(UPDATE_NETWORK_CONTEXT);
866 String error = "Update Network (neutron): " + networkId
873 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, networkId, cloudSiteId, tenantId, "Openstack", "updateNetwork", MsoLogger.ErrorCode.DataError, "Exception - updateNetwork", me);
874 LOGGER.recordMetricEvent(updateNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "UpdateNetwork", null);
875 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
876 throw new NetworkException(me);
879 // Add the network ID and previously queried vlans to the rollback object
880 networkRollback.setNetworkId(netInfo.getId());
881 networkRollback.setNeutronNetworkId(netInfo.getId());
882 networkRollback.setNetworkType(networkType);
883 // Save previous parameters
884 networkRollback.setNetworkName(netInfo.getName());
885 networkRollback.setPhysicalNetwork(netInfo.getProvider());
886 networkRollback.setVlans(netInfo.getVlans());
888 LOGGER.debug("Network " + networkId + " updated, id = " + netInfo.getId());
889 } else if ("HEAT".equals(mode)) {
891 // Use an MsoHeatUtils for all Heat commands
892 MsoHeatUtilsWithUpdate heat = new MsoHeatUtilsWithUpdate(MSO_PROP_NETWORK_ADAPTER, msoPropertiesFactory, cloudConfigFactory);
894 // First, look up to see that the Network already exists.
895 // For Heat-based orchestration, the networkId is the network Stack ID.
896 StackInfo heatStack = null;
897 long queryStackStarttime = System.currentTimeMillis();
899 heatStack = heat.queryStack(cloudSiteId, tenantId, networkName);
900 LOGGER.recordMetricEvent(queryStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", null);
901 } catch (MsoException me) {
902 me.addContext(UPDATE_NETWORK_CONTEXT);
903 String error = "UpdateNetwork (heat): query " + networkName
910 LOGGER.recordMetricEvent(queryStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryStack", null);
911 LOGGER.error(MessageEnum.RA_QUERY_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Exception - QueryStack", me);
912 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
913 throw new NetworkException(me);
916 if (heatStack == null || (heatStack.getStatus() == HeatStatus.NOTFOUND)) {
917 String error = "UpdateNetwork: Stack " + networkName
918 + " does not exist in "
922 LOGGER.error(MessageEnum.RA_NETWORK_NOT_FOUND, networkId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Network not found");
923 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
924 // Network stack does not exist. Return an error
925 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
928 // Get the previous parameters for rollback
929 Map<String, Object> heatParams = heatStack.getParameters();
931 String previousNetworkName = (String) heatParams.get("network_name");
932 String previousPhysicalNetwork = (String) heatParams.get(PHYSICAL_NETWORK);
934 List<Integer> previousVlans = new ArrayList<Integer>();
935 String vlansParam = (String) heatParams.get(VLANS);
936 if (vlansParam != null) {
937 for (String vlan : vlansParam.split(",")) {
939 previousVlans.add(Integer.parseInt(vlan));
940 } catch (NumberFormatException e) {
941 LOGGER.warn(MessageEnum.RA_VLAN_PARSE, networkId, vlansParam, "", "", MsoLogger.ErrorCode.DataError, "Exception - VLAN parse", e);
945 LOGGER.debug("Update Stack: Previous VLANS: " + previousVlans);
947 // Ready to deploy the updated Network via Heat
949 HeatTemplate heatTemplate = db.getHeatTemplate(networkResource.getTemplateId());
950 if (heatTemplate == null) {
951 String error = "Network error - undefined Heat Template. Network Type=" + networkType;
952 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);
953 alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
954 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
955 throw new NetworkException(error, MsoExceptionCategory.INTERNAL);
958 LOGGER.debug("Got HEAT Template from DB: " + heatTemplate.toString());
960 // "Fix" the template if it has CR/LF (getting this from Oracle)
961 String template = heatTemplate.getHeatTemplate();
962 template = template.replaceAll("\r\n", "\n");
964 boolean aic3template = false;
965 String aic3nw = AIC3_NW;
967 aic3nw = msoPropertiesFactory.getMsoJavaProperties(MSO_PROP_NETWORK_ADAPTER).getProperty(AIC3_NW_PROPERTY, AIC3_NW);
968 } catch (MsoPropertiesException e) {
969 String error = "Unable to get properties:" + MSO_PROP_NETWORK_ADAPTER;
970 LOGGER.error(MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - Unable to get properties", e);
972 if (template.contains(aic3nw))
975 // Build the common set of HEAT template parameters
976 Map<String, Object> stackParams = populateNetworkParams(neutronNetworkType,
985 // Validate (and update) the input parameters against the DB definition
986 // Shouldn't happen unless DB config is wrong, since all networks use same inputs
988 stackParams = heat.validateStackParams(stackParams, heatTemplate);
989 } catch (IllegalArgumentException e) {
990 String error = "UpdateNetwork: Configuration Error: Network Type=" + networkType;
991 LOGGER.error(MessageEnum.RA_CONFIG_EXC, "Network Type=" + networkType, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork: Configuration Error");
992 alarmLogger.sendAlarm(MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
993 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.SchemaError, error);
994 throw new NetworkException(error, MsoExceptionCategory.INTERNAL, e);
997 if (subnets != null) {
1000 template = mergeSubnetsAIC3(template, subnets, stackParams);
1002 template = mergeSubnets(template, subnets);
1004 } catch (MsoException me) {
1005 me.addContext(UPDATE_NETWORK_CONTEXT);
1006 String error = "Update Network (heat): type " + neutronNetworkType
1013 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergeSubnets ", me);
1014 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
1015 throw new NetworkException(me);
1019 if (policyFqdns != null && aic3template) {
1021 mergePolicyRefs(policyFqdns, stackParams);
1022 } catch (MsoException me) {
1023 me.addContext(UPDATE_NETWORK_CONTEXT);
1024 String error = "UpdateNetwork (heat) mergePolicyRefs type " + neutronNetworkType
1031 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergePolicyRefs", me);
1032 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
1033 throw new NetworkException(me);
1037 if (routeTableFqdns != null && !routeTableFqdns.isEmpty() && aic3template) {
1039 mergeRouteTableRefs(routeTableFqdns, stackParams);
1040 } catch (MsoException me) {
1041 me.addContext(UPDATE_NETWORK_CONTEXT);
1042 String error = "UpdateNetwork (heat) mergeRouteTableRefs type " + neutronNetworkType
1049 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergeRouteTableRefs", me);
1050 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
1051 throw new NetworkException(me);
1055 // Update the network stack
1056 // Ignore MsoStackNotFound exception because we already checked.
1057 long updateStackStarttime = System.currentTimeMillis();
1059 heatStack = heat.updateStack(cloudSiteId,
1065 heatTemplate.getTimeoutMinutes());
1066 LOGGER.recordMetricEvent(updateStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "UpdateStack", null);
1067 } catch (MsoException me) {
1068 me.addContext(UPDATE_NETWORK_CONTEXT);
1069 String error = "Update Network: " + networkId + " in " + cloudSiteId + "/" + tenantId + ": " + me;
1070 LOGGER.recordMetricEvent(updateStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "UpdateStack", null);
1071 LOGGER.error(MessageEnum.RA_UPDATE_NETWORK_ERR, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - update network", me);
1072 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1073 throw new NetworkException(me);
1076 Map<String, Object> outputs = heatStack.getOutputs();
1077 Map<String, String> sMap = new HashMap<String, String>();
1078 if (outputs != null) {
1079 for (String key : outputs.keySet()) {
1080 if (key != null && key.startsWith("subnet")) {
1081 if (aic3template) //one subnet output expected
1083 Map<String, String> map = getSubnetUUId(key, outputs, subnets);
1085 } else //multiples subnet_%aaid% outputs allowed
1087 String subnetUUId = (String) outputs.get(key);
1088 sMap.put(key.substring("subnet_id_".length()), subnetUUId);
1093 subnetIdMap.value = sMap;
1095 // Reach this point if createStack is successful.
1096 // Populate remaining rollback info and response parameters.
1097 networkRollback.setNetworkStackId(heatStack.getCanonicalName());
1098 networkRollback.setNeutronNetworkId((String) outputs.get(NETWORK_ID));
1099 networkRollback.setNetworkType(networkType);
1100 // Save previous parameters
1101 networkRollback.setNetworkName(previousNetworkName);
1102 networkRollback.setPhysicalNetwork(previousPhysicalNetwork);
1103 networkRollback.setVlans(previousVlans);
1105 rollback.value = networkRollback;
1107 LOGGER.debug("Network " + networkId + " successfully updated via HEAT");
1112 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully updated network");
1116 private NetworkResource networkCheck (CatalogDatabase db,
1120 String physicalNetworkName,
1121 List <Integer> vlans,
1122 List <String> routeTargets,
1123 CloudSite cloudSite) throws NetworkException {
1124 // Retrieve the Network Resource definition
1125 NetworkResource networkResource = db.getNetworkResource (networkType);
1126 if (networkResource == null) {
1127 String error = "CreateNetwork: Unknown Network Type: " + networkType;
1128 LOGGER.error (MessageEnum.RA_UNKOWN_PARAM, "Network Type", networkType, "OpenStack", "", MsoLogger.ErrorCode.DataError, "CreateNetwork: Unknown Network Type");
1130 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1132 LOGGER.debug ("Got Network definition from Catalog: " + networkResource.toString ());
1134 String mode = networkResource.getOrchestrationMode ();
1135 NetworkType neutronNetworkType = NetworkType.valueOf (networkResource.getNeutronNetworkType ());
1137 // All Networks are orchestrated via HEAT or Neutron
1138 if (!("HEAT".equals (mode) || NEUTRON_MODE.equals (mode))) {
1139 String error = "CreateNetwork: Configuration Error: Network Type = " + networkType;
1140 LOGGER.error (MessageEnum.RA_NETWORK_ORCHE_MODE_NOT_SUPPORT, mode, "OpenStack", "", MsoLogger.ErrorCode.DataError, "CreateNetwork: Configuration Error");
1141 // Alarm on this error, configuration must be fixed
1142 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
1144 throw new NetworkException (error, MsoExceptionCategory.INTERNAL);
1147 MavenLikeVersioning aicV = new MavenLikeVersioning();
1148 aicV.setVersion(cloudSite.getAic_version());
1150 if ((aicV.isMoreRecentThan(networkResource.getAicVersionMin()) || aicV.isTheSameVersion(networkResource.getAicVersionMin())) // aic >= min
1151 && (aicV.isTheSameVersion(networkResource.getAicVersionMax()) || !(aicV.isMoreRecentThan(networkResource.getAicVersionMax())))) //aic <= max
1153 LOGGER.debug("Network Type:" + networkType
1154 + " VersionMin:" + networkResource.getAicVersionMin()
1155 + " VersionMax:" + networkResource.getAicVersionMax()
1156 + " supported on Cloud:" + cloudSite.getId()
1157 + " with AIC_Version:" + cloudSite.getAic_version());
1159 String error = "Network Type:" + networkType
1160 + " Version_Min:" + networkResource.getAicVersionMin()
1161 + " Version_Max:" + networkResource.getAicVersionMax()
1162 + " not supported on Cloud:" + cloudSite.getId()
1163 + " with AIC_Version:" + cloudSite.getAic_version();
1164 LOGGER.error(MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Network Type not supported on Cloud");
1165 LOGGER.recordAuditEvent(startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
1166 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
1168 } catch (Exception e) {
1169 String error = "Exception during Network version check";
1170 LOGGER.error (MessageEnum.RA_GENERAL_EXCEPTION_ARG, e.getMessage(), "", "", MsoLogger.ErrorCode.DataError, error);
1172 throw new NetworkException (error, MsoExceptionCategory.INTERNAL);
1176 // Validate the Network parameters.
1177 String missing = validateNetworkParams (neutronNetworkType,
1179 physicalNetworkName,
1182 if (!missing.isEmpty ()) {
1183 String error = "Create Network: Missing parameters: " + missing;
1184 LOGGER.error (MessageEnum.RA_MISSING_PARAM, missing, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Create Network: Missing parameters");
1186 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1188 return networkResource;
1192 public void queryNetwork (String cloudSiteId,
1194 String networkNameOrId,
1195 MsoRequest msoRequest,
1196 Holder <Boolean> networkExists,
1197 Holder <String> networkId,
1198 Holder <String> neutronNetworkId,
1199 Holder <NetworkStatus> status,
1200 Holder <List <Integer>> vlans,
1201 Holder <Map <String, String>> subnetIdMap) throws NetworkException {
1202 queryNetwork (cloudSiteId,
1216 public void queryNetworkContrail (String cloudSiteId,
1218 String networkNameOrId,
1219 MsoRequest msoRequest,
1220 Holder <Boolean> networkExists,
1221 Holder <String> networkId,
1222 Holder <String> neutronNetworkId,
1223 Holder <NetworkStatus> status,
1224 Holder <List <String>> routeTargets,
1225 Holder <Map <String, String>> subnetIdMap) throws NetworkException {
1226 queryNetwork (cloudSiteId,
1240 * This is the queryNetwork method. It returns the existence and status of
1241 * the specified network, along with its Neutron UUID and list of VLANs.
1242 * This method attempts to find the network using both Heat and Neutron.
1243 * Heat stacks are first searched based on the provided network name/id.
1244 * If none is found, the Neutron is directly queried.
1246 private void queryNetwork (String cloudSiteId,
1248 String networkNameOrId,
1249 MsoRequest msoRequest,
1250 Holder <Boolean> networkExists,
1251 Holder <String> networkId,
1252 Holder <String> neutronNetworkId,
1253 Holder <NetworkStatus> status,
1254 Holder <List <Integer>> vlans,
1255 Holder <List <String>> routeTargets,
1256 Holder <Map <String, String>> subnetIdMap) throws NetworkException {
1257 MsoLogger.setLogContext (msoRequest);
1258 MsoLogger.setServiceName ("QueryNetwork");
1259 LOGGER.debug ("*** QUERY Network with Network: " + networkNameOrId
1265 // Will capture execution time for metrics
1266 long startTime = System.currentTimeMillis ();
1268 if (isNullOrEmpty (cloudSiteId)
1269 || isNullOrEmpty(tenantId)
1270 || isNullOrEmpty(networkNameOrId)) {
1272 String error = "Missing mandatory parameter cloudSiteId, tenantId or networkId";
1273 LOGGER.error (MessageEnum.RA_MISSING_PARAM, "cloudSiteId or tenantId or networkNameOrId", "OpenStack", "", MsoLogger.ErrorCode.DataError, "Missing mandatory parameter cloudSiteId, tenantId or networkId");
1274 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
1275 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1278 cloudConfig = cloudConfigFactory.getCloudConfig ();
1279 CloudSite cloudSite = cloudConfig.getCloudSite (cloudSiteId);
1280 if (cloudSite == null)
1282 String error = "Configuration Error. Stack " + networkNameOrId + " in "
1287 + " CloudSite does not exist in MSO Configuration";
1288 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Configuration Error");
1289 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
1290 // Set the detailed error as the Exception 'message'
1291 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1294 // Use MsoNeutronUtils for all NEUTRON commands
1295 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_NETWORK_ADAPTER,msoPropertiesFactory,cloudConfigFactory);
1296 MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
1299 String neutronId = null;
1300 // Try Heat first, since networks may be named the same as the Heat stack
1301 StackInfo heatStack = null;
1302 long queryStackStarttime = System.currentTimeMillis ();
1304 heatStack = heat.queryStack (cloudSiteId, tenantId, networkNameOrId);
1305 LOGGER.recordMetricEvent (queryStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", null);
1306 } catch (MsoException me) {
1307 me.addContext ("QueryNetwork");
1308 String error = "Query Network (heat): " + networkNameOrId
1315 LOGGER.recordMetricEvent (queryStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "BPMN", "QueryStack", null);
1316 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkNameOrId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Exception - Query Network (heat)", me);
1317 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1318 throw new NetworkException (me);
1321 // Populate the outputs based on the returned Stack information
1322 if (heatStack != null && heatStack.getStatus () != HeatStatus.NOTFOUND) {
1323 // Found it. Get the neutronNetworkId for further query
1324 Map <String, Object> outputs = heatStack.getOutputs ();
1325 neutronId = (String) outputs.get (NETWORK_ID);
1328 Map <String, String> sMap = new HashMap <String, String> ();
1329 if (outputs != null) {
1330 for (String key : outputs.keySet ()) {
1331 if (key != null && key.startsWith ("subnet_id_")) //multiples subnet_%aaid% outputs
1333 String subnetUUId = (String) outputs.get(key);
1334 sMap.put (key.substring("subnet_id_".length()), subnetUUId);
1336 else if (key != null && key.startsWith ("subnet")) //one subnet output expected
1338 Map <String, String> map = getSubnetUUId(key, outputs, null);
1344 subnetIdMap.value = sMap;
1346 // Input ID was not a Heat stack ID. Try it directly in Neutron
1347 neutronId = networkNameOrId;
1348 mode = NEUTRON_MODE;
1351 // Query directly against the Neutron Network for the details
1352 // no RouteTargets available for ContrailV2 in neutron net-show
1353 // networkId is heatStackId
1354 long queryNetworkStarttime = System.currentTimeMillis ();
1356 NetworkInfo netInfo = neutron.queryNetwork (neutronId, tenantId, cloudSiteId);
1357 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryNetwork", null);
1358 if (netInfo != null) {
1359 // Found. Populate the output elements
1360 networkExists.value = Boolean.TRUE;
1361 if ("HEAT".equals (mode)) {
1362 networkId.value = heatStack.getCanonicalName ();
1364 networkId.value = netInfo.getId ();
1366 neutronNetworkId.value = netInfo.getId ();
1367 status.value = netInfo.getStatus ();
1369 vlans.value = netInfo.getVlans ();
1371 LOGGER.debug ("Network " + networkNameOrId
1376 + ("HEAT".equals (mode) ? ",NeutronId = " + neutronNetworkId.value : ""));
1378 // Not found. Populate the status fields, leave the rest null
1379 networkExists.value = Boolean.FALSE;
1380 status.value = NetworkStatus.NOTFOUND;
1381 neutronNetworkId.value = null;
1383 vlans.value = new ArrayList <Integer> ();
1385 LOGGER.debug ("Network " + networkNameOrId + " not found");
1387 } catch (MsoException me) {
1388 me.addContext ("QueryNetwork");
1389 String error = "Query Network (neutron): " + networkNameOrId
1396 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryNetwork", null);
1397 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkNameOrId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - Query Network (neutron)", me);
1398 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1399 throw new NetworkException (me);
1401 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully queried network");
1406 * This is the "Delete Network" web service implementation.
1407 * It will delete a Network in the specified cloud and tenant.
1409 * If the network is not found, it is treated as a success.
1411 * This service supports two modes of Network creation/update/delete:
1412 * - via Heat Templates
1414 * The network orchestration mode for each network type is declared in its
1415 * catalog definition.
1417 * For Heat-based orchestration, the networkId should be the stack ID.
1418 * For Neutron-based orchestration, the networkId should be the Neutron network UUID.
1420 * The method returns nothing on success. Rollback is not possible for delete
1421 * commands, so any failure on delete will require manual fallout in the client.
1424 public void deleteNetwork (String cloudSiteId,
1428 MsoRequest msoRequest,
1429 Holder <Boolean> networkDeleted) throws NetworkException {
1430 MsoLogger.setLogContext (msoRequest);
1431 MsoLogger.setServiceName ("DeleteNetwork");
1432 LOGGER.debug ("*** DELETE Network adapter with Network: " + networkId
1438 // Will capture execution time for metrics
1439 long startTime = System.currentTimeMillis ();
1441 // Get a handle to the Catalog Database
1442 CatalogDatabase db = getCatalogDB ();
1444 // Make sure DB connection is always closed
1446 if (isNullOrEmpty (cloudSiteId)
1447 || isNullOrEmpty(tenantId)
1448 || isNullOrEmpty(networkId)) {
1449 String error = "Missing mandatory parameter cloudSiteId, tenantId or networkId";
1450 LOGGER.error (MessageEnum.RA_MISSING_PARAM, "cloudSiteId or tenantId or networkId", "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing mandatory parameter cloudSiteId, tenantId or networkId");
1451 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
1452 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1455 // Retrieve the Network Resource definition
1456 NetworkResource networkResource = db.getNetworkResource (networkType);
1458 if (networkResource != null) {
1459 LOGGER.debug ("Got Network definition from Catalog: " + networkResource.toString ());
1461 mode = networkResource.getOrchestrationMode ();
1464 if (NEUTRON_MODE.equals (mode)) {
1466 // Use MsoNeutronUtils for all NEUTRON commands
1467 MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
1468 long deleteNetworkStarttime = System.currentTimeMillis ();
1470 // The deleteNetwork function in MsoNeutronUtils returns success if the network
1471 // was not found. So don't bother to query first.
1472 boolean deleted = neutron.deleteNetwork (networkId, tenantId, cloudSiteId);
1473 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteNetwork", null);
1474 networkDeleted.value = deleted;
1475 } catch (MsoException me) {
1476 me.addContext ("DeleteNetwork");
1477 String error = "Delete Network (neutron): " + networkId
1484 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteNetwork", null);
1485 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Delete Network (neutron)", me);
1486 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1487 throw new NetworkException (me);
1489 } else { // DEFAULT to ("HEAT".equals (mode))
1490 long deleteStackStarttime = System.currentTimeMillis ();
1491 // Use MsoHeatUtils for all HEAT commands
1492 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_NETWORK_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
1495 // The deleteStack function in MsoHeatUtils returns NOTFOUND if the stack was not found or if the stack was deleted.
1496 // So query first to report back if stack WAS deleted or just NOTOFUND
1497 StackInfo heatStack = null;
1498 heatStack = heat.queryStack(cloudSiteId, tenantId, networkId);
1499 if (heatStack != null && heatStack.getStatus() != HeatStatus.NOTFOUND)
1501 heat.deleteStack (tenantId, cloudSiteId, networkId, true);
1502 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteStack", null);
1503 networkDeleted.value = true;
1507 networkDeleted.value = false;
1509 } catch (MsoException me) {
1510 me.addContext ("DeleteNetwork");
1511 String error = "Delete Network (heat): " + networkId
1518 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteStack", null);
1519 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Delete Network (heat)", me);
1520 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1521 throw new NetworkException (me);
1528 // On success, nothing is returned.
1529 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully deleted network");
1533 public CatalogDatabase getCatalogDB() {
1534 return new CatalogDatabase();
1538 * This web service endpoint will rollback a previous Create VNF operation.
1539 * A rollback object is returned to the client in a successful creation
1540 * response. The client can pass that object as-is back to the rollbackVnf
1541 * operation to undo the creation.
1543 * The rollback includes removing the VNF and deleting the tenant if the
1544 * tenant did not exist prior to the VNF creation.
1547 public void rollbackNetwork (NetworkRollback rollback) throws NetworkException {
1548 MsoLogger.setServiceName ("RollbackNetwork");
1549 // Will capture execution time for metrics
1550 long startTime = System.currentTimeMillis ();
1552 if (rollback == null) {
1553 LOGGER.error (MessageEnum.RA_ROLLBACK_NULL, "Openstack", "", MsoLogger.ErrorCode.DataError, "rollback is null");
1554 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, "No action to perform");
1558 MsoLogger.setLogContext (rollback.getMsoRequest());
1560 // Get the elements of the VnfRollback object for easier access
1561 String cloudSiteId = rollback.getCloudId ();
1562 String tenantId = rollback.getTenantId ();
1563 String networkId = rollback.getNetworkStackId ();
1564 String networkType = rollback.getNetworkType ();
1566 LOGGER.debug ("*** ROLLBACK Network " + networkId + " in " + cloudSiteId + "/" + tenantId);
1568 // rollback may be null (e.g. if network already existed when Create was called)
1569 // Get a handle to the Catalog Database
1570 CatalogDatabase db = getCatalogDB ();
1572 // Make sure DB connection is always closed
1575 // Retrieve the Network Resource definition
1576 NetworkResource networkResource = db.getNetworkResource (networkType);
1578 if (networkResource != null) {
1580 LOGGER.debug ("Got Network definition from Catalog: " + networkResource.toString ());
1582 mode = networkResource.getOrchestrationMode ();
1585 if (rollback.getNetworkCreated ()) {
1586 // Rolling back a newly created network, so delete it.
1587 if (NEUTRON_MODE.equals (mode)) {
1588 // Use MsoNeutronUtils for all NEUTRON commands
1589 MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
1590 long deleteNetworkStarttime = System.currentTimeMillis ();
1592 // The deleteNetwork function in MsoNeutronUtils returns success if the network
1593 // was not found. So don't bother to query first.
1594 neutron.deleteNetwork (networkId, tenantId, cloudSiteId);
1595 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteNetwork", null);
1596 } catch (MsoException me) {
1597 me.addContext ("RollbackNetwork");
1598 String error = "Rollback Network (neutron): " + networkId
1605 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteNetwork", null);
1606 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - Rollback Network (neutron)", me);
1607 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1608 throw new NetworkException (me);
1610 } else { // DEFAULT to if ("HEAT".equals (mode))
1611 // Use MsoHeatUtils for all HEAT commands
1612 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_NETWORK_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
1613 long deleteStackStarttime = System.currentTimeMillis ();
1615 // The deleteStack function in MsoHeatUtils returns success if the stack
1616 // was not found. So don't bother to query first.
1617 heat.deleteStack (tenantId, cloudSiteId, networkId, true);
1618 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteStack", null);
1619 } catch (MsoException me) {
1620 me.addContext ("RollbackNetwork");
1621 String error = "Rollback Network (heat): " + networkId
1628 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteStack", null);
1629 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - Rollback Network (heat)", me);
1630 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1631 throw new NetworkException (me);
1638 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully rolled back network");
1642 private String validateNetworkParams (NetworkType neutronNetworkType,
1644 String physicalNetwork,
1645 List <Integer> vlans,
1646 List <String> routeTargets) {
1648 StringBuilder missing = new StringBuilder ();
1649 if (isNullOrEmpty(networkName)) {
1650 missing.append ("networkName");
1654 if (neutronNetworkType == NetworkType.PROVIDER || neutronNetworkType == NetworkType.MULTI_PROVIDER) {
1655 if (isNullOrEmpty(physicalNetwork)) {
1656 missing.append (sep).append ("physicalNetworkName");
1659 if (vlans == null || vlans.isEmpty ()) {
1660 missing.append (sep).append (VLANS);
1664 return missing.toString ();
1667 private Map <String, Object> populateNetworkParams (NetworkType neutronNetworkType,
1669 String physicalNetwork,
1670 List <Integer> vlans,
1671 List <String> routeTargets,
1674 boolean aic3template) {
1675 // Build the common set of HEAT template parameters
1676 Map <String, Object> stackParams = new HashMap <String, Object> ();
1677 stackParams.put ("network_name", networkName);
1679 if (neutronNetworkType == NetworkType.PROVIDER) {
1680 // For Provider type
1681 stackParams.put (PHYSICAL_NETWORK, physicalNetwork);
1682 stackParams.put ("vlan", vlans.get (0).toString ());
1683 } else if (neutronNetworkType == NetworkType.MULTI_PROVIDER) {
1684 // For Multi-provider, PO supports a custom resource extension of ProviderNet.
1685 // It supports all ProviderNet properties except segmentation_id, and adds a
1686 // comma-separated-list of VLANs as a "segments" property.
1687 // Note that this does not match the Neutron definition of Multi-Provider network,
1688 // which contains a list of 'segments', each having physical_network, network_type,
1689 // and segmentation_id.
1690 StringBuilder buf = new StringBuilder ();
1692 for (Integer vlan : vlans) {
1693 buf.append (sep).append (vlan.toString ());
1696 String csl = buf.toString ();
1698 stackParams.put (PHYSICAL_NETWORK, physicalNetwork);
1699 stackParams.put (VLANS, csl);
1701 if (routeTargets != null && !routeTargets.isEmpty()) {
1702 StringBuilder buf = new StringBuilder ();
1704 for (String rt : routeTargets) {
1705 if (!isNullOrEmpty(rt))
1708 buf.append (sep).append ("target:" + rt.toString ());
1710 buf.append (sep).append (rt.toString ());
1715 String csl = buf.toString ();
1717 stackParams.put ("route_targets", csl);
1719 if (isNullOrEmpty(shared)) {
1720 stackParams.put ("shared", "False");
1722 stackParams.put ("shared", shared);
1724 if (isNullOrEmpty(external)) {
1725 stackParams.put ("external", "False");
1727 stackParams.put ("external", external);
1734 /** policyRef_list structure in stackParams
1737 "network_policy_refs_data_sequence": {
1738 "network_policy_refs_data_sequence_major": "1",
1739 "network_policy_refs_data_sequence_minor": "0"
1743 "network_policy_refs_data_sequence": {
1744 "network_policy_refs_data_sequence_major": "2",
1745 "network_policy_refs_data_sequence_minor": "0"
1750 private void mergePolicyRefs(List <String> pFqdns, Map <String, Object> stackParams) throws MsoException {
1752 List<ContrailPolicyRef> prlist = new ArrayList <ContrailPolicyRef> ();
1754 for (String pf : pFqdns) {
1755 if (!isNullOrEmpty(pf))
1757 ContrailPolicyRef pr = new ContrailPolicyRef();
1758 pr.populate(String.valueOf(index), "0");
1760 LOGGER.debug("Contrail PolicyRefs Data:" + pr.toString());
1765 JsonNode node = null;
1768 ObjectMapper mapper = new ObjectMapper();
1769 node = mapper.convertValue(prlist, JsonNode.class);
1770 String jsonString = mapper.writeValueAsString(prlist);
1771 LOGGER.debug("Json PolicyRefs Data:" + jsonString);
1775 String error = "Error creating JsonNode for policyRefs Data";
1776 LOGGER.error (MessageEnum.RA_MARSHING_ERROR, error, "Openstack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception creating JsonNode for policyRefs Data", e);
1777 throw new MsoAdapterException (error);
1780 if (pFqdns != null && node != null)
1782 StringBuilder buf = new StringBuilder ();
1784 for (String pf : pFqdns) {
1785 if (!isNullOrEmpty(pf))
1787 buf.append (sep).append (pf.toString ());
1791 String csl = buf.toString ();
1792 stackParams.put ("policy_refs", csl);
1793 stackParams.put ("policy_refsdata", node);
1796 LOGGER.debug ("StackParams updated with policy refs");
1800 private void mergeRouteTableRefs(List <String> rtFqdns, Map <String, Object> stackParams) throws MsoException {
1803 if (rtFqdns != null)
1805 StringBuilder buf = new StringBuilder ();
1807 for (String rtf : rtFqdns) {
1808 if (!isNullOrEmpty(rtf))
1810 buf.append (sep).append (rtf.toString ());
1814 String csl = buf.toString ();
1815 stackParams.put ("route_table_refs", csl);
1818 LOGGER.debug ("StackParams updated with route_table refs");
1823 /*** Subnet Output structure from Juniper
1828 "ip_prefix": "10.100.1.0",
1831 "addr_from_start": null,
1832 "enable_dhcp": false,
1833 "default_gateway": "10.100.1.1",
1834 "dns_nameservers": [],
1835 "dhcp_option_list": null,
1836 "subnet_uuid": "10391fbf-6b9c-4160-825d-2d018b7649cf",
1837 "allocation_pools": [
1839 "start": "10.100.1.3",
1843 "start": "10.100.1.6",
1847 "host_routes": null,
1848 "dns_server_address": "10.100.1.13",
1849 "subnet_name": "subnet_MsoNW1_692c9032-e1a2-4d64-828c-7b9a4fcc05b0"
1853 "ip_prefix": "10.100.2.16",
1856 "addr_from_start": null,
1857 "enable_dhcp": true,
1858 "default_gateway": "10.100.2.17",
1859 "dns_nameservers": [],
1860 "dhcp_option_list": null,
1861 "subnet_uuid": "c7aac5ea-66fe-443a-85f9-9c38a608c0f6",
1862 "allocation_pools": [
1864 "start": "10.100.2.18",
1865 "end": "10.100.2.20"
1868 "host_routes": null,
1869 "dns_server_address": "10.100.2.29",
1870 "subnet_name": "subnet_MsoNW1_692c9032-e1a2-4d64-828c-7b9a4fcc05b1"
1876 private String mergeSubnetsAIC3 (String heatTemplate, List <Subnet> subnets, Map <String, Object> stackParams) throws MsoException {
1879 List<ContrailSubnet> cslist = new ArrayList <ContrailSubnet> ();
1880 for (Subnet subnet : subnets) {
1881 ContrailSubnet cs = new ContrailSubnet();
1882 LOGGER.debug("Input Subnet:" + subnet.toString());
1883 cs.populateWith(subnet);
1884 LOGGER.debug("Contrail Subnet:" + cs.toString());
1888 JsonNode node = null;
1891 ObjectMapper mapper = new ObjectMapper();
1892 node = mapper.convertValue(cslist, JsonNode.class);
1893 String jsonString = mapper.writeValueAsString(cslist);
1894 LOGGER.debug("Json Subnet List:" + jsonString);
1898 String error = "Error creating JsonNode from input subnets";
1899 LOGGER.error (MessageEnum.RA_MARSHING_ERROR, error, "", "", MsoLogger.ErrorCode.DataError, "Exception creating JsonNode from input subnets", e);
1900 throw new MsoAdapterException (error);
1905 stackParams.put ("subnet_list", node);
1907 //Outputs - All subnets are in one ipam_subnets structure
1908 String outputTempl = " subnet:\n" + " description: Openstack subnet identifier\n"
1909 + " value: { get_attr: [network, network_ipam_refs, 0, attr]}\n";
1911 // append outputs in heatTemplate
1912 int outputsIdx = heatTemplate.indexOf ("outputs:");
1913 heatTemplate = insertStr (heatTemplate, outputTempl, outputsIdx + 8);
1914 LOGGER.debug ("Template updated with all AIC3.0 subnets:" + heatTemplate);
1915 return heatTemplate;
1919 private String mergeSubnets (String heatTemplate, List <Subnet> subnets) throws MsoException {
1921 String resourceTempl = " subnet_%subnetId%:\n" + " type: OS::Neutron::Subnet\n"
1924 + " network_id: { get_resource: network }\n"
1925 + " cidr: %cidr%\n";
1927 /* make these optional
1928 + " ip_version: %ipversion%\n"
1929 + " enable_dhcp: %enabledhcp%\n"
1930 + " gateway_ip: %gatewayip%\n"
1931 + " allocation_pools:\n"
1932 + " - start: %poolstart%\n"
1933 + " end: %poolend%\n";
1937 String outputTempl = " subnet_id_%subnetId%:\n" + " description: Openstack subnet identifier\n"
1938 + " value: {get_resource: subnet_%subnetId%}\n";
1942 StringBuilder resourcesBuf = new StringBuilder ();
1943 StringBuilder outputsBuf = new StringBuilder ();
1944 for (Subnet subnet : subnets) {
1946 // build template for each subnet
1947 curR = resourceTempl;
1948 if (subnet.getSubnetId () != null) {
1949 curR = curR.replace ("%subnetId%", subnet.getSubnetId ());
1951 String error = "Missing Required AAI SubnetId for subnet in HEAT Template";
1952 LOGGER.error (MessageEnum.RA_MISSING_PARAM, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing Required AAI ID for subnet in HEAT Template");
1953 throw new MsoAdapterException (error);
1956 if (subnet.getSubnetName () != null) {
1957 curR = curR.replace ("%name%", subnet.getSubnetName ());
1959 curR = curR.replace ("%name%", subnet.getSubnetId ());
1962 if (subnet.getCidr () != null) {
1963 curR = curR.replace ("%cidr%", subnet.getCidr ());
1965 String error = "Missing Required cidr for subnet in HEAT Template";
1966 LOGGER.error (MessageEnum.RA_MISSING_PARAM, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing Required cidr for subnet in HEAT Template");
1967 throw new MsoAdapterException (error);
1970 if (subnet.getIpVersion () != null) {
1971 curR = curR + " ip_version: " + subnet.getIpVersion () + "\n";
1973 if (subnet.getEnableDHCP () != null) {
1974 curR = curR + " enable_dhcp: " + Boolean.toString (subnet.getEnableDHCP ()) + "\n";
1976 if (subnet.getGatewayIp () != null && !subnet.getGatewayIp ().isEmpty() ) {
1977 curR = curR + " gateway_ip: " + subnet.getGatewayIp () + "\n";
1980 if (subnet.getAllocationPools() != null) {
1981 curR = curR + " allocation_pools:\n";
1982 for (Pool pool : subnet.getAllocationPools())
1984 if (!isNullOrEmpty(pool.getStart()) && !isNullOrEmpty(pool.getEnd()))
1986 curR = curR + " - start: " + pool.getStart () + "\n";
1987 curR = curR + " end: " + pool.getEnd () + "\n";
1992 resourcesBuf.append (curR);
1995 curO = curO.replace ("%subnetId%", subnet.getSubnetId ());
1997 outputsBuf.append (curO);
2000 // append resources and outputs in heatTemplate
2001 LOGGER.debug ("Tempate initial:" + heatTemplate);
2002 int outputsIdx = heatTemplate.indexOf ("outputs:");
2003 heatTemplate = insertStr (heatTemplate, outputsBuf.toString (), outputsIdx + 8);
2004 int resourcesIdx = heatTemplate.indexOf ("resources:");
2005 heatTemplate = insertStr (heatTemplate, resourcesBuf.toString (), resourcesIdx + 10);
2007 LOGGER.debug ("Template updated with all subnets:" + heatTemplate);
2008 return heatTemplate;
2011 private Map <String, String> getSubnetUUId(String key, Map <String, Object> outputs, List <Subnet> subnets) {
2013 Map <String, String> sMap = new HashMap <String, String> ();
2016 Object obj = outputs.get(key);
2017 ObjectMapper mapper = new ObjectMapper();
2018 String jStr = mapper.writeValueAsString(obj);
2019 LOGGER.debug ("Subnet_Ipam Output JSON String:" + obj.getClass() + " " + jStr);
2021 JsonNode rootNode = mapper.readTree(jStr);
2022 for (JsonNode sNode : rootNode.path("ipam_subnets"))
2024 LOGGER.debug("Output Subnet Node" + sNode.toString());
2025 String name = sNode.path("subnet_name").getTextValue();
2026 String uuid = sNode.path("subnet_uuid").getTextValue();
2027 String aaiId = name; // default
2028 // try to find aaiId for name in input subnetList
2029 if (subnets != null)
2031 for (Subnet subnet : subnets)
2033 if ( subnet != null && !isNullOrEmpty(subnet.getSubnetName()))
2035 if (subnet.getSubnetName().equals(name))
2037 aaiId = subnet.getSubnetId();
2043 sMap.put(aaiId, uuid); //bpmn needs aaid to uuid map
2048 LOGGER.error (MessageEnum.RA_MARSHING_ERROR, "error getting subnet-uuids", "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception getting subnet-uuids", e);
2051 LOGGER.debug ("Return sMap" + sMap.toString());
2055 private static String insertStr (String template, String snippet, int index) {
2057 String updatedTemplate = "";
2059 LOGGER.debug ("Index:" + index + " Snippet:" + snippet);
2061 String templateBeg = template.substring (0, index);
2062 String templateEnd = template.substring (index);
2064 updatedTemplate = templateBeg + "\n" + snippet + templateEnd;
2066 LOGGER.debug ("Template updated with a subnet:" + updatedTemplate);
2067 return updatedTemplate;