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://com.att.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 try (CatalogDatabase db = getCatalogDb()) {
285 NetworkResource networkResource = networkCheck (db,
293 String mode = networkResource.getOrchestrationMode ();
294 NetworkType neutronNetworkType = NetworkType.valueOf (networkResource.getNeutronNetworkType ());
296 if (NEUTRON_MODE.equals (mode)) {
298 // Use an MsoNeutronUtils for all neutron commands
299 MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
301 // See if the Network already exists (by name)
302 NetworkInfo netInfo = null;
303 long queryNetworkStarttime = System.currentTimeMillis ();
305 netInfo = neutron.queryNetwork (networkName, tenantId, cloudSiteId);
306 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Response successfully received from OpenStack", "OpenStack", "QueryNetwork", null);
307 } catch (MsoException me) {
308 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while querying network from OpenStack", "OpenStack", "QueryNetwork", null);
309 String error = "Create Network (neutron): query network " + networkName
316 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception while querying network from OpenStack", me);
317 me.addContext (CREATE_NETWORK_CONTEXT);
318 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while querying network from OpenStack");
319 throw new NetworkException (me);
322 if (netInfo != null) {
323 // Exists. If that's OK, return success with the network ID.
324 // Otherwise, return an exception.
325 if (failIfExists != null && failIfExists) {
326 String error = "Create Nework: Network " + networkName
327 + " already exists in "
331 + " with ID " + netInfo.getId();
332 LOGGER.error (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Network already exists");
333 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
334 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
336 // Populate the outputs from the existing network.
337 networkId.value = netInfo.getId ();
338 neutronNetworkId.value = netInfo.getId ();
339 rollback.value = networkRollback; // Default rollback - no updates performed
340 String msg = "Found Existing network, status=" + netInfo.getStatus () + " for Neutron mode";
341 LOGGER.warn (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "", "", MsoLogger.ErrorCode.DataError, "Found Existing network, status=" + netInfo.getStatus ());
342 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, msg);
347 long createNetworkStarttime = System.currentTimeMillis ();
349 netInfo = neutron.createNetwork (cloudSiteId,
355 LOGGER.recordMetricEvent (createNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Response successfully received from OpenStack", "OpenStack", "CreateNetwork", null);
356 } catch (MsoException me) {
357 me.addContext (CREATE_NETWORK_CONTEXT);
358 LOGGER.recordMetricEvent (createNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while communicate with OpenStack", "OpenStack", "CreateNetwork", null);
359 String error = "Create Network: type " + neutronNetworkType
366 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception while communicate with OpenStack", me);
367 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
369 throw new NetworkException (me);
372 // Note: ignoring MsoNetworkAlreadyExists because we already checked.
374 // If reach this point, network creation is successful.
375 // Since directly created via Neutron, networkId tracked by MSO is the same
376 // as the neutron network ID.
377 networkId.value = netInfo.getId ();
378 neutronNetworkId.value = netInfo.getId ();
380 networkRollback.setNetworkCreated (true);
381 networkRollback.setNetworkId (netInfo.getId ());
382 networkRollback.setNeutronNetworkId (netInfo.getId ());
383 networkRollback.setNetworkType (networkType);
385 LOGGER.debug ("Network " + networkName + " created, id = " + netInfo.getId ());
386 } else if ("HEAT".equals (mode)) {
388 // Use an MsoHeatUtils for all Heat commands
389 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_NETWORK_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
391 HeatTemplate heatTemplate = db.getHeatTemplate (networkResource.getTemplateId ());
392 if (heatTemplate == null) {
393 String error = "Network error - undefined Heat Template. Network Type = " + networkType;
394 LOGGER.error (MessageEnum.RA_PARAM_NOT_FOUND, "Heat Template", "Network Type", networkType, "Openstack", "", MsoLogger.ErrorCode.DataError, "Network error - undefined Heat Template. Network Type = " + networkType);
395 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error); // Alarm on this
399 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataNotFound, error);
400 throw new NetworkException (error, MsoExceptionCategory.INTERNAL);
403 LOGGER.debug ("Got HEAT Template from DB: " + heatTemplate.toString ());
405 // "Fix" the template if it has CR/LF (getting this from Oracle)
406 String template = heatTemplate.getHeatTemplate ();
407 template = template.replaceAll ("\r\n", "\n");
409 boolean aic3template=false;
410 String aic3nw = AIC3_NW;
412 aic3nw = msoPropertiesFactory.getMsoJavaProperties(MSO_PROP_NETWORK_ADAPTER).getProperty(AIC3_NW_PROPERTY, AIC3_NW);
413 } catch (MsoPropertiesException e) {
414 String error = "Unable to get properties:" + MSO_PROP_NETWORK_ADAPTER;
415 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "", "", MsoLogger.ErrorCode.DataError, "Exception - Unable to get properties", e);
418 if (template.contains(aic3nw))
421 // First, look up to see if the Network already exists (by name).
422 // For HEAT orchestration of networks, the stack name will always match the network name
423 StackInfo heatStack = null;
424 long queryNetworkStarttime = System.currentTimeMillis ();
426 heatStack = heat.queryStack (cloudSiteId, tenantId, networkName);
427 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Response successfully received from OpenStack", "OpenStack", "QueryNetwork", null);
428 } catch (MsoException me) {
429 me.addContext (CREATE_NETWORK_CONTEXT);
430 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, "Exception while querying stack from OpenStack", "OpenStack", "QueryNetwork", null);
431 String error = "Create Network (heat): query network " + networkName
438 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkName, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception while querying stack from OpenStack", me);
439 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
440 throw new NetworkException (me);
443 if (heatStack != null && !(heatStack.getStatus () == HeatStatus.NOTFOUND)) {
444 // Stack exists. Return success or error depending on input directive
445 if (failIfExists != null && failIfExists) {
446 String error = "CreateNetwork: Stack " + networkName
447 + " already exists in "
451 + " as " + heatStack.getCanonicalName();
452 LOGGER.error (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "", "", MsoLogger.ErrorCode.DataError, "Network already exists");
453 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Conflict, error);
454 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
456 // Populate the outputs from the existing stack.
457 networkId.value = heatStack.getCanonicalName ();
458 neutronNetworkId.value = (String) heatStack.getOutputs ().get (NETWORK_ID);
459 rollback.value = networkRollback; // Default rollback - no updates performed
462 networkFqdn.value = (String) heatStack.getOutputs().get(NETWORK_FQDN);
464 Map <String, Object> outputs = heatStack.getOutputs ();
465 Map <String, String> sMap = new HashMap <String, String> ();
466 if (outputs != null) {
467 for (String key : outputs.keySet ()) {
468 if (key != null && key.startsWith ("subnet")) {
469 if (aic3template) //one subnet_id output
471 Map <String, String> map = getSubnetUUId(key, outputs, subnets);
474 else //multiples subnet_%aaid% outputs
476 String subnetUUId = (String) outputs.get(key);
477 sMap.put (key.substring("subnet_id_".length()), subnetUUId);
482 subnetIdMap.value = sMap;
483 String msg = "Found Existing network stack, status=" + heatStack.getStatus () + " for Heat mode";
484 LOGGER.warn (MessageEnum.RA_NETWORK_ALREADY_EXIST, networkName, cloudSiteId, tenantId, "", "", MsoLogger.ErrorCode.DataError, "Found Existing network stack, status=" + heatStack.getStatus ());
485 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Suc, "Found Existing network stack");
490 // Ready to deploy the new Network
491 // Build the common set of HEAT template parameters
492 Map <String, Object> stackParams = populateNetworkParams (neutronNetworkType,
501 // Validate (and update) the input parameters against the DB definition
502 // Shouldn't happen unless DB config is wrong, since all networks use same inputs
503 // and inputs were already validated.
505 stackParams = heat.validateStackParams (stackParams, heatTemplate);
506 } catch (IllegalArgumentException e) {
507 String error = "Create Network: Configuration Error: " + e.getMessage ();
508 LOGGER.error (MessageEnum.RA_CONFIG_EXC, e.getMessage(), "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception - Create Network, Configuration Error", e);
509 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error); // Alarm on this
513 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
514 // Input parameters were not valid
515 throw new NetworkException (error, MsoExceptionCategory.INTERNAL);
518 if (subnets != null) {
522 template = mergeSubnetsAIC3 (template, subnets, stackParams);
526 template = mergeSubnets (template, subnets);
528 } catch (MsoException me) {
529 me.addContext (CREATE_NETWORK_CONTEXT);
530 String error = "Create Network (heat): type " + neutronNetworkType
537 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception Create Network, merging subnets", me);
538 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
539 throw new NetworkException (me);
543 if (policyFqdns != null && !policyFqdns.isEmpty() && aic3template) {
545 mergePolicyRefs (policyFqdns, stackParams);
546 } catch (MsoException me) {
547 me.addContext (CREATE_NETWORK_CONTEXT);
548 String error = "Create Network (heat) mergePolicyRefs type " + neutronNetworkType
555 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception Create Network, merging policyRefs", me);
556 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
557 throw new NetworkException (me);
561 if (routeTableFqdns != null && !routeTableFqdns.isEmpty() && aic3template) {
563 mergeRouteTableRefs (routeTableFqdns, stackParams);
564 } catch (MsoException me) {
565 me.addContext (CREATE_NETWORK_CONTEXT);
566 String error = "Create Network (heat) mergeRouteTableRefs type " + neutronNetworkType
573 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception Create Network, merging routeTableRefs", me);
574 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
575 throw new NetworkException (me);
579 // Deploy the network stack
580 // Ignore MsoStackAlreadyExists exception because we already checked.
581 long createStackStartTime = System.currentTimeMillis ();
585 heatStack = heat.createStack (cloudSiteId,
591 heatTemplate.getTimeoutMinutes (),
595 backout.booleanValue());
596 } catch (MsoException me) {
597 me.addContext (CREATE_NETWORK_CONTEXT);
598 String error = "Create Network (heat): type " + neutronNetworkType
605 LOGGER.error (MessageEnum.RA_CREATE_NETWORK_EXC, networkName, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception creating network", me);
606 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
607 throw new NetworkException (me);
610 // Reach this point if createStack is successful.
612 // For Heat-based orchestration, the MSO-tracked network ID is the heat stack,
613 // and the neutronNetworkId is the network UUID returned in stack outputs.
614 networkId.value = heatStack.getCanonicalName ();
615 neutronNetworkId.value = (String) heatStack.getOutputs ().get (NETWORK_ID);
618 networkFqdn.value = (String) heatStack.getOutputs().get(NETWORK_FQDN);
620 Map <String, Object> outputs = heatStack.getOutputs ();
621 Map <String, String> sMap = new HashMap <String, String> ();
622 if (outputs != null) {
623 for (String key : outputs.keySet ()) {
624 if (key != null && key.startsWith ("subnet")) {
625 if (aic3template) //one subnet output expected
627 Map <String, String> map = getSubnetUUId(key, outputs, subnets);
630 else //multiples subnet_%aaid% outputs allowed
632 String subnetUUId = (String) outputs.get(key);
633 sMap.put (key.substring("subnet_id_".length()), subnetUUId);
638 subnetIdMap.value = sMap;
640 rollback.value = networkRollback;
641 // Populate remaining rollback info and response parameters.
642 networkRollback.setNetworkStackId (heatStack.getCanonicalName ());
643 networkRollback.setNeutronNetworkId ((String) heatStack.getOutputs ().get (NETWORK_ID));
644 networkRollback.setNetworkCreated (true);
645 networkRollback.setNetworkType (networkType);
647 LOGGER.debug ("Network " + networkName + " successfully created via HEAT");
650 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.Suc, "Successfully created network");
655 public void updateNetwork (String cloudSiteId,
660 String physicalNetworkName,
661 List <Integer> vlans,
662 List <Subnet> subnets,
663 MsoRequest msoRequest,
664 Holder <Map <String, String>> subnetIdMap,
665 Holder <NetworkRollback> rollback) throws NetworkException {
666 updateNetwork (cloudSiteId,
686 public void updateNetworkContrail (String cloudSiteId,
691 List <String> routeTargets,
694 List <Subnet> subnets,
695 List <String> policyFqdns,
696 List<String> routeTableFqdns,
697 MsoRequest msoRequest,
698 Holder <Map <String, String>> subnetIdMap,
699 Holder <NetworkRollback> rollback) throws NetworkException {
700 updateNetwork (cloudSiteId,
719 * This is the "Update Network" web service implementation.
720 * It will update an existing Network of the requested type in the specified cloud
721 * and tenant. The typical use will be to replace the VLANs with the supplied
722 * list (to add or remove a VLAN), but other properties may be updated as well.
724 * There will be a pre-defined set of network types defined in the MSO Catalog.
725 * All such networks will have a similar configuration, based on the allowable
726 * Openstack networking definitions. This includes basic networks, provider
727 * networks (with a single VLAN), and multi-provider networks (one or more VLANs).
729 * Initially, all provider networks must currently be "vlan" type, and multi-provider
730 * networks must be multiple VLANs on the same physical network.
732 * This service supports two modes of Network update:
733 * - via Heat Templates
735 * The network orchestration mode for each network type is declared in its
736 * catalog definition. All Heat-based templates must support some subset of
737 * the same input parameters: network_name, physical_network, vlan, segments.
739 * The method returns a NetworkRollback object. This object can be passed
740 * as-is to the rollbackNetwork operation to undo everything that was updated.
741 * This is useful if a network is successfully updated but orchestration
742 * fails on a subsequent operation.
744 private void updateNetwork (String cloudSiteId,
749 String physicalNetworkName,
750 List <Integer> vlans,
751 List <String> routeTargets,
754 List <Subnet> subnets,
755 List <String> policyFqdns,
756 List<String> routeTableFqdns,
757 MsoRequest msoRequest,
758 Holder <Map <String, String>> subnetIdMap,
759 Holder <NetworkRollback> rollback) throws NetworkException {
760 MsoLogger.setLogContext (msoRequest);
761 MsoLogger.setServiceName ("UpdateNetwork");
762 LOGGER.debug ("***UPDATE Network adapter with Network: " + networkName
771 // Will capture execution time for metrics
772 long startTime = System.currentTimeMillis ();
774 // Build a default rollback object (no actions performed)
775 NetworkRollback networkRollback = new NetworkRollback ();
776 networkRollback.setCloudId (cloudSiteId);
777 networkRollback.setTenantId (tenantId);
778 networkRollback.setMsoRequest (msoRequest);
780 cloudConfig = cloudConfigFactory.getCloudConfig ();
781 CloudSite cloudSite = cloudConfig.getCloudSite (cloudSiteId);
782 if (cloudSite == null) {
783 String error = "UpdateNetwork: Configuration Error. Stack " + networkName + " in "
788 + " CloudSite does not exist in MSO Configuration";
789 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "CloudSite does not exist in MSO Configuration");
790 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
791 // Set the detailed error as the Exception 'message'
792 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
795 try(CatalogDatabase db = getCatalogDb()) {
796 NetworkResource networkResource = networkCheck (db,
804 String mode = networkResource.getOrchestrationMode ();
805 NetworkType neutronNetworkType = NetworkType.valueOf (networkResource.getNeutronNetworkType ());
807 // Use an MsoNeutronUtils for all Neutron commands
808 MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
810 if (NEUTRON_MODE.equals (mode)) {
812 // Verify that the Network exists
813 // For Neutron-based orchestration, the networkId is the Neutron Network UUID.
814 NetworkInfo netInfo = null;
815 long queryNetworkStarttime = System.currentTimeMillis ();
817 netInfo = neutron.queryNetwork (networkId, tenantId, cloudSiteId);
818 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryNetwork", null);
819 } catch (MsoException me) {
820 me.addContext (UPDATE_NETWORK_CONTEXT);
821 String error = "Update Network (neutron): query " + networkId
828 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryNetwork", null);
829 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "QueryNetwork", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - queryNetwork", me);
830 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
831 throw new NetworkException (me);
834 if (netInfo == null) {
835 String error = "Update Nework: Network " + networkId
836 + " does not exist in "
840 LOGGER.error (MessageEnum.RA_NETWORK_NOT_FOUND, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Network not found");
841 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
842 // Does not exist. Throw an exception (can't update a non-existent network)
843 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
845 long updateNetworkStarttime = System.currentTimeMillis ();
847 netInfo = neutron.updateNetwork (cloudSiteId,
853 LOGGER.recordMetricEvent (updateNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "UpdateNetwork", null);
854 } catch (MsoException me) {
855 me.addContext (UPDATE_NETWORK_CONTEXT);
856 String error = "Update Network (neutron): " + networkId
863 LOGGER.error (MessageEnum.RA_UPDATE_NETWORK_ERR, networkId, cloudSiteId, tenantId, "Openstack", "updateNetwork", MsoLogger.ErrorCode.DataError, "Exception - updateNetwork", me);
864 LOGGER.recordMetricEvent (updateNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "UpdateNetwork", null);
865 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
866 throw new NetworkException (me);
869 // Add the network ID and previously queried vlans to the rollback object
870 networkRollback.setNetworkId (netInfo.getId ());
871 networkRollback.setNeutronNetworkId (netInfo.getId ());
872 networkRollback.setNetworkType (networkType);
873 // Save previous parameters
874 networkRollback.setNetworkName (netInfo.getName ());
875 networkRollback.setPhysicalNetwork (netInfo.getProvider ());
876 networkRollback.setVlans (netInfo.getVlans ());
878 LOGGER.debug ("Network " + networkId + " updated, id = " + netInfo.getId ());
879 } else if ("HEAT".equals (mode)) {
881 // Use an MsoHeatUtils for all Heat commands
882 MsoHeatUtilsWithUpdate heat = new MsoHeatUtilsWithUpdate (MSO_PROP_NETWORK_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
884 // First, look up to see that the Network already exists.
885 // For Heat-based orchestration, the networkId is the network Stack ID.
886 StackInfo heatStack = null;
887 long queryStackStarttime = System.currentTimeMillis ();
889 heatStack = heat.queryStack (cloudSiteId, tenantId, networkName);
890 LOGGER.recordMetricEvent (queryStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", null);
891 } catch (MsoException me) {
892 me.addContext (UPDATE_NETWORK_CONTEXT);
893 String error = "UpdateNetwork (heat): query " + networkName
900 LOGGER.recordMetricEvent (queryStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryStack", null);
901 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Exception - QueryStack", me);
902 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
903 throw new NetworkException (me);
906 if (heatStack == null || (heatStack.getStatus () == HeatStatus.NOTFOUND)) {
907 String error = "UpdateNetwork: Stack " + networkName
908 + " does not exist in "
912 LOGGER.error (MessageEnum.RA_NETWORK_NOT_FOUND, networkId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Network not found");
913 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
914 // Network stack does not exist. Return an error
915 throw new NetworkException(error, MsoExceptionCategory.USERDATA);
918 // Get the previous parameters for rollback
919 Map <String, Object> heatParams = heatStack.getParameters ();
921 String previousNetworkName = (String) heatParams.get ("network_name");
922 String previousPhysicalNetwork = (String) heatParams.get (PHYSICAL_NETWORK);
924 List <Integer> previousVlans = new ArrayList <Integer> ();
925 String vlansParam = (String) heatParams.get (VLANS);
926 if (vlansParam != null) {
927 for (String vlan : vlansParam.split (",")) {
929 previousVlans.add (Integer.parseInt (vlan));
930 } catch (NumberFormatException e) {
931 LOGGER.warn (MessageEnum.RA_VLAN_PARSE, networkId, vlansParam, "", "", MsoLogger.ErrorCode.DataError, "Exception - VLAN parse", e);
935 LOGGER.debug ("Update Stack: Previous VLANS: " + previousVlans);
937 // Ready to deploy the updated Network via Heat
939 HeatTemplate heatTemplate = db.getHeatTemplate (networkResource.getTemplateId ());
940 if (heatTemplate == null) {
941 String error = "Network error - undefined Heat Template. Network Type=" + networkType;
942 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);
943 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
944 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
945 throw new NetworkException (error, MsoExceptionCategory.INTERNAL);
948 LOGGER.debug ("Got HEAT Template from DB: " + heatTemplate.toString ());
950 // "Fix" the template if it has CR/LF (getting this from Oracle)
951 String template = heatTemplate.getHeatTemplate ();
952 template = template.replaceAll ("\r\n", "\n");
954 boolean aic3template=false;
955 String aic3nw = AIC3_NW;
957 aic3nw = msoPropertiesFactory.getMsoJavaProperties(MSO_PROP_NETWORK_ADAPTER).getProperty(AIC3_NW_PROPERTY, AIC3_NW);
958 } catch (MsoPropertiesException e) {
959 String error = "Unable to get properties:" + MSO_PROP_NETWORK_ADAPTER;
960 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - Unable to get properties", e);
962 if (template.contains(aic3nw))
965 // Build the common set of HEAT template parameters
966 Map <String, Object> stackParams = populateNetworkParams (neutronNetworkType,
975 // Validate (and update) the input parameters against the DB definition
976 // Shouldn't happen unless DB config is wrong, since all networks use same inputs
978 stackParams = heat.validateStackParams (stackParams, heatTemplate);
979 } catch (IllegalArgumentException e) {
980 String error = "UpdateNetwork: Configuration Error: Network Type=" + networkType;
981 LOGGER.error (MessageEnum.RA_CONFIG_EXC, "Network Type=" + networkType, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork: Configuration Error");
982 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
983 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.SchemaError, error);
984 throw new NetworkException (error, MsoExceptionCategory.INTERNAL, e);
987 if (subnets != null) {
991 template = mergeSubnetsAIC3 (template, subnets, stackParams);
995 template = mergeSubnets (template, subnets);
997 } catch (MsoException me) {
998 me.addContext (UPDATE_NETWORK_CONTEXT);
999 String error = "Update Network (heat): type " + neutronNetworkType
1006 LOGGER.error (MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergeSubnets ", me);
1007 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
1008 throw new NetworkException (me);
1012 if (policyFqdns != null && aic3template) {
1014 mergePolicyRefs (policyFqdns, stackParams);
1015 } catch (MsoException me) {
1016 me.addContext (UPDATE_NETWORK_CONTEXT);
1017 String error = "UpdateNetwork (heat) mergePolicyRefs type " + neutronNetworkType
1024 LOGGER.error (MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergePolicyRefs", me);
1025 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
1026 throw new NetworkException (me);
1030 if (routeTableFqdns != null && !routeTableFqdns.isEmpty() && aic3template) {
1032 mergeRouteTableRefs (routeTableFqdns, stackParams);
1033 } catch (MsoException me) {
1034 me.addContext (UPDATE_NETWORK_CONTEXT);
1035 String error = "UpdateNetwork (heat) mergeRouteTableRefs type " + neutronNetworkType
1042 LOGGER.error (MessageEnum.RA_UPDATE_NETWORK_ERR, neutronNetworkType.toString(), cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception - UpdateNetwork mergeRouteTableRefs", me);
1043 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.InternalError, error);
1044 throw new NetworkException (me);
1048 // Update the network stack
1049 // Ignore MsoStackNotFound exception because we already checked.
1050 long updateStackStarttime = System.currentTimeMillis ();
1052 heatStack = heat.updateStack (cloudSiteId,
1058 heatTemplate.getTimeoutMinutes ());
1059 LOGGER.recordMetricEvent (updateStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "UpdateStack", null);
1060 } catch (MsoException me) {
1061 me.addContext (UPDATE_NETWORK_CONTEXT);
1062 String error = "Update Network: " + networkId + " in " + cloudSiteId + "/" + tenantId + ": " + me;
1063 LOGGER.recordMetricEvent (updateStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "UpdateStack", null);
1064 LOGGER.error (MessageEnum.RA_UPDATE_NETWORK_ERR, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - update network", me);
1065 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1066 throw new NetworkException (me);
1069 Map <String, Object> outputs = heatStack.getOutputs ();
1070 Map <String, String> sMap = new HashMap <String, String> ();
1071 if (outputs != null) {
1072 for (String key : outputs.keySet ()) {
1073 if (key != null && key.startsWith ("subnet")) {
1074 if (aic3template) //one subnet output expected
1076 Map <String, String> map = getSubnetUUId(key, outputs, subnets);
1079 else //multiples subnet_%aaid% outputs allowed
1081 String subnetUUId = (String) outputs.get(key);
1082 sMap.put (key.substring("subnet_id_".length()), subnetUUId);
1087 subnetIdMap.value = sMap;
1089 // Reach this point if createStack is successful.
1090 // Populate remaining rollback info and response parameters.
1091 networkRollback.setNetworkStackId (heatStack.getCanonicalName ());
1092 networkRollback.setNeutronNetworkId ((String) outputs.get (NETWORK_ID));
1093 networkRollback.setNetworkType (networkType);
1094 // Save previous parameters
1095 networkRollback.setNetworkName (previousNetworkName);
1096 networkRollback.setPhysicalNetwork (previousPhysicalNetwork);
1097 networkRollback.setVlans (previousVlans);
1099 rollback.value = networkRollback;
1101 LOGGER.debug ("Network " + networkId + " successfully updated via HEAT");
1104 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully updated network");
1108 private NetworkResource networkCheck (CatalogDatabase db,
1112 String physicalNetworkName,
1113 List <Integer> vlans,
1114 List <String> routeTargets,
1115 CloudSite cloudSite) throws NetworkException {
1116 // Retrieve the Network Resource definition
1117 NetworkResource networkResource = db.getNetworkResource (networkType);
1118 if (networkResource == null) {
1119 String error = "CreateNetwork: Unknown Network Type: " + networkType;
1120 LOGGER.error (MessageEnum.RA_UNKOWN_PARAM, "Network Type", networkType, "OpenStack", "", MsoLogger.ErrorCode.DataError, "CreateNetwork: Unknown Network Type");
1122 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1124 LOGGER.debug ("Got Network definition from Catalog: " + networkResource.toString ());
1126 String mode = networkResource.getOrchestrationMode ();
1127 NetworkType neutronNetworkType = NetworkType.valueOf (networkResource.getNeutronNetworkType ());
1129 // All Networks are orchestrated via HEAT or Neutron
1130 if (!("HEAT".equals (mode) || NEUTRON_MODE.equals (mode))) {
1131 String error = "CreateNetwork: Configuration Error: Network Type = " + networkType;
1132 LOGGER.error (MessageEnum.RA_NETWORK_ORCHE_MODE_NOT_SUPPORT, mode, "OpenStack", "", MsoLogger.ErrorCode.DataError, "CreateNetwork: Configuration Error");
1133 // Alarm on this error, configuration must be fixed
1134 alarmLogger.sendAlarm (MSO_CONFIGURATION_ERROR, MsoAlarmLogger.CRITICAL, error);
1136 throw new NetworkException (error, MsoExceptionCategory.INTERNAL);
1139 MavenLikeVersioning aicV = new MavenLikeVersioning();
1140 aicV.setVersion(cloudSite.getAic_version());
1141 if ((aicV.isMoreRecentThan(networkResource.getAicVersionMin()) || aicV.isTheSameVersion(networkResource.getAicVersionMin())) // aic >= min
1142 && (aicV.isTheSameVersion(networkResource.getAicVersionMax()) || !(aicV.isMoreRecentThan(networkResource.getAicVersionMax())))) //aic <= max
1144 LOGGER.debug ("Network Type:" + networkType
1145 + " VersionMin:" + networkResource.getAicVersionMin()
1146 + " VersionMax:" + networkResource.getAicVersionMax()
1147 + " supported on Cloud:" + cloudSite.getId()
1148 + " with AIC_Version:" + cloudSite.getAic_version());
1152 String error = "Network Type:" + networkType
1153 + " Version_Min:" + networkResource.getAicVersionMin()
1154 + " Version_Max:" + networkResource.getAicVersionMax()
1155 + " not supported on Cloud:" + cloudSite.getId()
1156 + " with AIC_Version:" + cloudSite.getAic_version();
1157 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Network Type not supported on Cloud");
1158 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
1159 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1163 // Validate the Network parameters.
1164 String missing = validateNetworkParams (neutronNetworkType,
1166 physicalNetworkName,
1169 if (!missing.isEmpty ()) {
1170 String error = "Create Network: Missing parameters: " + missing;
1171 LOGGER.error (MessageEnum.RA_MISSING_PARAM, missing, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Create Network: Missing parameters");
1173 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1175 return networkResource;
1179 public void queryNetwork (String cloudSiteId,
1181 String networkNameOrId,
1182 MsoRequest msoRequest,
1183 Holder <Boolean> networkExists,
1184 Holder <String> networkId,
1185 Holder <String> neutronNetworkId,
1186 Holder <NetworkStatus> status,
1187 Holder <List <Integer>> vlans,
1188 Holder <Map <String, String>> subnetIdMap) throws NetworkException {
1189 queryNetwork (cloudSiteId,
1203 public void queryNetworkContrail (String cloudSiteId,
1205 String networkNameOrId,
1206 MsoRequest msoRequest,
1207 Holder <Boolean> networkExists,
1208 Holder <String> networkId,
1209 Holder <String> neutronNetworkId,
1210 Holder <NetworkStatus> status,
1211 Holder <List <String>> routeTargets,
1212 Holder <Map <String, String>> subnetIdMap) throws NetworkException {
1213 queryNetwork (cloudSiteId,
1227 * This is the queryNetwork method. It returns the existence and status of
1228 * the specified network, along with its Neutron UUID and list of VLANs.
1229 * This method attempts to find the network using both Heat and Neutron.
1230 * Heat stacks are first searched based on the provided network name/id.
1231 * If none is found, the Neutron is directly queried.
1233 private void queryNetwork (String cloudSiteId,
1235 String networkNameOrId,
1236 MsoRequest msoRequest,
1237 Holder <Boolean> networkExists,
1238 Holder <String> networkId,
1239 Holder <String> neutronNetworkId,
1240 Holder <NetworkStatus> status,
1241 Holder <List <Integer>> vlans,
1242 Holder <List <String>> routeTargets,
1243 Holder <Map <String, String>> subnetIdMap) throws NetworkException {
1244 MsoLogger.setLogContext (msoRequest);
1245 MsoLogger.setServiceName ("QueryNetwork");
1246 LOGGER.debug ("*** QUERY Network with Network: " + networkNameOrId
1252 // Will capture execution time for metrics
1253 long startTime = System.currentTimeMillis ();
1255 if (isNullOrEmpty (cloudSiteId)
1256 || isNullOrEmpty(tenantId)
1257 || isNullOrEmpty(networkNameOrId)) {
1259 String error = "Missing mandatory parameter cloudSiteId, tenantId or networkId";
1260 LOGGER.error (MessageEnum.RA_MISSING_PARAM, "cloudSiteId or tenantId or networkNameOrId", "OpenStack", "", MsoLogger.ErrorCode.DataError, "Missing mandatory parameter cloudSiteId, tenantId or networkId");
1261 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
1262 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1265 cloudConfig = cloudConfigFactory.getCloudConfig ();
1266 CloudSite cloudSite = cloudConfig.getCloudSite (cloudSiteId);
1267 if (cloudSite == null)
1269 String error = "Configuration Error. Stack " + networkNameOrId + " in "
1274 + " CloudSite does not exist in MSO Configuration";
1275 LOGGER.error (MessageEnum.RA_CONFIG_EXC, error, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Configuration Error");
1276 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.DataError, error);
1277 // Set the detailed error as the Exception 'message'
1278 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1281 // Use MsoNeutronUtils for all NEUTRON commands
1282 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_NETWORK_ADAPTER,msoPropertiesFactory,cloudConfigFactory);
1283 MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
1286 String neutronId = null;
1287 // Try Heat first, since networks may be named the same as the Heat stack
1288 StackInfo heatStack = null;
1289 long queryStackStarttime = System.currentTimeMillis ();
1291 heatStack = heat.queryStack (cloudSiteId, tenantId, networkNameOrId);
1292 LOGGER.recordMetricEvent (queryStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryStack", null);
1293 } catch (MsoException me) {
1294 me.addContext ("QueryNetwork");
1295 String error = "Query Network (heat): " + networkNameOrId
1302 LOGGER.recordMetricEvent (queryStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "BPMN", "QueryStack", null);
1303 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkNameOrId, cloudSiteId, tenantId, "OpenStack", "queryStack", MsoLogger.ErrorCode.DataError, "Exception - Query Network (heat)", me);
1304 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1305 throw new NetworkException (me);
1308 // Populate the outputs based on the returned Stack information
1309 if (heatStack != null && heatStack.getStatus () != HeatStatus.NOTFOUND) {
1310 // Found it. Get the neutronNetworkId for further query
1311 Map <String, Object> outputs = heatStack.getOutputs ();
1312 neutronId = (String) outputs.get (NETWORK_ID);
1315 Map <String, String> sMap = new HashMap <String, String> ();
1316 if (outputs != null) {
1317 for (String key : outputs.keySet ()) {
1318 if (key != null && key.startsWith ("subnet_id_")) //multiples subnet_%aaid% outputs
1320 String subnetUUId = (String) outputs.get(key);
1321 sMap.put (key.substring("subnet_id_".length()), subnetUUId);
1323 else if (key != null && key.startsWith ("subnet")) //one subnet output expected
1325 Map <String, String> map = getSubnetUUId(key, outputs, null);
1331 subnetIdMap.value = sMap;
1333 // Input ID was not a Heat stack ID. Try it directly in Neutron
1334 neutronId = networkNameOrId;
1335 mode = NEUTRON_MODE;
1338 // Query directly against the Neutron Network for the details
1339 // no RouteTargets available for ContrailV2 in neutron net-show
1340 // networkId is heatStackId
1341 long queryNetworkStarttime = System.currentTimeMillis ();
1343 NetworkInfo netInfo = neutron.queryNetwork (neutronId, tenantId, cloudSiteId);
1344 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "QueryNetwork", null);
1345 if (netInfo != null) {
1346 // Found. Populate the output elements
1347 networkExists.value = Boolean.TRUE;
1348 if ("HEAT".equals (mode)) {
1349 networkId.value = heatStack.getCanonicalName ();
1351 networkId.value = netInfo.getId ();
1353 neutronNetworkId.value = netInfo.getId ();
1354 status.value = netInfo.getStatus ();
1356 vlans.value = netInfo.getVlans ();
1358 LOGGER.debug ("Network " + networkNameOrId
1363 + ("HEAT".equals (mode) ? ",NeutronId = " + neutronNetworkId.value : ""));
1365 // Not found. Populate the status fields, leave the rest null
1366 networkExists.value = Boolean.FALSE;
1367 status.value = NetworkStatus.NOTFOUND;
1368 neutronNetworkId.value = null;
1370 vlans.value = new ArrayList <Integer> ();
1372 LOGGER.debug ("Network " + networkNameOrId + " not found");
1374 } catch (MsoException me) {
1375 me.addContext ("QueryNetwork");
1376 String error = "Query Network (neutron): " + networkNameOrId
1383 LOGGER.recordMetricEvent (queryNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "QueryNetwork", null);
1384 LOGGER.error (MessageEnum.RA_QUERY_NETWORK_EXC, networkNameOrId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.DataError, "Exception - Query Network (neutron)", me);
1385 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1386 throw new NetworkException (me);
1388 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully queried network");
1393 * This is the "Delete Network" web service implementation.
1394 * It will delete a Network in the specified cloud and tenant.
1396 * If the network is not found, it is treated as a success.
1398 * This service supports two modes of Network creation/update/delete:
1399 * - via Heat Templates
1401 * The network orchestration mode for each network type is declared in its
1402 * catalog definition.
1404 * For Heat-based orchestration, the networkId should be the stack ID.
1405 * For Neutron-based orchestration, the networkId should be the Neutron network UUID.
1407 * The method returns nothing on success. Rollback is not possible for delete
1408 * commands, so any failure on delete will require manual fallout in the client.
1411 public void deleteNetwork (String cloudSiteId,
1415 MsoRequest msoRequest,
1416 Holder <Boolean> networkDeleted) throws NetworkException {
1417 MsoLogger.setLogContext (msoRequest);
1418 MsoLogger.setServiceName ("DeleteNetwork");
1419 LOGGER.debug ("*** DELETE Network adapter with Network: " + networkId
1425 // Will capture execution time for metrics
1426 long startTime = System.currentTimeMillis ();
1428 try (CatalogDatabase db = getCatalogDb()) {
1429 if (isNullOrEmpty (cloudSiteId)
1430 || isNullOrEmpty(tenantId)
1431 || isNullOrEmpty(networkId)) {
1432 String error = "Missing mandatory parameter cloudSiteId, tenantId or networkId";
1433 LOGGER.error (MessageEnum.RA_MISSING_PARAM, "cloudSiteId or tenantId or networkId", "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing mandatory parameter cloudSiteId, tenantId or networkId");
1434 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
1435 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1438 // Retrieve the Network Resource definition
1439 NetworkResource networkResource = db.getNetworkResource (networkType);
1440 if (networkResource == null) {
1441 String error = "Unknown Network Type: " + networkType;
1442 LOGGER.error (MessageEnum.RA_UNKOWN_PARAM, "Network Type", networkType, "Openstack", "", MsoLogger.ErrorCode.DataError, "Unknown Network Type");
1443 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
1444 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1446 LOGGER.debug ("Got Network definition from Catalog: " + networkResource.toString ());
1448 String mode = networkResource.getOrchestrationMode ();
1450 if (NEUTRON_MODE.equals (mode)) {
1452 // Use MsoNeutronUtils for all NEUTRON commands
1453 MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
1454 long deleteNetworkStarttime = System.currentTimeMillis ();
1456 // The deleteNetwork function in MsoNeutronUtils returns success if the network
1457 // was not found. So don't bother to query first.
1458 boolean deleted = neutron.deleteNetwork (networkId, tenantId, cloudSiteId);
1459 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteNetwork", null);
1460 networkDeleted.value = deleted;
1461 } catch (MsoException me) {
1462 me.addContext ("DeleteNetwork");
1463 String error = "Delete Network (neutron): " + networkId
1470 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteNetwork", null);
1471 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Delete Network (neutron)", me);
1472 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1473 throw new NetworkException (me);
1475 } else if ("HEAT".equals (mode)) {
1476 long deleteStackStarttime = System.currentTimeMillis ();
1477 // Use MsoHeatUtils for all HEAT commands
1478 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_NETWORK_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
1481 // The deleteStack function in MsoHeatUtils returns NOTFOUND if the stack was not found or if the stack was deleted.
1482 // So query first to report back if stack WAS deleted or just NOTOFUND
1483 StackInfo heatStack = null;
1484 heatStack = heat.queryStack(cloudSiteId, tenantId, networkId);
1485 if (heatStack != null && heatStack.getStatus() != HeatStatus.NOTFOUND)
1487 heat.deleteStack (tenantId, cloudSiteId, networkId, true);
1488 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteStack", null);
1489 networkDeleted.value = true;
1493 networkDeleted.value = false;
1495 } catch (MsoException me) {
1496 me.addContext ("DeleteNetwork");
1497 String error = "Delete Network (heat): " + networkId
1504 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteStack", null);
1505 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "Openstack", "", MsoLogger.ErrorCode.DataError, "Delete Network (heat)", me);
1506 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1507 throw new NetworkException (me);
1512 // On success, nothing is returned.
1513 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully deleted network");
1517 public CatalogDatabase getCatalogDb() {
1518 return new CatalogDatabase();
1522 * This web service endpoint will rollback a previous Create VNF operation.
1523 * A rollback object is returned to the client in a successful creation
1524 * response. The client can pass that object as-is back to the rollbackVnf
1525 * operation to undo the creation.
1527 * The rollback includes removing the VNF and deleting the tenant if the
1528 * tenant did not exist prior to the VNF creation.
1531 public void rollbackNetwork (NetworkRollback rollback) throws NetworkException {
1532 MsoLogger.setServiceName ("RollbackNetwork");
1533 // Will capture execution time for metrics
1534 long startTime = System.currentTimeMillis ();
1536 if (rollback == null) {
1537 LOGGER.error (MessageEnum.RA_ROLLBACK_NULL, "Openstack", "", MsoLogger.ErrorCode.DataError, "rollback is null");
1538 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, "No action to perform");
1542 MsoLogger.setLogContext (rollback.getMsoRequest());
1544 // Get the elements of the VnfRollback object for easier access
1545 String cloudSiteId = rollback.getCloudId ();
1546 String tenantId = rollback.getTenantId ();
1547 String networkId = rollback.getNetworkStackId ();
1548 String networkType = rollback.getNetworkType ();
1550 LOGGER.debug ("*** ROLLBACK Network " + networkId + " in " + cloudSiteId + "/" + tenantId);
1552 // rollback may be null (e.g. if network already existed when Create was called)
1553 // Get a handle to the Catalog Database
1555 try (CatalogDatabase db = getCatalogDb()){
1557 // Retrieve the Network Resource definition
1558 NetworkResource networkResource = db.getNetworkResource (networkType);
1559 if (networkResource == null) {
1560 String error = "Rollback Network: Unknown Network Type: " + networkType;
1561 LOGGER.error (MessageEnum.RA_UNKOWN_PARAM, "Network Type", networkType, "Openstack", "", MsoLogger.ErrorCode.DataError, "Rollback Network: Unknown Network Type");
1562 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.BadRequest, error);
1563 throw new NetworkException (error, MsoExceptionCategory.USERDATA);
1565 LOGGER.debug ("Got Network definition from Catalog: " + networkResource.toString ());
1567 String mode = networkResource.getOrchestrationMode ();
1569 if (rollback.getNetworkCreated ()) {
1570 // Rolling back a newly created network, so delete it.
1571 if (NEUTRON_MODE.equals (mode)) {
1572 // Use MsoNeutronUtils for all NEUTRON commands
1573 MsoNeutronUtils neutron = new MsoNeutronUtils (MSO_PROP_NETWORK_ADAPTER, cloudConfigFactory);
1574 long deleteNetworkStarttime = System.currentTimeMillis ();
1576 // The deleteNetwork function in MsoNeutronUtils returns success if the network
1577 // was not found. So don't bother to query first.
1578 neutron.deleteNetwork (networkId, tenantId, cloudSiteId);
1579 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteNetwork", null);
1580 } catch (MsoException me) {
1581 me.addContext ("RollbackNetwork");
1582 String error = "Rollback Network (neutron): " + networkId
1589 LOGGER.recordMetricEvent (deleteNetworkStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteNetwork", null);
1590 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - Rollback Network (neutron)", me);
1591 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1592 throw new NetworkException (me);
1594 } else if ("HEAT".equals (mode)) {
1595 // Use MsoHeatUtils for all HEAT commands
1596 MsoHeatUtils heat = new MsoHeatUtils (MSO_PROP_NETWORK_ADAPTER, msoPropertiesFactory,cloudConfigFactory);
1597 long deleteStackStarttime = System.currentTimeMillis ();
1599 // The deleteStack function in MsoHeatUtils returns success if the stack
1600 // was not found. So don't bother to query first.
1601 heat.deleteStack (tenantId, cloudSiteId, networkId, true);
1602 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully received response from Open Stack", "OpenStack", "DeleteStack", null);
1603 } catch (MsoException me) {
1604 me.addContext ("RollbackNetwork");
1605 String error = "Rollback Network (heat): " + networkId
1612 LOGGER.recordMetricEvent (deleteStackStarttime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error, "OpenStack", "DeleteStack", null);
1613 LOGGER.error (MessageEnum.RA_DELETE_NETWORK_EXC, networkId, cloudSiteId, tenantId, "OpenStack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception - Rollback Network (heat)", me);
1614 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.ERROR, MsoLogger.ResponseCode.CommunicationError, error);
1615 throw new NetworkException (me);
1620 LOGGER.recordAuditEvent (startTime, MsoLogger.StatusCode.COMPLETE, MsoLogger.ResponseCode.Suc, "Successfully rolled back network");
1624 private String validateNetworkParams (NetworkType neutronNetworkType,
1626 String physicalNetwork,
1627 List <Integer> vlans,
1628 List <String> routeTargets) {
1630 StringBuilder missing = new StringBuilder ();
1631 if (isNullOrEmpty(networkName)) {
1632 missing.append ("networkName");
1636 if (neutronNetworkType == NetworkType.PROVIDER || neutronNetworkType == NetworkType.MULTI_PROVIDER) {
1637 if (isNullOrEmpty(physicalNetwork)) {
1638 missing.append (sep).append ("physicalNetworkName");
1641 if (vlans == null || vlans.isEmpty ()) {
1642 missing.append (sep).append (VLANS);
1646 return missing.toString ();
1649 private Map <String, Object> populateNetworkParams (NetworkType neutronNetworkType,
1651 String physicalNetwork,
1652 List <Integer> vlans,
1653 List <String> routeTargets,
1656 boolean aic3template) {
1657 // Build the common set of HEAT template parameters
1658 Map <String, Object> stackParams = new HashMap <String, Object> ();
1659 stackParams.put ("network_name", networkName);
1661 if (neutronNetworkType == NetworkType.PROVIDER) {
1662 // For Provider type
1663 stackParams.put (PHYSICAL_NETWORK, physicalNetwork);
1664 stackParams.put ("vlan", vlans.get (0).toString ());
1665 } else if (neutronNetworkType == NetworkType.MULTI_PROVIDER) {
1666 // For Multi-provider, PO supports a custom resource extension of ProviderNet.
1667 // It supports all ProviderNet properties except segmentation_id, and adds a
1668 // comma-separated-list of VLANs as a "segments" property.
1669 // Note that this does not match the Neutron definition of Multi-Provider network,
1670 // which contains a list of 'segments', each having physical_network, network_type,
1671 // and segmentation_id.
1672 StringBuilder buf = new StringBuilder ();
1674 for (Integer vlan : vlans) {
1675 buf.append (sep).append (vlan.toString ());
1678 String csl = buf.toString ();
1680 stackParams.put (PHYSICAL_NETWORK, physicalNetwork);
1681 stackParams.put (VLANS, csl);
1683 if (routeTargets != null && !routeTargets.isEmpty()) {
1684 StringBuilder buf = new StringBuilder ();
1686 for (String rt : routeTargets) {
1687 if (!isNullOrEmpty(rt))
1690 buf.append (sep).append ("target:" + rt.toString ());
1692 buf.append (sep).append (rt.toString ());
1697 String csl = buf.toString ();
1699 stackParams.put ("route_targets", csl);
1701 if (isNullOrEmpty(shared)) {
1702 stackParams.put ("shared", "False");
1704 stackParams.put ("shared", shared);
1706 if (isNullOrEmpty(external)) {
1707 stackParams.put ("external", "False");
1709 stackParams.put ("external", external);
1716 /** policyRef_list structure in stackParams
1719 "network_policy_refs_data_sequence": {
1720 "network_policy_refs_data_sequence_major": "1",
1721 "network_policy_refs_data_sequence_minor": "0"
1725 "network_policy_refs_data_sequence": {
1726 "network_policy_refs_data_sequence_major": "2",
1727 "network_policy_refs_data_sequence_minor": "0"
1732 private void mergePolicyRefs(List <String> pFqdns, Map <String, Object> stackParams) throws MsoException {
1734 List<ContrailPolicyRef> prlist = new ArrayList <ContrailPolicyRef> ();
1736 for (String pf : pFqdns) {
1737 if (!isNullOrEmpty(pf))
1739 ContrailPolicyRef pr = new ContrailPolicyRef();
1740 pr.populate(String.valueOf(index), "0");
1742 LOGGER.debug("Contrail PolicyRefs Data:" + pr.toString());
1747 JsonNode node = null;
1750 ObjectMapper mapper = new ObjectMapper();
1751 node = mapper.convertValue(prlist, JsonNode.class);
1752 String jsonString = mapper.writeValueAsString(prlist);
1753 LOGGER.debug("Json PolicyRefs Data:" + jsonString);
1757 String error = "Error creating JsonNode for policyRefs Data";
1758 LOGGER.error (MessageEnum.RA_MARSHING_ERROR, error, "Openstack", "", MsoLogger.ErrorCode.BusinessProcesssError, "Exception creating JsonNode for policyRefs Data", e);
1759 throw new MsoAdapterException (error);
1762 if (pFqdns != null && node != null)
1764 StringBuilder buf = new StringBuilder ();
1766 for (String pf : pFqdns) {
1767 if (!isNullOrEmpty(pf))
1769 buf.append (sep).append (pf.toString ());
1773 String csl = buf.toString ();
1774 stackParams.put ("policy_refs", csl);
1775 stackParams.put ("policy_refsdata", node);
1778 LOGGER.debug ("StackParams updated with policy refs");
1782 private void mergeRouteTableRefs(List <String> rtFqdns, Map <String, Object> stackParams) throws MsoException {
1785 if (rtFqdns != null)
1787 StringBuilder buf = new StringBuilder ();
1789 for (String rtf : rtFqdns) {
1790 if (!isNullOrEmpty(rtf))
1792 buf.append (sep).append (rtf.toString ());
1796 String csl = buf.toString ();
1797 stackParams.put ("route_table_refs", csl);
1800 LOGGER.debug ("StackParams updated with route_table refs");
1805 /*** Subnet Output structure from Juniper
1810 "ip_prefix": "10.100.1.0",
1813 "addr_from_start": null,
1814 "enable_dhcp": false,
1815 "default_gateway": "10.100.1.1",
1816 "dns_nameservers": [],
1817 "dhcp_option_list": null,
1818 "subnet_uuid": "10391fbf-6b9c-4160-825d-2d018b7649cf",
1819 "allocation_pools": [
1821 "start": "10.100.1.3",
1825 "start": "10.100.1.6",
1829 "host_routes": null,
1830 "dns_server_address": "10.100.1.13",
1831 "subnet_name": "subnet_MsoNW1_692c9032-e1a2-4d64-828c-7b9a4fcc05b0"
1835 "ip_prefix": "10.100.2.16",
1838 "addr_from_start": null,
1839 "enable_dhcp": true,
1840 "default_gateway": "10.100.2.17",
1841 "dns_nameservers": [],
1842 "dhcp_option_list": null,
1843 "subnet_uuid": "c7aac5ea-66fe-443a-85f9-9c38a608c0f6",
1844 "allocation_pools": [
1846 "start": "10.100.2.18",
1847 "end": "10.100.2.20"
1850 "host_routes": null,
1851 "dns_server_address": "10.100.2.29",
1852 "subnet_name": "subnet_MsoNW1_692c9032-e1a2-4d64-828c-7b9a4fcc05b1"
1858 private String mergeSubnetsAIC3 (String heatTemplate, List <Subnet> subnets, Map <String, Object> stackParams) throws MsoException {
1861 List<ContrailSubnet> cslist = new ArrayList <ContrailSubnet> ();
1862 for (Subnet subnet : subnets) {
1863 ContrailSubnet cs = new ContrailSubnet();
1864 LOGGER.debug("Input Subnet:" + subnet.toString());
1865 cs.populateWith(subnet);
1866 LOGGER.debug("Contrail Subnet:" + cs.toString());
1870 JsonNode node = null;
1873 ObjectMapper mapper = new ObjectMapper();
1874 node = mapper.convertValue(cslist, JsonNode.class);
1875 String jsonString = mapper.writeValueAsString(cslist);
1876 LOGGER.debug("Json Subnet List:" + jsonString);
1880 String error = "Error creating JsonNode from input subnets";
1881 LOGGER.error (MessageEnum.RA_MARSHING_ERROR, error, "", "", MsoLogger.ErrorCode.DataError, "Exception creating JsonNode from input subnets", e);
1882 throw new MsoAdapterException (error);
1887 stackParams.put ("subnet_list", node);
1889 //Outputs - All subnets are in one ipam_subnets structure
1890 String outputTempl = " subnet:\n" + " description: Openstack subnet identifier\n"
1891 + " value: { get_attr: [network, network_ipam_refs, 0, attr]}\n";
1893 // append outputs in heatTemplate
1894 int outputsIdx = heatTemplate.indexOf ("outputs:");
1895 heatTemplate = insertStr (heatTemplate, outputTempl, outputsIdx + 8);
1896 LOGGER.debug ("Template updated with all AIC3.0 subnets:" + heatTemplate);
1897 return heatTemplate;
1901 private String mergeSubnets (String heatTemplate, List <Subnet> subnets) throws MsoException {
1903 String resourceTempl = " subnet_%subnetId%:\n" + " type: OS::Neutron::Subnet\n"
1906 + " network_id: { get_resource: network }\n"
1907 + " cidr: %cidr%\n";
1909 /* make these optional
1910 + " ip_version: %ipversion%\n"
1911 + " enable_dhcp: %enabledhcp%\n"
1912 + " gateway_ip: %gatewayip%\n"
1913 + " allocation_pools:\n"
1914 + " - start: %poolstart%\n"
1915 + " end: %poolend%\n";
1919 String outputTempl = " subnet_id_%subnetId%:\n" + " description: Openstack subnet identifier\n"
1920 + " value: {get_resource: subnet_%subnetId%}\n";
1924 StringBuilder resourcesBuf = new StringBuilder ();
1925 StringBuilder outputsBuf = new StringBuilder ();
1926 for (Subnet subnet : subnets) {
1928 // build template for each subnet
1929 curR = resourceTempl;
1930 if (subnet.getSubnetId () != null) {
1931 curR = curR.replace ("%subnetId%", subnet.getSubnetId ());
1933 String error = "Missing Required AAI SubnetId for subnet in HEAT Template";
1934 LOGGER.error (MessageEnum.RA_MISSING_PARAM, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing Required AAI ID for subnet in HEAT Template");
1935 throw new MsoAdapterException (error);
1938 if (subnet.getSubnetName () != null) {
1939 curR = curR.replace ("%name%", subnet.getSubnetName ());
1941 curR = curR.replace ("%name%", subnet.getSubnetId ());
1944 if (subnet.getCidr () != null) {
1945 curR = curR.replace ("%cidr%", subnet.getCidr ());
1947 String error = "Missing Required cidr for subnet in HEAT Template";
1948 LOGGER.error (MessageEnum.RA_MISSING_PARAM, error, "Openstack", "", MsoLogger.ErrorCode.DataError, "Missing Required cidr for subnet in HEAT Template");
1949 throw new MsoAdapterException (error);
1952 if (subnet.getIpVersion () != null) {
1953 curR = curR + " ip_version: " + subnet.getIpVersion () + "\n";
1955 if (subnet.getEnableDHCP () != null) {
1956 curR = curR + " enable_dhcp: " + Boolean.toString (subnet.getEnableDHCP ()) + "\n";
1958 if (subnet.getGatewayIp () != null && !subnet.getGatewayIp ().isEmpty() ) {
1959 curR = curR + " gateway_ip: " + subnet.getGatewayIp () + "\n";
1962 if (subnet.getAllocationPools() != null) {
1963 curR = curR + " allocation_pools:\n";
1964 for (Pool pool : subnet.getAllocationPools())
1966 if (!isNullOrEmpty(pool.getStart()) && !isNullOrEmpty(pool.getEnd()))
1968 curR = curR + " - start: " + pool.getStart () + "\n";
1969 curR = curR + " end: " + pool.getEnd () + "\n";
1974 resourcesBuf.append (curR);
1977 curO = curO.replace ("%subnetId%", subnet.getSubnetId ());
1979 outputsBuf.append (curO);
1982 // append resources and outputs in heatTemplate
1983 LOGGER.debug ("Tempate initial:" + heatTemplate);
1984 int outputsIdx = heatTemplate.indexOf ("outputs:");
1985 heatTemplate = insertStr (heatTemplate, outputsBuf.toString (), outputsIdx + 8);
1986 int resourcesIdx = heatTemplate.indexOf ("resources:");
1987 heatTemplate = insertStr (heatTemplate, resourcesBuf.toString (), resourcesIdx + 10);
1989 LOGGER.debug ("Template updated with all subnets:" + heatTemplate);
1990 return heatTemplate;
1993 private Map <String, String> getSubnetUUId(String key, Map <String, Object> outputs, List <Subnet> subnets) {
1995 Map <String, String> sMap = new HashMap <String, String> ();
1998 Object obj = outputs.get(key);
1999 ObjectMapper mapper = new ObjectMapper();
2000 String jStr = mapper.writeValueAsString(obj);
2001 LOGGER.debug ("Subnet_Ipam Output JSON String:" + obj.getClass() + " " + jStr);
2003 JsonNode rootNode = mapper.readTree(jStr);
2004 for (JsonNode sNode : rootNode.path("ipam_subnets"))
2006 LOGGER.debug("Output Subnet Node" + sNode.toString());
2007 String name = sNode.path("subnet_name").getTextValue();
2008 String uuid = sNode.path("subnet_uuid").getTextValue();
2009 String aaiId = name; // default
2010 // try to find aaiId for name in input subnetList
2011 if (subnets != null)
2013 for (Subnet subnet : subnets)
2015 if ( subnet != null && !isNullOrEmpty(subnet.getSubnetName()))
2017 if (subnet.getSubnetName().equals(name))
2019 aaiId = subnet.getSubnetId();
2025 sMap.put(aaiId, uuid); //bpmn needs aaid to uuid map
2030 LOGGER.error (MessageEnum.RA_MARSHING_ERROR, "error getting subnet-uuids", "Openstack", "", MsoLogger.ErrorCode.DataError, "Exception getting subnet-uuids", e);
2033 LOGGER.debug ("Return sMap" + sMap.toString());
2037 private static String insertStr (String template, String snippet, int index) {
2039 String updatedTemplate = "";
2041 LOGGER.debug ("Index:" + index + " Snippet:" + snippet);
2043 String templateBeg = template.substring (0, index);
2044 String templateEnd = template.substring (index);
2046 updatedTemplate = templateBeg + "\n" + snippet + templateEnd;
2048 LOGGER.debug ("Template updated with a subnet:" + updatedTemplate);
2049 return updatedTemplate;